1、背景
大语言模型的蓬勃发展,让传统NLP技术的凌乱复杂多变的算法统一到一个大模型,那么传统的NLP技术优势不再了吗?
人工智能上的明珠,对话,像一个非常聪明的助理一样对话,已经实现了吗?
现在智能体技术比较火,该文章就以对话来说明2中方案的比较
1、状态管理方案,大模型相当于一个全能的NLP算法
2、智能体方案,相当于大模型是一个个人来做
最大的区别是一个颗粒度是NLP算法,一个是以智能体维度来考虑问题
方案1、状态管理之langgraph实现
做好状态管理,并做好上下文直接的切换

方案2,多智能体方案
多智能体架构优势
1. 清晰的职责分离
1.协调器 Agent(Orchestrator)
唯一的流程控制中心
负责意图识别和路由
管理全局上下文和状态
处理Agent之间的切换
2.推荐 Agent
专注槽位填充逻辑
管理自己的槽位状态
生成追问问题
3.闲聊 Agent
简单响应,无状态
知识问答 Agent
调用知识库API
格式化答案
2. 自动处理意图切换
不需要复杂的判断逻辑!每次用户输入都回到协调器:
3 Agent之间独立开发
每个Agent都是独立模块:
推荐Agent
class RecommendAgent:
REQUIRED_SLOTS = ["cuisine", "budget", "location"]
def __init__(self):
self.slots = {}
def handle(self, user_input, state):
# 提取槽位
self.extract_slots(user_input)
# 检查完整性
missing = self.get_missing_slots()
if missing:
return {
"complete": False,
"response": f"请问您的{missing[0]}是?",
"next_action": "wait_slot"
}
else:
recommendations = self.recommend()
return {
"complete": True,
"response": recommendations
}
def get_state(self):
"""保存当前状态供协调器使用"""
return {
"agent": "recommend",
"slots": self.slots.copy(),
"missing": self.get_missing_slots()
}
def restore_state(self, state):
"""恢复之前的状态"""
self.slots = state["slots"]
# 闲聊Agent
class ChatAgent:
def handle(self, user_input, state):
response = self.generate_chat(user_input)
return {
"complete": True,
"response": response
}
# 知识问答Agent
class QAAgent:
def handle(self, user_input, state):
answer = self.call_knowledge_api(user_input)
return {
"complete": True,
"response": answer
}
一个用例图如下:

