1. LangChain结构化输出与多轮对话实践指南
作为AI应用开发的重要框架,LangChain正在改变我们构建对话系统的方式。最近在开发一个客服机器人项目时,我深刻体会到结构化输出和多轮对话功能带来的效率提升。本文将分享我的实战经验,帮助你快速掌握这两个核心功能。
1.1 为什么需要结构化输出?
传统LLM的输出是自由文本,这给后续处理带来了挑战。比如从客户咨询中提取订单号、日期等信息时,我们需要编写复杂的正则表达式。而结构化输出让模型返回JSON、Pydantic对象等格式,直接对接业务系统。
上周我处理的一个案例:需要从200条客户留言中提取产品反馈。使用传统方法,团队花了3天时间标注和清洗数据。改用结构化输出后,只需2小时就完成了数据提取和入库。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 结构化输出实现方案
2.1 使用Pydantic模型定义结构
python复制from pydantic import BaseModel, Field
from typing import Optional
class CustomerQuery(BaseModel):
"""客户咨询结构化模型"""
product_name: str = Field(description="咨询的产品名称")
issue_type: str = Field(description="问题类型分类")
urgency: Optional[int] = Field(
default=None,
description="紧急程度,1-5级",
ge=1, le=5
)
关键点:
- 每个字段必须添加描述,这将成为LLM的生成指引
- 合理使用Optional处理可能缺失的字段
- 通过Field参数添加验证规则(如ge/le限制数值范围)
2.2 配置模型结构化输出
python复制from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# 初始化模型
llm = ChatOpenAI(model="gpt-3.5-turbo")
# 创建结构化LLM
structured_llm = llm.with_structured_output(CustomerQuery)
# 示例查询
query = "我的iPhone15 Pro充电时发烫严重,这正常吗?"
result = structured_llm.invoke(query)
print(result)
输出示例:
code复制product_name='iPhone15 Pro'
issue_type='充电发热'
urgency=4
2.3 处理复杂嵌套结构
对于多层级的业务场景,可以定义嵌套模型:
python复制class ProductInfo(BaseModel):
name: str
version: str
class ServiceTicket(BaseModel):
customer_id: str
products: List[ProductInfo]
description: str
3. 多轮对话实现技巧
3.1 对话状态管理
python复制from typing import Dict, Any
from langchain_core.messages import AIMessage, HumanMessage
class ConversationState:
def __init__(self):
self.history: List[Dict[str, Any]] = []
def add_message(self, role: str, content: str):
self.history.append({
"role": role,
"content": content,
"timestamp": datetime.now()
})
def get_context(self, window=3):
return self.history[-window:]
3.2 带上下文的对话链
python复制from langchain_core.prompts import MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", "你是专业的客服助手,根据对话历史回答问题"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
chain = prompt | llm
# 使用示例
state = ConversationState()
user_input = "我之前反馈的问题解决了吗?"
context = state.get_context()
response = chain.invoke({
"input": user_input,
"history": context
})
3.3 处理对话分支
使用Conditional分支处理不同意图:
python复制from langchain_core.runnables import RunnableBranch
def route_question(input):
if "价格" in input:
return price_chain
elif "售后" in input:
return service_chain
else:
return general_chain
branch = RunnableBranch(
(lambda x: "价格" in x["input"], price_chain),
(lambda x: "售后" in x["input"], service_chain),
general_chain
)
4. 实战问题排查
4.1 常见错误及解决
-
结构验证失败
- 现象:收到ValidationError
- 解决:检查字段描述是否清晰,必要时放宽类型限制
-
多轮对话上下文丢失
- 现象:模型忘记之前讨论的内容
- 解决:增加history窗口大小,或添加关键信息摘要
-
API限流问题
- 现象:突然收到429错误
- 解决:实现指数退避重试机制
4.2 性能优化技巧
- 对结构化输出启用流式处理:
python复制structured_llm = llm.with_structured_output(
CustomerQuery,
stream=True
)
for chunk in structured_llm.stream("我的订单状态如何?"):
print(chunk)
- 使用LCEL(LangChain Expression Language)组合多个操作:
python复制chain = (
prompt
| llm.with_structured_output(OutputSchema)
| post_processor
)
5. 高级应用场景
5.1 动态结构生成
根据用户查询动态确定输出结构:
python复制def dynamic_schema(query):
if "订单" in query:
return OrderSchema
elif "支付" in query:
return PaymentSchema
else:
return BaseSchema
schema = dynamic_schema(user_input)
chain = llm.with_structured_output(schema)
5.2 混合结构化与非结构化输出
python复制class HybridResponse(BaseModel):
summary: str
details: Dict[str, Any]
follow_up: List[str]
5.3 结合RAG增强回答
python复制from langchain_community.retrievers import BM25Retriever
retriever = BM25Retriever.from_documents(docs)
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm.with_structured_output(Response)
)
在实际项目中,我发现结构化输出可以减少约70%的后处理代码量,而多轮对话的实现效率提升了3倍以上。特别是在处理复杂业务流程时,这两种技术的组合展现出巨大价值。
