一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

LangGraph 主流程解析:分类路由与确认闸门

时间:2026-09-20 12:38:01 编辑:袖梨 来源:一聚教程网

在带宽销售客服中,真正危险的往往不是回答不够流畅,而是流程在信息不足或用户尚未确认时提前进入推荐。要稳定控制这类多轮对话,不能只依赖提示词判断,还需要把业务约束写进状态和路由。下面从 LangGraph 主图出发,拆解分类分流、条件边与确认闸门的具体配合方式。

LangGraph 主图:分类分流与确认闸门

做带宽销售客服最容易翻车的,不是模型不会说话,而是意图混在一起还急着推产品:用户刚问,系统已经甩一堆卡片;金额期限用途还没齐,推荐理由却写得像成交了。缺字段就推、未确认就推,信任会先垮掉。

公开仓库 langgraph_fly_base 的解法不是「再写一个更大的 Prompt」,而是把主链路收成一张 LangGraph 主图FlowState 显式记账,分类分流后用条件边把闸门卡住——信息未齐、未确认时,路由强制停在收集与确认,进不了推荐。

本文只讲主图编排:问题分类、条件边、确认闸门。双库 TopN 推荐细节留给后续文章,这里只点到「确认通过后进推荐子图」。

封面:LangGraph 主图分类分流与确认闸门

依据仅限公开仓库 README 与源码;下文会把「已实现 / 半成品 / 未来」分开写,并给出文件证据。


一、主图全景:入口固定,分流靠条件边

入口不是分类,而是 问题修复 → 问题分类build_flow_graphset_entry_point(FIX),再 add_edge(FIX, CLASSIFY),保证每轮先过修复节点,再进分类总闸。

架构:主图节点与闸门字段

对应节点(sale_app/core/mutil/node_names.py):

常量中文节点名角色
FIX问题修复改写 / 规范用户问题
CLASSIFY问题分类五类分流总闸
CHAT闲聊经理非业务闲聊
INTENT意图确认是否有带宽意向
GATHER信息收集四项信息多轮补齐
CONFIRM信息确认摘要 + 确认闸门
RECOMMEND产品推荐推荐子图挂载点
QA产品解答专家知识库 RAG
CONVERSION客户转化推荐后留资 / 预约

中文标签流程图如下(与 flow_graph.py 边一致):

主流程图:修复→分类→分流与确认闸门

flowchart TD
  START([用户提问]) --> FIX[问题修复]
  FIX --> CLASSIFY[问题分类]

  CLASSIFY -->|decide_router| CHAT[闲聊经理]
  CLASSIFY -->|decide_router| QA[产品解答专家]
  CLASSIFY -->|decide_router| INTENT[意图确认]
  CLASSIFY -->|decide_router| GATHER[信息收集]
  CLASSIFY -->|decide_router| CONFIRM[信息确认]
  CLASSIFY -->|decide_router| RECOMMEND[产品推荐]
  CLASSIFY -->|decide_router| CONVERSION[客户转化]

  INTENT -->|有意向| GATHER
  INTENT -->|无意向| CHAT

  GATHER -->|information_router 未齐或本轮结束| END1([本轮结束])
  GATHER -->|四项齐且需推荐| CONFIRM

  CONFIRM -->|confirm_router 未确认| END2([本轮结束等确认])
  CONFIRM -->|已确认 isInfoConfirmed| RECOMMEND

  CHAT --> END3([结束])
  QA --> END4([结束])
  RECOMMEND --> END5([结束])
  CONVERSION --> END6([结束])

要点有三:

  1. 分类后不是直接信 LLM 的 next,而是过 decide_router 再改写目标节点。
  2. 收集齐了也不直接推荐information_router 先送进确认。
  3. confirm_router 只有 isInfoConfirmed 为真才进推荐,否则本轮 END,等用户下一句。

二、FlowState:闸门靠状态字段,不靠 Prompt 自觉

主图状态在 sale_app/core/mutil/flow_graph.pyFlowState

