FastAPI + OpenAI 兼容协议 + DeepSeek 实战:大模型 Function Calling 工具调用全拆解
FastAPI OpenAI 兼容协议 DeepSeek 实战大模型 Function Calling 工具调用全拆解功能概览功能核心内容天气查询工具声明tools、单轮发起、解析tool_calls打印函数名参数不执行学历查询多工具声明、get_xueli外部调用 Redis 缓存、工具结果回灌第二轮合成调用链路总览用户问题 → messages tools 发给模型 → 模型返回 tool_calls函数名 JSON 参数 → 本地执行对应函数天气/学历 → 把 函数结果 以 roletool 追加回 messages → 再次请求模型 → 模型生成最终自然语言回答一、环境准备OpenAI 依赖下载与配置单列工具调用依赖 OpenAI 官方 SDK配置单独拎出来讲不与业务代码混在一起。1.1 依赖下载pipinstallopenai代码顶部都是from openai import OpenAI装好这个包即可。redis与requests是学历查询里缓存和调用外部 API 用到的按需安装pip install redis requests。1.2 密钥配置环境变量raw_keyos.getenv(DASHSCOPE_API_KEY)api_keyraw_key.strip()代码通过DASHSCOPE_API_KEY读取阿里云百炼的 API Key需提前在系统或.env中导出该变量。1.3 base_url 兼容端点clientOpenAI(api_keyapi_key,base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1,)关键是base_url必须带/compatible-mode/v1后缀——百炼把 OpenAI 协议做成了兼容模式漏写这一截会直接 404。二、知识点讲解2.1 什么是 Function Calling模型本身不能直接查天气、查数据库。我们告诉模型你有这些函数可用模型在觉得需要时返回我想调用某个函数、参数是这样真正的函数由我们本地执行再把结果交还给模型整理成话。这就是模型决策 本地执行的混合模式。2.2 tools 工具声明结构每个工具是一个 JSON-Schematype: functionfunction.name函数名function.description给模型看的功能描述function.parameters入参的 JSON Schema。description写得好不好直接决定模型会不会在该调用时调用。2.3 tool_calls 是什么模型认为需要调用工具时返回的消息里message.tool_calls不为None里面是列表每项含function.name函数名、function.argumentsJSON 字符串参数、id该次调用的标识回灌结果时必须带上。2.4 单轮识别 vs 完整闭环单轮拿到tool_calls就结束仅解析函数名/参数闭环执行函数 → 把结果以roletool追加 → 再请求一次模型由模型产出最终回答。少了回灌这步用户永远看不到自然语言结果。三、代码逻辑拆解3.1 客户端初始化与模型选择两个功能的顶部完全一致raw_keyos.getenv(DASHSCOPE_API_KEY)api_keyraw_key.strip()clientOpenAI(api_keyapi_key,base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1,)第 1 行从环境变量取密钥原始值第 2 行.strip()去掉首尾空白避免复制粘贴带换行导致鉴权失败第 3–5 行构造 OpenAI 客户端base_url指向百炼兼容端点。模型名不在客户端里写而是在每次create时指定见 3.3。3.2 第一个功能天气查询3.2.1 工具声明与本地函数tools[{type:function,function:{name:get_current_weather,description:当你想查询指定城市的天气时非常有用。,parameters:{type:object,properties:{location:{type:string,description:城市或县区比如北京市、杭州市、余杭区等。,}},required:[location],},},},]defget_current_weather(arguments):weather_conditions[晴天,多云,雨天]random_weatherrandom.choice(weather_conditions)locationarguments[location]returnf{location}今天是{random_weather}。name函数标识必须与本地真实函数同名模型返回时原样带回description模型的使用说明书决定何时触发parameters.properties.location入参 schemarequired声明该参数必填模型被要求必须产出它get_current_weather是本地实现从参数里取location随机返回一个天气演示用真实场景替换为气象 API。3.2.2 发起请求与单轮解析defget_response(messages):completionclient.chat.completions.create(modeldeepseek-v4-flash-0731,messagesmessages,toolstools,)returncompletion user_message[{role:user,content:你是谁}]messages.extend(user_message)completionget_response(messages)messages.append(completion.choices[0].message)ifcompletion.choices[0].message.tool_callsisNone:print(f无需调用工具直接回复{completion.choices[0].message.content})else:print(需要调用工具:)tool_callscompletion.choices[0].message.tool_callsforiintool_calls:f_namei.function.name f_argi.function.argumentsprint(f调用工具是{f_name}参数{f_arg})modeldeepseek-v4-flash-0731具体模型名写在每次请求里toolstools把工具清单一并提交模型才会返回tool_callsmessages.extend把用户问题追加进对话列表模块级messages []completion.choices[0].message模型原始消息先整体append进messages保证多轮上下文连续if ... tool_calls is None判断是否触发工具——None说明模型直接回答了否则进入工具分支工具分支里i.function.name取函数名、i.function.arguments取参数字符串是字符串不是字典要用json.loads解析注意这一段到这里只print没真正执行函数、也没回灌所以它只是识别演示。3.3 第二个功能学历查询3.3.1 Redis 客户端与外部学历查询工具rRedis(host127.0.0.1,port6379,db11,decode_responsesTrue)defget_xueli(arguments):vcodearguments[vcode]keyfboos:llm:academic_credential_verification:{vcode}redis_vreifr.get(key)ifredis_vreifisNone:API_KEYMY_KEY_le0KRXAsCh6cNphDEURqJCs02jt3x1BASE_URLhttps://www.apimy.cn/api/xxw/bgcxparams{key:API_KEY,vcode:arguments[vcode]}headers{Content-Type:application/json}responserequests.get(BASE_URL,paramsparams,timeout30)response.raise_for_status()dataresponse.json()r.set(key,json.dumps(data,ensure_asciiFalse))returnjson.dumps(data,ensure_asciiFalse)else:returnredis_vreif第 1–4 行Redis 客户端db11与多轮对话的db10区分开decode_responsesTrue让取出的 value 直接是字符串key用学历验证码拼键同一验证码只查一次if redis_vreif is None缓存未命中才真打外部 API命中直接返回省额度requests.get(..., timeout30)timeout必带外部接口抽风时不会把连接挂死r.set(key, json.dumps(data))把结果以 JSON 字符串写回 Redis返回时json.dumps(data)与缓存写入格式保持一致工具结果对模型而言都是字符串即可。3.3.2 多工具声明tools[{type:function,function:{name:get_current_weather,description:当你想查询指定城市的天气时非常有用。,parameters:{type:object,properties:{location:{type:string,description:城市或县区比如北京市、杭州市、余杭区等。,}},required:[location],},},},{type:function,function:{name:get_xueli,description:当你想查询学历或验证学历时非常有用。,parameters:{type:object,properties:{vcode:{type:string,description:学历验证码,}},required:[vcode],},},},]在天气工具之外还声明了get_xueli工具结构一致参数换成了vcode学历验证码required: [vcode]。两个工具并列放在同一个tools列表里模型可自由选其一或都用。3.3.3 完整闭环执行工具 结果回灌user_message[{role:user,content:帮我查下一下学历验证码是:你自己的学历吗}]messages.extend(user_message)completionget_response(messages)messages.append(completion.choices[0].message)ifcompletion.choices[0].message.tool_callsisNone:print(f无需调用工具直接回复{completion.choices[0].message.content})else:print(需要调用工具:)tool_callscompletion.choices[0].message.tool_calls fun{get_current_weather:get_current_weather,get_xueli:get_xueli}foriintool_calls:f_namei.function.name f_argi.function.argumentsprint(f调用工具是{f_name}参数{f_arg})tool_resultfun[f_name](json.loads(f_arg))print(f工具返回结果是{tool_result})# 把工具结果追加消息再次请求模型生成自然文本messages.append({role:tool,tool_call_id:i.id,content:tool_result})final_respget_response(messages)print(模型整理后的文本回答,final_resp.choices[0].message.content)fun {...}函数名到本地函数对象的映射表模型返回函数名后据此分发执行fun[f_name](json.loads(f_arg))用json.loads把参数字符串还原成字典后调用messages.append({role: tool, ...})这是闭环的关键——role必须是tooltool_call_id填模型给的i.idcontent填工具返回值get_response(messages)再次发起此时模型已拿到工具结果会生成最终自然语言回答。源码注释也点明把工具结果追加消息再次请求模型生成自然文本就是回灌 二次请求。

