deepseek 的 function calling 是“意图识别 + 手动调度”流程:模型仅输出结构化 tool_calls 请求,需开发者解析 arguments(字符串,须 json.loads)、执行函数并回填结果;务必用 try/except 处理非法 json,流式响应中需累积 delta 直至 finish_reason="tool_calls" 再解析。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

DeepSeek 的 Function Calling 不是模型自动执行函数,而是由你控制的“意图识别 + 手动调度”流程:模型只输出结构化调用请求,你负责解析、执行、再喂回结果。
tool_calls 字段怎么解析?
API 返回的 response.choices[0].message.tool_calls 是一个列表,每个元素含 id、function.name 和 function.arguments(字符串格式的 JSON)。注意:arguments 是原始字符串,不是已解析的 dict,必须用 json.loads() 转换。
- 常见错误:直接对
arguments做.get("location")—— 会报AttributeError,因为它是 str 不是 dict - 安全做法:始终用
try/except json.JSONDecodeError包裹解析逻辑,模型偶尔会返回不合法 JSON(比如多加逗号、缺引号) - 多个工具调用时,
tool_calls列表长度可能 >1,需逐个处理;但 DeepSeek 当前版本(v3.2)默认只返回一个,除非显式设tool_choice="required"并定义多个工具
tools 参数必须严格按 JSON Schema 写吗?
是的,tools 必须是符合 OpenAI 兼容格式的 list,每个 tool 的 function.parameters 必须是合法 JSON Schema 对象。DeepSeek 不接受 Python dict 描述或简化写法。
统一LLM网关 - 一个API对接70+AI模型,使用单一API密钥即可调用GPT、Claude、Gemini、Qwen、Deepseek、Grok等主流模型。
- 必填字段:每个
function至少要有name、description、parameters;parameters里type: "object"和properties不能省 - 参数类型提示很重要:比如把
location的type写成"string",模型才可能从“上海浦东”中准确提取字符串;若漏掉type,模型大概率忽略该参数 - 枚举值要显式声明:如温度单位支持
"c"或"f",必须写"enum": ["c", "f"],否则模型可能传入"cel"或"C"导致你的函数出错
为什么模型没触发函数调用?
最常见原因是描述(description)太模糊或与用户提问语义不匹配,导致模型判断“不需要工具”。它不会因为你定义了函数就一定调用。
- 检查点:把用户问题和
function.description一起读一遍——是否能自然推出“这个问题应该用这个函数解决”?例如描述写成“查天气”,不如“获取指定城市的实时天气状况(含温度、湿度、风向)”明确 - 避免过度泛化:不要给一个函数起名
do_something或写描述“处理各种查询”,模型无法建立稳定映射 - 调试技巧:先用固定 prompt 测试,比如 messages = [{"role":"user","content":"北京现在多少度?"}],排除对话历史干扰;确认仍不触发,再检查 tools 格式和模型是否为
deepseek-chat
流式响应下怎么处理 tool_calls?
流式(stream=True)时,tool_calls 不会在首个 chunk 出现,而是在某个中间 chunk 中以 delta 形式分段到达,且可能跨 chunk 拆分 function.arguments 字符串。
- 关键动作:必须累积所有
delta.tool_calls,直到收到finish_reason="tool_calls"的 chunk,才能认为调用请求完整 - 容易踩的坑:在第一个含
tool_calls的 chunk 就急着解析arguments,此时字符串往往不完整(比如只有{"location": "北),直接json.loads必然失败 - 建议做法:用字典按
id缓存每个 call 的function.name和拼接中的arguments字符串,等 finish_reason 到达再统一解析
真正卡住人的往往不是语法,而是模型对 description 的理解偏差和 arguments 解析时的 JSON 边界问题——这两处不加防御性处理,上线后一定会遇到奇怪的空指针或 JSONDecodeError。










