This commit is contained in:
commit
46af290db3
100 files changed
+16663
No files matched your search
@@ -0,0 +1,126 @@
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import httpx
|
||||
from config.settings import settings
|
||||
|
||||
from services.model_config import model_config
|
||||
|
||||
|
||||
class LLMRouter:
|
||||
def __init__(self):
|
||||
self.ollama_base_url = settings.OLLAMA_BASE_URL
|
||||
self.openrouter_base_url = settings.OPENROUTER_BASE_URL
|
||||
|
||||
async def generate_ollama(
|
||||
self,
|
||||
prompt: str,
|
||||
model: Optional[str] = None,
|
||||
preset: str = "creative_draft",
|
||||
options: Optional[Dict[str, Any]] = None,
|
||||
) -> str:
|
||||
"""Генерация через локальную Ollama с пресетами"""
|
||||
from services.presets import get_preset
|
||||
|
||||
# Используем модель из конфига, если не указана
|
||||
model = model or model_config.get_default_model("ollama")
|
||||
|
||||
# Валидация модели
|
||||
if not model_config.validate_model("ollama", model):
|
||||
raise ValueError(f"Model {model} not available for Ollama")
|
||||
|
||||
# Получаем базовые параметры из пресета
|
||||
preset_options = get_preset(preset, "ollama")
|
||||
# Объединяем с пользовательскими опциями (пользовательские переопределяют пресет)
|
||||
merged_options = {**preset_options, **(options or {})}
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
payload = {
|
||||
"model": model,
|
||||
"prompt": prompt,
|
||||
"stream": False,
|
||||
"options": merged_options,
|
||||
}
|
||||
response = await client.post(
|
||||
f"{self.ollama_base_url}/api/generate", json=payload, timeout=60.0
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()["response"]
|
||||
|
||||
async def generate_openrouter(
|
||||
self,
|
||||
prompt: str,
|
||||
model: Optional[str] = None,
|
||||
api_key: Optional[str] = None,
|
||||
preset: str = "creative_draft",
|
||||
options: Optional[Dict[str, Any]] = None,
|
||||
) -> str:
|
||||
"""Генерация через OpenRouter API с пресетами"""
|
||||
from services.presets import get_preset
|
||||
|
||||
# Используем ключ из settings, если не передан явно
|
||||
actual_api_key = api_key or settings.OPENROUTER_API_KEY
|
||||
|
||||
# Валидация API ключа
|
||||
if not actual_api_key or actual_api_key == "your_api_key_here":
|
||||
raise ValueError(
|
||||
"OpenRouter API key not configured. "
|
||||
"Please set OPENROUTER_API_KEY in backend/.env file"
|
||||
)
|
||||
|
||||
# Используем модель из конфига, если не указана
|
||||
model = model or model_config.get_default_model("openrouter")
|
||||
|
||||
# Валидация модели
|
||||
if not model_config.validate_model("openrouter", model):
|
||||
raise ValueError(f"Model {model} not available for OpenRouter")
|
||||
|
||||
# Получаем базовые параметры из пресета
|
||||
preset_options = get_preset(preset, "openrouter")
|
||||
# Объединяем с пользовательскими опциями
|
||||
merged_options = {**preset_options, **(options or {})}
|
||||
|
||||
async with httpx.AsyncClient() as client:
|
||||
payload = {
|
||||
"model": model,
|
||||
"messages": [{"role": "user", "content": prompt}],
|
||||
}
|
||||
# Добавляем объединённые опции (включая frequency_penalty, presence_penalty и temperature)
|
||||
if merged_options:
|
||||
payload.update(merged_options)
|
||||
headers = {
|
||||
"Authorization": f"Bearer {actual_api_key}",
|
||||
"Content-Type": "application/json",
|
||||
"HTTP-Referer": "http://localhost:3000", # Для OpenRouter
|
||||
"X-Title": "Writer IDE", # Для OpenRouter
|
||||
}
|
||||
response = await client.post(
|
||||
f"{self.openrouter_base_url}/chat/completions",
|
||||
json=payload,
|
||||
headers=headers,
|
||||
timeout=60.0,
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()["choices"][0]["message"]["content"]
|
||||
|
||||
async def generate(
|
||||
self,
|
||||
prompt: str,
|
||||
provider: str = "ollama",
|
||||
model: Optional[str] = None,
|
||||
api_key: Optional[str] = None,
|
||||
preset: str = "creative_draft",
|
||||
options: Optional[Dict[str, Any]] = None,
|
||||
) -> str:
|
||||
"""Универсальный метод генерации"""
|
||||
if provider == "ollama":
|
||||
return await self.generate_ollama(prompt, model, preset, options)
|
||||
elif provider == "openrouter":
|
||||
return await self.generate_openrouter(
|
||||
prompt, model, api_key, preset, options
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unknown provider: {provider}")
|
||||
|
||||
|
||||
# Singleton instance
|
||||
llm_router = LLMRouter()
|
||||
Reference in new issue
Block a user