LangChain 应用开发实战 · 运维手册
适用场景:基于 LLM 构建运维助手、知识库问答、自动化工单系统等 AI 应用。
1. LangChain 核心概念
1.1 架构概览
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ LLM │ │ Memory │ │ Tools │
│ (Ollama) │ │ (Redis) │ │ (API/CLI) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────────┼───────────────────┘
│
┌──────▼──────┐
│ Chain │
│ (编排器) │
└──────┬──────┘
│
┌──────▼──────┐
│ Output │
│ (结果) │
└─────────────┘
1.2 核心组件
| 组件 | 作用 | 典型用法 |
|---|---|---|
| LLM | 调用大模型 | ChatOllama, ChatOpenAI |
| PromptTemplate | 提示词模板 | 固定结构 + 变量填充 |
| OutputParser | 解析输出 | JSON, String |
| Chain | 链式调用 | LLMChain, SequentialChain |
| Memory | 会话历史 | ConversationBufferMemory |
| Tool | 外部工具 | Python 函数封装 |
| Agent | 自主决策 | AgentExecutor |
2. 最小可用 Chain
2.1 基础聊天链
# basic_chain.py
from langchain.chains import LLMChain
from langchain.prompts import ChatPromptTemplate
from langchain_community.llms import Ollama
# 初始化 LLM
llm = Ollama(model="qwen2.5:7b", temperature=0.7)
# 定义 Prompt
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个运维专家助手。"),
("user", "{question}")
])
# 创建 Chain
chain = LLMChain(llm=llm, prompt=prompt)
# 执行
result = chain.invoke({"question": "Kubernetes Pod 处于 Pending 状态怎么办?"})
print(result["text"])
2.2 带结构化输出的 Chain
# structured_chain.py
from langchain.output_parsers import JsonOutputParser
from langchain.chains import LLMChain
# JSON 解析器
parser = JsonOutputParser()
prompt = ChatPromptTemplate.from_template(
"分析以下运维问题,输出 JSON:\n{question}\n\n{format_instructions}"
)
chain = LLMChain(llm=llm, prompt=prompt)
result = chain.invoke({
"question": "Nginx 502 错误",
"format_instructions": parser.get_format_instructions()
})
# 输出结构化 JSON
print(result["text"])
3. Memory 会话管理
3.1 内存存储(开发环境)
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True
)
# 每次对话自动保存历史
chain = LLMChain(llm=llm, prompt=prompt, memory=memory)
3.2 Redis 存储(生产环境)
from langchain_community.storage import RedisStore
from langchain_community.chat_message_histories import RedisChatMessageHistory
def get_memory(session_id: str):
"""获取会话历史"""
return RedisChatMessageHistory(
session_id=session_id,
url="redis://localhost:6379/0"
)
# 使用时
history = get_memory("user_123")
chain = LLMChain(llm=llm, prompt=prompt, memory=history)
3.3 Memory 清理策略
# 设置 TTL 避免泄漏
import redis
r = redis.Redis()
r.expire(f"chat_history:user_123", 86400) # 24 小时过期
# 定期清理
def cleanup_expired_memories():
keys = r.keys("chat_history:*")
for key in keys:
if r.ttl(key) < 0:
r.delete(key)
4. Tools 工具集成
4.1 定义 Tool
from langchain.tools import Tool
def check_service(service_name: str) -> str:
"""检查服务状态"""
import subprocess
result = subprocess.run(
["systemctl", "status", service_name],
capture_output=True, text=True
)
return result.stdout[:1000]
def query_metrics(metric: str) -> str:
"""查询 Prometheus 指标"""
import requests
resp = requests.get(
f"http://prometheus:9090/api/v1/query?query={metric}"
)
return resp.text[:2000]
# 注册 Tools
tools = [
Tool(
name="check_service",
func=check_service,
description="检查 Linux 服务状态"
),
Tool(
name="query_metrics",
func=query_metrics,
description="查询 Prometheus 指标"
)
]
4.2 Tool 安全沙箱
import subprocess
import time
ALLOWED_COMMANDS = ["systemctl", "docker", "kubectl", "curl"]
MAX_TIMEOUT = 30
def safe_tool_call(func_name: str, **kwargs) -> dict:
"""安全执行 Tool"""
# 检查命令白名单
if func_name not in ALLOWED_COMMANDS:
return {"error": f"Command {func_name} not allowed"}
# 执行并限制超时
try:
result = subprocess.run(
kwargs.get("cmd", ""),
shell=True,
capture_output=True,
text=True,
timeout=MAX_TIMEOUT
)
return {
"stdout": result.stdout[:5000],
"stderr": result.stderr[:5000],
"returncode": result.returncode
}
except subprocess.TimeoutExpired:
return {"error": "Command timed out"}
5. Agent 智能体
5.1 ReAct Agent
from langchain.agents import create_react_agent, AgentExecutor
# 创建 Agent
agent = create_react_agent(
llm=llm,
tools=tools,
prompt=react_prompt # ReAct 提示词模板
)
executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
max_iterations=5,
handle_parsing_errors=True
)
# 执行
result = executor.invoke({
"input": "Nginx 返回 502,请帮我诊断"
})
5.2 Agent 工作流
6. RAG Pipeline
6.1 完整 RAG 链
from langchain.chains import RetrievalQA
from langchain.vectorstores import Chroma
from langchain.embeddings import OllamaEmbeddings
# 初始化向量库
embeddings = OllamaEmbeddings(model="bge-m3")
vectorstore = Chroma(
persist_directory="/data/chroma/ops-manuals",
embedding_function=embeddings
)
# 检索器
retriever = vectorstore.as_retriever(
search_kwargs={"k": 5, "score_threshold": 0.6}
)
# RAG Chain
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=retriever,
return_source_documents=True
)
# 查询
result = qa_chain.invoke("Nginx 502 错误如何排查?")
print(result["result"])
print(result["source_documents"])
6.2 检索优化
# 多路检索:向量 + 关键词
from langchain.retrievers import EnsembleRetriever
from langchain.retrievers import BM25Retriever
vector_retriever = vectorstore.as_retriever()
bm25_retriever = BM25Retriever.from_documents(documents)
ensemble_retriever = EnsembleRetriever(
retrievers=[vector_retriever, bm25_retriever],
weights=[0.7, 0.3]
)
7. 错误处理与重试
7.1 重试机制
from langchain.globals import set_verbose, set_debug
from tenacity import retry, wait_exponential, stop_after_attempt
@retry(
wait=wait_exponential(multiplier=1, min=4, max=10),
stop=stop_after_attempt(3)
)
def call_llm_with_retry(prompt: str) -> str:
"""带重试的 LLM 调用"""
return llm.invoke(prompt)
7.2 降级策略
def robust_chain_call(question: str) -> dict:
"""健壮调用:失败降级"""
try:
result = chain.invoke({"question": question})
return {"status": "success", "result": result}
except Exception as e:
# 降级到简单模式
try:
result = simple_llm.invoke(question)
return {"status": "degraded", "result": result}
except:
return {"status": "error", "result": "服务暂时不可用"}
8. 监控与日志
8.1 调用链追踪
import uuid
import logging
logger = logging.getLogger(__name__)
def trace_chain_call(question: str):
trace_id = str(uuid.uuid4())[:8]
logger.info(f"[TRACE:{trace_id}] 开始处理: {question}")
try:
result = chain.invoke({"question": question})
logger.info(f"[TRACE:{trace_id}] 成功,耗时: {elapsed}ms")
return result
except Exception as e:
logger.error(f"[TRACE:{trace_id}] 失败: {e}")
raise
8.2 指标收集
from prometheus_client import Counter, Histogram
REQUEST_COUNT = Counter('llm_requests_total', 'LLM request count', ['model', 'status'])
REQUEST_LATENCY = Histogram('llm_request_latency_seconds', 'LLM request latency')
@REQUEST_LATENCY.time()
def tracked_call(question: str):
try:
result = chain.invoke({"question": question})
REQUEST_COUNT.labels(model='qwen2.5', status='success').inc()
return result
except:
REQUEST_COUNT.labels(model='qwen2.5', status='error').inc()
raise
9. 常见问题排查(5 个坑)
问题 1:Memory 泄漏
现象:Redis 占用持续增长
排查:
解决:设置 TTL,定期清理
问题 2:Token 超限
现象:BadRequestError: This model's maximum context length is 8192 tokens
解决:
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64)
chunks = splitter.split_documents(documents)
问题 3:Tool 权限过大
现象:Agent 执行了危险命令
解决:命令白名单 + 沙箱隔离
问题 4:幻觉导致错误操作
现象:Agent 编造不存在的命令
解决:增加 RAG 上下文 + 人工确认关键操作
问题 5:长运行超时
现象:Agent 循环超过最大迭代次数
解决:设置 max_iterations=5,添加超时回调