class FlowState(TypedDict):
    messages: Annotated[List[BaseMessage], operator.add]
    next: str
    pre_node: str
    question: str
    fixed_question: str
    history: list
    information_sequences: Annotated[list, operator.add]
    product_list: list
    isRecommend: bool
    isInfoConfirmed: bool
    awaiting_info_confirm: bool
    info_summary: str
    awaiting_conversion: bool
    conversion_completed: bool

和「闸门」直接相关的字段:

字段作用
information_sequences已收集序号;满 4 项才算齐(collection_utils.is_collection_complete
awaiting_info_confirm已出摘要,正在等用户确认或修改
isInfoConfirmed确认通过;confirm_router 看它放行推荐
info_summary给用户看的摘要文本
product_list / isRecommend推荐结果与推荐意图标记
awaiting_conversion / conversion_completed推荐后转化阶段

多轮续跑靠 SQLite Checkpointstartup_chainAsyncSqliteSaver.from_conn_string(...),路径落在 storage/memory_file/ch@t_history.db,图 compile(checkpointer=_checkpointer)。同一 session_id 进来时,闸门位不会丢——这是条件边能「卡住」的前提。


三、问题分类:五类 + 规则快路径 + JSON 兜底

分类成员在构图时写死(flow_graph.py):

信息收集 / 闲聊经理 / 意图确认 / 产品推荐 / 产品解答专家

链路是:

  1. suggest_category_from_stateclassify_utils.py):能规则定就直接返回,跳过分类 LLM。例如已推过产品且像转化 → 客户转化;正在等确认 → 信息确认;等转化未完成 → 客户转化
  2. 否则走 question_class_funcquestion_class_node.py):拼历史(QUESTION_CLASS_HISTORY_TURNS)+ 当前问题 + 类别列表,调 LLM。
  3. parse_category_name:先剥 markdown 代码块,再 json.loadscategory_name;解析失败则在原文里扫合法类名;再不行用 fallback_category

fallback_category 同样看闸门:等确认、收集未齐、推荐后转化 / QA,避免分类抽风把流程打乱。README 里也提示可用 QUESTION_CLASS_FEW_SHOTLLM_ENABLE_REASONING=false 给分类提速——分类是简单结构化输出,没必要开长思考。


四、条件边三件套:decide / information / confirm

三个 router 都在 sale_app/core/mutil/flow_routers.py。这是主图的「硬逻辑」,比 Prompt 自觉可靠。

1. decide_router:分类后总闸

分类节点只写出 state["next"],真正去哪由 decide_router 决定。典型规则:

  • 已经推荐过has_recommended):转化意图 → 客户转化;产品问答关键词 → 产品解答专家;若分类仍想回收集 / 确认 / 推荐 → 也倾向转化,避免推完又绕回推销。
  • 未确认信息awaiting_info_confirm 或上一节点是确认 → 强制回 信息确认
  • 分类想去推荐但未确认:收集已齐 → 改送 信息确认;上一节点还在收集 → 继续 信息收集;否则才允许 产品推荐
  • 分类想去收集:若已推过 → 转转化;否则进收集。

一句话:LLM 可以猜错下一跳,router 会把人拦回正确阶段。

2. information_router:收集齐了先确认,否则本轮结束

已确认或已推荐 → FINISH(END)
isRecommend 且四项齐 → 信息确认
否则 → FINISH(等用户下一轮继续填)

收集节点可以多轮说话,但齐了也不直连推荐,必须过确认门。

3. confirm_router:确认位为真才进推荐

isInfoConfirmed → 产品推荐
否则 → FINISH

这就是「确认闸门」的最后一扇门:摘要发出去、用户还没说确认时,图直接结束本轮;下一轮分类 / decide 会因 awaiting_info_confirm 再次落到确认节点。

推荐发生在确认之后——双库并行、TopN 合并去重是推荐子图的事,本文不展开,排期另文。


五、信息确认节点:关键词「确认」vs 修改(诚实权衡)

实现见 sale_app/core/agent/information_confirm.py

从收集刚进入pre_node == 信息收集 且尚未 awaiting):调摘要链,写出汇总,并设:

  • awaiting_info_confirm=True
  • isInfoConfirmed=False
  • info_summary=...(末尾提示回复「确认」或说明修改)

用户回复阶段