相关新闻

从《绝地求生》逆向提取虚幻引擎4 SDK:IDA Pro与Cheat Engine实战指南

从《绝地求生》逆向提取虚幻引擎4 SDK:IDA Pro与Cheat Engine实战指南

1. 项目概述:从游戏到引擎的逆向之路最近在逆向分析圈里,一个经久不衰的话题就是如何从热门游戏中提取出游戏引擎的软件开发工具包。这听起来像是个黑魔法,但实际上,它是一套结合了静态分析与动态调试的严谨技术流程。今天要聊的&…

2026/8/6 5:05:03 阅读更多 →
为什么你在公司能成事,独处时却一事无成?

为什么你在公司能成事,独处时却一事无成?

——从脚手架、意识形态到情绪战争的三个维度解剖你有没有发现一个悖论: 同一个人,同一颗大脑,同一套意志力。 在公司里,你能连续加班三个月交付一个复杂项目,能在状态极差的情况下完成高质量的方案,能在截…

2026/8/6 5:05:03 阅读更多 →
非线性控制中的Lipschitz条件:从数学基础到工程实践

非线性控制中的Lipschitz条件:从数学基础到工程实践

1. 项目概述:为什么非线性控制绕不开Lipschitz条件?如果你刚开始接触非线性控制理论,可能会被一堆数学条件搞得头大,其中“Lipschitz条件”绝对是出场率最高的明星之一。它不像“稳定性”、“能控性”那样直观,名字听起…

