Add LLM token

This commit is contained in:
wangwei
2026-07-02 22:03:39 +08:00
parent e3afb8a07a
commit 52e67b0e7b
36 changed files with 2392 additions and 394 deletions
+33 -5
View File
@@ -1,4 +1,8 @@
"""Provide service-layer logic for qwen client."""
"""Provide service-layer logic for qwen client.
P0-0: ``chat()`` now accepts an optional ``tools`` list and parses ``tool_calls``
from the model response so that callers can dispatch tool invocations.
"""
import time
import json
@@ -7,6 +11,7 @@ from loguru import logger
import httpx
from .base_client import BaseLLMClient, LLMResponse, LLMConfig, LLMProvider
from .tool_types import Tool, ToolCall
# Keep provider-specific behavior explicit so debugging stays straightforward.
@@ -54,14 +59,20 @@ class QwenClient(BaseLLMClient):
messages: List[Dict[str, str]],
max_tokens: Optional[int] = None,
temperature: Optional[float] = None,
tools: Optional[List[Tool]] = None,
**kwargs
) -> LLMResponse:
"""Handle chat for the Qwen Client instance."""
"""Handle chat for the Qwen Client instance.
When ``tools`` is provided the request includes the tool definitions and
``tool_choice="auto"``; any tool_calls returned by the model are parsed
into ``LLMResponse.tool_calls``.
"""
start_time = time.time()
try:
# Keep provider-specific behavior explicit so debugging stays straightforward.
payload = {
payload: Dict = {
"model": self.config.model,
"messages": messages,
"max_tokens": max_tokens or self.config.max_tokens,
@@ -70,6 +81,11 @@ class QwenClient(BaseLLMClient):
"stream": False
}
# P0-0: inject tool definitions when provided.
if tools:
payload["tools"] = [t.to_openai_format() for t in tools]
payload["tool_choice"] = "auto"
# Keep provider-specific behavior explicit so debugging stays straightforward.
response = self._client.post("/chat/completions", json=payload)
response.raise_for_status()
@@ -82,12 +98,24 @@ class QwenClient(BaseLLMClient):
choices = data.get("choices", [{}])
message = choices[0].get("message", {})
# P0-0: parse tool_calls returned by the model.
raw_tool_calls = message.get("tool_calls") or []
parsed_tool_calls: List[ToolCall] = []
for tc in raw_tool_calls:
fn = tc.get("function", {})
try:
args = json.loads(fn.get("arguments", "{}"))
except json.JSONDecodeError:
args = {}
parsed_tool_calls.append(ToolCall(id=tc.get("id", ""), name=fn.get("name", ""), arguments=args))
return LLMResponse(
content=message.get("content", ""),
content=message.get("content", "") or "",
model=data.get("model", self.config.model),
usage=data.get("usage", {}),
finish_reason=choices[0].get("finish_reason", "stop"),
latency_ms=latency_ms
latency_ms=latency_ms,
tool_calls=parsed_tool_calls,
)
except httpx.HTTPStatusError as e: