首页 / 资讯中心 / 文章详情

LangChain大模型接入全攻略:云端API、Ollama与vLLM实战

LangChain大模型接入全攻略:云端API、Ollama与vLLM实战 ★ FEATURED ARTICLE
刚开始学LangChain我遇到的第一道坎就是大模型接入。官方文档里丢了一堆示例代码什么ChatOpenAI、ChatOllama、init_chat_model看上去都能用但真正动手时才发现接入并不只有一种方式有接云端API的有接本地模型的还有同一套OpenAI兼容协议到处用的。这篇基础学习笔记就把几种主流接入方式串起来讲清楚顺便把我自己私底下跑过的代码和踩过的坑一起放出来。无论你是刚装好LangChain、还不知道怎么把模型接进来还是已经会在云端跑通了想换本地模型这篇都适合你。1. 接入大模型之前先明白LangChain为什么值得你绕一圈1.1 直接调API也能跑但代码会变得又碎又难维护很多人一开始会犯嘀咕我明明可以直接用requests去调大模型接口为什么要非得多包一层LangChain我承认直接调API确实简单两三行就能发一次请求。但当你开始做稍微真实一点的东西比如一个带历史记忆的客服机器人或者一个需要多次调用大模型来完成任务的Agent直接调API的代码会迅速变成一团乱麻。直接调API时你得手动处理这些问题每次请求都要拼完整的历史消息数组把用户输入塞进messages字段里要自己处理temperature、max_tokens这些参数不同厂商的参数名还不一样要应付限流、超时、网络重试调用完还要解析返回的JSON再提取里面的content字段。这还只是单次调用如果连成链、多轮对话条件分支一多代码就会变得特别脆弱改动一个需求要牵连好几个地方。LangChain做的事就是把这些重复劳动抽象成一层标准接口。你只需要一个模型对象然后调用invoke、stream这类统一方法它内部帮你完成消息格式化、参数转换、请求重试等脏活。更重要的是模型对象可以被组合到链、图、Agent里而非散落的HTTP调用。这样一套抽象之后业务代码才能集中精力处理流程而不是通信细节。1.2 模型层的统一抽象LLM和ChatModel到底在包装什么LangChain里有两个容易混淆的概念LLM和ChatModel。简单理解LLM对应的是文本补全模型输入一段文本输出一段文本典型场景像是老式的接龙式模型ChatModel对应的是聊天模型输入的是消息列表SystemMessage、HumanMessage、AIMessage输出一个AIMessage像GPT、Claude、通义千问这类模型都属于这个范畴。现在新模型基本都是聊天模型所以我建议你不要在LLM上花太多时间直接以ChatModel为主。ChatModel的接口设计非常统一核心方法就是invoke单次调用、stream流式输出、batch批量调用另外还有一些绑定参数、工具调用的方法。不管底层接的是OpenAI、Anthropic还是本地Llama你在业务代码里面对的都是同一套API。这就是LangChain给的标准插座——插座形状统一了插在上面的电器模型厂商就可以频繁换。2. 云端API接入把base_url当作万能接口的突破口2.1 官方SDK下的ChatOpenAI标准写法云端API是大多数人的第一站。以OpenAI接口为例LangChain在较新版本里把相关封装拆成了独立包langchain-openai所以一开始要装它pip install langchain langchain-openai python-dotenv接着在项目根目录建一个.env文件把你的API Key放进去OPENAI_API_KEYsk-xxxxxxx然后在代码里读取环境变量并创建模型对象import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI load_dotenv() llm ChatOpenAI( modelgpt-4o-mini, temperature0.7, api_keyos.getenv(OPENAI_API_KEY), )调用一次的方式是invokefrom langchain_core.messages import HumanMessage response llm.invoke([HumanMessage(content用一句话解释什么是LangChain)]) print(response.content)invoke返回的是一个AIMessage对象要拿文本就取.content。不要直接打印整个response否则会看到一大堆id、usage_metadata之类的元数据。初次接触容易误以为调用失败了其实数据都在。temperature这类生成参数可以在构造模型时传也可以在调用时通过bind临时覆盖。另外max_tokens这个参数我建议每次都显式写出来否则不同平台默认值差别很大有些默认上限很低长文本生成到一半会被截断。2.2 一条配置切换到国产大模型OpenAI这套接口规范后来成了事实标准国内很多大模型平台都提供了兼容接口。这意味着你写好的LangChain代码不需要改动调用逻辑只要把base_url和model替换成目标平台的配置就能从OpenAI切换到国产模型。我自己测试过的通用写法大致是这样llm ChatOpenAI( modeldeepseek-chat, api_keyyour-deepseek-api-key, base_urlhttps://api.deepseek.com/v1, temperature0.3, )其他平台也是同样的套路比如阿里云的百炼平台、智谱开放平台、百度千帆基本都是换base_url、换model名、换api_key。对开发者来说这大大降低了迁移成本。你完全可以把模型选择做成配置项让程序从环境变量里读LLM_BASE_URL和LLM_MODEL这样切换模型连代码都不用改改配置就行。这种OpenAI兼容协议还有一个好处如果你以后想接的不是国内大厂的云端API而是自己拿vLLM部署的开源模型只要服务是OpenAI兼容格式代码一样通用。多了一步抽象换模型时才不用伤筋动骨。2.3 API Key管理别做那个把密钥提交到仓库的人接云端API绕不开的安全问题是密钥管理。我看过太多新手项目直接api_keysk-xxxx写在Python文件里然后大大方方推到GitHub上。轻则被白嫖重则被人拿去生成大量内容甚至刷爆账单。正确做法是前面提到的.env文件加python-dotenv并且把.env写进.gitignore。如果公司内部有配置中心也可以从配置中心读取。还有一个更保险的思路不要在前端代码里放任何密钥所有调用大模型的请求都应该由后端统一转发。密钥留在服务端前端只跟自己的后端通信。另外我习惯在ChatOpenAI里显式传timeout和max_retries。云API偶尔会抖动默认重试策略不一定符合你的业务需求llm ChatOpenAI( modelgpt-4o-mini, api_keyos.getenv(OPENAI_API_KEY), timeout30, max_retries2, )把超时控制在30秒、重试控制在2次至少不会让用户等太久。3. 本地大模型接入Ollama与vLLM是两条互补的路线3.1 隐私和成本驱动下的本地化选择为什么要接本地大模型对我个人来说两个理由最直接一是隐私有些业务数据不能出内网比如医疗、金融、企业内部文档明文发给云端API在合规上就是死路二是成本如果调用量稳定且模型参数规模又不大跑在自有GPU上长期比按token付费划算。但本地部署不是没有代价。你需要自己搞定推理框架、显存、模型格式、并发吞吐。最开始我建议从7B14B这个量级的开源模型入手比如Qwen系列、Llama系列别一上来就拉70B普通显卡根本跑不动。量化是这个环节的关键词。开源模型文件通常以GGUF格式存在这种格式支持把模型参数从FP16量化到4bit、8bit。常见如Q4_K_M模型体积缩小不少显存压力也小生成质量损失在可接受范围内。以7B模型为例FP16大约需要14GB显存Q4量化后大约只需要46GB很多16GB显存的消费级显卡就能跑得动。3.2 Ollama轻量部署与ChatOllamaOllama是目前本地跑模型最省事的工具之一。它把模型下载、依赖环境、推理服务都封装好了对不熟悉Python推理栈的人非常友好。安装好Ollama后命令行直接拉模型ollama pull qwen2.5:7b然后启动服务ollama serveLangChain这边有对应的ChatOllama封装安装langchain_community包后就能用pip install langchain-communityfrom langchain_community.chat_models import ChatOllama llm ChatOllama( modelqwen2.5:7b, temperature0.7, )这个ChatOllama同样支持invoke和stream接口和ChatOpenAI保持高度一致所以业务代码可以无缝切换。本地模型的一大优势是离线也能跑我甚至见过有人把LangChain应用直接装到船载工控机上在完全没外网的环境里做设备状态分析靠的就是Ollama这类工具。不过要提醒一句Ollama适合单机、小并发场景如果要做高并发的线上推理它并不是最优解。它更像个本地玩具/原型验证工具跑通流程很快但吞吐一上来就吃力。3.3 vLLM追求吞吐时选高性能推理服务如果你的业务已经明确要上生产环境并发量可能同时几十上百个请求那更合适的方案是vLLM。vLLM是一个大模型推理服务框架核心卖点是高性能、高吞吐使用了PagedAttention等优化技术显存利用率比直接跑原生transformers高很多。vLLM部署之后通常也会暴露一个OpenAI兼容的HTTP接口所以LangChain接入时依然可以用ChatOpenAI只是要把base_url指向本地服务vllm serve Qwen/Qwen2.5-7B-Instruct --served-model-name qwen2.5-7b --port 8000llm ChatOpenAI( modelqwen2.5-7b, api_keyvllm-no-key-needed, base_urlhttp://localhost:8000/v1, )你会发现api_key填什么并不重要vLLM默认不校验但ChatOpenAI要求这个字段非空所以随便填一个占位符。很多刚接触的人卡在这一步以为本地服务也要实时Key其实没有。vLLM更适合GPU服务器、多卡环境下部署开源模型用于生产。它的启动参数比较灵活比如--max-model-len可以控制上下文长度--gpu-memory-utilization可以控制显存利用率。新手建议先用Ollama打通流程再根据实际吞吐需求决定要不要迁移到vLLM。3.4 一个隐藏细节本地模型也走OpenAI兼容协议很多本地推理引擎都支持OpenAI兼容API。这意味着你甚至不需要单独用ChatOllama或ChatVLLM直接用ChatOpenAI指定base_url和model即可。以Ollama为例它默认监听的http://localhost:11434/v1就是OpenAI兼容接口llm ChatOpenAI( modelqwen2.5:7b, api_keyollama, base_urlhttp://localhost:11434/v1, )这种做法的好处是代码统一。无论云端还是本地你只需要维护一份模型接入代码通过base_url指向不同环境应用层完全无感。我在实际项目里就是这么做的开发环境用本地Ollama测试环境用云厂商的OpenAI兼容接口生产环境用vLLM集群代码里只改了环境变量没有改业务逻辑。4. 接入后的调用姿势消息对象、invoke/stream/batch与参数绑定4.1 消息类型和对话历史管理接入模型只是第一步真正用起来还要理解LangChain的消息体系。模型对象invoke接收的不是明文字符串而是消息对象列表。常用三种消息类型from langchain_core.messages import SystemMessage, HumanMessage, AIMessage messages [ SystemMessage(content你是一个严谨的技术编辑。), HumanMessage(content帮我写一段LangChain入门介绍。), ]SystemMessage用来设定系统提示词HumanMessage表示用户输入AIMessage表示模型的回答。多轮对话时你需要把历史消息都塞进列表让模型看到上下文。如果你有持久化需求可以把每次的AIMessage和新的HumanMessage不断追加到这个列表里存到数据库也行。有一个容易忽略的点模型会限制上下文总量消息越多占用的token越多。对话一长要么截断历史要么做向量召回。LangChain社区有一些记忆组件可以自动管理聊天历史但底层逻辑仍然是拼接消息列表这回事理解了这一步后续看任何记忆模块都会很轻松。4.2 三种调用方式的使用场景模型对象的核心调度方法有三种invoke、stream、batch。invoke就是同步等一个完整响应适合对话结果出来再展示的场景。比如你点击一个总结按钮等两秒拿到完整总结交互足够自然。stream则是流式输出模型逐字生成客户端能像打字机一样把内容打出来提高等待体验。写越长的内容越明显不流式会让用户干等十几秒。stream用起来也不复杂for chunk in llm.stream([HumanMessage(content写一篇关于大模型接入的长文)]): print(chunk.content, end, flushTrue)每个chunk都是AIMessageChunk里面的content可能只有一小段文字。batch适合一批互不依赖的任务比如批量给100条评论打标签、批量生成摘要。LangChain的batch内部会做并发控制比你自己写循环挨个调用要高效。这些统一方法还有一个好处它们不仅仅属于模型对象也属于Runnable协议。后续你用prompt | llm | parser拼链条整条链也是一个Runnable照样有invoke、stream、batch。这种一致性让从单次调用到复杂链的过渡变得非常顺。4.3 bind和with_config这类隐藏能力实际调用中你可能希望临时改生成参数而不是每次重新new模型对象。这时候可以用bindllm_fixed llm.bind(temperature0.0, max_tokens256)比如做开票信息抽取时我一般绑定temperature0.0保证模型输出尽量稳定做创意文案时再绑定高一点的temperature。同一个底层模型对象可以绑定出多个不同参数风格的副本然后组合到不同链路里。with_config则用来控制单次调用的行为细节llm.invoke(messages, config{timeout: 30, max_retries: 3})还有with_fallbacks给模型接口做降级。比如云端API临时不可用你可以备一个本地Ollama模型主用提供商挂了就自动走备胎llm_with_fallback primary_llm.with_fallbacks([local_llm])这在生产环境里特别实用。我做过一个夜间定时机器人凌晨正好赶上云API维护靠这个机制自动切到本地模型没有中断任务。5. 接入方式选型对比与实录中的坑5.1 三种接入方式怎么选成本、硬件、使用场景先给出一张我自己的对比表方便你快速决策接入方式成本隐私部署难度并发与吞吐适合场景云端API按token付费数据出域最低只需Key高平台兜底原型验证、业务变化快、不想管GPUOllama本地仅硬件成本完全内网低中低单机离线环境、开发调试、个人工具vLLM本地硬件成本运维完全内网中高高适合生产高并发私有化部署、数据敏感业务我的建议是如果你刚开始学习先接云端API因为反馈速度最快能让你把注意力放在LangChain的链和Agent逻辑上而不是折腾模型部署。等你对调用方式熟悉了再本地部署一个Ollama用同一套代码切过去体验本地模型。上线之前再评估QPS如果并发压力大再上vLLM。另外要提一下开发环境一致性。团队协作时大家机器的显存水平参差不齐指望每个人都本地跑一个7B模型很不现实。比较舒服的方案是日常开发用云端API或公司共享的OpenAI兼容网关CI环境也走这个网关只有涉及私有数据联调时才切本地模型。这样可以避免因为显存不足导致部分成员跑不动。5.2 版本迁移带来的麻烦LangChain版本演进很快特别是0.x到1.x的变化很多老代码会突然跑不通。最典型的是模型封装包的拆分。早期ChatOpenAI在langchain主包里后来集中到langchain-openai而ChatOllama在langchain_community。如果你在网上抄了一段老代码from langchain.chat_models import ChatOpenAI在新版本下很可能直接ModuleNotFoundError。解决办法是安装时尽量分开装pip install langchain langchain-openai langchain-community langchain-core并且不要在代码里依赖langchain.chat_models这种旧路径。我的习惯是把langchain-core里的Runnable、messages这些基础类型单独导入模型封装从各自的集成包导入遇到问题也好排查。更新版本前先看CHANGELOG。我吃过亏某次升级后invoke返回的对象从字符串变成了AIMessage结果下游代码还在做字符串操作一堆报错。建议在项目里锁住关键版本或者用虚拟环境隔离不同项目。5.3 上下文长度和输出截断模型接入后最常见的假故障就是输出突然变短。有人以为是模型傻了查了半天才发现是max_tokens默认值太小。比如某平台的max_tokens默认只有几百生成一篇长文时后面全被截断。你需要做两件事第一创建模型时显式设置max_tokens第二了解所接模型的上下文上限。云端模型动辄128K、256K上下文请记住一个原则上下文长度并不等于你可以把所有内容全塞进去。上下文越长推理成本越高响应越慢很多模型在中后段还会出现注意力涣散。所以实用的做法是对长文档先做切片、摘要或向量化再拼进Prompt而不是把全文一股脑传给模型。本地模型的max_model_len更是如此vLLM启动参数里需要提前预留显存上下文开太大可能导致显存溢出。5.4 本地模型的输出质量和格式问题本地模型和云端模型在输出能力上有差距尤其体现在指令遵循和结构化输出上。同样一个只输出JSON的提示词云端模型可能稳稳地输出一个合法JSON而7B本地模型偶尔会输出一堆散文。LangChain有结构化输出辅助能力比如with_structured_output可以让模型绑定输出格式或走工具调用链路来保证结构。但底层还是依赖模型本身的指令遵循能力模型太弱的时候照样会出错。我的经验是如果业务强依赖结构化输出先测你选用的模型能不能稳定遵循格式不能稳定就直接选更大的模型或换云API。还有一个容易被忽视的问题本地模型幻觉并不比云端少。尤其是在你需要它回答某个具体内网知识库问题时没有检索增强兜底它依旧会一本正经编造。接入模型以后一定要把结果校验当成独立环节比如做实体抽取后校验日期格式、金额范围做摘要后检查有没有关键数字错误不要因为模型跑通了就默认输出是对的。最后顺便提一句工具链的扩展。LangChain现在只是模型接入的一种方式市面上还有Dify、CrewAI、Agent框架等它们核心都在解决同一个问题如何让大模型以更规范的方式嵌入业务系统。如果你把模型接入这层搞明白了再去看那些框架的模型配置页会发现它们本质上也都是同一个套路配置base_url、model、api_key只是有的是配置项有的是写代码。这就是基础学习的价值——底层知识沉淀下来换什么壳都不慌。
阅读完成 · 觉得有帮助?
咨询建站