Github开源生信云平台 DEMO
LLM 本身只能输出文本,工具调用需要开发者根据文本匹配函数名,并传入llm提取的参数进行调用
首先我们看下商业大模型的tool calls 输出的原始文本
curl https://api.deepseek.com/v1/chat/completions \ -H "Authorization: Bearer sk-xxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -N \ -d '{ "model": "deepseek-chat", "stream": true, "messages": [ {"role": "user", "content": "查询一下杭州天气"} ], "tools": [ { "type": "function", "function": { "name": "get_weather", "parameters": { "type": "object", "properties": { "city": {"type": "string"} }, "required": ["city"] } } } ] }'
输出结果
data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "content": "我来" }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "content": "帮" }, "logprobs": null, "finish_reason": null } ] } // 类似的格式这里省略 您查询杭州的天气 data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "content": "情况" }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "content": "。" }, "logprobs": null, "finish_reason": null } ] } // 提取参数 data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "tool_calls": [ { "index": 0, "id": "call_00_EAGlGsFUdTpSUdeBuNANMRQK", "type": "function", "function": { "name": "get_weather", "arguments": "" } } ] }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "tool_calls": [ { "index": 0, "function": { "arguments": "{" } } ] }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "tool_calls": [ { "index": 0, "function": { "arguments": "\"" } } ] }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "tool_calls": [ { "index": 0, "function": { "arguments": "city" } } ] }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "tool_calls": [ { "index": 0, "function": { "arguments": "\"" } } ] }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "tool_calls": [ { "index": 0, "function": { "arguments": ": " } } ] }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "tool_calls": [ { "index": 0, "function": { "arguments": "\"" } } ] }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "tool_calls": [ { "index": 0, "function": { "arguments": "杭州" } } ] }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "tool_calls": [ { "index": 0, "function": { "arguments": "\"" } } ] }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "tool_calls": [ { "index": 0, "function": { "arguments": "}" } } ] }, "logprobs": null, "finish_reason": null } ] } data: { "id": "6214827f-bae2-4a73-a169-9d7badc50cd8", "object": "chat.completion.chunk", "created": 1765527423, "model": "deepseek-chat", "system_fingerprint": "fp_eaab8d114b_prod0820_fp8_kvcache", "choices": [ { "index": 0, "delta": { "content": "" }, "logprobs": null, "finish_reason": "tool_calls" } ], "usage": { "prompt_tokens": 295, "completion_tokens": 52, "total_tokens": 347, "prompt_tokens_details": { "cached_tokens": 192 }, "prompt_cache_hit_tokens": 192, "prompt_cache_miss_tokens": 103 } } data: [DONE]
可以看到原始的输出就是一个个的字符流。参数和函数名只是一段文字。此时当我们使用python的openaipip包进行调用时,这个python工具会自动帮助我们将函数名称和参数封装成一个对象
openai
(type='tool_calls.function.arguments.done', name='get_error_log', index=0, arguments='{"biz_id": "1111", "biz_type": "2222"}', parsed_arguments=None)
此时开发者再进行函数调用
if pending_tool_calls: tool_results = [] for tc in pending_tool_calls: func = tc.function.name # get_error_log args = json.loads(tc.function.arguments) if func == "get_error_log": result = await tool_get_error_log( args["biz_id"], args["biz_type"] )