智能对话系统架构设计文档
基于 LangGraph + LangChain 的 Agent 框架技术栈详解
文档版本: v1.0 · 2026-06-06
1. 综述:这不是 Chatbot,是 Agent 架构
1.1 从 Chatbot 到 Agent 的范式转变
| 维度 | Chatbot(聊天机器人) | Agent(智能体) |
|---|---|---|
| 核心模式 | 输入 → LLM → 文本输出 | 感知 → 规划 → 工具 → 记忆 → 反思 |
| 输出产物 | 自然语言文本 | 结构化指令(命令/工具调用/动作) |
| 状态管理 | 上下文窗口塞历史 | 层次化记忆(槽位/栈/持久化存储) |
| 控制流 | Prompt 暗示 LLM 怎么做 | 确定性图编排决定流程 |
| 安全机制 | 靠 LLM "自觉" | 硬性边界(最大步数/路由锁) |
本框架的核心设计哲学:
LLM 是 Agent 的"大脑"但不是"中枢神经"
大脑负责推理和理解,中枢神经(LangGraph + Policy + Action)负责协调执行
1.2 整体架构图
┌──────────────────────────────────────┐
│ LangGraph 编排器 │
│ (MessageProcessingState 状态图) │
│ │
│ START → understand → policy → action │
│ ↕ ↕ │
│ ┌────────── guard ───┘ │
│ ↓ │
│ response → END │
└──────────┬───────────────────────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ 感知层 │ │ 规划层 │ │ 工具层 │
│ LLM命令 │ │ Policy │ │ Action │
│ 生成器 │ │ Ensemble │ │ 注册表 │
└───────────┘ └───────────┘ └───────────┘
│ │ │
│ ┌─────▼─────┐ │
│ │ 记忆层 │ │
│ │ Tracker + │ │
│ │ Stack │ │
│ └───────────┘ │
│ │
└─────────────────┬─────────────────────────┘
│
┌──────▼──────┐
│ 安全层 │
│ Guard Node │
└─────────────┘
2. 感知层:LLM 命令生成
核心命题:LLM 的输出不应该是"文本回复",而应该是"结构化指令"
2.1 技术栈
| 组件 | 选型 | 版本 |
|---|---|---|
| LLM 调用框架 | LangChain (langchain-openai) |
0.3+ |
| LLM 提供商 | 阿里云 DashScope (通义千问) / OpenAI / Anthropic | - |
| 输出解析 | CommandParser + PromptBuilder(自定义实现) |
- |
| 结构化输出 | Pydantic 命令模型 | 2.0+ |
| 环境配置 | python-dotenv + YAML 配置 |
- |
2.2 为什么不是"让 LLM 直接说话"?
最朴素的 Agent 写法:
# ❌ 错误做法:LLM 直接回复
response = llm.invoke("用户说: 我要查订单。请回复")
# 回复: "好的,我来帮您查订单,请问订单号是多少?"
问题:
- 回复是"文本",而不是"动作指令"------后续代码无法判断"现在该干嘛"
- LLM 的回复风格不稳定,同样的语义可能每轮输出不同格式
- 没有结构化信息,谁也不知道"查哪个订单""用什么查"
2.3 本框架的做法
# ✅ 正确做法:LLM 生成结构化命令
prompt = PromptBuilder.build(
user_message="我要查订单",
tracker=current_tracker, # 当前对话状态
domain=domain, # 可用的槽位定义
flows=available_flows, # 可触发的业务Flow
)
commands: List[Command] = llm_generator.generate(prompt)
# 输出: [
# TriggerFlow(name="query_order_detail"),
# SetSlot(name="user_id", value="123")
# ]
2.4 命令类型体系
所有 LLM 的输出被统一映射到这几种命令类型:
class Command(ABC):
"""所有命令的基类"""
class TriggerFlow(Command):
"""触发一个业务流程"""
flow_name: str
slots: Dict[str, Any]
class SetSlot(Command):
"""设置槽位值"""
name: str
value: Any
class ChitchatCommand(Command):
"""闲聊回复(当无法匹配业务时)"""
text: str
class CannotHandleCommand(Command):
"""无法处理"""
text: str
class ErrorCommand(Command):
"""系统错误"""
message: str
2.5 架构价值
| 问题 | LLM 直接回复 | 本方案 |
|---|---|---|
| 输出可解析性 | ❌ 文本,需 NLP 后处理 | ✅ 结构化命令,直接处理 |
| 格式稳定性 | ❌ 每轮可能不同 | ✅ 统一类型体系 |
| 模型可替换 | ⚠️ 需微调 Prompt | ✅ 换模型不改逻辑 |
| 可测试性 | ❌ 难以断言文本 | ✅ assert isinstance(cmd, TriggerFlow) |
| 链路追踪 | ❌ 全是字符串 | ✅ 每个命令有类型和参数 |
一句话 :感知层的核心价值是把 LLM 从"发言人"降级为"翻译官"------它负责把用户自然语言翻译成系统内部可执行的统一指令格式。
3. 规划层:PolicyEnsemble + Flow
核心命题 :Agent 的下一步动作应该由"策略算法"决定,而不是"让 LLM 再猜一次"
3.1 技术栈
| 组件 | 选型 | 版本 |
|---|---|---|
| 策略框架 | 自定义 PolicyEnsemble(Chain of Responsibility 模式) |
- |
| 流程引擎 | FlowPolicy + YAML 定义 |
- |
| 知识策略 | EnterpriseSearchPolicy(RAG 式知识检索) |
- |
| 配置语言 | YAML (ruamel.yaml / pyyaml) |
6.0+ |
| 状态持有 | DialogueStack(栈式 Flow 管理) |
- |
3.2 为什么不是"让 LLM 无脑决策"?
# ❌ 错误做法:每轮都问 LLM "下一步做什么"
while True:
action = llm.invoke("看对话历史,决定下一步动作")
execute(action)
问题:
- LLM 没有"任务完成"的概念------它不知道 Flow 何时结束
- LLM 没有"确定性路由"能力------同样的场景可能每次决策不同
- LLM 容易被带偏------用户说"别查了",它可能真的不查了
- 没有优先级------业务逻辑和闲聊混在一起
3.3 本框架的做法
class PolicyEnsemble:
"""策略集成器 - 链式调用多个策略"""
def __init__(self, policies: List[Policy]):
self.policies = policies
async def predict(self, tracker, domain, flows) -> PolicyPrediction:
for policy in self.policies:
prediction = await policy.predict(tracker, domain, flows)
if prediction.confidence > self.THRESHOLD:
logger.info(f"策略 {policy.name} 决策: {prediction.action}")
return prediction
# 所有策略都无法决策 → 默认等待用户输入
return PolicyPrediction(action=ACTION_LISTEN, confidence=1.0)
3.4 内置策略体系
Policy A: FlowPolicy(业务流程驱动)
其工作原理类似于一个"图遍历器":
当前 Flow: modify_order_receive_info
当前步骤索引: 3 (collect: receiver_name)
↓
FlowPolicy 读取第 3 步定义:
- 动作: utter_ask_receiver_name (向用户问姓名)
- 下一步: collect 接收用户输入
↓
决策输出:
action = "utter_ask_receiver_name"
metadata = {slot_to_collect: "receiver_name"}
YAML 定义 Flow 步骤就是"预编程的规划图":
flows:
modify_order_receive_info:
steps:
- collect: order_id # 步骤0: 收集订单号
- action: action_get_order_detail # 步骤1: 查订单详情
- collect: receiver_name # 步骤2: 收集新姓名
ask_before_filling: true # 每次都重新问
- action: action_update_order # 步骤3: 更新数据库
Policy B: EnterpriseSearchPolicy(知识检索驱动)
当 FlowPolicy 无法匹配时接管:
无匹配 Flow
↓
EnterpriseSearchPolicy 工作:
1. 检查是否有知识库(Neo4j 图/向量库)
2. 有 → 检索相关内容,生成回复
3. 没有 → 走闲聊或降级
↓
决策输出:
action = "action_chitchat_response"
或 action = "action_search_enterprise_knowledge"
链式决策流程图
用户: "帮我改一下收货地址"
│
▼
PolicyEnsemble.predict()
│
├── FlowPolicy
│ ├── 检查是否有匹配的 Flow → ✅ modify_order_receive_info
│ ├── 检查当前 Flow 进度 → 步骤 0 (collect order_id)
│ └── 决策 → action_ask_order_id_before_delivered (置信度 1.0)
│
└── EnterpriseSearchPolicy (未执行,因为 FlowPolicy 已高置信度决策)
3.5 为什么用 YAML 定义 Flow?
| 优势 | 说明 |
|---|---|
| 业务人员可编辑 | 不需要会 Python,写 YAML 就能定义对话流程 |
| 版本可追踪 | YAML 是文本文件,可以 Git diff |
| 条件分支清晰 | if: slots.order_id != "false" 直观可读 |
| 运行时热加载 | 修改 YAML 理论上可以不用重启(当前实现需重载 Agent) |
| 工具链丰富 | YAML lint、schema 校验成熟 |
一句话 :规划层的核心价值是 "确定性逻辑 + LLM 弹性"的混合架构------FlowPolicy 提供可靠的业务逻辑骨架,EnterpriseSearchPolicy 提供灵活的 AI 弹性填充。
4. 工具层:Action 注册表
核心命题:Agent 的工具应该是"可注册"的,而不是"硬编码 if-else"
4.1 技术栈
| 组件 | 选型 |
|---|---|
| 工具框架 | 自定义 Action 基类 + 全局注册表 |
| 发现机制 | importlib 动态模块加载 + 目录扫描 |
| 数据模型 | ActionResult (dataclass) |
| 对话访问 | DialogueStateTracker 作为 Action 的上下文 |
4.2 为什么不是"硬编码 if-else"?
# ❌ 错误做法:if-else 硬编码动作
async def execute_action(action_name, tracker, domain):
if action_name == "action_get_order_detail":
# 查数据库...
return "订单详情是..."
elif action_name == "action_cancel_order":
# 取消订单...
return "订单已取消"
elif action_name == "utter_greet":
return "你好!"
# ... 每新增一个动作,加一个 elif
问题:
- 每加一个功能就要改框架代码
- 多人协作时 merge 冲突
- 无法"插件化"分发
- 动作个数膨胀后,一个文件几千行
4.3 本框架的做法
全局注册表:
# 全局单例注册表
_action_registry: Dict[str, Action] = {}
def register_action(action: Action) -> None:
"""注册动作到全局注册表"""
_action_registry[action.name] = action
def get_action(name: str) -> Optional[Action]:
"""根据名称获取动作"""
return _action_registry.get(name)
自动发现机制:
def _load_custom_actions(actions_path: Path) -> List[str]:
"""自动扫描 actions/ 目录,发现并注册 Action 子类"""
for py_file in actions_path.glob("*.py"):
if py_file.name.startswith("_"):
continue # 跳过 __init__.py
# 动态导入
spec = importlib.util.spec_from_file_location(...)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# 扫描类定义,找到继承 Action 的子类
for name, obj in inspect.getmembers(module, inspect.isclass):
if issubclass(obj, Action) and obj is not Action:
action_instance = obj()
register_action(action_instance)
Action 定义示例:
class ActionGetOrderDetail(Action):
"""查询订单详情"""
@property
def name(self) -> str:
return "action_get_order_detail"
async def run(self, tracker, domain, **kwargs) -> ActionResult:
# 从 tracker 获取上下文
order_id = tracker.get_slot("order_id")
user_id = tracker.get_slot("user_id")
# 执行实际操作
order = await db.query_order(order_id, user_id)
# 返回结构化响应
result = ActionResult()
result.add_response(
text=f"订单 #{order.id} 的详情:\n"
f"状态: {order.status}\n"
f"金额: ¥{order.amount}\n"
f"收货地址: {order.address}"
)
return result
4.4 Action 类型一览
| 类型 | 命名规范 | 示例 | 作用 |
|---|---|---|---|
| 模板响应 | utter_xxx |
utter_greet |
回复预定义模板文本 |
| 收集槽位 | utter_ask_xxx |
utter_ask_order_id |
向用户询问槽位值 |
| 自定义动作 | action_xxx |
action_get_order_detail |
执行任意代码逻辑 |
| 特殊动作 | action_listen |
- | 等待用户输入 |
| 闲聊 | action_chitchat_response |
- | LLM 生成自由回复 |
4.5 架构价值
| 能力 | 硬编码 if-else | 注册表 + 自动发现 |
|---|---|---|
| 扩展性 | 改框架源码 | 新建文件就行 |
| 可插拔 | ❌ | ✅ 复制 actions/ 目录就能迁移 |
| 测试性 | 需测整个文件 | 单测一个 Action 类 |
| 团队协作 | 改同一文件冲突 | 各写各的文件 |
| 复用性 | 复制粘贴 | pip 包分发 |
一句话 :工具层的核心价值是 "注册而非硬编码"的插件化架构------让 Agent 的工具扩展从侵入式变成声明式。
5. 记忆层:Tracker + DialogueStack + Store
核心命题:Agent 的记忆不能依赖 LLM 的上下文窗口,需要独立的层次化记忆系统
5.1 技术栈
| 组件 | 选型 | 作用 |
|---|---|---|
| 会话状态 | DialogueStateTracker (自定义) |
管理槽位、事件、消息历史 |
| Flow 上下文 | DialogueStack + StackFrame |
管理 Flow 嵌套和中断 |
| 持久化 | TrackerStore (Memory / JSON / MySQL) |
跨会话存储 |
| 外部记忆 | Neo4j 图数据库 / 向量数据库 | RAG 式企业知识检索 |
5.2 为什么不是"塞上下文窗口"?
# ❌ 错误做法:把历史消息全塞进 Prompt
history = "\n".join([f"{m.role}: {m.text}" for m in last_50_messages])
response = llm.invoke(f"{history}\n用户: 我的订单是什么状态?")
python
Copy
问题:
- 不可靠:LLM 可能忽略前面的重要信息
- 成本高:每轮都重复传所有历史,token 消耗线性增长
- 没有"关键信息"概念:用户说过的"我的订单号是 123"和"今天天气不错"权重一样
- 没有持久化:会话结束就丢失,再来要重问
5.3 本框架的层次化记忆
记忆层级金字塔:
┌─────────────────────┐
│ 企业知识库 (RAG) │ ← 外部知识
│ Neo4j / 向量搜索 │ 生命周期: 永久
└─────────────────────┘
↑
┌─────────────────────┐
│ TrackerStore (持久化)│ ← 跨会话
│ JSON / MySQL │ 生命周期: 永久
└─────────────────────┘
↑
┌─────────────────────┐
│ DialogueStateTracker │ ← 会话内
│ 槽位 + 事件 + 消息 │ 生命周期: 会话起止
└─────────────────────┘
↑
┌─────────────────────┐
│ DialogueStack │ ← Flow 内
│ Flow 嵌套/中断/恢复 │ 生命周期: Flow 起止
└─────────────────────┘
↑
┌─────────────────────┐
│ LangGraph State │ ← 单轮请求内
│ 中间结果缓存 │ 生命周期: 一次 invoke
└─────────────────────┘
5.4 关键设计:槽位系统
槽位是 Agent 的"长时记忆单元":
slots:
user_id:
type: text
mappings:
- type: from_llm # LLM 从用户输入提取
description: "用户ID"
order_id:
type: text
mappings:
- type: controlled # Action 代码控制设置
description: "订单编号"
current_flow:
type: categorical
values:
- query_order
- modify_address
- cancel_order
mappings:
- type: from_llm # LLM 自动识别当前流程
设计价值:
用户: "我要查订单 123"
│
▼
LLM 生成命令: [SetSlot(user_id="abc"), SetSlot(order_id="123"), TriggerFlow("query_order")]
│
▼
Tracker 记录:
user_id = "abc" ← 从会话开始就记住了
order_id = "123" ← 后续 Action 直接读取
current_flow = "query_order" ← 不用每轮重新问 LLM
│
▼ 十轮对话后...
用户: "改成送到新地址"
│
▼
FlowPolicy 检查: 当前在 order_detail Flow 中
→ 步骤 5: 修改地址 (直接取 user_id 和 order_id)
→ 无需 LLM 重新提取这些信息!
5.5 对话栈的安全中断与恢复
class DialogueStack:
"""栈式 Flow 管理,支持嵌套"""
frames: List[StackFrame]
# 栈顶 = 当前活动的 Flow
#
# 例如:
# [0] main_flow (query_order)
# → 流程中触发了售后服务
# [1] postsale_flow (refund_request)
# → 售后完成, pop()
# [0] main_flow (继续原来的 query_order)
class FlowStackFrame:
"""一个 Flow 的执行上下文"""
flow_name: str # 当前 Flow 名称
step_index: int # 执行到第几步
collected_slots: dict # 已收集的槽位
state: FrameState # ACTIVE / PAUSED / COMPLETED
一句话 :记忆层的核心价值是 "把记忆从 LLM 的上下文窗口解放出来"------Agent 的记忆是结构化的、分层的、可持久化的,不是聊天历史的一堆文字。
6. 安全层:Guard Node + 条件边
核心命题:Agent 的安全措施不能依赖 LLM 的"自觉",需要硬的工程化边界
6.1 技术栈
| 组件 | 选型 |
|---|---|
| 循环防护 | guard_node + max_actions 计数器 |
| 流程控制 | LangGraph add_conditional_edges(确定性条件边) |
| 限流 | action_count 运行时计数 |
| 异常回退 | try/except + ActionResult(success=False) 优雅降级 |
6.2 为什么不是"靠 LLM 自觉"?
# ❌ 错误做法:在 Prompt 里告诉 LLM "别死循环"
prompt = """
你是客服助手。
注意:不要无限循环,每个问题最多回答3次。
如果用户说结束,就结束。
"""
问题:
- LLM 可能忽略指令(越狱、prompt 注入)
- LLM 不知道"已经回答了 3 次"------它没有计数器
- LLM 的"结束"判断不可靠------用户说"再说几句"它可能就继续了
6.3 本框架的硬性安全边界
安全机制 1:Guard Node ------ 循环计数器
async def guard_node(state: MessageProcessingState) -> Dict[str, Any]:
"""保护节点:检查循环次数,超限强制终止"""
action_count = state.get("action_count", 0)
max_actions = state.get("max_actions", 10)
if action_count >= max_actions:
# 强制终止!不管 LLM 还想干嘛
logger.warning(
f"达到最大动作数限制 ({action_count}/{max_actions}),强制终止"
)
return {
"is_finished": True,
"error": f"达到最大动作数限制: {max_actions}",
}
return {} # 正常继续
安全机制 2:条件边 ------ 确定性路由
# 这条路由是 Python 代码,不是 LLM Prompt
# 它决定了"什么时候该结束"
def should_continue(state: Dict[str, Any]) -> Literal["policy", "response"]:
"""决定是继续循环还是结束"""
is_finished = state.get("is_finished", False)
action_count = state.get("action_count", 0)
max_actions = state.get("max_actions", 10)
# 条件1:任务完成
if is_finished:
return "response" # → 结束本轮
# 条件2:超步数限制
if action_count >= max_actions:
return "response" # → 强制结束
# 否则继续
return "policy" # → 回到规划层
安全机制 3:Action 级别的异常隔离
async def action_node(state):
try:
action = get_action(action_name)
if action is None:
# 动作不存在 → 优雅跳过,不崩溃
return {"current_action_result": ActionResult(success=False)}
result = await action.run(tracker, domain, **kwargs)
# 即使 Action 内部报错,也不会使整个 Agent 崩溃
except Exception as e:
logger.error(f"动作执行失败: {e}")
return {
"error": str(e),
"current_action_result": ActionResult(success=False),
# 继续执行,不会挂掉整个流程
}
6.4 多层安全体系
| 安全层 | 防护内容 | 实现方式 |
|---|---|---|
| 图级别 | 死循环 | guard_node + max_actions |
| 节点级别 | 节点崩溃 | try/except 包围每个节点逻辑 |
| 动作级别 | Action 异常 | 每个 Action 独立捕获异常 |
| 调用级别 | LLM 超时 | LLMClient 配置 timeout 参数 |
| 外部级别 | API 调用失败 | HTTP 请求 + 重试机制 |
一句话 :安全层的核心价值是 "让 Agent 的每一次执行都在可控范围内"------有计数器、有边界、有优雅降级,而不是"让 LLM 自己控制自己"。
7. 各层技术栈总览
| 架构层 | 核心技术 | 辅助技术 | 设计模式 |
|---|---|---|---|
| 编排层 | LangGraph | StateGraph / CompiledStateGraph | 图编排(DAG) |
| 感知层 | LangChain + 自定义 CommandParser | Pydantic / DashScope SDK | Strategy(策略模式) |
| 规划层 | PolicyEnsemble / YAML Flow | ruamel.yaml / pyyaml | Chain of Responsibility |
| 工具层 | Action 注册表 | importlib 动态加载 | Registry + Plugin |
| 记忆层 | DialogueStateTracker / DialogueStack | SQLAlchemy / Neo4j Driver | Memento + Stack |
| 安全层 | Guard Node / 条件边 | - | Guard (防御性编程) |
| 通信层 | FastAPI / uvicorn | python-socketio / WebSocket | Channel Adapter |
| 配置层 | YAML + ${ENV_VAR} 替换 | python-dotenv | Configuration Injection |
| 部署层 | pip install / setup.py | Click CLI | CLI Facade |
技术栈选择原则
选型决策树:
这个能力需要确定性吗?
├── 是 → 用 Python 代码(条件边、Guard、Action)
└── 否 → 用 LLM(命令生成、闲聊、知识检索)
│
▼
这个数据需要持久化吗?
├── 是 → TrackerStore / MySQL / Neo4j
└── 否 → 内存(LangGraph State / DialogueStack)
│
▼
这个配置需要用户修改吗?
├── 是 → YAML 配置(Domain / Flow / endpoints)
└── 否 → Python 常量(constants.py)
Copy
8. 延伸:通向 Multi-Agent 的架构基础
该框架的架构设计使其天然适合扩展为 Multi-Agent 系统。
8.1 当前架构已具备的条件
| 当前组件 | Multi-Agent 映射 | 改动量 |
|---|---|---|
PolicyEnsemble(多策略链式调用) |
→ Agent 路由分发器 | 小 |
DialogueStack(栈式 Flow 管理) |
→ 跨 Agent 调用栈 | 零 |
Action 注册表(工具查找) |
→ Agent 服务发现 | 小 |
TrackerStore(会话持久化) |
→ 全局会话存储 | 零 |
| YAML Flow 定义 | → Agent 间的通信协议 | 中 |
8.2 可能的 Multi-Agent 架构
┌─────────────────────────────┐
│ Supervisor Agent │
│ 意图识别 + 任务路由 │
│ (使用当前 PolicyEnsemble 机制) │
└──────────┬──────────────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ 订单 Agent │ │ 物流 Agent │ │ 售后 Agent │
│ │ │ │ │ │
│ 自身 Flow │ │ 自身 Flow │ │ 自身 Flow │
│ 自身 Action │ │ 自身 Action │ │ 自身 Action │
│ 自身 Domain │ │ 自身 Domain │ │ 自身 Domain │
│ 自身 Tracker │ │ 自身 Tracker │ │ 自身 Tracker │
└──────────────┘ └──────────────┘ └──────────────┘
8.3 架构优势总结
单一 Agent Multi-Agent
┌─────────────┐ ┌─────────────────────┐
│ Policy A │ │ Supervisor Policy │
│ Policy B │ → │ ├─ 订单子 Agent │
│ Action 1-N │ │ ├─ 物流子 Agent │
│ Tracker │ │ ├─ 售后子 Agent │
│ Store │ │ └─ 知识库子 Agent │
└─────────────┘ │ 全局 Store / 栈 │
└─────────────────────┘
改动: 结构不变,把"策略"和"Action"换成"子 Agent"
Copy
附录:关键文件索引
| 模块 | 核心文件 | 职责 |
|---|---|---|
| 图编排 | agent/graph/builder.py |
LangGraph 图构建 |
| 图状态 | agent/graph/state.py |
状态定义 |
| 条件边 | agent/graph/edges.py |
路由逻辑 |
| 感知节点 | agent/graph/nodes/understand.py |
LLM 命令生成 |
| 规划节点 | agent/graph/nodes/policy.py |
策略预测 |
| 工具节点 | agent/graph/nodes/action.py |
Action 执行 |
| 安全节点 | agent/graph/nodes/guard.py |
循环防护 |
| 响应节点 | agent/graph/nodes/response.py |
结果收集 |
| Agent 主类 | agent/agent.py |
Agent 生命周期管理 |
| Action 系统 | agent/actions.py |
注册表 + 内置动作 |
| 消息处理器 | agent/message_processor.py |
旧版(备用)处理器 |
| LLM 生成器 | dialogue_understanding/generator/llm_generator.py |
LLM 调用 + 命令解析 |
| 命令定义 | dialogue_understanding/commands/ |
所有命令类型 |
| 对话栈 | dialogue_understanding/stack/dialogue_stack.py |
Flow 嵌套管理 |
| 策略集成 | policies/policy_ensemble.py |
链式策略调用 |
| Flow 策略 | policies/flow_policy.py |
业务流程推进 |
| 知识策略 | policies/enterprise_search_policy.py |
RAG 检索决策 |
| Tracker | core/tracker.py |
会话状态追踪 |
| 存储 | core/stores/ |
持久化存储 |
| 配置 | shared/config.py |
全量配置加载 |
| LLM 客户端 | shared/llm/ |
多模型客户端抽象 |
| 电商 Demo | ecs_demo/ |
完整电商客服示例 |