资讯动态

LangChain 从入门到实战(04):一套代码接所有模型——多 Provider 统一适配

发布时间:2026/10/6 12:36:19 来源:尧图企业网站定制
LangChain 从入门到实战04一套代码接所有模型——多 Provider 统一适配前 3 篇我们不停在写ChatOpenAI(...)但真实项目里你几乎不会只用 OpenAI 一家——国产的 DeepSeek、智谱 GLM、通义千问各有各的价码和长项。如果每个厂商都改一遍调用代码维护就炸了。这一篇做一件事把「会变的模型差异」全部收进一份配置用一套代码接上 OpenAI、DeepSeek、智谱、通义等任意模型业务代码一行不改。你会得到一个「切换模型只改一处配置、其他代码完全不动」的最小方案——这正是 LangChain「对模型做接口抽象」最值钱的地方。一、一个标准就够了OpenAI 兼容协议先立一个关键认知OpenAI、DeepSeek、智谱 GLM、通义千问、Moonshot……绝大多数厂都实现了OpenAI 兼容协议/chat/completions同款接口。所以 LangChain 只需一个 OpenAI 适配器再换算一下base_url就能接上所有厂商——「选模型」本质上是在选一个「OpenAI 兼容端点 一个模型名」。先看 LangChain 提供的工厂函数init_chat_model它能按名字直接拿到模型实例importosfromlangchain.chat_modelsimportinit_chat_modelfromdotenvimportload_dotenv load_dotenv()# 只靠一个字符串 供应商 ID拿到模型实例llminit_chat_model(gpt-4o,# 模型名model_provideropenai,# 供应商openai / deepseek / mooonshot / ollama / ...api_keyos.getenv(API_KEY),temperature0,)注意model_provider只能填 init_chat_model注册表里有的 id如openai、deepseek。像智谱、通义这种没内置注册的厂商别硬填厂商名会报 provider not found统一走model_provideropenai 自定义base_url即可见下一节。二、把「会变的」做成配置一个极简 MultiProvider正确姿势是「全部走 OpenAI 兼容 各家 base_url」——不依赖任何第三方集成包最稳。把「会变的模型名/key/base_url」收进一张配置表用函数按档返回模型importosfromlangchain.chat_modelsimportinit_chat_modelfromdotenvimportload_dotenvfromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportStrOutputParser load_dotenv()# 一份配置 一个厂商。切换只改这里或环境变量 PROFILECONFIG{openai:{model:gpt-4o,api_key:os.getenv(OPENAI_API_KEY),base_url:},# 留空用官方默认deepseek:{model:deepseek-chat,api_key:os.getenv(DEEPSEEK_API_KEY),base_url:https://api.deepseek.com/v1},zhipu:{model:glm-4-flash,api_key:os.getenv(ZHIPU_API_KEY),base_url:https://open.bigmodel.cn/api/paas/v4/},tongyi:{model:qwen-plus,api_key:os.getenv(DASHSCOPE_API_KEY),base_url:https://dashscope.aliyuncs.com/compatible-mode/v1},}defmake_chain(profile:str):cfgCONFIG[profile]# 关键统一走 openai 适配器 各自 base_urlllminit_chat_model(modelcfg[model],model_provideropenai,api_keycfg[api_key],base_urlcfg[base_url]orNone,temperature0,)promptChatPromptTemplate.from_messages([(system,你是严谨的 Java 后端工程师。),(human,{question}),])return(prompt|llm|StrOutputParser())if__name____main__:chainmake_chain(deepseek)# 换厂商只需改这一行 / 或读环境变量 PROFILEprint(chain.invoke({question:什么是一致性哈希}))这样改供应商只改make_chain传的 profile或.env里的PROFILE业务调用chain.invoke()完全不动。这就是「面向模型抽象编程」跟你在 Java 里用接口隔离 DAO 实现是同一套思想。踩坑提醒新手第一坑base_url 别漏路径尾段——DeepSeek 是/v1、DashScope 是/compatible-mode/v1写错直接 404。三、数 Token别拍脑袋用库或模型自算切供应商后你最关心两件事这一单要多少钱、响应快不快。「数 token」不是字符数 × 常数就能估准的中文、英文、代码的编码差异极大不要自己拍脑袋乘系数。最省心的做法是让 LangChain 或模型自己数fromlangchain_core.messagesimportHumanMessage# ① 用模型自带的 tokenizer最准—— 不实际发请求messages[HumanMessage(content什么是 CAP 定理)]tokensllm.get_num_tokens_from_messages(messages)# 或 llm.get_num_tokens(文本)print(本段约,tokens,token)schema提示这段只发 msg 到模型自带 tokenizer 数数不产生调用费用。做成本对比时按模型每千 token 单价 × 这个数即可。四、流式stream首字更快体验更顺普通invoke要等整句出完才返回流式能让字符一边生成一边吐forchunkinllm.stream(用一句话解释什么叫幂等):print(chunk.content,end,flushTrue)想做 UI 打字机效果、或想在超长生成中途分段处理流式都是产品必上的能力。整句话耗时没省但「首字延迟」和「给用户的感知」天差地别。五、工程化对照Java 视角init_chat_model≈ Spring 的工厂传一个字符串返回对应适配器的实现——正是 Java「按配置实例化不同实现」的套路。配置表 CONFIG ≈ 多 profile 配置把「哪家/模型/key/base_url」收进一张表跟application-{env}.yml是同一个思路改配置不改代码。流式 ≈ SSE / WebFluxJava 后端做「打字机」版 Agent本质是走流式响应 主动推送而不是整包 JSON 一次返回。小结能力解决了什么OpenAI 兼容协议用一个适配器兼容绝大多数厂商配置表CONFIG换厂商只改配置业务代码不动get_num_tokens_from_messages准确数 token不拍脑袋流式stream()首字更快体验陡升下一篇预告模型能随意切了但它手里没有你「上一轮说过什么」——第05篇《记忆与上下文让对话真的有状态》我们把记忆接进链里讲窗口记忆、摘要记忆、以及怎么让 Agent 跨轮次「不健忘」。我们下回见。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