跳转至

指南 01 · 条件分支与分类路由

Agent 最常见的需求就是「按情况走不同分支」。本章覆盖两条路径:

  1. 规则判定 IfElse:写代码做条件判断(转人工?金额够不够?)。
  2. 模型分类 QuestionClassify:让模型把用户问题归到预定义类别,再分流。

两者都产出路由键 branch,配合 add_conditional_edge 做多路分发。

1. IfElse 条件判定

1.1 二分支(bool)

IfElsecondition 返回 bool,条件边按 True/False 二选一。

from agentframework import Workflow
from agentframework.nodes import Answer, ChatLLM, IfElse

wf = Workflow(name="demo_binary")
wf.add_node(ChatLLM(name="llm", chat_model=model, output=False))
# left: 把上游 llm.reply 作为「待判断值」传进来供 condition 读取
wf.add_node(
    IfElse(
        name="judge",
        left=wf.ref("llm.reply"),
        condition=lambda inputs, ctx: "转人工" in str(inputs["left"]),
    )
)
wf.add_node(Answer(name="handoff", text="好的,为您转人工客服"))
wf.add_node(Answer(name="auto", text="已为您自动处理"))
wf.add_edge("llm", "judge")
wf.add_conditional_edge("judge", {True: "handoff", False: "auto"})

condition(inputs, ctx) -> 分支值 的可调用对象,可读 inputs["left"],也能读 ctx.variables(如判断 ctx.variables["flag"])。

1.2 多分支(str / 任意可哈希值)

condition 返回 str(或任意可哈希值),条件边查表路由。

wf.add_node(
    IfElse(
        name="cls",
        left=wf.ref("llm.reply"),
        condition=lambda inputs, ctx: "投诉" if "投诉" in str(inputs["left"]) else "其他",
    )
)
wf.add_conditional_edge("cls", {"投诉": "complaint", "其他": "default"})

1.3 condition 的三种形态

形态 说明 典型
可调用对象 (inputs, ctx) -> 分支值,最灵活,可读 ctx.variables 上面两个例子
常量 / 引用 condition 取某输入或 wf.ref 到某节点输出 由上游算好的布尔/值
缺失 ValueError

1.4 进阶:把 IfElse 当「纯计算节点」

IfElse 不一定要用于路由——它的 branch 输出也可被下游 wf.ref数据引用(读取而不路由)。例如在完整案例里,用无 LLM 的纯函数节点做「取最后 user 文本」「读变量」「解析响应」「成败判定」,作为联合路由的输入。这种用法让流程逻辑完全可测、不烧模型:

# 例:判定第三方接口调用是否成功
wf.add_node(
    IfElse(
        name="http_ok",
        left=wf.ref("http.json"),
        condition=lambda inputs, ctx: dict(inputs["left"]).get("code") == "FBASE0000",
    )
)

# 例:读控制变量
wf.add_node(
    IfElse(
        name="flag_value",
        left=None,
        condition=lambda inputs, ctx: str(ctx.variables.get("flag")),
    )
)

这样把「判定逻辑」沉淀为可单测的节点,是复杂状态机的推荐做法。完整源码见 withdrawal_customer_service 示例

2. QuestionClassify 模型分类

给模型一组类别,让它把当前问题归到其中一类;未命中归为 "其他"。输出 branch(=命中类别名)稳定匹配条件边。

from agentframework.nodes import QuestionClassify

wf.add_node(
    QuestionClassify(
        name="cls",
        chat_model=model,  # LLM 客户端(可注入 mock)
        categories=[
            {"name": "退款", "description": "用户要求退款/退货"},
            {"name": "物流", "description": "查询快递进度"},
        ],
        description="判断用户意图",  # 可选,默认「判断用户的意图」
        query=wf.ref("input"),  # 待分类问题
    )
)
wf.add_conditional_edge("cls", {"退款": "refund", "物流": "logistics", "其他": "default"})

要点:

  • 输入 query(必填,待分类问题)、history(可选)。
  • 输出 branch / category(命中类别名)、confidence(置信度,占位 1.0)。
  • 框架做确定性匹配(规范化 → 精确 → 双向包含 → 兜底 "其他"),保证 branch 不会因模型输出抖动而对不上条件边 key。
  • 必填 chat_modelcategories,缺失抛 ValueError

3. 把路由接到分支工作流

两种节点都产出 branch,路由写法一致:

# 规则 or 分类二选一作为判据源
wf.add_node(IfElse(name="judge", ...))            # 或 QuestionClassify(name="cls", ...)
wf.add_node(Answer(name="refund", text="正在为您处理退款"))
wf.add_node(Answer(name="logistics", text="您的快递正在派送"))
wf.add_node(Answer(name="default", text="转人工"))

wf.add_conditional_edge("judge", {True: "refund", False: "logistics"})  # 示例,按需改
# 或分类版:
wf.add_conditional_edge("cls", {"退款": "refund", "物流": "logistics", "其他": "default"})

4. 完整可运行示例

下一步