对话示例
用户: 我想找个餐厅
协调器: [识别意图=推荐] → 路由到推荐Agent
推荐Agent: 您想吃什么菜系?
用户: 今天天气真好
协调器: [识别意图=闲聊,切换Agent,保存推荐状态]
闲聊Agent: 是啊,阳光明媚的日子心情也会变好呢!
协调器: [检测到有挂起任务] 您之前想找餐厅,要继续吗?
用户: 好的
协调器: [恢复推荐Agent状态]
推荐Agent: 您想吃什么菜系?
用户: 川菜有什么特色?
协调器: [识别意图=知识问答,切换Agent]
知识问答Agent: 川菜以麻辣鲜香著称...
协调器: 您之前想找川菜餐厅,要继续吗?
用户: 继续
推荐Agent: [恢复状态,已知菜系=川菜] 您的预算大概多少?
多智能体架构的核心优势:
✅ 职责清晰:每个Agent只做一件事
✅ 易于扩展:新增意图只需添加新Agent
✅ 自动切换:协调器统一管理,无需复杂判断
✅ 状态隔离:每个Agent维护自己的状态
✅ 可测试性强:可以独立测试每个Agent
比之前的单体流程图简洁太多了!
多智能体架构的上下文管理更简单
关键区别:
❌ 单体架构:需要手动保存每个节点的状态(槽位、流程位置、变量等)
✅ 多智能体:只需保存Agent对象的状态,Agent自己知道自己在哪一步
多智能体架构的上下文管理:
✅ 需要保存:必须记住用户切换前的任务
✅ 但更简单:
只保存Agent引用或名称
Agent对象自己管理内部状态
不需要保存细粒度的流程节点
❌ 传统架构:需要保存节点位置、变量、槽位、流程状态...
✅ 多智能体:只需保存"哪个Agent在工作"
本质区别:
传统:保存"流程图走到哪个节点了"
多智能体:保存"哪个Agent被打断了"
所以多智能体的上下文管理虽然还需要,但工作量减少80%以上!
# 3、多智能体的实现
```python
"""
LangGraph多智能体对话系统
支持意图识别、槽位填充、动态切换
"""
from typing import TypedDict, Literal, List, Dict, Any, Optional
from langgraph.graph import StateGraph, END
import json
# ============= 状态定义 =============
class DialogueState(TypedDict):
"""对话状态"""
messages: List[str] # 对话历史
current_intent: str # 当前意图
agent_stack: List[Dict] # 挂起的Agent栈
agents_data: Dict[str, Any] # 各Agent的数据
last_response: str # 最后的回复
should_continue: bool # 是否继续对话
# ============= Agent基类 =============
class BaseAgent:
"""Agent基类"""
def __init__(self, name: str):
self.name = name
def handle(self, user_input: str, agent_data: Dict) -> Dict:
"""
处理用户输入
返回: {
'complete': bool, # 任务是否完成
'response': str, # 回复内容
'data': dict # 更新后的Agent数据
}
"""
raise NotImplementedError
def is_complete(self, agent_data: Dict) -> bool:
"""检查任务是否完成"""
raise NotImplementedError
def get_description(self, agent_data: Dict) -> str:
"""获取任务描述(用于恢复提示)"""
return f"{self.name}任务"
# ============= 推荐Agent =============
class RecommendAgent(BaseAgent):
"""推荐Agent - 负责收集槽位并推荐"""
REQUIRED_SLOTS = ["cuisine", "budget", "location"]
QUESTIONS = {
"cuisine": "您想吃什么菜系?(如:川菜、湘菜、粤菜)",
"budget": "您的预算大概多少?(如:100元、200元)",
"location": "您在哪个区域用餐?(如:朝阳区、海淀区)"
}
def __init__(self):
super().__init__("recommend")
def handle(self, user_input: str, agent_data: Dict) -> Dict:
# 初始化数据
if not agent_data:
agent_data = {"slots": {}, "asked_slots": []}
# 提取槽位
extracted = self.extract_slots(user_input)
agent_data["slots"].update(extracted)
# 检查缺失槽位
missing = self.get_missing_slots(agent_data["slots"])
if missing:
# 继续追问
next_slot = missing[0]
agent_data["asked_slots"].append(next_slot)
return {
"complete": False,
"response": self.QUESTIONS[next_slot],
"data": agent_data
}
else:
# 槽位完整,执行推荐
result = self.do_recommend(agent_data["slots"])
return {
"complete": True,
"response": result,
"data": agent_data
}
def extract_slots(self, user_input: str) -> Dict:
"""提取槽位(简化版,实际应用用NER)"""
slots = {}
# 菜系识别
cuisines = ["川菜", "湘菜", "粤菜", "鲁菜", "淮扬菜", "东北菜"]
for cuisine in cuisines:
if cuisine in user_input:
slots["cuisine"] = cuisine
break
# 预算识别
if "元" in user_input or "块" in user_input:
import re
numbers = re.findall(r'\d+', user_input)
if numbers:
slots["budget"] = numbers[0] + "元"
# 位置识别
locations = ["朝阳区", "海淀区", "东城区", "西城区", "丰台区"]
for loc in locations:
if loc in user_input:
slots["location"] = loc
break
return slots
def get_missing_slots(self, slots: Dict) -> List[str]:
"""获取缺失的槽位"""
return [s for s in self.REQUIRED_SLOTS if s not in slots]
def is_complete(self, agent_data: Dict) -> bool:
if not agent_data:
return False
slots = agent_data.get("slots", {})
return len(self.get_missing_slots(slots)) == 0
def get_description(self, agent_data: Dict) -> str:
if not agent_data:
return "找餐厅"
slots = agent_data.get("slots", {})
if slots.get("cuisine"):
return f"找{slots['cuisine']}餐厅"
return "找餐厅"
def do_recommend(self, slots: Dict) -> str:
"""执行推荐"""
return f"""
🍽️ 为您推荐以下餐厅:
1. 【川味轩】
- 菜系:{slots['cuisine']}
- 人均:{slots['budget']}
- 位置:{slots['location']}附近
- 特色:正宗麻辣,环境优雅
2. 【蜀香阁】
- 菜系:{slots['cuisine']}
- 人均:{slots['budget']}
- 位置:{slots['location']}商圈
- 特色:经典川菜,性价比高
推荐完毕!还需要其他帮助吗?
"""
# ============= 闲聊Agent =============
class ChatAgent(BaseAgent):
"""闲聊Agent - 简单回复"""
def __init__(self):
super().__init__("chat")
def handle(self, user_input: str, agent_data: Dict) -> Dict:
response = self.generate_chat_response(user_input)
return {
"complete": True,
"response": response,
"data": {}
}
def generate_chat_response(self, user_input: str) -> str:
"""生成闲聊回复(简化版)"""
if "天气" in user_input:
return "是啊,今天天气不错!适合出去走走😊"
elif "你好" in user_input or "您好" in user_input:
return "您好!很高兴为您服务,有什么可以帮您的吗?"
elif "谢谢" in user_input:
return "不客气!很高兴能帮到您😊"
else:
return "嗯嗯,我明白了。还有什么可以帮您的吗?"
def is_complete(self, agent_data: Dict) -> bool:
return True
# ============= 知识问答Agent =============
class QAAgent(BaseAgent):
"""知识问答Agent"""
def __init__(self):
super().__init__("qa")
# 简化的知识库
self.knowledge_base = {
"川菜": "川菜是中国八大菜系之一,以麻辣鲜香著称。代表菜有:麻婆豆腐、宫保鸡丁、水煮鱼、回锅肉等。",
"湘菜": "湘菜注重香辣、酸辣、焦麻。代表菜有:剁椒鱼头、毛氏红烧肉、辣椒炒肉等。",
"粤菜": "粤菜讲究清淡鲜美,原汁原味。代表菜有:白切鸡、烧鹅、清蒸鱼等。"
}
def handle(self, user_input: str, agent_data: Dict) -> Dict:
answer = self.search_knowledge(user_input)
return {
"complete": True,
"response": answer,
"data": {}
}
def search_knowledge(self, question: str) -> str:
"""搜索知识库"""
for key, value in self.knowledge_base.items():
if key in question:
return f"💡 {value}"
return "抱歉,我暂时不知道这个问题的答案。您可以换个问题试试?"
def is_complete(self, agent_data: Dict) -> bool:
return True
# ============= 意图识别 =============
def identify_intent(user_input: str, current_intent: str) -> str:
"""
识别用户意图
简化版:基于关键词匹配
实际应用应使用分类模型
"""
user_input_lower = user_input.lower()
# 推荐意图关键词
recommend_keywords = ["找", "推荐", "餐厅", "饭店", "吃饭", "用餐"]
if any(kw in user_input for kw in recommend_keywords):
return "recommend"
# 知识问答关键词
qa_keywords = ["什么", "怎么", "为什么", "哪些", "介绍", "特色", "代表"]
if any(kw in user_input for kw in qa_keywords) and any(cuisine in user_input for cuisine in ["川菜", "湘菜", "粤菜"]):
return "qa"
# 闲聊关键词
chat_keywords = ["天气", "你好", "谢谢", "再见", "早上好"]
if any(kw in user_input for kw in chat_keywords):
return "chat"
# 继续/恢复关键词
continue_keywords = ["继续", "好的", "是的", "嗯"]
if any(kw in user_input for kw in continue_keywords) and len(user_input) < 5:
# 如果输入很短且是确认词,保持当前意图
return current_intent if current_intent else "chat"
# 默认:如果正在槽位填充,尝试作为槽位回答
if current_intent == "recommend":
return "recommend"
# 其他情况默认闲聊
return "chat"
# ============= LangGraph节点函数 =============
def orchestrator_node(state: DialogueState) -> DialogueState:
"""协调器节点 - 意图识别和路由"""
user_input = state["messages"][-1]
# 意图识别
new_intent = identify_intent(user_input, state["current_intent"])
print(f"\n[协调器] 识别意图: {new_intent}")
# 判断是否切换Agent
if state["current_intent"] and new_intent != state["current_intent"]:
# 需要切换
print(f"[协调器] 从 {state['current_intent']} 切换到 {new_intent}")
# 检查当前Agent是否完成
agents_map = {
"recommend": recommend_agent,
"chat": chat_agent,
"qa": qa_agent
}
current_agent = agents_map.get(state["current_intent"])
if current_agent:
current_data = state["agents_data"].get(state["current_intent"], {})
if not current_agent.is_complete(current_data):
# 保存未完成的Agent
print(f"[协调器] 保存未完成的 {state['current_intent']} 任务")
state["agent_stack"].append({
"intent": state["current_intent"],
"data": current_data
})
state["current_intent"] = new_intent
return state
def recommend_agent_node(state: DialogueState) -> DialogueState:
"""推荐Agent节点"""
user_input = state["messages"][-1]
agent_data = state["agents_data"].get("recommend", {})
print(f"[推荐Agent] 当前槽位: {agent_data.get('slots', {})}")
# 处理输入
result = recommend_agent.handle(user_input, agent_data)
# 更新状态
state["agents_data"]["recommend"] = result["data"]
state["last_response"] = result["response"]
# 如果完成且有挂起任务,添加恢复提示
if result["complete"] and state["agent_stack"]:
paused = state["agent_stack"][-1]
agents_map = {
"recommend": recommend_agent,
"chat": chat_agent,
"qa": qa_agent
}
paused_agent = agents_map[paused["intent"]]
desc = paused_agent.get_description(paused["data"])
state["last_response"] += f"\n\n💡 您之前正在{desc},要继续吗?"
return state
def chat_agent_node(state: DialogueState) -> DialogueState:
"""闲聊Agent节点"""
user_input = state["messages"][-1]
print(f"[闲聊Agent] 处理闲聊")
result = chat_agent.handle(user_input, {})
state["last_response"] = result["response"]
# 如果有挂起任务,添加恢复提示
if state["agent_stack"]:
paused = state["agent_stack"][-1]
agents_map = {
"recommend": recommend_agent,
"chat": chat_agent,
"qa": qa_agent
}
paused_agent = agents_map[paused["intent"]]
desc = paused_agent.get_description(paused["data"])
state["last_response"] += f"\n\n💡 您之前正在{desc},要继续吗?"
return state
def qa_agent_node(state: DialogueState) -> DialogueState:
"""知识问答Agent节点"""
user_input = state["messages"][-1]
print(f"[知识问答Agent] 回答问题")
result = qa_agent.handle(user_input, {})
state["last_response"] = result["response"]
# 如果有挂起任务,添加恢复提示
if state["agent_stack"]:
paused = state["agent_stack"][-1]
agents_map = {
"recommend": recommend_agent,
"chat": chat_agent,
"qa": qa_agent
}
paused_agent = agents_map[paused["intent"]]
desc = paused_agent.get_description(paused["data"])
state["last_response"] += f"\n\n💡 您之前正在{desc},要继续吗?"
return state
def check_resume_node(state: DialogueState) -> DialogueState:
"""检查是否恢复挂起任务"""
user_input = state["messages"][-1]
# 检查用户是否想恢复
if any(kw in user_input for kw in ["继续", "好的", "是的", "嗯", "对"]) and state["agent_stack"]:
# 恢复挂起的Agent
paused = state["agent_stack"].pop()
print(f"[协调器] 恢复 {paused['intent']} 任务")
state["current_intent"] = paused["intent"]
state["agents_data"][paused["intent"]] = paused["data"]
return state
def route_to_agent(state: DialogueState) -> Literal["recommend", "chat", "qa", "end"]:
"""路由到对应的Agent"""
if not state["should_continue"]:
return "end"
intent = state["current_intent"]
print(f"[路由] -> {intent}")
return intent
# ============= 创建Agent实例 =============
recommend_agent = RecommendAgent()
chat_agent = ChatAgent()
qa_agent = QAAgent()
# ============= 构建LangGraph =============
def create_dialogue_graph():
"""创建对话图"""
workflow = StateGraph(DialogueState)
# 添加节点
workflow.add_node("orchestrator", orchestrator_node)
workflow.add_node("check_resume", check_resume_node)
workflow.add_node("recommend", recommend_agent_node)
workflow.add_node("chat", chat_agent_node)
workflow.add_node("qa", qa_agent_node)
# 设置入口
workflow.set_entry_point("check_resume")
# check_resume -> orchestrator
workflow.add_edge("check_resume", "orchestrator")
# orchestrator -> 各Agent
workflow.add_conditional_edges(
"orchestrator",
route_to_agent,
{
"recommend": "recommend",
"chat": "chat",
"qa": "qa",
"end": END
}
)
# 各Agent -> check_resume(循环)
workflow.add_edge("recommend", "check_resume")
workflow.add_edge("chat", "check_resume")
workflow.add_edge("qa", "check_resume")
return workflow.compile()
# ============= 主程序 =============
def main():
"""主程序 - 交互式对话"""
print("="*60)
print("🤖 多智能体对话系统")
print("="*60)
print("支持功能:")
print(" 1. 餐厅推荐 - 输入:我想找餐厅")
print(" 2. 知识问答 - 输入:川菜有什么特色?")
print(" 3. 闲聊对话 - 输入:今天天气真好")
print(" 4. 动态切换 - 随时切换话题")
print("输入 'quit' 退出")
print("="*60)
# 创建图
graph = create_dialogue_graph()
# 初始化状态
state = DialogueState(
messages=[],
current_intent="",
agent_stack=[],
agents_data={},
last_response="",
should_continue=True
)
while True:
# 获取用户输入
user_input = input("\n👤 您: ").strip()
if not user_input:
continue
if user_input.lower() in ['quit', 'exit', '退出']:
print("\n👋 再见!")
break
# 添加到消息历史
state["messages"].append(user_input)
state["should_continue"] = True
# 执行图
try:
state = graph.invoke(state)
# 输出回复
if state["last_response"]:
print(f"\n🤖 助手: {state['last_response']}")
except Exception as e:
print(f"\n❌ 错误: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
main()
程序流程


443

被折叠的 条评论
为什么被折叠?



