init
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Optional
|
||||
from collections import deque
|
||||
|
||||
from config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LLMService:
|
||||
def __init__(self) -> None:
|
||||
self._ready = False
|
||||
self._error: Optional[str] = None
|
||||
self._client = None
|
||||
self._model = (settings.llm_model or "").strip()
|
||||
self._history: deque[dict] = deque(maxlen=12) # 6 turns (user+assistant)
|
||||
self._system_prompt = "请用中文口语化简短回复,1-2句。"
|
||||
|
||||
if not settings.llm_api_key:
|
||||
return
|
||||
if not self._model:
|
||||
base = (settings.llm_base_url or "").lower()
|
||||
self._model = "deepseek-chat" if "deepseek.com" in base else "gpt-4o-mini"
|
||||
try:
|
||||
from openai import AsyncOpenAI
|
||||
|
||||
self._client = AsyncOpenAI(
|
||||
api_key=settings.llm_api_key,
|
||||
base_url=settings.llm_base_url,
|
||||
timeout=settings.llm_timeout,
|
||||
)
|
||||
self._ready = True
|
||||
except Exception as exc: # pragma: no cover
|
||||
self._error = str(exc)
|
||||
logger.warning("LLM online mode unavailable: %s", exc)
|
||||
|
||||
async def reply_with_meta(self, text: str) -> tuple[str, str]:
|
||||
if not self._ready or self._client is None:
|
||||
return f"收到:{text}。这是本地兜底回复。", "fallback"
|
||||
|
||||
try:
|
||||
resp = await self._client.chat.completions.create(
|
||||
model=self._model,
|
||||
messages=[{"role": "system", "content": self._system_prompt}, *list(self._history), {"role": "user", "content": text}],
|
||||
max_tokens=settings.llm_max_tokens,
|
||||
temperature=0.7,
|
||||
)
|
||||
content = (resp.choices[0].message.content or "").strip()
|
||||
if content:
|
||||
self._history.append({"role": "user", "content": text})
|
||||
self._history.append({"role": "assistant", "content": content})
|
||||
return content, "online"
|
||||
except Exception as exc: # pragma: no cover
|
||||
self._error = str(exc)
|
||||
logger.warning("LLM request failed, fallback used: %s", exc)
|
||||
|
||||
return f"收到:{text}。这是本地兜底回复。", "fallback"
|
||||
|
||||
async def reply(self, text: str) -> str:
|
||||
content, _ = await self.reply_with_meta(text)
|
||||
return content
|
||||
|
||||
@property
|
||||
def health(self) -> dict:
|
||||
return {
|
||||
"ready": self._ready,
|
||||
"model": self._model,
|
||||
"history_items": len(self._history),
|
||||
"error": self._error,
|
||||
}
|
||||
|
||||
def clear_history(self) -> None:
|
||||
self._history.clear()
|
||||
Reference in New Issue
Block a user