news 2026/9/10 7:48:55

deepagents 航空客服策略文档(policy.md)全解析:tau2 Airline 评测中的规则约束与执行细节

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
deepagents 航空客服策略文档(policy.md)全解析:tau2 Airline 评测中的规则约束与执行细节

deepagents 航空客服策略文档(policy.md)全解析:tau2 Airline 评测中的规则约束与执行细节

【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents

本文以 libs/evals/tests/evals/tau2_airline/data/policy.md 为绝对主线,逐节拆解这份"航空客服 Agent 业务策略"。它定义了 Agent 在 book(订票)、modify(改签)、cancel(取消)与 refunds/compensation(退款与补偿)四类场景下的全部行为边界,同时结合同目录下的 domain.py、evaluation.py、test_tau2_airline.py 等源码,说明该策略如何被装载进 deepagents 系统提示词、被 14 个 LangChain 工具调用链执行、并被 DB 状态比对 + 沟通信息检查双维度打分。读完本文,你将完整掌握这份策略文档的规则矩阵、其与底层工具实现的对应关系,以及 tau2 评测的判定机制。

一、策略文档在评测体系中的定位

在 deepagents 仓库中,这份 policy.md 并非普通的产品说明,而是 libs/evals/tests/evals/tau2_airline 评测模块的"规则引擎"。它由 domain.py 中的load_policy()函数直接读取并原样注入 Agent 系统提示词:

def load_policy() -> str: """Load the airline customer service policy.""" with (_DATA_DIR / "policy.md").open() as fp: return fp.read()

真正的注入发生在 test_tau2_airline.py 的测试夹具中:AGENT_SYSTEM_PROMPT模板把整个策略放进<policy>...</policy>标签内,通过create_deep_agent构建带 checkpointer 的 deepagents 图:

AGENT_SYSTEM_PROMPT = """\ You are a customer service agent that helps the user according to the <policy> provided below. Use the available tools to look up information, verify customer identity, and take actions. Always follow the policy. Be helpful, concise, and accurate. <policy> {domain_policy} </policy>\ """ agent = create_deep_agent( model=model, tools=tools, system_prompt=AGENT_SYSTEM_PROMPT.format(domain_policy=policy), checkpointer=MemorySaver(), )

该模块源自 Sierra Research 的 τ-bench / τ²-bench / τ³-bench(MIT License,见目录内 LICENSE),是验证"Agent 能否在复杂业务规则约束下合规工作"的标准场景。策略文档设置了固定的模拟时间2024-05-15 15:00:00 EST,这与 domain.py 中_CURRENT_DATETIME = "2024-05-15T15:00:00"保持一致,保证"24 小时取消窗口""已起飞航班"等时间敏感规则可判定。

二、全局行为准则:所有动作的第一道门槛

policy.md 开头部分是适用于全部场景的通用规则,也是评测中最容易被扣分的"隐性红线":

准则原文要点实现印证
先确认再执行任何会更新预订数据库的动作(订票、改航班、改行李、改舱位、改乘客信息)必须先列明动作细节并取得用户明确的 yes对应book_reservationupdate_reservation_flights等工具的入参均为"用户确认后一次性提交"的设计
不越界输出不得提供用户或工具之外的信息、知识、流程,不得给出主观建议对应 user_sim.py 中模拟用户"不编造场景外信息"的对称约束
一次只做一件事一次只能调用一个工具;调用工具时不得同时回复用户对应run_multi_turn单轮单次run_agent的驱动方式
拒绝违规请求对违反本策略的请求必须拒绝大量测试任务的nl_assertions就是检查"Agent 是否拒绝"
转人工仅当请求超出自身动作范围时才转人工;先调用transfer_to_human_agents,再发送固定话术YOU ARE BEING TRANSFERRED TO A HUMAN AGENT. PLEASE HOLD ON.domain.py 中transfer_to_human_agents(summary)工具,以及 user_sim.py 中###TRANSFER###终止令牌与之呼应

从源码结构看,transfer_to_human_agents是 14 个工具中唯一一个"结束会话"性质的出口;用户模拟器识别到转人工时输出###TRANSFER###令牌,双方通过这一协议完成场景收束。

