LangChain Model I/O 学习笔记 -- 模型调用全解析
目录
1. Model I/O 体系总览
LangChain 的 Model I/O 模块是整个框架的骨架,把和大语言模型交互拆成三个清晰的步骤:
Prompts (构造提示词) --> Models (调用模型) --> Output Parsers (解析输出)
// 其实 Model I/O 这个命名很直觉:输入(I)是 Prompts,处理(O)是 Models,再输出(I)给 Parsers。但这个 I/O 更像是管道的上下游,不是传统意义上的设备 I/O。
[Prompts] --输入--> [Models] --输出--> [Output Parsers]
提示词构造 模型调用 输出解析
2. 模型初始化
2.1 统一入口: init_chat_model
LangChain 提供了一个统一初始化函数,不管用什么模型,一个函数搞定:
from langchain.chat_models import init_chat_model
llm = init_chat_model("gpt-4o-mini", model_provider="openai")
response = llm.invoke("Hello!")
print(response.content)
支持的 provider 包括 openai、anthropic、google_genai 等。
注意: init_chat_model 是 LangChain 核心包自带的,但如果要用特定 provider,还是需要安装对应的包。比如 OpenAI 需要
pip install langchain-openai。
2.2 两种初始化路径对比
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
init_chat_model |
统一入口,切换模型只需改两个参数 | 需要多装 provider 包 | 频繁切换模型 |
| Provider 类 (ChatOpenAI) | 直接、细粒度配置 | 代码与 provider 耦合 | 只用一种模型 |
2.3 关键参数一览
| Parameter | Type | Description | Example |
|---|---|---|---|
model |
str | 模型名称 | "gpt-4o-mini" |
model_provider |
str | 提供商 | "openai", "anthropic" |
temperature |
float | 随机性控制 (0-2) | 0 = 确定性输出 |
api_key |
str | API 密钥 (也可用环境变量) | 推荐用 .env 文件 |
base_url |
str | 自定义 API 端点 | 代理 / 兼容平台 |
TODO: 实际项目中 API Key 千万不要硬编码到代码里!用 python-dotenv 的 .env 文件管理。
3. 消息类型
LangChain 用标准化的消息对象来封装对话内容,一共有 四种核心消息类型:
| Message Type | Role | Usage | Example |
|---|---|---|---|
SystemMessage |
系统 | 设定模型角色和行为规则 | “你是一个翻译助手” |
HumanMessage |
用户 | 用户的实际输入 | “翻译:Hello World” |
AIMessage |
AI | 模型的回复(可用于多轮对话上下文) | “你好世界” |
ToolMessage |
工具 | Agent 调用外部工具后的返回结果 | { "result": 42 } |
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
messages = [
SystemMessage(content="你是一个 Python 教学助手,用简洁的方式回答"),
HumanMessage(content="什么是装饰器?"),
]
response = llm.invoke(messages)
print(response.content)
// 留意:AIMessage 不只是用来"展示"模型回复的。在多轮对话中,你需要把之前的 AI 回复也塞进 messages 列表里,模型才知道上下文。这和 OpenAI API 的 messages 数组是一样的逻辑。
消息传递的两种写法
# 方式1: Messages 列表 (推荐)
llm.invoke([
SystemMessage("..."),
HumanMessage("...")
])
# 方式2: 字符串快捷方式
# LangChain 会自动包装成 HumanMessage
llm.invoke("直接传字符串")
4. 四种调用方式
LangChain 提供了 四种调用模式,覆盖同步、异步、流式、批量四大场景。
4.1 invoke – 同步调用 (最常用)
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
response = llm.invoke("用一句话解释什么是量子计算")
print(response.content)
Tip: 同步 = 发出请求后代码会阻塞等待,直到模型返回结果才继续执行下一行。适合脚本、命令行工具等简单场景。
4.2 ainvoke – 异步调用
import asyncio
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
async def main():
response = await llm.ainvoke("你好")
print(response.content)
asyncio.run(main())
// Jupyter vs .py 的区别:Jupyter 里已有事件循环,直接
await main();普通 .py 文件需要asyncio.run(main())。这个坑我踩过不止一次…
4.3 stream – 流式调用 (打字机效果)
def streaming_example():
llm = ChatOpenAI(model="gpt-4o-mini")
for chunk in llm.stream("请写一首关于春天的诗"):
print(chunk.content, end="", flush=True)
flush=True 强制立即输出,不攒缓冲区。这是实现打字机效果的关键。
Advanced: 异步流式事件监听
astream_events可以捕获更细粒度的事件:on_chat_model_start、on_chat_model_stream、on_chat_model_end,适合需要精细控制 UI 更新的场景。
4.4 batch – 批次调用
questions = ["什么是Python?", "什么是JavaScript?"]
responses = llm.batch(questions) # 并行处理
// batch 和手动 for 循环 invoke 的区别:batch 是并行发的,底层用了 asyncio.gather。就像同时下单 5 杯咖啡,谁好了取谁,而不是一杯一杯排队等。
4.5 调用模式速查
| Method | Async Version | Feature | Best For |
|---|---|---|---|
invoke() |
ainvoke() |
单次同步/异步调用 | 简单脚本、命令行工具 |
stream() |
astream() |
逐 Token 流式返回 | 聊天机器人、长文本生成 |
batch() |
abatch() |
并行批量处理 | 数据分析、批量内容生成 |
5. 多平台接入实战
这节最有意思的地方是:凡是兼容 OpenAI 接口格式的平台,都可以直接用 ChatOpenAI,只需要改 base_url 和 api_key。这就是标准化接口的威力。
5.1 平台接入一览
| Platform | Class | Model Example | Env Variables | Note |
|---|---|---|---|---|
| OpenAI / CloseAI | ChatOpenAI |
gpt-4o-mini |
OPENAI_API_KEY + OPENAI_BASE_URL |
CloseAI 完全兼容 |
| DeepSeek | ChatOpenAI |
deepseek-chat |
DEEPSEEK_API_KEY + DEEPSEEK_BASE_URL |
兼容 OpenAI 格式 |
| SiliconFlow | ChatOpenAI |
Qwen/Qwen3-8B |
SILICONFLOW_API_KEY + SILICONFLOW_BASE_URL |
新用户送 2000 万 Token |
| Anthropic | ChatAnthropic |
claude-sonnet-4 |
ANTHROPIC_API_KEY |
自有 API 格式 |
ChatGoogleGenerativeAI |
gemini-2.5-flash |
GOOGLE_API_KEY |
自有 API 格式 | |
| Ollama (本地) | ChatOllama |
qwen3.5:4b |
无需 API Key | 适合原型开发和本地测试 |
5.2 Ollama: 本地模型自由
# 下载并运行模型(首次使用会自动下载)
ollama run qwen3.5:4b
from langchain_ollama import ChatOllama
llm = ChatOllama(model="qwen3.5:4b", base_url="http://localhost:11434")
response = llm.invoke("你好,介绍一下你自己")
Tip: 学习阶段强烈推荐硅基流动 + Qwen3-8B(完全免费),或者本地 Ollama。零成本跑通所有实验。
5.3 不兼容平台用 init_chat_model 统管
llm_openai = init_chat_model("gpt-4o-mini",
model_provider="openai", api_key=os.getenv("OPENAI_API_KEY"))
llm_claude = init_chat_model("claude-sonnet-4",
model_provider="anthropic", api_key=os.getenv("ANTHROPIC_API_KEY"))
llm_gemini = init_chat_model("gemini-2.5-flash",
model_provider="google_genai", api_key=os.getenv("GEMINI_API_KEY"))
# 调用方式完全一致!
for name, llm in [("OpenAI", llm_openai), ("Claude", llm_claude), ("Gemini", llm_gemini)]:
response = llm.invoke("用一句话介绍你自己")
print(f"{name}: {response.content}")
// 这就是 LangChain 设计哲学的核心体现:统一接口,模型无关。切换模型就像换鞋一样简单,你的业务代码完全不用动。
6. 高级主题
6.1 多模态输入 (Vision)
LangChain 支持将图像等多模态数据传给支持视觉的模型。原理是将图片编码为 Base64,然后通过 Data URL 嵌入消息:
import base64
from langchain_core.messages import HumanMessage
with open("image.jpg", "rb") as f:
image_data = f.read()
base64_string = base64.b64encode(image_data).decode("utf-8")
message = HumanMessage(content=[
{"type": "text", "text": "描述这张图片"},
{"type": "image_url",
"image_url": {"url": f"data:image/jpeg;base64,{base64_string}"}}
])
response = llm.invoke([message])
Base64 编码原理: 将每 3 字节 (24 bit) 切为 4 组 (每组 6 bit),每组映射到 A-Z、a-z、0-9、+、/ 共 64 个可打印字符。末尾不足 3 字节用
=填充。这样二进制数据就能放进 JSON 文本协议里传输了。
6.2 速率限制 (Rate Limiting)
from langchain_core.rate_limiters import InMemoryRateLimiter
rate_limiter = InMemoryRateLimiter(
requests_per_second=0.1, # 10秒1个请求
check_every_n_seconds=0.1 # 每0.1秒检查一次令牌桶
)
llm = ChatOpenAI(model="gpt-4o-mini", rate_limiter=rate_limiter)
用的是令牌桶算法(Token Bucket)。适合控制调用频率,避免触发 API 的 rate limit 报错。
6.3 Token 使用追踪
from langchain_core.callbacks import get_usage_metadata_callback
llm = ChatOpenAI(model="gpt-4o-mini")
with get_usage_metadata_callback() as cb:
llm.invoke("你好")
llm.invoke("再见")
print(cb.usage_metadata)
# {'input_tokens': ..., 'output_tokens': ..., 'total_tokens': ...}
6.4 提示词缓存 (Prompt Caching)
这个知识点很多人容易搞混,一定要分清楚两个概念:
| Dimension | Prompt Caching | LLM Cache (本地缓存) |
|---|---|---|
| 缓存位置 | 模型服务商的服务器 | 你本地的内存/磁盘 |
| 缓存内容 | 已计算的提示词中间状态 (KV cache) | 完整的"问题->回答"键值对 |
| 效果 | 减少 token 费用和延迟 | 相同问题完全不调 API |
| 可控性 | 不能控制 | 完全可控 |
OpenAI: 全自动,零配置,自动识别相同前缀并缓存,缓存命中 token 费用减半。
Anthropic: 需要显式标记,通过 AnthropicPromptCachingMiddleware 中间件,缓存命中 token 费用降低 90%。
// 这里的"缓存"发生在模型服务商的服务器上,不是本地硬盘。你的项目目录里不会多出 cache.sqlite 之类的东西。这是个很容易误解的点。
7. 知识点总览
| 主题 | 核心 | 状态 |
|---|---|---|
| 模型输入输出总览 | Prompts -> Models -> Output Parsers | 已完成 |
| 初始化 | init_chat_model /provider-specific classes | 已完成 |
| 消息类型 | System / Human / AI / Tool Message | 已完成 |
| 调用模式 | invoke /ainvoke/stream /batch | 已完成 |
| 平台集成 | OpenAI / DeepSeek / Claude / Gemini / Ollama | 已完成 |
| 高级功能 | Multimodal / Rate Limit / Token Tracking / Caching | 已完成 |
| 输出解析器 | Next lecture… | 待处理 |
总结
LangChain Model I/O 的核心设计哲学就是 统一接口,模型无关。不管底层用的是 GPT、Claude、Gemini 还是本地 Ollama,你的调用代码可以做到几乎一模一样。这对于需要做多模型对比、A/B 测试、多租户系统的项目来说,是巨大的优势。
更多推荐

所有评论(0)