fix(llm): httpx с HTTP/2 вместо requests
api.aillm.ru за ddos-guard — требует HTTP/2. requests (HTTP/1.1) не работал. httpx[http2] — поддержка HTTP/2, работает с ddos-guard.
This commit is contained in:
@@ -5,3 +5,4 @@ requests
|
|||||||
psycopg2-binary
|
psycopg2-binary
|
||||||
python-dotenv
|
python-dotenv
|
||||||
pdfplumber
|
pdfplumber
|
||||||
|
httpx[http2]
|
||||||
|
|||||||
+12
-8
@@ -4,13 +4,15 @@ llm_client.py — Тонкий HTTP-клиент к LLM API.
|
|||||||
Только отправить промпт → получить ответ. Никакой бизнес-логики.
|
Только отправить промпт → получить ответ. Никакой бизнес-логики.
|
||||||
Бизнес-логика (промпты, парсинг ответа) → extractor.py.
|
Бизнес-логика (промпты, парсинг ответа) → extractor.py.
|
||||||
|
|
||||||
Использует:
|
Использует httpx (HTTP/2) — api.aillm.ru за ddos-guard, требует HTTP/2.
|
||||||
|
|
||||||
|
Переменные окружения:
|
||||||
LLM_API_URL — URL API (по умолчанию https://api.aillm.ru/v1/chat/completions)
|
LLM_API_URL — URL API (по умолчанию https://api.aillm.ru/v1/chat/completions)
|
||||||
LLM_API_KEY — ключ авторизации
|
LLM_API_KEY — ключ авторизации
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import requests
|
import httpx
|
||||||
|
|
||||||
# ── Конфигурация ────────────────────────────────────────────────
|
# ── Конфигурация ────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -55,9 +57,11 @@ def ask(prompt: str, model: str = None, max_tokens: int = 8000) -> dict:
|
|||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resp = requests.post(api_url, json=payload, headers=headers, timeout=120)
|
# httpx с HTTP/2 — обязательно для ddos-guard
|
||||||
resp.raise_for_status()
|
with httpx.Client(http2=True, timeout=120) as client:
|
||||||
data = resp.json()
|
resp = client.post(api_url, json=payload, headers=headers)
|
||||||
|
resp.raise_for_status()
|
||||||
|
data = resp.json()
|
||||||
|
|
||||||
# OpenAI-совместимый формат ответа
|
# OpenAI-совместимый формат ответа
|
||||||
choice = data.get("choices", [{}])[0]
|
choice = data.get("choices", [{}])[0]
|
||||||
@@ -70,11 +74,11 @@ def ask(prompt: str, model: str = None, max_tokens: int = 8000) -> dict:
|
|||||||
"usage": data.get("usage", {}),
|
"usage": data.get("usage", {}),
|
||||||
}
|
}
|
||||||
|
|
||||||
except requests.exceptions.Timeout:
|
except httpx.TimeoutException:
|
||||||
return {"error": "LLM timeout (120s)"}
|
return {"error": "LLM timeout (120s)"}
|
||||||
except requests.exceptions.HTTPError as e:
|
except httpx.HTTPStatusError as e:
|
||||||
return {"error": f"LLM HTTP {e.response.status_code}: {e.response.text[:500]}"}
|
return {"error": f"LLM HTTP {e.response.status_code}: {e.response.text[:500]}"}
|
||||||
except requests.exceptions.RequestException as e:
|
except httpx.RequestError as e:
|
||||||
return {"error": f"LLM request failed: {e}"}
|
return {"error": f"LLM request failed: {e}"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {"error": f"LLM unexpected: {e}"}
|
return {"error": f"LLM unexpected: {e}"}
|
||||||
|
|||||||
Reference in New Issue
Block a user