三、领域基础知识:User、Flight、Reservation 三个数据模型

策略文档紧接着定义了评测世界的三个核心实体,这些实体在 domain.py 中被建模为 Pydantic 模型,并最终由db.json(见 libs/evals/tests/evals/tau2_airline/data/db.json)装载:

User(用户)

每个用户包含:user id、email、地址、出生日期、支付方式、会员等级、预订号列表。两类枚举值是策略计算的关键:

  • 支付方式三种:credit card(信用卡)、gift card(礼品卡)、travel certificate(旅行凭证)。
  • 会员等级三种:regular、silver、gold——直接决定免费托运行李额度(见下文"行李配额矩阵")。

对应源码User模型:payment_methods: dict[str, PaymentMethod](PaymentMethod 是 CreditCard | GiftCard | Certificate 的联合类型),membership: MembershipLevel

Flight(航班)

航班属性:航班号、出发地、目的地、计划起飞/到达时间(均为当地时间)。同一航班在多个日期各有状态:

  • available:未起飞,可订,列出各舱位余座与价格;
  • delayed / on time:未起飞但不可预订
  • flying:已起飞未落地,不可预订;
  • 另有 landed、cancelled 状态(见 domain.py 的FlightDateStatus联合类型)。

舱位三种:basic economy(基础经济舱,独立于 economy)、economybusiness。余座与价格按舱位分别列出。

源码中的_search_direct_flights正是按此实现筛选逻辑:if flight.dates[date].status != "available": continue,即只有 available 状态才进入可订结果集。

Reservation(预订)

每个预订包含:reservation id、user id、trip type(行程类型)、flights、passengers、payment methods、created time(创建时间)、baggages、travel insurance information(旅行保险信息)。

  • 行程类型两种:one way(单程)、round trip(往返)。
  • 对应源码Reservation模型字段:flight_typecabinflightspassengerspayment_historycreated_attotal_baggagesnonfree_baggagesinsurancestatus

四、Book flight(订票):策略最密集的业务流

订票流程是策略文档中规则最密集的部分,Agent 必须按顺序采集信息并严格遵守约束。policy.md 的规定与 domain.py 中book_reservation工具的输入校验一一对应。

信息采集顺序

  1. 首先必须取得user id
  2. 然后询问trip type、origin(出发地)、destination(目的地)
  3. 依次确认舱位、乘客、支付方式、托运行李、旅行保险。

对应book_reservation的完整入参 schema(BookReservationInput):user_id, origin, destination, flight_type, cabin, flights, passengers, payment_methods, total_baggages, nonfree_baggages, insurance

舱位约束

  • 同一预订内所有航班舱位必须一致(源码中Reservation.cabin是单一字段,天然保证这一点)。

乘客约束

  • 每个预订最多 5 名乘客
  • 需收集每位乘客的 first name、last name、date of birth(对应Passenger模型的 first_name/last_name/dob);
  • 所有乘客必须乘坐相同的航班、相同的舱位(源码按len(parsed_passengers)统一计算座位与价格)。

支付约束

  • 每个预订最多 1 张旅行凭证 + 1 张信用卡 + 3 张礼品卡
  • 旅行凭证的剩余金额不可退款(源码中证书扣款后直接user.payment_methods.pop(pm.payment_id)移除,不会找零);
  • 出于安全考虑,所有支付方式必须已存在于用户档案中(源码逐一校验pm.payment_id not in user.payment_methods即报错)。

免费托运行李配额矩阵(核心表格,务必完整继承)

配额由订票用户的会员等级×每位乘客的舱位共同决定:

订票用户会员等级basic economy 乘客economy 乘客business 乘客
regular0 件1 件2 件
silver1 件2 件3 件
gold2 件3 件4 件
  • 超出免费额度的每件行李 50 美元(源码total_price += 50 * nonfree_baggages与此一致);
  • 不得添加用户不需要的托运行李——这是典型"过度服务"陷阱,评测中会通过nl_assertions检查。

旅行保险

  • Agent必须主动询问用户是否购买旅行保险;
  • 每人 30 美元;购买后若因健康或天气原因取消航班可全额退款(源码total_price += 30 * len(parsed_passengers)按乘客数计费)。

