feat(Ф2): llm_client.py — DI LLM (HttpxLLMClient + FakeLLMClient)

This commit is contained in:
2026-06-28 09:21:54 +04:00
parent a05a9691a0
commit fd01aadf95
3 changed files with 113 additions and 40 deletions
+20 -22
View File
@@ -1,34 +1,32 @@
"""LLM service — call LLM API."""
"""LLM service — call LLM API with optional DI."""
import os, json
import httpx
LLM_URL = "https://api.aillm.ru/v1/chat/completions"
LLM_KEY = os.environ.get("LLM_KEY") or os.environ.get("LLM_API_KEY", "")
LLM_MODEL = "gpt-oss-120b"
# Ленивый singleton — обратная совместимость
_llm_client = None
def _get_default_client():
global _llm_client
if _llm_client is None:
from .llm_client import HttpxLLMClient
_llm_client = HttpxLLMClient(url=LLM_URL, key=LLM_KEY, model=LLM_MODEL)
return _llm_client
def call_llm(current_spec, doc_text, build_prompt_fn, llm_client=None):
"""Call LLM. Returns (parsed_result, prompt_id).
llm_client: LLMClient (optional). Default — HttpxLLMClient (prod).
"""
if llm_client is None:
llm_client = _get_default_client()
def call_llm(current_spec, doc_text, build_prompt_fn):
"""Call LLM. Returns (parsed_result, prompt_id)."""
prompt, prompt_id = build_prompt_fn(current_spec, doc_text)
payload = {
"model": LLM_MODEL,
"messages": [{"role": "user", "content": prompt}],
"max_tokens": 8000,
"temperature": 0.1,
}
with httpx.Client(http2=True, timeout=120, verify=True) as client:
resp = client.post(
LLM_URL,
json=payload,
headers={
"Authorization": f"Bearer {LLM_KEY}",
"Content-Type": "application/json",
},
)
resp.raise_for_status()
data = resp.json()
raw_text = llm_client.complete(prompt)
raw_text = data.get("choices", [{}])[0].get("message", {}).get("content", "")
json_text = raw_text
if "```json" in json_text:
json_text = json_text.split("```json")[1].split("```")[0]