Langchain 1.2.0 中 Models 模型有哪些特点?

摘要:LangChain Models 学习笔记 如果你正在开发 AI 应用,那么 LangChain 的 Models 模块是你必须掌握的核心组件。它就像是你与各种大语言模型(LLM)沟通的"翻译官&q
LangChain Models 学习笔记 如果你正在开发 AI 应用,那么 LangChain 的 Models 模块是你必须掌握的核心组件。它就像是你与各种大语言模型(LLM)沟通的"翻译官"和"调度中心"。本文将带你全面了解 LangChain 1.2.0 中 Models 的用法,并通过大量示例帮助你快速上手。 1. 初识 LangChain Models 想象一下这样的场景:你开了一家餐厅雇用了来自不同国家的厨师(有会做川菜的、有会做西餐的、有会做日本料理的)。但是你发现一个问题——每个厨师的烹饪风格和流程都不一样,你需要分别用不同的方式和他们沟通。 LangChain Models 就是解决这个问题的"万能经理"。它提供了一套统一的接口,让你能够轻松地与各种大语言模型(OpenAI、Anthropic、百度、阿里等)进行交互,而不需要关心底层 API 的差异。 为什么要掌握 Models API? 统一接口:一套代码切换不同模型 灵活配置:精确控制输出行为 完整功能:支持同步/流式/批量调用、工具调用、结构化输出、多模态等高级特性 2. 快速上手:模型初始化 在 LangChain 中,初始化模型有两种主要方式。让我带你一步步了解。 2.1 使用 init_chat_model(推荐) 这是 LangChain 1.2.0 推荐的统一初始化方式,类似于"一站式服务"——你只需要告诉它想用什么模型,其他的事情它帮你搞定。 from langchain.chat_models import init_chat_model import os # 从环境变量读取配置 baidu_api_key = os.getenv("BAIDU_API_KEY") baidu_base_url = os.getenv("BAIDU_BASEURL") # 方式一:只指定模型名,提供商自动识别 model = init_chat_model( model="kimi-k2.5", model_provider="openai", # 明确指定提供商 base_url=baidu_base_url, api_key=baidu_api_key, ) # 方式二:使用 "provider:model" 格式 model = init_chat_model( model="openai:kimi-k2.5", # 提供商:模型名 base_url=baidu_base_url, api_key=baidu_api_key, ) 💡 小贴士:如果你省略 model_provider,LangChain 会尝试自动识别。但显式指定可以避免歧义,也更易于理解和维护。 2.2 使用具体的模型类 有时候你需要更精细的控制,这时候可以直接使用具体的模型类,比如 ChatOpenAI。 from langchain_openai import ChatOpenAI # 完整的配置选项 model = ChatOpenAI( base_url="https://api.baidu.com/v1", # API 端点 api_key="your-api-key", # API 密钥 model="minimax-m2.5", # 模型名称 temperature=0.7, # 温度参数 max_tokens=1000, # 最大输出 token 数 timeout=30, # 超时时间(秒) max_retries=6, # 最大重试次数 ) # 快速测试 response = model.invoke("你好,请介绍一下自己") print(response.content) 3. 核心参数详解:像调味料一样配置你的模型 如果说大语言模型是一道菜,那么参数就是烹饪时的调味料。不同的调味料组合,会做出完全不同口味菜肴。让我为你详细讲解每个参数的作用和推荐用法。 3.1 temperature——控制"创意"还是"保守" 想象一下:你聘请了一位厨师。temperature=0 时,这位厨师严格按照菜谱操作,每次做出的菜几乎一模一样;temperature=1.5 时,这位厨师极具创意,每次都可能给你带来惊喜(或者惊吓)。 temperature 的取值范围是 0-2,数值越低输出越确定保守,数值越高输出越创意随机。 from langchain_openai import ChatOpenAI import os baidu_api_key = os.getenv("BAIDU_API_KEY") baidu_base_url = os.getenv("BAIDU_BASEURL") # 演示不同 temperature 的效果 for temp in [0, 0.7, 1.5]: print(f"\n{'='*50}") print(f"🌡️ Temperature = {temp}") print(f"{'='*50}") model_temp = ChatOpenAI( temperature=temp, max_tokens=100, base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) # 同一问题,多次调用观察差异 for i in range(2): response = model_temp.invoke("用一句话描述人工智能") print(f" 回答 {i+1}: {response.content}") 场景 推荐 Temperature 说明 代码生成 0.0 - 0.3 需要精确、确定性的输出 数据提取 0.0 - 0.3 需要结构化、一致的输出 问答系统 0.3 - 0.7 平衡准确性和自然度 创意写作 0.7 - 1.0 需要多样性和创造性 头脑风暴 1.0 - 1.5 最大化创意输出 3.2 max_tokens——控制输出的"预算" 想象你给厨师一个食材预算。max_tokens=50 意味着只能用很少的食材做一道小菜;max_tokens=300 则可以做一个丰盛的大餐。 max_tokens 控制模型生成的最大 token 数量,用于限制输出长度和控制成本。 # 不同 max_tokens 的效果 for max_tok in [50, 150, 300]: print(f"\n📏 max_tokens = {max_tok}") model_max = ChatOpenAI( max_tokens=max_tok, temperature=0.7, base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) response = model_max.invoke("请详细介绍 Python 编程语言的特点") print(f"输出长度: {len(response.content)} 字符") print(f"内容预览: {response.content[:100]}...") 场景 推荐 max_tokens 说明 简短回答 50-100 节省成本,快速响应 中等回答 150-300 平衡详细度和成本 长文档生成 500-1000 允许详细解释 代码生成 500-2000 代码通常需要更多空间 3.3 top_p——核采样的秘密 想象服务员给你菜单,但只给你看最可能点到的菜品。top_p=0.1 只展示最热门的 10% 菜品,top_p=0.9 则展示 90% 的菜品供你选择。 top_p(核采样)是 temperature 的替代方案,用于控制输出多样性。通常不建议同时调整这两个参数。 # 演示 top_p 效果 for top_p in [0.1, 0.5, 0.9]: print(f"\n🎯 top_p = {top_p}") model_top = ChatOpenAI( top_p=top_p, temperature=0, # 固定为 0 以便观察 top_p 效果 max_tokens=100, base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) response = model_top.invoke("列举三种编程语言") print(f"回答: {response.content}") 场景 推荐 top_p 说明 精确输出 0.1 - 0.3 只考虑高概率词,减少随机性 平衡模式 0.5 - 0.7 兼顾质量和多样性 创意生成 0.8 - 0.95 允许更多样化的选择 3.4 frequency_penalty——避免重复的"词汇税" 想象一位作家,如果他在文章中重复使用同一个词,就要交"词汇税"。frequency_penalty 越高,作者越会被迫使用不同的表达方式。 # 演示 frequency_penalty 效果 for penalty in [0, 0.5, 1.5]: print(f"\n🔄 frequency_penalty = {penalty}") model_fp = ChatOpenAI( frequency_penalty=penalty, temperature=0.7, max_tokens=150, base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) response = model_fp.invoke("用丰富的词汇描述编程的美好") print(f"输出: {response.content}") 场景 推荐值 说明 默认 0 无特殊需求时不调整 减少重复 0.3 - 0.7 避免相同词汇过度重复 高度多样 1.0 - 1.5 强制使用不同表达方式 3.5 presence_penalty——话题探索的"推进器" 这位作家如果在一个话题上停留太久,就会被"推"到新话题。presence_penalty 越高,文章引入新主题的可能性越大。 # 演示 presence_penalty 效果 for penalty in [-0.5, 0, 1.0]: print(f"\n💡 presence_penalty = {penalty}") model_pp = ChatOpenAI( presence_penalty=penalty, temperature=0.7, max_tokens=200, base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) response = model_pp.invoke("先介绍 Python,然后自然地切换到其他编程语言") print(f"输出: {response.content}") 场景 推荐值 说明 深入讨论 -0.5 - -0.2 保持在同一主题深入探讨 默认 0 平衡主题切换 广泛覆盖 0.5 - 1.0 鼓励覆盖多个不同主题 3.6 seed——让输出"可复现"的魔法种子 就像你在玩大富翁游戏时设定随机种子,每次用同样的骰子和起始位置,游戏过程和结果是完全一样的。seed 参数让模型输出可复现。 # 测试相同 seed + temperature=0 = 相同输出 print("测试1: 相同 seed,应该得到相同输出\n") for i in range(2): model_seed = ChatOpenAI( seed=42, temperature=0, # 必须为 0 才能完全复现 base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) response = model_seed.invoke("用10个字定义人工智能") print(f" 运行 {i+1}: {response.content}") # 测试不同 seed = 不同输出 print("\n测试2: 不同 seed,应该得到不同输出\n") for seed in [1, 999]: model_seed = ChatOpenAI( seed=seed, temperature=0.5, base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) response = model_seed.invoke("用一句话形容夏天") print(f" seed={seed}: {response.content}") 场景 推荐设置 说明 测试/调试 固定 seed + temperature=0 确保结果可复现 生产环境 不设置或随机 seed 获得自然的输出变化 A/B 测试 使用不同 seed 比较相同参数下的输出差异 3.7 stop——让模型"适可而止" 这就像是告诉服务员:"上完这三道菜后就停,不要再上了。"stop 参数让模型在遇到指定字符串时立即停止生成。 # 单个停止字符串 model_stop = ChatOpenAI( stop=".", max_tokens=200, base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) response = model_stop.invoke("人工智能正在改变世界。它影响了许多行业。") print(f"输出: {response.content}") print(f"停止原因: {response.response_metadata.get('finish_reason')}") # 多个停止字符串 model_stop2 = ChatOpenAI( stop=["步骤 3", "总结"], max_tokens=500, base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) response = model_stop2.invoke("请列出步骤:步骤1:准备工作 步骤2:开始实施 步骤3:验证结果 步骤4:总结") print(f"输出: {response.content}") 场景 推荐 stop 设置 说明 单句输出 "." 或 "\n" 限制为单句或单行 列表生成 ["1.", "2.", "3."] 限制列表项数 结构化输出 ["}", "]"] 在 JSON/数组结束处停止 特定标记 ["", "[STOP]"] 自定义停止标记 3.8 timeout 和 max_retries——网络问题的"防护盾" 想象你点了一份外卖,timeout 就像是等待送餐的最长时间。如果超过了,订单可能取消或者你会重新下单。max_retries 就是你愿意尝试重新下单的次数。 # 生产环境推荐配置 model_production = ChatOpenAI( timeout=60, # 60秒超时 max_retries=10, # 最多重试10次 temperature=0.3, base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) # 快速响应配置 model_fast = ChatOpenAI( timeout=10, # 10秒超时 max_retries=2, # 最多重试2次 temperature=0.7, base_url=baidu_base_url, api_key=baidu_api_key, model="kimi-k2.5", ) 4. 模型的"三板斧":invoke、stream、batch LangChain 提供了三种主要的模型调用方式,就像不同的沟通方式适用于不同场景。 4.1 invoke——同步调用,像打电话 最简单的调用方式,等待模型完全生成回答后再返回。 from langchain_openai import ChatOpenAI from langchain_core.messages import SystemMessage, HumanMessage model = ChatOpenAI(model="glm-5", api_key=baidu_api_key, base_url=baidu_base_url) # 单条消息调用 response = model.invoke("为什么鹦鹉会说话?") print(f"回答: {response.content}") print(f"Token 使用: {response.usage_metadata}") # 多轮对话 conversation = [ SystemMessage("你是一个友好的中文助手。"), HumanMessage("你好!"), ] response = model.invoke(conversation) print(f"回答: {response.content}") 4.2 stream——流式调用,像看直播 实时获取模型输出,提供更好的用户体验,特别适合长文本生成场景。 print("🌊 流式输出:\n") full_response = "" for chunk in model.stream("讲一个关于AI的短故事"): content = chunk.content full_response += content print(content, end="", flush=True) # 实时显示 print(f"\n\n✅ 流式输出完成,总长度: {len(full_response)} 字符") 💡 使用场景:当用户需要等待较长时间才能看到完整回答时,流式输出可以显著提升体验,让用户"看得见"AI 正在思考。 4.3 batch——批量调用,像群发消息 同时处理多个独立请求,提高效率降低成本。 # 批量调用 questions = [ "什么是Python?", "什么是JavaScript?", "什么是Rust?" ] responses = model.batch(questions) for q, r in zip(questions, responses): print(f"❓ {q}") print(f" 💡 {r.content}\n") # 按完成顺序返回(适合耗时不同的任务) for response in model.batch_as_completed(questions): print(f"✅ 完成: {response.text}...") # 控制并发数(避免 API 限流) many_questions = [f"问题 {i}: 什么是编程语言?" for i in range(10)] responses = model.batch(many_questions, config={"max_concurrency": 3}) 5. 工具调用(Tool Calling)——让 AI 学会"使用工具" 想象一位博学的助手,虽然知识渊博,但有时候也需要查资料、计算数据。Tool Calling 就是让 AI 学会主动"寻求帮助"的能力。 5.1 定义工具 from langchain.tools import tool @tool def get_weather(location: str) -> str: """获取指定地区的天气。""" weather_data = { "北京": "晴天,25°C", "上海": "多云,22°C", "纽约": "小雨,18°C" } return weather_data.get(location, f"未知天气信息: {location}") @tool def calculate(expression: str) -> str: """计算数学表达式。""" try: result = eval(expression) return f"结果: {result}" except: return "计算错误" 5.2 绑定工具并调用 # 将工具绑定到模型 model_with_tools = model.bind_tools([get_weather, calculate]) # 调用模型 response = model_with_tools.invoke("北京的天气怎么样?") print(f"工具调用: {response.tool_calls}") # 执行工具 for tool_call in response.tool_calls: result = get_weather.invoke(tool_call) print(f"工具结果: {result.content}") 5.3 完整的工具调用流程 # 完整流程示例 messages = [{"role": "user", "content": "北京和纽约的天气怎么样?"}] # 1. 模型决定调用工具 ai_msg = model_with_tools.invoke(messages) messages.append(ai_msg) # 2. 执行工具 for tool_call in ai_msg.tool_calls: if tool_call['name'] == 'get_weather': result = get_weather.invoke(tool_call) messages.append(result) # 3. 将结果返回给模型,生成最终回答 final_response = model_with_tools.invoke(messages) print(f"最终回答: {final_response.text}") 6. 结构化输出——让 AI 回答"格式化" 想象你填写表格时,只需要按格式填就好,不需要自己排版。结构化输出就是让 AI 按照你定义的"表格"来回答。 6.1 使用 Pydantic 模型(推荐) from pydantic import BaseModel, Field from typing import List class Movie(BaseModel): """电影信息""" title: str = Field(description="电影标题") year: int = Field(description="上映年份") director: str = Field(description="导演") rating: float = Field(description="评分(0-10)", ge=0, le=10) genres: List[str] = Field(description="电影类型列表") # 创建结构化输出模型 model_structured = model.with_structured_output(Movie) # 调用 response = model_structured.invoke("提供电影《阿甘正传》的详细信息") print(f"标题: {response.title}") print(f"年份: {response.year}") print(f"导演: {response.director}") print(f"评分: {response.rating}") print(f"类型: {response.genres}") print(f"对象类型: {type(response)}") # <class '__main__.Movie'> 6.2 使用 TypedDict(轻量级) from typing import TypedDict, Annotated class PersonDict(TypedDict): """人物信息""" name: Annotated[str, ..., "姓名"] age: Annotated[int, ..., "年龄"] occupation: Annotated[str, ..., "职业"] model_typeddict = model.with_structured_output(PersonDict) response = model_typeddict.invoke("介绍一下爱因斯坦") print(response) # {'name': '阿尔伯特·爱因斯坦', 'age': 76, 'occupation': '物理学家'} 6.3 使用 JSON Schema json_schema = { "title": "Book", "description": "书籍信息", "type": "object", "properties": { "title": {"type": "string", "description": "书名"}, "author": {"type": "string", "description": "作者"}, "published_year": {"type": "integer", "description": "出版年份"}, "isbn": {"type": "string", "description": "ISBN编号"} }, "required": ["title", "author", "published_year"] } model_json_schema = model.with_structured_output(json_schema, method="json_schema") response = model_json_schema.invoke("提供《三国演义》的信息") import json print(json.dumps(response, indent=2, ensure_ascii=False)) 方法 优点 缺点 适用场景 Pydantic 自动验证、类型安全、支持嵌套 需要定义模型类 生产环境、复杂结构 TypedDict 轻量、无需实例化 无运行时验证 简单结构、快速原型 JSON Schema 最大灵活性、跨语言 冗长、无验证 动态结构、外部集成 7. 多模态模型——让 AI"看见"世界 传统 AI 只能"读"文字,现代 AI 还能"看"图片、"听"音频。多模态模型就是 AI 的"五感"。 7.1 图像输入 from langchain_core.messages import HumanMessage model_vision = ChatOpenAI(model="qwen3-omni-flash", api_key=ali_api_key, base_url=ail_base_url) # 方式一:通过 URL message = HumanMessage( content=[ {"type": "text", "text": "描述这张图片的内容:"}, { "type": "image_url", "image_url": {"url": "https://example.com/image.jpg"} }, ] ) response = model_vision.invoke([message]) print(response.text) # 方式二:通过 Base64 编码本地图像 import base64 def encode_image(image_path: str) -> str: with open(image_path, "rb") as f: return base64.b64encode(f.read()).decode("utf-8") base64_image = encode_image("/path/to/image.jpg") message = HumanMessage( content=[ {"type": "text", "text": "描述这张图片:"}, { "type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"} }, ] ) 7.2 PDF 输入 # PDF URL 方式 pdf_message = HumanMessage( content=[ {"type": "text", "text": "总结这份 PDF 文档的主要内容:"}, { "type": "file", "file": { "url": "https://example.com/document.pdf", "filename": "document.pdf" } }, ] ) # PDF Base64 方式 with open("document.pdf", "rb") as f: pdf_base64 = base64.b64encode(f.read()).decode("utf-8") pdf_message = HumanMessage( content=[ {"type": "text", "text": "分析这份文档:"}, { "type": "file", "file": { "filename": "document.pdf", "file_data": pdf_base64 } }, ] ) 7.3 Content Block 标准格式 LangChain 1.2.0 引入了标准化的 Content Block 格式: # 使用 content_blocks 属性(推荐) message = HumanMessage( content_blocks=[ {"type": "text", "text": "分析这张图片:"}, {"type": "image", "url": "https://example.com/image.jpg"} ] ) # 或使用 Base64 message = HumanMessage( content_blocks=[ {"type": "text", "text": "描述这张图片:"}, { "type": "image", "base64": "AAAAIGZ0eXBtcDQyAAAAAGlzb21tcDQy...", "mime_type": "image/jpeg" }, ] ) 8. 最佳实践总结 参数选择速查表 ┌─────────────────────────────────────────────────────────────┐ │ Temperature 选择指南 │ ├─────────────────────────────────────────────────────────────┤ │ 代码生成/数学计算: temperature=0.0 - 0.2 │ │ 数据提取/分类: temperature=0.0 - 0.3 │ │ 对话/问答: temperature=0.3 - 0.7 │ │ 创意写作: temperature=0.7 - 1.0 │ │ 头脑风暴: temperature=1.0 - 1.5 │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ Max Tokens 设置建议 │ ├─────────────────────────────────────────────────────────────┤ │ 简短回答: max_tokens=100-300 │ │ 中等长度: max_tokens=500-1000 │ │ 长文档: max_tokens=2000-4000 │ │ 代码生成: max_tokens=2000-4000 │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ 生产环境推荐配置 │ ├─────────────────────────────────────────────────────────────┤ │ model = ChatOpenAI( │ │ model="gpt-4o", │ │ timeout=60, # 复杂查询需要更长时间 │ │ max_retries=10, # 网络不稳定时增加重试 │ │ temperature=0.3, # 根据场景调整 │ │ ) │ └─────────────────────────────────────────────────────────────┘ 9. 总结 本文全面介绍了 LangChain 1.2.0 中 Models 的核心概念和用法: 模型初始化:init_chat_model() vs 直接实例化 核心参数:temperature、max_tokens、top_p 等参数的作用和推荐值 调用方式:invoke(同步)、stream(流式)、batch(批量) 工具调用:让 AI 能够主动使用外部工具 结构化输出:Pydantic、TypedDict、JSON Schema 三种方式 多模态模型:图像、PDF、音频输入处理 📝 个人笔记:本文档基于 LangChain 1.2.0 版本,不同版本可能存在 API 差异,请以官方文档为准;文中使用LLM为百度千帆,多模态大模型使用阿里百炼