五、Modify flight(改签):分段规则与"API 不检查"陷阱

改签场景首先要求取得user id 与 reservation id:用户必须提供 user id;若用户不知道 reservation id,Agent 应使用工具协助定位(get_user_details返回用户的预订列表)。

改航班(Change flights)

  • basic economy 航班不可改签
  • 其他预订可改签,但不得改变 origin、destination、trip type
  • 部分航段可以保留,但保留航段的价格不会按当前价格更新(源码update_reservation_flightsexisting逻辑:保留航段沿用existing.price);
  • 关键警告:API 不会替 Agent 校验这些规则,"so the agent must make sure the rules apply before calling the API"——即策略合规是 Agent 自身的责任,这正是评测的核心考察点。

对应工具为update_reservation_flights(reservation_id, cabin, flights, payment_id),其参数描述明确要求"All flight segments must be included (even unchanged ones)"(改签时必须提交全部航段,含未改动的)。

改舱位(Change cabin)

  • 若预订中任一航班已起飞,则不能改舱位;
  • 其他情况(含 basic economy 预订)可在不改变航班的前提下改舱位;
  • 同一预订内所有航段舱位必须一致,不能只改某一个航段
  • 改后价格更高 → 用户需补差价;改后价格更低 → 用户应获得差额退款。

改行李与保险(Change baggage and insurance)

  • 行李只能增加不能减少
  • 预订创建后不能再添加保险

改乘客(Change passengers)

  • 可以修改乘客信息,但不能修改乘客数量
  • 策略明确强调"Even a human agent cannot modify the number of passengers"——源码update_reservation_passengersif len(parsed) != len(reservation.passengers): raise ToolException("Number of passengers does not match")硬性校验了这一点。

支付

  • 若航班被更改,用户需提供一张礼品卡或信用卡作为支付/退款方式,且必须已在用户档案中(源码_payment_for_update同时拒绝证书:"Certificate cannot be used to update reservation")。

六、Cancel flight(取消):四种合法理由与转人工边界

取消场景同样要求 user id + reservation id(未知则用工具定位),且必须取得取消原因(change of plan、airline cancelled flight、other)。

硬性边界

  • 若航班任何部分已经起飞,Agent 无法处理,必须转人工

四种可取消条件(满足任一即可)

  1. 预订发生在最近 24 小时内
  2. 航班被航空公司取消
  3. business 舱位的预订;
  4. 用户购买了旅行保险且取消原因在保险覆盖范围内(健康或天气原因)。

同样有"API 不检查"警告:cancel_reservation工具本身不做策略判断,Agent 必须在调用前自行核对规则。

退款

  • 退款将在5 至 7 个工作日内原路退回(源码cancel_reservationpayment_history追加等额负值退款记录,即按原支付方式冲销)。

七、Refunds and Compensation(退款与补偿):谨慎授予的证书逻辑

补偿场景是"防滥用"设计的典型,策略强调不主动提出补偿补偿前必须核实事实

  • 不主动提供补偿,除非用户明确要求;
  • 不向"regular 会员 + 无保险 + 乘坐(基础)经济舱"的用户补偿
  • 补偿前总是先确认事实
  • 仅当用户是 silver/gold 会员,或购买了保险,或乘坐 business 舱位时才可补偿。

两种允许的补偿(均为 certificate 证书形式,对应send_certificate(user_id, amount)工具):

场景前提金额
预订中航班被取消且用户投诉核实事实后$100 × 乘客数
预订中航班延误且用户投诉并要求改签/取消核实事实并完成改签/取消后$50 × 乘客数
  • 除上述理由外,不得因任何其他理由提供补偿

八、从策略到评测:DB + COMMUNICATE 双重打分机制

策略合规与否如何被机器判定?evaluation.py 实现了 τ-bench 风格的评估管线,evaluate_task的最终奖励为:

reward = db_score * communicate_score

DB 检查(db_score)