2026/8/6 5:05:03 阅读更多 →

最新新闻

DeepSeek 4 Flash 模型部署指南:从环境配置到 API 集成实战

DeepSeek 4 Flash 模型部署指南:从环境配置到 API 集成实战

这次我们来看一个在开源社区引发热议的模型:DeepSeek 4 Flash。它并非一个全新的图像或语音生成工具,而是一个在推理能力、代码能力和性价比上取得显著突破的大型语言模型。简单来说,它最大的吸引力在于,用更低的计算成本&#xf…

2026/8/6 23:57:18 阅读更多 →
如何高效使用AutoRemesher:3D建模的完整四边形网格重划分指南

如何高效使用AutoRemesher:3D建模的完整四边形网格重划分指南

如何高效使用AutoRemesher:3D建模的完整四边形网格重划分指南 【免费下载链接】autoremesher Automatic quad remeshing tool 项目地址: https://gitcode.com/GitHub_Trending/au/autoremesher 还在为3D建模中的复杂网格优化而烦恼吗?&#x1f91…

2026/8/6 23:57:18 阅读更多 →
计算机留学生的冲刺之路:技术底子好,为何仍在大厂面试中卡壳?

计算机留学生的冲刺之路:技术底子好,为何仍在大厂面试中卡壳?

摘要: 许多在海外名校就读计算机科学的留学生,虽然算法基础扎实、学术背景优异,但在面对全球科技大厂(如亚马逊)时,常因缺乏对企业独特文化(如 LP 领导力准则)的表达重构及系统设计实…

2026/8/6 23:57:18 阅读更多 →
深入解析Newelle虚拟助手的高性能模块化架构设计

深入解析Newelle虚拟助手的高性能模块化架构设计

深入解析Newelle虚拟助手的高性能模块化架构设计 【免费下载链接】Newelle Newelle - Your Ultimate Virtual Assistant 项目地址: https://gitcode.com/gh_mirrors/ne/Newelle Newelle是一款基于GNOME桌面环境的开源虚拟助手,采用模块化架构设计&#xff0c…

2026/8/6 23:57:18 阅读更多 →
留学生冲刺顶级资管:如何突破语言优势与偏好壁垒?

留学生冲刺顶级资管:如何突破语言优势与偏好壁垒?

摘要: 许多在海外名校就读金融双学位的中国留学生,即使成绩优异、实习丰富,在冲刺顶级资产管理公司(如 PIMCO)时仍常因投递石沉大海而受阻。破局的关键在于跳出机械的知识复习,深度对齐资管巨头的核心价值观…

2026/8/6 23:57:18 阅读更多 →
BingMaps.dll丢失的解决方案与系统文件修复指南

BingMaps.dll丢失的解决方案与系统文件修复指南

1. 问题背景:BingMaps.dll文件丢失的典型场景BingMaps.dll是微软Bing地图服务相关的动态链接库文件,常见于以下三类软件环境:使用Bing地图API开发的第三方应用程序(如物流管理系统、GIS工具)某些预装Windows组件的旧版…

2026/8/6 23:56:18 阅读更多 →

日新闻

深入解析LimboAI C++内核:架构设计与性能优化实战

深入解析LimboAI C++内核:架构设计与性能优化实战

1. 项目概述:为什么我们需要深入LimboAI的C内核?如果你是一名使用Godot引擎的游戏开发者,尤其是对AI行为逻辑有较高要求的项目,那么LimboAI这个名字你大概率不会陌生。它作为Godot 4生态中一个备受瞩目的行为树与状态机插件&#…

2026/8/6 0:00:06 阅读更多 →
Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

1. 项目概述与核心思路大家好,我是老张,一个在游戏开发一线摸爬滚打了十多年的老码农。今天咱们接着聊《空洞骑士》风格2D动作游戏的Demo制作。上一期我们搭好了基础框架,处理了角色移动和碰撞,这一期,我们要让游戏世界…

2026/8/6 0:00:06 阅读更多 →
被动防火门市场前景发展趋势

被动防火门市场前景发展趋势

被动防火门依靠材质结构、密闭构造阻隔烟火蔓延,无需电控启动,是建筑被动消防系统核心构件,行业依托新规管控、城市更新、工业安全升级迎来稳定扩容,整体朝着合规化、专项化、低碳化、智能化方向发展。现阶段 GB12955‑2024 新版国…

2026/8/6 0:00:06 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/6 22:02:27 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/6 22:02:27 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/6 22:02:27 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/5 23:28:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/6 22:02:28 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/5 23:46:51 阅读更多 →