04 · Agent/User 变体、领域与语音知识扩展
本章把「参赛选手」和「赛场」讲全,最后给巧妙之处、边界、横向对比与总代码地图。
4.1 三种 Agent,各测一件事
都在 llm_agent.py,共享「读策略 → 调工具/回话」的骨架,区别在拿到多少信息:
| Agent | 拿到什么 | 测什么 |
|---|---|---|
LLMAgent(llm_agent.py:54) | 只有领域策略 + 工具 | 正常被考对象:真本事 |
LLMGTAgent(llm_agent.py:166) | 策略 + 工具 + 标准答案步骤 | 「答案喂到嘴边还能不能做对」——主要用来验 user 模拟器是否正常 |
LLMSoloAgent(llm_agent.py:321) | 策略 + 工具 + ticket 工单,无用户 | 纯执行力:给足信息自己把库改对 |
LLMSoloAgent 有两个专属机关:tool_choice="required" 强制每步必出工具调用(llm_agent.py:473),以及一个注入进去的 done 工具——调它就返回 ###STOP### 收工(llm_agent.py:357-364、426-431)。
4.2 User 模拟器:LLM 反串顾客
UserSimulator(user_simulator.py:99)是个「角色对调」的 LLM 调用。它的系统提示 = 全局模拟守则 + 该任务的 user_scenario(顾客剧本),生成时把对话里的 assistant/user 角色翻转(flip_roles),让模型站在顾客立场说话(user_simulator.py:232)。若领域给了用户工具,它也能发工具调用,框架再把 requestor 翻成 "user"(user_simulator.py:255-265)。
顾客行为由三处叠加控制,源码特意提醒三者要一致不重叠(user_simulator.py:104-110):全局守则(data/tau2/user_simulator/*.md)、任务里烤进去的 persona、运行时 persona_config。
4.3 五个领域一览
| 领域 | 场景 | 特点 |
|---|---|---|
mock | 开发测试 用 | 最小双控(含用户通知箱工具) |
airline | 订票/退改签 | 经典单控,策略约束多 |
retail | 订单/退货 | 经典单控 |
telecom | 宽带/话费排障 | 双控标杆:sync_tools 把用户设备与账户 DB 耦合(见 01 章) |
banking_knowledge | 知识型银行客服 | τ³ 新增:靠检索文档答题 |
telecom 还有个花样:同一环境可挂两种技术支持策略——manual(自然语言步骤)和 workflow(结构化流程),分别注册成 telecom 和 telecom-workflow(telecom/environment.py:96-150、registry.py:330-345),用来对比「策略写法」对 Agent 的影响。
4.4 τ³ 扩展一:语音全双工(Tick 轨迹)
文本模式是回合制——你说完我说。语音客服不是:两边可以同时出声、可以打断。为此 τ³ 换了套轨迹单位——不再是一条条 Message,而是一格格 Tick(message.py:636)。
一个 Tick = 某个极短时间片(如 50ms)里同时发生的一切:Agent 说了什么 chunk、User 说了什么 chunk、双方各自的工具调用与结果(message.py:656-664)。评测时再把 Tick 序列线性化回消息去比 DB、比沟通(evaluator_env.py:168 的 ticks_to_message_history),所以 03 章那套打分逻辑对语音同样适用——只是喂进去的轨迹形态不同。全双工由 FullDuplexOrchestrator(orchestrator/full_duplex_orchestrator.py)驱动,评测器也各有 FullDuplex* 对应类。
4.5 τ³ 扩展二:banking_knowledge 检索
这个领域和别的最不同:答对题不光靠调 API,还得从 700+ 文档里检索出正确依据。它有两套数据源(交易 DB + 知识库),可配置检索管线(--retrieval-config,如纯 grep、嵌入向量、终端沙箱),且大量用 @is_discoverable_tool——工具藏在文档里,Agent 得先「读到」才能用(domains/README.md:71-78)。检索栈在 src/tau2/knowledge/。
4.6 装配总线:registry
所有部件用名字挂到一张全局表 registry(registry.py:70)上:领域、Agent 工厂、User 类、任务集各一栏。命令行 --domain airline --agent-llm ... 本质就是拿名字去表里取构造器,再由 runner 分层组装成一个 Orchestrator(run.py 委托 tau2.runner 的 build 层)。想加自己的领域/Agent,就是往这张表里 register_* 一笔。
4.7 巧妙之处(可借鉴的技术)
- 只比终态、不比过程。 用整库哈希做终态指纹(toolkit.py:242),天然容忍「殊途同归」的多种解法,避免过拟合某条黄金路径。评测哲学层面的关键取舍。
- 答案即参考轨迹,终态现推。 出题人只给一种解法,gold 环境重放它自动得出正确终态(evaluator_env.py:99-105)——出题成本低、且和 DB 比对逻辑复用同一套
set_state。 - 重放区分 mutates_state。 读/think 类工具重放时跳过,既省事又躲开非确定输出的比对陷阱(environment.py:373-377 + toolkit.py:82-83)。
- 乘法奖励门。 任何选中维度不达标即全题 0 分(evaluator.py:215-248),精准表达客服「不能有硬伤」的验收标准。
- pass^k 抗噪。 用组合数比值把「碰运气过」和「真会」分开(agent_metrics.py:113)。
- 双控状态耦合。 telecom 用每步
sync_tools让两个控制者共享一个物理一致的世界(telecom/environment.py:39),把「指挥用户动手」变成可评测的真任务。
4.8 边界与局限(诚实)
- 沟通检查很脆。 子串匹配、去逗号小写化,改个措辞或单位就可能误判,源码自标 TODO(evaluator_communicate.py:69)。
- NL 断言实验性。 LLM 当裁判本身有噪声与成本,默认不进
reward_basis(tasks.py:415-425 标 WIP)。 - DB 哈希是全有全无。 终态差一个字段就 0 分,不给「改对了 8 成」的部分分(DB 维度层面);细粒度看得靠 action_checks 的诊断信息。
- 重放依赖确定性。 工具输出若不确定(如带真实时间戳),重放核对会抛错;领域工具必须写成可复现的。
- 成本与依赖。 每通电话是多次 LLM 调用(Agent+User,语音还要 realtime API),跑全量不便宜;语音/知识扩展还需额外系统依赖(portaudio/ffmpeg、嵌入模型)。
4.9 横向对比(同 shelf 的 evals-observability 兄弟)
tau2-bench 在「评测类」项目里的独特站位:
| 维度 | tau2-bench | 一般 LLM eval 框架 |
|---|---|---|
| 评什么 | 多轮交互式客服任务 | 多为单轮问答/分类正确率 |
| 打分依据 | 环境终态哈希(副作用) | 多为输出文本匹配/打分 |
| 用户 | LLM 动态扮演、会挂电话 | 通常静态数据集 |
| 独门 | 双控(agent+user 共改环境) | 少见 |
| 稳定性 | pass^k 重复全对率 | 多为单次准确率 |
一句话:多数 eval 在测「模型说得对不对」,tau2-bench 在测「模型带着人把事办成没办成」。
4.10 总代码地图
| 主题 | 文件 | 符号名 |
|---|---|---|
| 普通 Agent | src/tau2/agent/llm_agent.py | LLMAgent |
| 作弊 GT Agent | src/tau2/agent/llm_agent.py | LLMGTAgent |
| solo Agent | src/tau2/agent/llm_agent.py | LLMSoloAgent |
| 用户模拟器 | src/tau2/user/user_simulator.py | UserSimulator |
| 占位空用户 | src/tau2/user/user_simulator.py | DummyUser |
| 停止哨兵串 | src/tau2/user/user_simulator_base.py | STOP / TRANSFER / OUT_OF_SCOPE |
| 全局装配表 | src/tau2/registry.py | Registry |
| 运行入口(facade) | src/tau2/run.py | run_domain / run_single_task |
| 语音全双工引擎 | src/tau2/orchestrator/full_duplex_orchestrator.py | FullDuplexOrchestrator |
| 语音轨迹单位 | src/tau2/data_model/message.py | Tick |
| 双控范例领域 | src/tau2/domains/telecom/environment.py | TelecomEnvironment |
| 知识检索栈 | src/tau2/knowledge/ | pipeline.py / retrievers/ |