fix: switch default model to qwen3-coder-plus for better function calling

DeepSeek-chat has limited/partial function calling support. Qwen3-coder-plus
(DashScope) has robust OpenAI-compatible function calling.

Also added tool usage instructions to system prompt and enhanced logging
to trace tool propagation through the pipeline.
This commit is contained in:
chiguyong 2026-06-12 09:27:52 +08:00
parent 44f19fcf14
commit 2110c84fb6
4 changed files with 22 additions and 9 deletions

View File

@ -21,13 +21,13 @@ providers:
cost_per_1k_output: 0.00028 cost_per_1k_output: 0.00028
model_aliases: model_aliases:
default: "deepseek/deepseek-chat" default: "openai/qwen3-coder-plus"
fast: "deepseek/deepseek-chat" fast: "openai/qwen3-coder-plus"
powerful: "deepseek/deepseek-chat" powerful: "openai/qwen3-coder-plus"
fallbacks: fallbacks:
deepseek/deepseek-chat: openai/qwen3-coder-plus:
- "openai/qwen3-coder-plus" - "deepseek/deepseek-chat"
# 上下文压缩配置 — 长会话自动压缩历史消息,保持 Token 在预算内 # 上下文压缩配置 — 长会话自动压缩历史消息,保持 Token 在预算内
# GEO Pipeline 启用后,工具输出(搜索结果、网页抓取等)会自动压缩 # GEO Pipeline 启用后,工具输出(搜索结果、网页抓取等)会自动压缩

View File

@ -213,10 +213,17 @@ async def resolve_skill_routing(
# Append available tools to system prompt so LLM knows what it can call # Append available tools to system prompt so LLM knows what it can call
if result.tools: if result.tools:
tools_desc = _build_tools_description(result.tools) tools_desc = _build_tools_description(result.tools)
tool_instruction = (
"\n\n## Tool Usage\n"
"You have access to the following tools. When you need to use a tool, "
"respond with a tool call in the format specified by the system.\n"
"Never make up information or guess answers when you can use a tool to find the answer.\n"
"Always prefer using tools over guessing.\n"
)
if result.system_prompt: if result.system_prompt:
result.system_prompt += f"\n\n## Available Tools\n{tools_desc}" result.system_prompt += f"{tool_instruction}\n## Available Tools\n{tools_desc}"
else: else:
result.system_prompt = f"## Available Tools\n{tools_desc}" result.system_prompt = f"{tool_instruction}\n## Available Tools\n{tools_desc}"
return result return result

View File

@ -184,8 +184,10 @@ class OpenAICompatibleProvider(LLMProvider):
if request.tools: if request.tools:
payload["tools"] = request.tools payload["tools"] = request.tools
payload["tool_choice"] = request.tool_choice payload["tool_choice"] = request.tool_choice
tool_names = [t.get("function", {}).get("name", "?") for t in request.tools]
logger.debug(f"Stream request to {url}: model={request.model}, messages={len(request.messages)}, tools={len(request.tools or [])}") logger.info(f"OpenAIProvider stream: model={request.model}, tools={len(request.tools)} {tool_names}")
else:
logger.info(f"OpenAIProvider stream: model={request.model}, NO tools")
response_ctx = self._client.stream("POST", url, json=payload, headers=headers) response_ctx = self._client.stream("POST", url, json=payload, headers=headers)
response = await response_ctx.__aenter__() response = await response_ctx.__aenter__()

View File

@ -390,6 +390,10 @@ async def _handle_chat_message(
session_id=session_id, session_id=session_id,
) )
# Debug: log tools that will be passed to ReActEngine
tool_names = [t.name for t in routing.tools]
logger.info(f"Chat {session_id}: resolved {len(routing.tools)} tools: {tool_names}, model={routing.model}, skill={routing.skill_name}")
# Notify frontend about skill match # Notify frontend about skill match
if routing.matched: if routing.matched:
await websocket.send_json({ await websocket.send_json({