1. LangChain入门:为什么从模型调用开始?
第一次接触LangChain时,我被它繁杂的组件搞得晕头转向——记忆(Memory)、链(Chains)、代理(Agents)这些概念一股脑涌来。直到我意识到:所有高级功能都建立在稳定的模型调用基础上。就像盖房子要先打地基,模型调用就是LangChain的地基。
在实际项目中,我见过太多因为基础不牢导致的问题:API超时没有重试机制、token计算错误引发账单爆炸、流式输出处理不当让用户体验卡顿...这些坑我都踩过。所以这个系列教程,我决定从最基础也最重要的模型调用讲起。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备:Python工具链的选择
2.1 Python环境管理
新手常犯的第一个错误是直接使用系统Python。我强烈推荐使用专门的Python环境管理工具。目前主流选择有:
| 工具 | 特点 | 适用场景 |
|---|---|---|
| virtualenv | 传统方案,兼容性好 | 老项目维护 |
| pipenv | 整合了依赖管理 | 小型项目 |
| poetry | 强大的依赖解析和发布功能 | 开源库开发 |
| uv | 极速安装,Rust编写 | 新项目/追求效率的场景 |
我选择uv作为演示环境,因为它安装依赖的速度比传统pip快10倍以上。安装命令:
bash复制curl -LsSf https://astral.sh/uv/install.sh | sh
注意:如果系统提示权限问题,可以在命令前加上
sudo,或者使用--user参数进行用户级安装
2.2 依赖安装
创建项目目录后,初始化虚拟环境:
bash复制mkdir langchain-demo && cd langchain-demo
uv venv # 创建虚拟环境
source .venv/bin/activate # 激活环境
接着安装核心依赖:
bash复制uv pip install langchain-core langchain-community
我特意拆分了langchain-core和langchain-community的安装,因为完整包langchain会包含大量你可能暂时用不到的组件。这种按需安装的方式能保持环境干净。
3. 模型调用的四种基础模式
3.1 直接调用API
最简单的调用方式是使用LangChain提供的ChatModel类。以OpenAI为例:
python复制from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="gpt-3.5-turbo",
temperature=0.7,
max_tokens=500,
api_key="your_key_here" # 实际项目应该用环境变量
)
response = llm.invoke("请用中文解释量子计算")
print(response.content)
这里有几个关键参数需要理解:
temperature:控制输出的随机性(0-2之间)max_tokens:限制响应长度(注意:输入+输出不能超过模型上下文窗口)streaming:是否启用流式输出(后面会详细讲)
3.2 异步调用
当需要并发处理多个请求时,同步调用会成为性能瓶颈。LangChain原生支持异步:
python复制import asyncio
from langchain_openai import ChatOpenAI
async def batch_query():
llm = ChatOpenAI(model="gpt-3.5-turbo")
tasks = [
llm.ainvoke(f"解释概念{i}")
for i in range(5)
]
return await asyncio.gather(*tasks)
results = asyncio.run(batch_query())
实战技巧:异步调用时要注意API的速率限制。我的经验是对于GPT-3.5,并发控制在5-10个请求比较安全。
3.3 流式输出处理
处理长文本时,流式输出可以显著提升用户体验:
python复制from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo", streaming=True)
for chunk in llm.stream("写一篇关于AI伦理的文章"):
print(chunk.content, end="", flush=True)
流式输出的几个注意事项:
- 确保终端/前端支持流式渲染
- 错误处理更复杂(网络中断时需要重试机制)
- 不适合需要完整响应才能继续的场景
3.4 自定义封装
实际项目中,我推荐对基础调用进行封装:
python复制from typing import Optional
from langchain_core.language_models import BaseChatModel
from langchain_core.messages import HumanMessage
class SafeChatModel:
def __init__(self, model: BaseChatModel, max_retries: int = 3):
self.model = model
self.max_retries = max_retries
async def safe_invoke(self, prompt: str) -> Optional[str]:
for attempt in range(self.max_retries):
try:
response = await self.model.ainvoke(
[HumanMessage(content=prompt)]
)
return response.content
except Exception as e:
print(f"Attempt {attempt + 1} failed: {str(e)}")
if attempt == self.max_retries - 1:
return None
await asyncio.sleep(2 ** attempt) # 指数退避
# 使用示例
llm = SafeChatModel(ChatOpenAI())
response = asyncio.run(llm.safe_invoke("你好"))
这个封装实现了:
- 自动重试机制
- 指数退避策略
- 类型提示
- 错误隔离
4. 高级调用技巧
4.1 Token计算与成本控制
大模型API按token计费,精确计算token能避免账单爆炸:
python复制from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm = ChatOpenAI()
messages = [HumanMessage(content="请总结这篇文章")]
token_count = llm.get_num_tokens_from_messages(messages)
print(f"本次调用将消耗约{token_count}个token")
我的成本控制策略:
- 对长文本先做摘要再处理
- 设置
max_tokens硬限制 - 监控每日用量(各大平台都有用量API)
4.2 超时与限速配置
生产环境必须配置超时:
python复制from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
request_timeout=30, # 整个请求超时时间
max_retries=2, # 自动重试次数
model_kwargs={
"timeout": 10 # 单次请求超时
}
)
4.3 回退策略
当主模型不可用时,自动降级到备用模型:
python复制from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
from langchain_core.language_models import BaseChatModel
class FallbackModel:
def __init__(self, primary: BaseChatModel, fallback: BaseChatModel):
self.primary = primary
self.fallback = fallback
async def invoke(self, prompt: str):
try:
return await self.primary.ainvoke(prompt)
except Exception:
print("Primary model failed, using fallback")
return await self.fallback.ainvoke(prompt)
llm = FallbackModel(
primary=ChatOpenAI(),
fallback=ChatAnthropic(model="claude-2")
)
5. 常见问题排查
5.1 API连接问题
错误现象:
code复制APIError: Error communicating with OpenAI: HTTPSConnectionPool...
解决方案:
- 检查网络连接
- 验证API密钥是否正确
- 测试
curl https://api.openai.com/v1/models是否能通
5.2 速率限制
错误现象:
code复制RateLimitError: You exceeded your current quota...
处理方案:
- 实现请求队列
- 添加延迟
time.sleep(1) - 升级API套餐
5.3 上下文过长
错误现象:
code复制ContextLengthExceeded: This model's maximum context length is 4097 tokens...
优化策略:
- 使用
split_text分割长文档 - 选择上下文窗口更大的模型
- 实现自动摘要功能
6. 项目结构建议
一个可维护的LangChain项目应该这样组织:
code复制/project
│── /config
│ └── settings.py # API密钥等配置
│── /models
│ ├── base.py # 基础模型封装
│ └── fallback.py # 回退逻辑
│── /utils
│ ├── token_counter.py # Token计算工具
│ └── retry.py # 重试装饰器
│── main.py # 主入口
└── requirements.txt # 依赖声明
这种结构的好处是:
- 配置与代码分离
- 功能模块化
- 便于单元测试
- 支持多环境部署
7. 性能优化实战
7.1 批量处理技巧
当需要处理大量相似查询时:
python复制from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm = ChatOpenAI()
messages = [
[HumanMessage(content=f"解释术语{i}")]
for i in range(10)
]
# 批量调用比循环单次调用快3-5倍
results = llm.batch(messages)
7.2 缓存机制
使用LangChain的缓存组件避免重复计算:
python复制from langchain.globals import set_llm_cache
from langchain.cache import SQLiteCache
set_llm_cache(SQLiteCache(database_path=".langchain.db"))
# 第一次调用会访问API
llm.invoke("解释神经网络")
# 相同输入第二次调用直接从缓存读取
llm.invoke("解释神经网络")
7.3 早期终止
对于某些场景可以使用stop参数提前终止生成:
python复制llm.invoke(
"列出10个编程语言",
stop=["6"] # 生成到6就停止
)
8. 模型调用监控
生产环境必须添加监控:
python复制from datetime import datetime
import logging
class MonitoredChatModel:
def __init__(self, model):
self.model = model
self.logger = logging.getLogger("model_monitor")
def invoke(self, prompt):
start = datetime.now()
try:
result = self.model.invoke(prompt)
duration = (datetime.now() - start).total_seconds()
self.logger.info(
f"Model call succeeded | "
f"Duration: {duration:.2f}s | "
f"Prompt length: {len(prompt)}"
)
return result
except Exception as e:
self.logger.error(f"Model call failed: {str(e)}")
raise
# 使用示例
llm = MonitoredChatModel(ChatOpenAI())
监控指标应该包括:
- 调用成功率
- 响应时间P99
- Token使用量
- 错误类型分布
9. 本地模型调用
除了云API,LangChain也支持本地模型:
python复制from langchain_community.llms import Ollama
llm = Ollama(model="llama3")
response = llm.invoke("用中文解释RAG架构")
print(response)
本地模型调用的注意事项:
- 需要足够的内存(7B模型约需14GB)
- 首次运行会自动下载模型
- 性能远低于云API(需要GPU加速)
10. 模型调用最佳实践
根据我的项目经验,总结出这些黄金法则:
- 稳定性优先:所有调用必须包含超时、重试和回退
- 成本可控:监控token使用,设置预算警报
- 可观测性:记录每次调用的元数据
- 模块化设计:业务代码不应该直接依赖具体模型
- 性能优化:批量处理+缓存可以节省50%以上成本
最后分享一个我实际项目中使用的模型调用模板:
python复制from dataclasses import dataclass
from typing import Any, Dict, Optional
import backoff
import openai
from langchain_core.language_models import BaseChatModel
@dataclass
class ModelConfig:
model_name: str = "gpt-3.5-turbo"
temperature: float = 0.7
max_tokens: int = 1000
timeout: int = 30
class ProductionChatModel:
def __init__(self, config: ModelConfig):
self.config = config
self._client = self._init_client()
@backoff.on_exception(
backoff.expo,
(openai.APIError, TimeoutError),
max_tries=5
)
def invoke(self, prompt: str) -> Dict[str, Any]:
messages = [{"role": "user", "content": prompt}]
response = self._client.chat.completions.create(
model=self.config.model_name,
messages=messages,
temperature=self.config.temperature,
max_tokens=self.config.max_tokens,
timeout=self.config.timeout,
)
return {
"content": response.choices[0].message.content,
"usage": response.usage.dict(),
"model": response.model
}
def _init_client(self):
# 这里可以扩展为支持多厂商
return openai.Client()
这个模板包含了:
- 类型安全的配置管理
- 自动重试机制
- 详细的返回结构
- 可扩展的客户端初始化
- 完整的类型提示
