ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

「AI Agent 全栈开发 50 讲」——从本地模型部署到多智能体系统,一年省 87 万 第7节

2026/9/10 2:00:20 拓冰建站 浏览量
「AI Agent 全栈开发 50 讲」——从本地模型部署到多智能体系统,一年省 87 万 第7节 第 07 课 | 统一 LLM 客户端本地与云端 API 无缝切换第 6 课我们写了一个简易的 LLMClient这课把它升级成生产级——支持 5 种后端、自动重试、Token 估算、流式输出一套代码通吃本地和云端。一、为什么需要统一客户端先看一个真实的场景你在开发一个 AI Agent 系统。开发阶段你用 Ollama 在本地跑 qwen2:7b 模型免费、快速、不联网也能用。验证通过后你部署到服务器换成 vLLM 跑 Qwen2-14B高并发性能拉满。然后有一天你的系统需要处理一些特别复杂的推理任务本地模型搞不定你接入了 DeepSeek 的 API——便宜质量好兼容 OpenAI 格式。再过一阵子老板说公司采购了阿里云的通义千问要求统一用 DashScope。如果你每个后端都写一套调用代码光是维护这些代码就能让你崩溃。更何况后面还有 40 多节课要基于这个客户端构建 Agent 系统——底层不稳定上层全得塌。统一 LLM 客户端的核心价值一套代码多后端适配改一行配置从 Ollama 切到 DeepSeek代码不用动不被厂商绑定今天用 OpenAI明天用 DeepSeek后天用开源模型自由切换生产级可靠性自动重试、超时控制、错误处理不是玩具代码降低学习成本后面所有 Agent 课程都基于这个客户端学一次用到底这就是我们这节课要做的事——把一个能用的客户端升级成一个好用的、能上生产的基础设施。二、多后端架构设计2.1 各后端差异分析在动手写代码之前先搞清楚不同后端之间到底有哪些差异。看起来都是 OpenAI 兼容的 API但细节上各不相同后端基础 URLAPI Key 来源Header 格式模型名示例Ollamahttp://localhost:11434/v1不需要无qwen2:7bvLLMhttp://localhost:8000/v1不需要无Qwen/Qwen2-7B-InstructOpenAIhttps://api.openai.com/v1OPENAI_API_KEYAuthorization: Bearer xxxgpt-4o-miniDeepSeekhttps://api.deepseek.com/v1DEEPSEEK_API_KEYAuthorization: Bearer xxxdeepseek-chat通义千问https://dashscope.aliyuncs.com/compatible-mode/v1DASHSCOPE_API_KEYAuthorization: Bearer xxxqwen-plus可以发现虽然 API 格式都是/v1/chat/completions但 URL 不同、模型名不同、API Key 的获取方式也不同。Ollama 和 vLLM 是本地部署不需要 API Key云端服务都需要 API Key但各自的环境变量名不一样。2.2 设计思路我们的设计遵循两个原则配置驱动每个后端的差异通过配置来描述代码逻辑统一工厂模式根据配置自动创建对应的客户端实例用户只需指定后端名称配置BackendConfigname: strbase_url: strapi_key_env: strapi_key_header: strdefault_model: strrequires_api_key: boolLLMClient-backend: str-model: str-base_url: str-_api_key: strchat(messages) : strchat_stream(messages) : Generatorestimate_tokens(text) : intswitch_backend(name) : LLMClientinfo() : dict统一接口多后端适配图 1客户端架构类图整个架构就两个核心组件BackendConfig纯数据类描述一个后端的配置信息LLMClient核心客户端读取 BackendConfig 并执行实际的 API 调用三、增强版 LLMClient 实现下面我们分模块实现这个增强版客户端。完整代码在code/llm_client.py。3.1 后端配置定义fromdataclassesimportdataclassdataclassclassBackendConfig:后端配置name:str# 后端名称base_url:str# API 基础 URLapi_key_env:str# 环境变量名API Key 从哪读api_key_header:str# HTTP Header 名称default_model:str# 默认模型requires_api_key:boolTrueBACKENDS:dict[str,BackendConfig]{ollama:BackendConfig(nameOllama,base_urlhttp://localhost:11434/v1,api_key_env,api_key_header,default_modelqwen2:7b,requires_api_keyFalse,),deepseek:BackendConfig(nameDeepSeek,base_urlhttps://api.deepseek.com/v1,api_key_envDEEPSEEK_API_KEY,api_key_headerAuthorization,default_modeldeepseek-chat,),# ... 其他后端同理}这种设计的好处是新增后端只需加一个配置项不用改任何业务逻辑。比如哪天你想支持 Groq 或者 Anthropic只需要在BACKENDS字典里加一个条目即可。3.2 自动重试机制生产环境中API 调用失败是家常便饭——网络抖动、服务限流、临时故障这些都会导致请求失败。一个健壮的客户端必须内置重试机制。def_request_with_retry(self,payload:dict)-str:带重试的请求支持指数退避last_errorNoneforattemptinrange(self.max_retries):try:responserequests.post(url,jsonpayload,headersheaders,timeoutself.timeout)response.raise_for_status()returnresponse.json()[choices][0][message][content]exceptrequests.HTTPErrorase:statuse.response.status_codeife.responseisnotNoneelseNoneifstatus429:# 限流 → 等待后重试sleep_timeself.retry_delay*(2**attempt)time.sleep(sleep_time)last_errorecontinueelifstatusandstatus500:# 服务端错误 → 重试sleep_timeself.retry_delay*(2**attempt)time.sleep(sleep_time)last_errorecontinueelse:# 客户端错误400/401→ 不重试raiseRuntimeError(fLLM 请求失败 (HTTP{status}):{e})fromeexceptrequests.RequestExceptionase:ifattemptself.max_retries-1:sleep_timeself.retry_delay*(2**attempt)time.sleep(sleep_time)last_errorecontinueraiseRuntimeError(fLLM 请求失败已重试{self.max_retries}次:{e})fromeraiseRuntimeError(fLLM 请求失败已重试{self.max_retries}次:{last_error})重试策略的关键点指数退避第 1 次重试等 1 秒第 2 次等 2 秒第 3 次等 4 秒——给服务端恢复的时间分类处理HTTP 429限流和 5xx服务端错误才重试4xx 客户端错误直接抛出最大重试次数默认 3 次防止无限重试3.3 流式输出流式输出在第 6 课已经实现过这课做了增强——也加入重试逻辑defchat_stream(self,messages,systemNone,temperatureNone):流式聊天逐 token 返回ifisinstance(messages,str):messages[{role:user,content:messages}]ifsystem:messages[{role:system,content:system}]messages payload{model:self.model,messages:messages,temperature:temperatureorself.temperature,stream:True,}forattemptinrange(self.max_retries):try:responserequests.post(url,jsonpayload,headersheaders,timeoutself.timeout,streamTrue)response.raise_for_status()forlineinresponse.iter_lines():ifnotline:continueline_strline.decode(utf-8)ifline_str.startswith(data: ):dataline_str[6:]ifdata[DONE]:returntry:chunkjson.loads(data)deltachunk[choices][0].get(delta,{})ifcontentindelta:yielddelta[content]exceptjson.JSONDecodeError:continuereturnexceptrequests.RequestExceptionase:ifattemptself.max_retries-1:time.sleep(self.retry_delay*(2**attempt))continueraiseRuntimeError(f流式请求失败:{e})frome流式输出的使用场景聊天界面需要逐字显示、长文本生成时给用户反馈、Agent 实时展示思考过程。3.4 Token 估算精确的 Token 计数需要加载 tiktoken 库需要额外的模型文件但大多数场景下一个粗略的估算就够用了defestimate_tokens(self,text:str)-int:估算文本的 token 数量chinese_charssum(1forcintextif\u4e00c\u9fff)other_charslen(text)-chinese_charsreturnint(chinese_chars/1.5other_chars/4)这个估算基于经验规则中文约 1.5 个字符 ≈ 1 个 token英文约 4 个字符 ≈ 1 个 token虽然不是精确值但对于判断上下文是否超长、预估 API 成本等场景已经足够实用。3.5 便捷方法为了让客户端更好用我们加了几个辅助方法defchat(self,messages,systemNone,temperatureNone,max_tokensNone):支持纯文本输入自动转为消息格式ifisinstance(messages,str):messages[{role:user,content:messages}]ifsystem:messages[{role:system,content:system}]messages# ... 后续逻辑defswitch_backend(self,backend:str)-LLMClient:运行时切换后端返回新实例returnLLMClient(backendbackend,...)definfo(self)-dict:返回客户端信息return{backend:self.backend,model:self.model,...}现在你可以这样用# 纯文本快速对话clientLLMClient(ollama)replyclient.chat(你好)# 不需要写消息列表# 带系统提示词replyclient.chat(分析市场,system你是专业分析师)# 运行时切换后端deepseek_clientclient.switch_backend(deepseek)四、后端适配器详解4.1 Ollama本地免费推理Ollama 是我们教程的主力后端贯穿整个开发阶段优势免费、离线可用、数据不出本机、安装简单一行命令劣势单请求处理、不支持高并发、模型选择有限适用场景本地开发、个人项目、数据敏感场景clientLLMClient(ollama)# 自动使用 http://localhost:11434/v1不需要 API Keyreplyclient.chat(介绍一下你自己)4.2 vLLM高性能生产推理vLLM 在第 6 课已经详细讲过这里只需知道它和 Ollama 的 API 格式完全一样切换只需改 URLclientLLMClient(vllm)# 自动使用 http://localhost:8000/v14.3 OpenAI行业标准OpenAI 的 API 是所有后端的参考标准其他后端都兼容它的格式# 设置环境变量: export OPENAI_API_KEYsk-xxxclientLLMClient(openai)replyclient.chat(Hello)4.4 DeepSeek性价比之王DeepSeek 的 API 完全兼容 OpenAI 格式价格只有 OpenAI 的 1/10 左右质量却接近 GPT-4# 设置环境变量: export DEEPSEEK_API_KEYsk-xxxclientLLMClient(deepseek)replyclient.chat(用中文介绍一下 AI Agent)4.5 通义千问DashScope阿里云生态通义千问通过阿里云的 DashScope 平台提供 API 服务需要单独申请 API Key# 设置环境变量: export DASHSCOPE_API_KEYsk-xxxclientLLMClient(dashscope)replyclient.chat(介绍一下通义千问)注意DashScope 的 API 格式也兼容 OpenAI但 URL 路径略有不同/compatible-mode/v1我们的 BackendConfig 已经处理了。五、配置管理与切换5.1 环境变量配置在.env文件中配置默认后端# .env 文件LLM_BACKENDollama# 各个后端的 API Key按需配置OPENAI_API_KEYsk-xxxDEEPSEEK_API_KEYsk-xxxDASHSCOPE_API_KEYsk-xxx代码中自动读取# 不传参数自动从环境变量读取clientLLMClient()# 使用 LLM_BACKEND 指定的后端5.2 运行时动态切换# 同一个 Prompt用不同后端测试prompt用 3 句话总结 AI Agent 的核心价值system你是一个专业的 AI 技术顾问forbackendin[ollama,deepseek,openai]:clientLLMClient(backend)try:replyclient.chat(prompt,systemsystem)print(f[{backend}]{reply[:80]}...)exceptExceptionase:print(f[{backend}] 错误:{e})这种灵活性意味着你可以在不同场景选择最合适的后端开发调试用 Ollama免费数据不出本机高并发上线切换到 vLLM 或 DeepSeek成本敏感优先使用 DeepSeek价格低质量好复杂推理切换到 OpenAI 的 GPT-4 或通义千问 Max5.3 配置优先级LLMClient 的配置遵循明确的优先级构造函数参数 环境变量 默认值例如LLMClient(modelgpt-4)会覆盖环境变量LLM_MODEL和默认模型六、实战多后端性能对比code/backend_compare.py提供了一个完整的对比测试脚本对同一个 Prompt 分别用不同后端测试fromllm_clientimportcreate_clientimporttimedeftest_single_backend(backend,prompt):clientcreate_client(backend)starttime.time()replyclient.chat(prompt,system你是专业的 AI 助手)elapsedround(time.time()-start,2)tokensclient.estimate_tokens(reply)return{backend:backend,elapsed:elapsed,tokens:tokens}在我的 RTX 3090 机器上实际测试结果如下后端模型耗时输出 Token备注Ollamaqwen2:7b3.2s45本地免费vLLMQwen2-7B-Instruct2.1s48本地免费DeepSeekdeepseek-chat1.8s52云端约 ¥0.001/次OpenAIgpt-4o-mini2.5s55云端约 ¥0.003/次通义千问qwen-plus2.0s50云端约 ¥0.002/次关键发现本地模型速度不慢Ollama 和 vLLM 在 RTX 3090 上跑 7B 模型单请求速度已经接近云端 APIDeepSeek 性价比最高速度快价格低质量好云端 API 的模型质量通常更好特别是复杂推理任务GPT-4 和 DeepSeek 的输出质量明显优于本地 7B 模型选择建议开发调试 → Ollama免费数据安全生产高并发 → vLLM 或 DeepSeek性能好预算充足 → OpenAI质量最好中文场景 → 通义千问或 DeepSeek中文理解更好七、小结与预告这节课我们完成了教程的基础设施建设——一个支持 5 种后端的增强版 LLM 客户端。核心收获BackendConfig 设计模式用配置描述后端差异代码逻辑统一自动重试机制指数退避 分类处理生产级可靠性Token 估算快速判断上下文是否超长多后端切换改一行配置代码不动从此以后所有 Agent 课程的底层调用都通过这个客户端完成。你不需要再关心底层是 Ollama 还是 OpenAI——统一接口自由切换。下一节课我们将进入Prompt Engineering的深度实战——如何让模型输出稳定可靠的结构化数据。这是 Agent 系统中至关重要的一环模型输出必须能被程序解析才能实现自动化。我们下一课见。系列教程导航上一篇第 06 课 | 高性能推理vLLM 部署与 OpenAI 兼容接口下一篇第 08 课 | Prompt Engineering让模型输出稳定可靠的结构化数据本系列共 50 课持续更新中。关注我不迷路。