2.Langchain 1.2.0 学习 --- Models
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/数组结束处停止 |
| 特定标记 | [" |
自定义停止标记 |
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为百度千帆,多模态大模型使用阿里百炼

浙公网安备 33010602011771号