7.1 调试与追踪
LLM 应用的调试比传统软件更具挑战性,因为模型的输出具有不确定性。LangChain 提供了多种调试工具。
7.1.1 Callback 机制
LangChain 的 Callback 系统允许你在链执行过程中插入自定义逻辑:
python
callbacks.py
from langchain_openai import ChatOpenAI
from langchain_core.callbacks import BaseCallbackHandler
from langchain_core.outputs import LLMResult
from typing import Any, List, Dict
# 自定义回调处理器
class DebugCallback(BaseCallbackHandler):
def on_llm_start(self, serialized: Dict, prompts: List[str], **kwargs):
print("🔵 LLM 开始调用")
print(f" 提示词: {prompts[0][:100]}...")
def on_llm_end(self, response: LLMResult, **kwargs):
print("🟢 LLM 调用完成")
print(f" Token 使用: {response.llm_output.get('token_usage', {})}")
def on_chain_start(self, serialized: Dict, inputs: Dict, **kwargs):
print(f"🔵 Chain 开始: {serialized.get('name', 'unnamed')}")
def on_chain_end(self, outputs: Dict, **kwargs):
print("🟢 Chain 执行完成")
def on_tool_start(self, serialized: Dict, inputs: Dict, **kwargs):
print(f"⚡ 工具开始: {serialized.get('name', 'unnamed')}")
def on_tool_end(self, output: str, **kwargs):
print(f"✅ 工具完成: {output[:50]}...")
# 使用回调
llm = ChatOpenAI(model="gpt-4o-mini", callbacks=[DebugCallback()])
response = llm.invoke("你好")
print(f"最终回复: {response.content}")
7.1.2 内置回调工具
python
builtin_callbacks.py
from langchain_core.callbacks import StdOutCallbackHandler
from langchain_openai import ChatOpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
# StdOutCallbackHandler - 打印到标准输出
handler = StdOutCallbackHandler()
llm = ChatOpenAI(model="gpt-4o-mini")
prompt = PromptTemplate.from_template("翻译成{lang}:{text}")
chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler])
result = chain.invoke({"lang": "日语", "text": "Hello, World!"})
图 7-1:Callback 回调流程
7.2 LangSmith 使用指南
LangSmith 是 LangChain 官方提供的调试、追踪和评估平台,帮助你深入了解 LLM 应用的行为。
🔧 LangSmith 核心功能
| 功能 | 作用 |
|---|---|
| Trace 追踪 | 记录每个 Chain、Agent、Tool 的执行详情 |
| Dataset 数据集 | 创建测试数据集,批量评估应用效果 |
| Evaluation 评估 | 自动评估输出质量,对比不同版本 |
| Monitor 监控 | 监控生产环境性能,及时发现问题 |
7.2.1 快速集成
python
langsmith_setup.py
# 1. 安装
pip install langsmith
# 2. 设置环境变量
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your-api-key" # 从 langsmith.ai 获取
os.environ["LANGCHAIN_PROJECT"] = "my-langchain-app" # 项目名称
# 3. 使用(自动追踪)
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
response = llm.invoke("你好,请介绍一下自己")
7.2.2 添加数据集和评估
python
langsmith_eval.py
from langchain_openai import ChatOpenAI
from langchain.smith import RunEvalConfig, run_on_dataset
from langchain_core.output_parsers import StrOutputParser
# 定义评估配置
eval_config = RunEvalConfig(
evaluators=[
# 检查输出是否包含关键词
"qa",
# 自定义评估器
{
"criteria": {
"helpfulness": {
"scale": 1,
"prompt": "评估回答是否有帮助..."
}
}
}
]
)
# 创建 Chain
llm = ChatOpenAI(model="gpt-4o-mini")
chain = prompt | llm | StrOutputParser()
# 在数据集上运行评估
run_on_dataset(
client=None,
dataset_name="qa-test-dataset",
llm_or_chain_factory=chain,
evaluation=eval_config,
)
💡 获取 LangSmith API Key
1. 访问 smith.langchain.com
2. 注册并登录账号
3. 在 Settings -> API Keys 中创建新 Key
4. 免费版有每月 5000 条追踪额度
7.3 性能优化
LLM 应用通常延迟较高,以下是常用的优化策略。
7.3.1 缓存优化
python
caching.py
from langchain_openai import ChatOpenAI
from langchain.cache import InMemoryCache
from langchain.globals import set_llm_cache
# 启用 LLM 响应缓存
set_llm_cache(InMemoryCache())
llm = ChatOpenAI(model="gpt-4o-mini")
# 相同输入直接返回缓存结果
response1 = llm.invoke("什么是人工智能")
response2 = llm.invoke("什么是人工智能") # 几乎瞬时返回
7.3.2 并行处理
python
parallel.py
from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage
from langchain.utilities import SerpAPIWrapper
import asyncio
llm = ChatOpenAI(model="gpt-4o-mini")
# 并行执行多个独立任务
async def parallel_tasks():
# 创建多个任务
tasks = [
llm.agenerate([[HumanMessage(content="解释 Python")]]),
llm.agenerate([[HumanMessage(content="解释 JavaScript")]]),
llm.agenerate([[HumanMessage(content="解释 Rust")]]),
]
# 并行执行
results = await asyncio.gather(*tasks)
return results
# 运行
results = asyncio.run(parallel_tasks())
7.3.3 Token 控制
📊 Token 优化策略
| 策略 | 说明 | 节省比例 |
|---|---|---|
| 减少 Context | 只传递必要的对话历史 | 30-50% |
| 使用 Compact | 摘要历史消息 | 40-60% |
| 限制 Max Tokens | 设置输出上限 | 可变 |
| 选择小模型 | 简单任务用 GPT-4o-mini | ~80% |
7.4 生产环境部署
7.4.1 Docker 部署
dockerfile
Dockerfile
FROM python:3.11-slim
WORKDIR /app
# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制代码
COPY . .
# 设置环境变量
ENV PYTHONUNBUFFERED=1
# 启动命令
CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8000"]
yaml
docker-compose.yml
version: '3.8'
services:
api:
build: .
ports:
- "8000:8000"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- LANGCHAIN_TRACING_V2=true
- LANGCHAIN_API_KEY=${LANGCHAIN_API_KEY}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
7.4.2 Kubernetes 部署
yaml
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: langchain-api
spec:
replicas: 3
selector:
matchLabels:
app: langchain-api
template:
metadata:
labels:
app: langchain-api
spec:
containers:
- name: api
image: your-registry/langchain-api:latest
ports:
- containerPort: 8000
env:
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: api-secrets
key: openai-api-key
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "2Gi"
cpu: "1000m"
7.4.3 API 服务封装
python
api.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
app = FastAPI(title="LangChain API", version="1.0")
# 初始化 Chain
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)
prompt = ChatPromptTemplate.from_template("{question}")
chain = prompt | llm | StrOutputParser()
class Question(BaseModel):
question: str
@app.get("/health")
async def health():
return {"status": "ok"}
@app.post("/ask")
async def ask(question: Question):
try:
result = chain.invoke({"question": question.question})
return {"answer": result}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
7.5 安全与最佳实践
7.5.1 敏感信息处理
⚠️ 重要安全提示
- 永远不要在代码中硬编码 API Key
- 永远不要将用户输入直接用于 Prompt
- 永远不要在日志中记录敏感信息
python
security.py
import os
from dotenv import load_dotenv
# 从环境变量读取密钥(安全)
load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")
# 输入验证和清理
import re
def sanitize_input(user_input: str) -> str:
"""清理用户输入,防止注入"""
# 移除潜在的危险字符
cleaned = re.sub(r'[\x00-\x1f\x7f-\x9f]', '', user_input)
# 限制长度
return cleaned[:2000]
# 使用清理后的输入
def create_safe_prompt(user_input: str) -> str:
safe_input = sanitize_input(user_input)
return f"用户问题: {safe_input}\n请简要回答。"
7.5.2 速率限制
python
rate_limit.py
from fastapi import FastAPI, Request
from slowapi import Limiter
from slowapi.util import get_remote_address
app = FastAPI()
limiter = Limiter(key_func=get_remote_address)
@app.post("/ask")
@limiter.limit("10/minute") # 每分钟10次请求
async def ask(request: Request):
# 处理请求
pass
# 或者使用 token bucket 算法
from ratelimit import limits
@limits(calls=10, period=60) # 60秒内最多10次
def call_llm(prompt: str):
# 调用 LLM
pass
7.5.3 最佳实践清单
✅ 生产环境检查清单
| 类别 | 检查项 |
|---|---|
| 安全 | API Key 存储、环境变量、输入验证、输出过滤 |
| 监控 | 日志记录、错误追踪、性能监控、LangSmith |
| 性能 | 缓存、异步处理、Token 优化、模型选择 |
| 可靠性 | 重试机制、熔断器、超时设置、备份方案 |
| 成本 | 用量监控、预算告警、模型降级策略 |
7.6 本章小结
本章学习了 LangChain 进阶主题与生产环境部署的核心内容:
📚 本章要点
| 主题 | 核心技能 |
|---|---|
| 调试追踪 | Callback 机制、自定义处理器 |
| LangSmith | Trace、Dataset、Evaluation |
| 性能优化 | 缓存、并行、Token 控制 |
| 生产部署 | Docker、K8s、API 服务 |
| 安全实践 | 输入验证、速率限制、环境变量 |
🎉 恭喜完成!
你已经完成了「图解 LangChain」的全部内容。从基础概念到项目实战,从调试追踪到生产部署,你已经具备了构建生产级 LLM 应用的能力。
继续探索更多 AI 开发技巧,关注我们获取最新内容!
📱 关注我们
微信公众号
第一时间获取更新
小红书
更多学习干货分享