
写在前面这篇文章解决什么问题这篇博客围绕《第02章模型的创建与调用》展开核心目标不是简单记录“怎么调用一次大模型”而是帮助你从“能跑通模型调用”进一步升级到“能在项目中稳定、可维护、可扩展地接入模型”。学习 LangChain 的模型调用时很多人一开始只关注两件事填 API Key、调用invoke()。这当然能跑起来但距离企业级开发还差几层能力配置如何隔离模型如何切换调用超时怎么办Token 成本怎么统计同步调用、流式调用、批量调用分别适合什么场景返回结果除了文本内容以外还能提供什么工程价值本文会围绕这些问题展开重点掌握两条主线模型初始化如何选择模型提供商、配置 API Key/Base URL、使用init_chat_model或专用 Chat Class 初始化模型。模型调用如何使用invoke、stream、batch、batch_as_completed和异步调用并理解消息格式与AIMessage返回对象。读完后你应该不仅能写出一个调用模型的 Demo还能开始思考如何在真实项目中设计一个更专业的模型接入层。一、从 Model I/O 到 Chat Model为什么现在重点是对话模型早期 LangChain 常用Model I/O来描述大模型调用过程可以拆成三段Prompt Template把用户输入、系统指令、变量组织成模型能理解的提示词。Model真正调用大模型。Output Parser把模型输出解析成程序可继续消费的数据。这套思路到现在依然重要但模型本身的形态已经发生变化。早期大模型更多是“补全模型”本质上是在已有文本后面续写内容现在主流应用更多使用“对话模型”也就是 Chat Model。Chat Model 天然支持 system、user、assistant 等角色更适合指令跟随、多轮对话、工具调用和结构化输出。因此学习 LangChain 的模型调用时应该优先掌握 Chat Model而不是把模型简单理解成一个“输入字符串、输出字符串”的函数。更准确的理解是你给模型一组带角色的消息模型返回一个包含文本、元数据、Token 使用量、工具调用信息的消息对象。二、模型初始化的三种理解视角模型初始化看似只是创建一个对象但如果从工程角度看它至少包含三个问题调用谁家的模型、配置写在哪里、模型部署在哪里。2.1 按模型提供商理解调用谁家的模型LangChain 本身不提供大模型它是一个调用与编排框架真正的模型来自不同提供商或本地运行环境。常见选择包括类型示例适合场景专有模型平台OpenAI、Anthropic、DeepSeek、智谱、通义千问生产项目、稳定能力、云端服务OpenAI-compatible 平台阿里云百炼兼容模式、CloseAI、OpenRouter 等用统一协议接入多个模型本地模型Ollama Llama/Qwen/DeepSeek-R1 等学习、隐私数据、离线实验、低成本验证企业项目中很少永远只用一个模型。你可能在开发环境使用本地 Ollama在测试环境使用便宜模型在生产环境使用稳定模型在不同业务场景里按成本、速度和效果做路由。因此初始化代码最好不要和具体业务逻辑强绑定。2.2 按配置来源理解参数写在哪里调用模型通常离不开三个核心配置model name模型名称例如deepseek-chat、qwen-plus、llama3.1。api key访问模型平台的密钥。base url模型服务地址尤其是第三方平台或 OpenAI-compatible 服务。不推荐把这些信息硬编码在 Python 文件中原因很直接容易泄露密钥。不方便区分本地、测试、生产环境。更换模型或平台时需要改业务代码。代码上传仓库后存在安全风险。更推荐的方式是本地开发使用.env生产环境使用环境变量或专门的密钥管理服务。DEEPSEEK_API_KEYyour_deepseek_api_key DEEPSEEK_BASE_URLhttps://api.deepseek.com DASHSCOPE_API_KEYyour_dashscope_api_key DASHSCOPE_BASE_URLhttps://dashscope.aliyuncs.com/compatible-mode/v12.3 按部署位置理解在线模型还是本地模型在线模型和本地模型的取舍不是“谁更高级”而是“谁更适合当前场景”。在线模型的优势是能力强、更新快、稳定性高、接入门槛低适合正式业务、复杂推理和高质量生成。但它依赖网络和平台账户也会带来成本、限流、数据合规等问题。本地模型通过 Ollama 等工具运行在自己的机器或内网环境中适合学习实验、隐私数据处理、离线开发、低成本原型验证。但本地模型受硬件资源影响明显效果、速度、上下文长度都可能不如云端强模型。企业项目中常见的做法是开发和调试阶段可以优先使用本地或低成本模型生产关键链路再切换到质量更高的在线模型。三、推荐主线使用 init_chat_model 统一初始化模型LangChain 中初始化聊天模型有两类常见方式使用模型提供商专用类例如ChatDeepSeek、ChatOpenAI、ChatTongyi、ChatOllama。使用统一入口init_chat_model。如果你的目标是学习和项目开发我更推荐把init_chat_model作为主线。它的价值在于用更统一的方式初始化不同模型减少业务代码对具体提供商类的依赖。3.1 最小初始化示例下面是一个使用 DeepSeek 模型的示例。代码里没有写死 API Key而是从环境变量读取。importosfromdotenvimportload_dotenvfromlangchain.chat_modelsimportinit_chat_model load_dotenv(overrideTrue)modelinit_chat_model(modeldeepseek:deepseek-chat,api_keyos.getenv(DEEPSEEK_API_KEY),base_urlos.getenv(DEEPSEEK_BASE_URL),temperature0.2,timeout30,max_tokens1000,max_retries2,)responsemodel.invoke(用一句话解释 LangChain 是什么)print(response.content)这里最关键的是modeldeepseek:deepseek-chat。前半部分可以理解为提供商标识后半部分是具体模型名称。实际项目中如果 LangChain 无法根据模型名称自动判断提供商就需要显式传入model_provider。3.2 使用 .env 管理 API Key 和 Base URLpython-dotenv的作用是把.env文件中的配置加载到进程环境变量中fromdotenvimportload_dotenv load_dotenv(overrideTrue)overrideTrue表示.env文件里的值会覆盖当前环境里已经存在的同名变量。这个选项在本地调试时很方便但在生产环境要谨慎因为生产环境通常希望由部署平台或密钥系统统一注入变量。对于 OpenAI-compatible 服务初始化时经常需要显式传入model_provideropenaiimportosfromdotenvimportload_dotenvfromlangchain.chat_modelsimportinit_chat_model load_dotenv(overrideTrue)qwen_modelinit_chat_model(modelqwen-plus,model_provideropenai,api_keyos.getenv(DASHSCOPE_API_KEY),base_urlos.getenv(DASHSCOPE_BASE_URL),temperature0.3,)print(qwen_model.invoke(列出 3 个企业级 LLM 应用场景).content)这里的model_provideropenai不代表你一定在调用 OpenAI 官方模型而是代表该服务使用 OpenAI 兼容协议。很多国内外平台都提供这种兼容模式让开发者可以用较统一的客户端方式接入不同模型。3.3 关键参数temperature、max_tokens、timeout、max_retries初始化模型时除了模型名、密钥和服务地址还应该重点理解这些参数参数作用实战建议temperature控制输出随机性分类、抽取、代码解释用低温创意写作用中高温max_tokens限制最大输出长度控制成本和响应长度避免无限生成timeout请求超时时间Web 服务必须设置避免请求长期挂起max_retries失败重试次数应对临时网络波动或服务抖动temperature越低输出越稳定适合企业应用中的分类、信息抽取、结构化生成、代码解释等场景。temperature越高输出越发散适合头脑风暴、文案创作、故事生成等场景。max_tokens不只是“限制回答字数”还和成本治理有关。企业应用中通常需要给不同任务设置不同的 Token 上限例如标题生成可以很短报告生成可以更长。四、补充方式使用模型提供商专用 Chat Class除了init_chat_modelLangChain 也为许多模型提供商提供了专用 Chat Class。以 DeepSeek 为例importosfromdotenvimportload_dotenvfromlangchain_deepseekimportChatDeepSeek load_dotenv(overrideTrue)modelChatDeepSeek(modeldeepseek-chat,api_keyos.getenv(DEEPSEEK_API_KEY),api_baseos.getenv(DEEPSEEK_BASE_URL),temperature0.2,)print(model.invoke(请介绍模型提供商专用类的优缺点).content)这种方式的优点是直观、明确可以直接使用某个提供商暴露的特殊参数。缺点是模型切换成本更高业务代码会更依赖具体提供商。还要注意不同集成类的参数名可能不同。例如某些 OpenAI-compatible 初始化习惯使用base_url而某些提供商类可能使用api_base。这类差异在 Demo 阶段不明显但在项目封装时很容易踩坑。简单判断方式如果你正在写学习 Demo 或只接一个固定平台专用类很直观。如果你希望未来切换模型、做多模型路由、统一封装调用层优先考虑init_chat_model。五、本地模型调用Ollama 与 ChatOllamaOllama 可以让你在本地运行开源模型。常见命令包括ollama pull llama3.1 ollama run llama3.1 ollama list在 LangChain 中可以继续使用init_chat_model初始化 Ollama 模型fromlangchain.chat_modelsimportinit_chat_model local_modelinit_chat_model(modelllama3.1,model_providerollama,temperature0.5,)print(local_model.invoke(用中文解释本地模型适合哪些开发场景).content)实际模型名称要以你本地ollama list的结果为准。例如你本地安装的是qwen2.5:7b那初始化时就应该使用对应名称。本地模型特别适合这些场景学习 LangChain 调用流程不想消耗云端 Token。处理不方便发送到外部平台的隐私数据。在弱网或离线环境做实验。为线上模型调用层设计本地替身方便开发调试。但本地模型不等于生产可直接替代云端强模型。你仍然需要评估回答质量、响应速度、硬件成本、并发能力和上下文长度。六、模型调用方式全景模型初始化解决的是“拿到一个可调用对象”真正使用时还要根据业务场景选择合适的调用方式。6.1 invoke最基础的同步调用invoke是最基础、最容易理解的调用方式输入一段文本或一组消息等待模型生成完整结果后返回。messages[(system,你是一名资深 Python 后端工程师回答要强调工程可落地性。),(human,在项目中接入大模型时为什么不应该硬编码 API Key),]ai_msgmodel.invoke(messages)print(ai_msg.content)invoke适合简单问答。文本分类。信息抽取。摘要生成。命令行脚本或离线任务。它的特点是调用方会一直等待直到完整结果返回。如果模型输出很长用户会明显感到等待。6.2 stream流式输出改善长文本体验stream会把模型输出拆成一个个 chunk 逐步返回。对于聊天界面、长文本生成、技术博客生成等场景流式输出能显著改善体验。messages[(system,你是一名技术博客作者。),(human,写一段关于 LangChain 模型调用方式的开场白。),]forchunkinmodel.stream(messages):print(chunk.content,end,flushTrue)流式输出并不会让模型实际生成得更快但它能让用户更早看到内容降低感知延迟。需要注意的是不同模型提供商对流式输出的支持程度可能不同。6.3 batch批量处理独立任务当你有多个互不依赖的输入时可以使用batch批量调用。questions[什么是 temperature,什么是 max_tokens,timeout 和 max_retries 分别解决什么问题,]resultsmodel.batch(questions)forquestion,resultinzip(questions,results):print(问题,question)print(回答,result.content)batch的一个重要特点是返回结果顺序与输入顺序一致。这对批量摘要、批量分类、批量解释日志、批量生成标题等任务很有用。6.4 batch_as_completed谁先完成先返回如果每个任务耗时差异较大并且你希望谁先完成就先处理谁可以使用batch_as_completed。questions[用一句话解释 LangChain。,列出 5 个模型调用的常见错误。,写一段较长的企业级 LLM 接入建议。,]forindex,resultinmodel.batch_as_completed(questions):print(f第{index}个任务完成)print(result.content)它的返回顺序不一定等于输入顺序所以必须保留index。这类模式适合后台批处理、队列任务、批量内容生产等场景。6.5 async 调用在高并发服务中的意义在 Web 服务中如果模型调用是阻塞的请求线程或事件循环可能会被长时间占用。异步调用可以帮助你更好地处理并发任务。importasyncioasyncdefmain():messages[(system,你是一名 AI 应用架构师。),(human,为什么 Web 服务中更常见异步模型调用),]ai_msgawaitmodel.ainvoke(messages)print(ai_msg.content)asyncio.run(main())异步不是为了让单次模型调用一定更快而是为了让服务在等待外部 I/O 时不阻塞其他请求。对于 FastAPI、异步任务队列、多模型并发评估等场景这一点非常重要。七、消息格式与返回对象不要只把模型当字符串函数7.1 字符串输入最简单的方式是直接传字符串responsemodel.invoke(请用一句话解释什么是 Chat Model)print(response.content)这种方式适合快速测试但它不适合复杂业务因为你无法清晰表达 system 指令、历史对话和 assistant 消息。7.2 role message 输入更推荐的方式是传入带角色的消息列表messages[(system,你是一名严谨的技术导师。),(human,请解释 LangChain 模型调用为什么通常是无状态的。),]responsemodel.invoke(messages)print(response.content)这里的 system 消息负责定义模型行为human 消息代表用户问题。如果要做多轮对话就需要把历史消息一起传入。模型本身不会天然记住你上一次调用时说了什么除非你把上下文再次传给它或者使用额外的状态管理机制。7.3 LangChain Message 对象LangChain 还提供了更明确的消息对象fromlangchain.messagesimportAIMessage,HumanMessage,SystemMessage conversation[SystemMessage(你是一个严谨的技术导师。),HumanMessage(请解释模型调用为什么通常是无状态的。),]ai_msgmodel.invoke(conversation)print(ai_msg.content)当代码规模变大时显式消息对象比字符串 tuple 更清晰也更便于类型提示和封装。7.4 AIMessage 中的 content、usage_metadata 和 response_metadatainvoke返回的通常不是普通字符串而是AIMessage对象。最常用字段是contentai_msgmodel.invoke(conversation)print(ai_msg.content)print(ai_msg.usage_metadata)print(ai_msg.response_metadata)你应该重点关注content模型生成的正文。usage_metadataToken 使用情况常用于成本统计。response_metadata模型名、结束原因、服务商返回信息等常用于排查问题。tool_calls如果涉及工具调用这里会包含模型请求调用工具的信息。很多初学者只打印content这在 Demo 里没问题但在企业项目中远远不够。你需要知道一次调用用了多少 Token、耗时多久、由哪个模型完成、是否触发截断、是否命中错误或限流。八、企业级项目开发中必须补上的能力8.1 配置与密钥管理企业项目里配置管理应该遵循几个原则API Key 不进入代码仓库。本地、测试、生产环境配置分离。生产环境优先使用部署平台环境变量或密钥管理系统。日志中不要打印完整密钥、请求头或敏感输入。.env很适合本地学习和开发但它不是完整的密钥治理方案。真正上线时还要结合 CI/CD、容器平台、云厂商密钥服务或公司内部配置中心。8.2 统一模型工厂当项目里接入多个模型时可以设计一个简单的模型工厂把模型选择和初始化集中起来。importosfromdotenvimportload_dotenvfromlangchain.chat_modelsimportinit_chat_model load_dotenv(overrideTrue)MODEL_CONFIGS{deepseek:{model:deepseek:deepseek-chat,api_key_env:DEEPSEEK_API_KEY,base_url_env:DEEPSEEK_BASE_URL,},qwen:{model:qwen-plus,model_provider:openai,api_key_env:DASHSCOPE_API_KEY,base_url_env:DASHSCOPE_BASE_URL,},local:{model:llama3.1,model_provider:ollama,},}defcreate_chat_model(name:str,*,temperature:float0.2):configMODEL_CONFIGS[name]kwargs{model:config[model],temperature:temperature,timeout:30,max_retries:2,}ifmodel_providerinconfig:kwargs[model_provider]config[model_provider]ifapi_key_envinconfig:kwargs[api_key]os.getenv(config[api_key_env])ifbase_url_envinconfig:kwargs[base_url]os.getenv(config[base_url_env])returninit_chat_model(**kwargs)对于一个只有几十行的学习脚本这样封装可能显得多余。但在企业项目中它能带来几个好处切换模型不需要改业务代码。本地、测试、生产可以使用不同模型。便于统一设置超时、重试、温度和 Token 限制。便于后续加入 fallback、路由和灰度策略。8.3 超时、重试、降级与观测模型调用本质上是外部服务调用所以你要按调用外部 API 的标准来设计它设置timeout避免请求长期卡住。设置max_retries应对短暂网络抖动。对关键业务设计 fallback例如主模型失败时降级到备用模型。记录调用耗时、输入长度、输出长度、模型名、错误类型。一个简单的观测封装可以这样写importtimedefinvoke_with_metrics(model,messages):started_attime.perf_counter()ai_msgmodel.invoke(messages)elapsedtime.perf_counter()-started_atreturn{content:ai_msg.content,usage:ai_msg.usage_metadata,metadata:ai_msg.response_metadata,elapsed_seconds:round(elapsed,3),}真实项目里还需要把这些信息写入日志、指标系统或链路追踪系统。否则当用户反馈“AI 回答很慢”或“成本突然变高”时你很难定位问题。8.4 Token 成本统计模型调用的成本通常和 Token 数量相关。AIMessage的usage_metadata可以帮助你记录输入 Token 数。输出 Token 数。总 Token 数。你可以按用户、接口、业务场景、模型提供商统计调用成本。例如哪个功能最耗 Token哪类提示词输出过长是否需要给某些任务降低max_tokens是否可以把简单任务路由到更便宜的模型这就是从 Demo 走向企业级应用必须补上的成本意识。8.5 在线模型与本地模型的选择策略可以用下面的思路做选择场景推荐选择学习 LangChain 调用流程本地 Ollama 或低成本在线模型高质量内容生成能力更强的在线模型隐私数据初步处理本地模型或企业内网部署模型高并发简单分类低成本快速模型关键业务决策辅助稳定、可观测、经过评测的模型不要只看模型效果也要看延迟、成本、稳定性、合规和可维护性。九、常见误区与排查清单学习和项目实践中可以重点避开这些坑把 API Key 写死在代码或博客里这是最常见也最危险的问题。混淆参数名例如某些类使用api_base某些初始化方式使用base_url。误解model_provideropenai它可能只是表示 OpenAI-compatible 协议不等于调用 OpenAI 官方模型。以为模型天然记得历史对话多数模型调用是无状态的多轮对话需要显式传入历史消息或使用状态管理。只读取response.content忽略usage_metadata和response_metadata会让成本统计和问题排查变困难。在 Web 服务中大量同步阻塞调用高并发场景应考虑异步调用、任务队列或流式返回。本地 Ollama 示例不确认模型是否存在调用前先用ollama list检查本地模型名称。没有设置超时和重试外部模型服务可能波动工程代码不能假设每次都稳定成功。排查模型调用问题时可以按这个顺序检查环境变量是否正确加载。API Key 是否有效且没有过期。Base URL 是否与平台文档一致。模型名称是否正确。当前模型提供商是否支持该调用方式例如 streaming。返回对象的response_metadata是否包含错误、截断或限流信息。本地模型是否已经通过 Ollama 下载并启动。十、总结从会调用模型到会设计模型接入层LangChain 的模型创建与调用可以分成两个层次来学习。第一层是“会用”知道如何安装依赖、配置 API Key、初始化模型、调用invoke()拿到回答。第二层是“会设计”知道如何统一初始化不同模型如何管理配置和密钥如何选择在线或本地模型如何使用stream改善体验如何用batch提升批处理效率如何记录 Token 成本和响应元数据如何在 Web 服务中避免同步阻塞。对于个人学习建议你先用init_chat_model跑通一个在线模型和一个 Ollama 本地模型再分别练习invoke、stream、batch。对于项目开发建议尽早抽象出模型工厂和调用封装把模型接入层从业务逻辑中拆出来。后续可以继续学习这些方向Prompt Template让提示词可复用、可测试。Output Parser / Structured Output让模型输出可被程序可靠消费。Runnable 链式组合把 prompt、model、parser 串成可观测流程。LangSmith 或日志系统跟踪调用链、成本和错误。RAG、Tool Calling、Agent在模型调用层稳定后再构建更复杂的 AI 应用。真正的企业级 LLM 开发不只是“调用一个模型”而是围绕模型调用建立一套稳定、安全、可观测、可演进的工程体系。