判定关键词示例状态回写
确认确认、没问题、正确、对的、可以、是的、好的、ok、yesisInfoConfirmed=Trueawaiting_info_confirm=False
修改改、修改、不对、错了、更正、补充、换成、应该是重生成摘要,继续 awaiting
其它提示再确认,闸门仍关

这里要说清楚权衡:确认是半规则关键词,不是完整 NLU。优点是稳、快、可测;缺点是「嗯可以吧再看看」这类软同意可能判不准,复杂纠错也依赖摘要 LLM。对带宽场景,「明确确认才推」比「模型觉得可以就推」更安全,所以仓库选择了关键词闸门。

确认通过后,confirm_router 放行到 产品推荐 节点;该节点挂的是 build_recommend_graph(llm).compile() 子图——主图只负责「何时能进」,子图负责「怎么推」。


六、SSE:哪些节点吐 token,哪些整段推

公开代码里流式能力是齐的:

  • HTTP:POST /api/ch@t/streamapp/routers/[email protected])→ StreamingResponse,事件 meta / 业务 item / done / error
  • 图侧:astream_flowflow_graph.py)基于 chain.astream_events(..., version="v2")

可见性策略:

集合节点行为
STREAM_TOKEN_NODES闲聊经理、产品解答专家、产品推荐on_ch@t_model_stream 逐 token
STRUCTURED_REPLY_NODES信息收集、信息确认、客户转化节点结束时整段推 token
TRACKED_WORKFLOW_NODES含修复、分类及业务节点step_start / step_end / progress

_is_graph_node_chain_event 还会过滤:事件名必须等于 langgraph_node、非 hidden、非子图内部任务——聊天页「执行过程面板」才不会被内部 Runnable 刷屏。


七、状态表:已实现 / 半成品 / 未来

状态内容公开证据
已实现主图节点与边;FIX→CLASSIFY;五类分类;三 router;确认闸门;意图→收集;SQLite Checkpoint;SSE step / tokenflow_graph.pyflow_routers.pyinformation_confirm.pyapp/routers/[email protected];README 更新日志 2026-09-04
半成品 / 权衡确认靠关键词非 NLU;分类依赖 LLM JSON + 启发式兜底;推荐后路由大量短语规则(转化 / QA)information_confirm.py 关键词表;classify_utils.pyPRODUCT_QA_KEYWORDS / CONVERSION_PHRASES
未来 / 另文双库 TopN 并行检索、合并去重深挖(排期约 9/26);Milvus 稠密 + SPLADE 混合检索细节README「推荐系统」节;本文只点到确认后进推荐子图

不要把「仓库里已有推荐子图」理解成「本文已经讲透双库」——主图闸门和推荐检索是两层问题。


八、本地短复现

环境变量至少配好 LLM_API_KEY(或 ZHIPU_API_KEY),可参考 README。

Docker(推荐)

cp .env.example .env
docker compose up -d --build
# 聊天:http://127.0.0.1:8182/api/ch@t
# 健康:http://127.0.0.1:8182/health

本地 uvicorn

pip install -r requirements.txt
uvicorn app.main:app --reload --host 127.0.0.1 --port 8000

建议在聊天页走通一条闭环(不必盯双库细节):

  1. 表达带宽意向 → 进入意图 / 收集
  2. 补齐金额、期限、用途、资质等四项
  3. 看摘要,回复「确认」
  4. 观察执行过程面板出现 信息确认 → 产品推荐(闸门打开)

若升级 LangGraph 1.x 后状态怪异,README 建议清理旧 checkpoint:storage/memory_file/ch@t_history.db


九、小结

销售客服主图的核心不是「分类模型有多聪明」,而是:

  1. FlowState 把闸门做成布尔位与摘要,多轮靠 SQLite Checkpoint 续上。
  2. 分类可以猜,决定权在 decide_router / information_router / confirm_router
  3. 确认节点用关键词半规则换稳定性;未确认则本轮 END,绝不偷渡推荐。

下一篇会专门拆 双库并行 TopN 推荐recommend_product 与默认 KB 如何并行召回、合并去重——那是确认闸门打开之后的故事。

项目地址(欢迎 Star / Issue):

github.com/liuyanqun08…

相关专栏:大模型学习记录

热门栏目