check_db_state将任务定义的期望动作(evaluation_criteria.actions)在一个全新数据库上重放(_replay_expected_actions),再用_hash_db对"重放后的期望库"与"真实对话后的实际库"计算 SHA-256 规范化哈希,二者一致得 1.0,否则 0.0。不一致时通过_diff_db输出逐字段 diff。也就是说:Agent 是否准确、无多余动作地执行了预订/改签/取消,最终落在数据库状态上

沟通检查(communicate_score)

check_communicate将任务声明的communicate_info信息项逐一在 assistant 消息文本中查找(子串匹配),返回命中比例。例如任务 3 要求 Agent 告知 silver 会员 + economy 舱可携带 4 件行李("4"),若 Agent 没说出正确数字,沟通分就会打折。

动作检查(action_check,参考性)

check_actions用贪心匹配比对工具日志与期望动作(名称 + 参数子集一致),结果仅作信息性诊断,不计入最终 reward。

成功判定

score_tau2_episode要求db_score == 1.0 且 communicate_score == 1.0才判定 episode 成功,失败原因分别记为db_state_mismatch/communicate_mismatch,并通过actions_match_rate提供诊断指标。

九、策略如何被驱动执行:多轮对话编排

策略文档虽然不直接出现在运行时代码里,但它决定了整个交互的"剧本"。执行层面由 runner.py 的run_multi_turn驱动:在一个线程内循环调用run_agent让 Agent 产出回复与工具调用,再用 LLM 驱动的 user_sim.py(默认gpt-4.1-mini,见 test_tau2_airline.py 中USER_SIM_MODEL)扮演客户角色。

用户模拟器按 τ-bench 规范渐进式透露信息(等待 Agent 追问才给出),并维护"剧本一致性"——任务 3 中用户坚持声称自己是 Gold 会员、要求数字形式答复,而数据库实际是 Silver,Agent 必须用get_user_details核实事实并拒绝其错误认知。这正印证了策略第七条"Always confirms the facts before offering compensation"及全局准则"不提供主观建议"的必要性。会话以三种终止令牌之一收束:###STOP###(任务完成)、###TRANSFER###(被转人工)、###OUT-OF-SCOPE###(场景信息不足),对应ConversationResult.terminated_by字段。

测试通过 pytest 参数化覆盖 15 个任务(TASK_IDS),运行方式(仓库只读,仅介绍查看与运行):

uv run --group test pytest tests/evals/tau2_airline/ -v --model claude-sonnet-4-6 uv run --group test pytest tests/evals/tau2_airline/ -k "task_2" --model claude-sonnet-4-6

十、策略阅读与评测写作的要点总结

  1. 先采集再行动:user id、reservation id、取消原因等关键信息必须主动获取,用户不知道时用get_user_detailsget_reservation_details等工具定位;
  2. 边界条件务必核对:basic economy 不可改签、已起飞不可取消、改签不可改起降地/行程类型、乘客数不可变——这些"API 不检查"的规则全靠 Agent 自觉;
  3. 补偿是稀缺授权:只有"取消 × $100/人"和"延误且改签/取消 × $50/人"两种补偿路径,且只面向 silver/gold、有保险或 business 乘客;
  4. 数据库状态是最终裁判:无论对话多么顺畅,期望动作重放后的 DB 哈希必须与真实对话后的 DB 哈希完全一致;
  5. 沟通要给出可断言的信息:行李件数、价格、金额等数字性结论要落在communicate_info可命中的文本里。

进一步阅读:策略的落地实现见 domain.py(14 个 LangChain 工具与数据模型)、评分逻辑见 evaluation.py、对话编排见 runner.py 与 user_sim.py,任务剧本与断言见 tasks.json,运行入口与系统提示词见 test_tau2_airline.py。

【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 7:48:54

CVAT 键盘快捷键完整指南:一套按键让数据标注效率翻倍

CVAT 键盘快捷键完整指南&#xff1a;一套按键让数据标注效率翻倍 【免费下载链接】cvat Computer Vision Annotation Tool (CVAT) is a leading platform for building high-quality visual datasets for vision AI. It offers open-source, cloud, and enterprise products, …

作者头像 李华
网站建设 2026/9/10 7:45:16

Java Web实战:图书信息平台从设计到高性能部署全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华