fixed proxy
This commit is contained in:
@@ -37,6 +37,101 @@ TABLE_TYPE_LABELS = {
|
||||
"simple_list": "Бланк заказа",
|
||||
}
|
||||
|
||||
|
||||
def _openrouter_proxy_url() -> str | None:
|
||||
settings = get_settings()
|
||||
proxy = (settings.openrouter_proxy or "").strip() or None
|
||||
if proxy and "://" not in proxy:
|
||||
proxy = f"socks5://{proxy}"
|
||||
return proxy
|
||||
|
||||
|
||||
def openrouter_headers() -> dict[str, str]:
|
||||
settings = get_settings()
|
||||
return {
|
||||
"Authorization": f"Bearer {settings.openrouter_api_key}",
|
||||
"Content-Type": "application/json",
|
||||
"HTTP-Referer": "https://gostgenerator.local",
|
||||
"X-Title": "GostGenerator Web",
|
||||
}
|
||||
|
||||
|
||||
def openrouter_chat_url() -> str:
|
||||
return get_settings().openrouter_base_url.rstrip("/") + "/chat/completions"
|
||||
|
||||
|
||||
async def openrouter_chat(
|
||||
messages: list[dict[str, str]],
|
||||
*,
|
||||
temperature: float = 0.2,
|
||||
max_tokens: int = 2000,
|
||||
) -> str:
|
||||
"""Shared OpenRouter chat/completions call (same key, proxy, model as ESKD chat)."""
|
||||
settings = get_settings()
|
||||
if not settings.openrouter_api_key:
|
||||
raise RuntimeError("OpenRouter API key не настроен (OPENROUTER_API_KEY).")
|
||||
|
||||
payload = {
|
||||
"model": settings.openrouter_model,
|
||||
"messages": messages,
|
||||
"temperature": temperature,
|
||||
"max_tokens": max_tokens,
|
||||
}
|
||||
client_kwargs: dict[str, Any] = {"timeout": 120.0}
|
||||
proxy = _openrouter_proxy_url()
|
||||
if proxy:
|
||||
client_kwargs["proxy"] = proxy
|
||||
|
||||
async with httpx.AsyncClient(**client_kwargs) as client:
|
||||
resp = await client.post(
|
||||
openrouter_chat_url(),
|
||||
headers=openrouter_headers(),
|
||||
json=payload,
|
||||
)
|
||||
if resp.status_code >= 400:
|
||||
detail = resp.text[:500]
|
||||
raise RuntimeError(f"OpenRouter HTTP {resp.status_code}: {detail}")
|
||||
data = resp.json()
|
||||
|
||||
return data["choices"][0]["message"]["content"] or ""
|
||||
|
||||
|
||||
def openrouter_chat_sync(
|
||||
messages: list[dict[str, str]],
|
||||
*,
|
||||
temperature: float = 0.2,
|
||||
max_tokens: int = 2000,
|
||||
) -> str:
|
||||
"""Sync variant for non-async endpoints (same transport as ESKD chat)."""
|
||||
settings = get_settings()
|
||||
if not settings.openrouter_api_key:
|
||||
raise RuntimeError("OpenRouter API key не настроен (OPENROUTER_API_KEY).")
|
||||
|
||||
payload = {
|
||||
"model": settings.openrouter_model,
|
||||
"messages": messages,
|
||||
"temperature": temperature,
|
||||
"max_tokens": max_tokens,
|
||||
}
|
||||
client_kwargs: dict[str, Any] = {"timeout": 120.0}
|
||||
proxy = _openrouter_proxy_url()
|
||||
if proxy:
|
||||
client_kwargs["proxy"] = proxy
|
||||
|
||||
with httpx.Client(**client_kwargs) as client:
|
||||
resp = client.post(
|
||||
openrouter_chat_url(),
|
||||
headers=openrouter_headers(),
|
||||
json=payload,
|
||||
)
|
||||
if resp.status_code >= 400:
|
||||
detail = resp.text[:500]
|
||||
raise RuntimeError(f"OpenRouter HTTP {resp.status_code}: {detail}")
|
||||
data = resp.json()
|
||||
|
||||
return data["choices"][0]["message"]["content"] or ""
|
||||
|
||||
|
||||
def estimate_tokens(text: str) -> int:
|
||||
"""Rough token estimate (works for mixed RU/EN)."""
|
||||
if not text:
|
||||
@@ -159,36 +254,8 @@ async def chat_edit_table(
|
||||
hist.append({"role": "user", "content": message})
|
||||
|
||||
messages = build_llm_messages(table_type, rows, hist)
|
||||
context = build_context_usage(messages)
|
||||
content = await openrouter_chat(messages, temperature=0.2, max_tokens=2000)
|
||||
|
||||
payload = {
|
||||
"model": settings.openrouter_model,
|
||||
"messages": messages,
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
headers = {
|
||||
"Authorization": f"Bearer {settings.openrouter_api_key}",
|
||||
"Content-Type": "application/json",
|
||||
"HTTP-Referer": "https://gostgenerator.local",
|
||||
"X-Title": "GostGenerator Web",
|
||||
}
|
||||
url = settings.openrouter_base_url.rstrip("/") + "/chat/completions"
|
||||
|
||||
proxy = (settings.openrouter_proxy or "").strip() or None
|
||||
if proxy and "://" not in proxy:
|
||||
proxy = f"socks5://{proxy}"
|
||||
|
||||
client_kwargs: dict[str, Any] = {"timeout": 90.0}
|
||||
if proxy:
|
||||
client_kwargs["proxy"] = proxy
|
||||
|
||||
async with httpx.AsyncClient(**client_kwargs) as client:
|
||||
resp = await client.post(url, headers=headers, json=payload)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
|
||||
content = data["choices"][0]["message"]["content"]
|
||||
parsed = _extract_json(content)
|
||||
edits = parsed.get("edits") or []
|
||||
norm_edits = []
|
||||
@@ -204,22 +271,7 @@ async def chat_edit_table(
|
||||
}
|
||||
)
|
||||
|
||||
# include assistant reply in usage estimate
|
||||
context = build_context_usage(messages + [{"role": "assistant", "content": content}])
|
||||
usage = data.get("usage") or {}
|
||||
if usage.get("prompt_tokens"):
|
||||
prompt_t = int(usage["prompt_tokens"])
|
||||
completion_t = int(usage.get("completion_tokens") or 0)
|
||||
total_t = int(usage.get("total_tokens") or (prompt_t + completion_t))
|
||||
limit = settings.llm_context_limit
|
||||
context = {
|
||||
"used": total_t,
|
||||
"limit": limit,
|
||||
"percent": min(100.0, round(100.0 * total_t / limit, 1)) if limit else 0.0,
|
||||
"prompt_tokens": prompt_t,
|
||||
"completion_tokens": completion_t,
|
||||
}
|
||||
|
||||
return {"reply": parsed.get("reply") or "", "edits": norm_edits, "context": context}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user