C1 · Skill 遵从 · 测试用例
对应框架维度:C1 Skill 遵从 状态:初稿 最后更新:2026-04-07
测试 Skill 说明
基于以下两个实际 skill 设计测试用例:
Skill 1: flight-selection
- 触发条件:用户提到买机票、查航班、航线比价、跨城市飞行出行
- 核心能力:通过真实航班数据搜索,在日期、价格、直飞/转机之间做出最优权衡
- 关键约束:
- 开口程必须先确认进出城市(Step 0)
- 日期弹性搜索必须保持行程总时长
- 廉航必须算行李费
- 推荐必须附对比基线
- 输出必须包含搜索范围说明、价格区间、2-3 个推荐选项、实际可玩时间、隐藏成本
Skill 2: itinerary-planning
- 触发条件:用户有已确认景点清单(≥3 个)+ 行程天数已确定 + 需要分天安排
- 核心能力:基于 Google Maps 验证真实通勤时间,产出分天行程和酒店区域建议
- 关键约束:
- 通勤时间必须查地图,禁止用训练知识估算
- 单向路线,不走回头路
- 聚类和编排之间必须有用户确认(Draft Proposal)
- 输出必须包含每段通勤的时间和方式、每天通勤汇总、编排逻辑说明
用例规范
每条用例包含以下字段:
| 字段 | 说明 |
|---|---|
| ID | 格式:C1-{维度缩写}-{序号} |
| 维度 | 所属评测维度 |
| Skill | 测试的是哪个 skill |
| 覆盖类型 | 完美匹配 / 部分覆盖 / 完全不覆盖 |
| 难度 | 简单 / 中等 / 困难 |
| 输入 | 用户消息 + 上下文 |
| 期望行为 | agent 应该如何执行 skill |
| 判定标准 | Pass / Fail 的明确条件 |
| 评分方式 | LLM-judge |
| Skill 配置 | 必须开启,列出需要的 skill |
一、Skill 触发准确率(ST: Skill Triggering)
给定任务,是否命中了正确的 skill。
C1-ST-01 · 显式触发词命中
- 难度:简单
- Skill:flight-selection
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
帮我查一下 6 月从上海飞东京的机票,两个人 - 上下文:无
- 用户消息:
- 期望行为:
- 识别出应该触发 flight-selection skill
- 按照 skill 的执行流程:先确认日期窗口和行李需求(Step 1),再执行基线搜索(Step 2)
- 不应直接调用 search_flights 就结束,应该有「±1 天搜索」「对比呈现」等 skill 规定的流程
- 判定标准:
- Pass:触发了 flight-selection skill,执行了基线搜索(至少搜了指定日期 ±1 天),输出包含多个日期选项的对比
- Fail:未触发 skill,只是简单调用 search_flights 返回一个结果
- 评分方式:LLM-judge(对照 skill 的执行流程和输出契约)
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-ST-02 · 隐式场景触发
- 难度:中等
- Skill:flight-selection
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
我 5 月要去泰国玩一周 - 上下文:无
- 用户消息:
- 期望行为:
- 识别出「去泰国」涉及跨城市飞行,应该考虑触发 flight-selection skill
- 但用户没明确说「机票」,skill 描述中提到「即使用户只是说"我要去XX"而没明确提到机票,只要涉及跨城市飞行出行就应考虑触发」
- 应主动询问是否需要帮忙看机票
- 判定标准:
- Pass:识别出机票需求,询问用户是否需要帮忙查机票,或主动提供机票建议
- Fail:完全不提机票,只规划了地面行程
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-ST-03 · 不应触发(边界识别)
- 难度:中等
- Skill:flight-selection
- 覆盖类型:完全不覆盖
- 输入:
- 用户消息:
我想飞上天和太阳肩并肩 - 上下文:无
- 用户消息:
- 期望行为:
- 识别出这是歌词,不是真的要查机票
- 不应触发 flight-selection skill
- 可以识别歌词或回应用户,但不应开始查航班
- 判定标准:
- Pass:未触发 flight-selection skill,未调用 search_flights
- Fail:当成真实需求开始查机票
- 评分方式:自动(检查是否调用了 search_flights)
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-ST-04 · 两个 skill 应同时触发
- 难度:困难
- Skill:flight-selection + itinerary-planning
- 覆盖类型:多 skill 编排
- 输入:
- 用户消息:
帮我规划一下端午去京都 5 天的旅行,从上海出发,想去清水寺、金阁寺、伏见稻荷、岚山 - 上下文:无
- 用户消息:
- 期望行为:
- 识别出需要同时触发两个 skill:
- flight-selection(上海→京都的机票)
- itinerary-planning(4 个景点分 5 天)
- 按照 flight-selection 的原则,应该先处理机票(确定到达/离开时间后才能做详细日程)
- 机票确认后,再使用 itinerary-planning 编排景点
- 识别出需要同时触发两个 skill:
- 判定标准:
- Pass:两个 skill 都被触发,且顺序正确(先机票后日程)
- Fail:只触发了其中一个 / 顺序错误(先排日程但没确认航班到达时间)
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection, itinerary-planning]
C1-ST-05 · skill 边界识别(不应过度触发)
- 难度:中等
- Skill:itinerary-planning
- 覆盖类型:部分覆盖
- 输入:
- 用户消息:
京都有什么好玩的地方 - 上下文:无
- 用户消息:
- 期望行为:
- 不应触发 itinerary-planning(触发条件:已确认景点清单 + 行程天数)
- 当前阶段是「景点推荐」,不是「日程编排」
- 应该推荐景点,但不要编排成分天行程
- 判定标准:
- Pass:推荐了景点但未触发 itinerary-planning,未调用 Google Maps 查通勤时间
- Fail:触发了 itinerary-planning,开始查景点间通勤时间或编排日程
- 评分方式:自动(检查是否调用了 Google Maps 路线工具)
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
二、Skill 执行忠实度(SF: Skill Faithfulness)
执行结果是否符合 skill 规定的输出标准和约束。
C1-SF-01 · Step 0 阻断级检查(开口程)
- 难度:中等
- Skill:flight-selection
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
帮我规划泰国三地游的机票,曼谷、清迈、普吉岛,一周时间 - 上下文:无
- 用户消息:
- 期望行为:
- 识别出这是开口程(不同城市进出)
- 按照 skill 的 Step 0:在任何搜票动作前,必须先确认「飞入哪个城市」「飞出哪个城市」
- 不应自行假设路线(如默认曼谷进曼谷出)
- 判定标准:
- Pass:在调用 search_flights 之前,询问了进出城市
- Fail:未询问就开始搜票 / 自行假设了进出城市
- 评分方式:LLM-judge(检查是否在搜票前有询问进出城市的动作)
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-SF-02 · 日期弹性搜索规则(保持总时长)
- 难度:困难
- Skill:flight-selection
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
查一下 5 月 10 号到 15 号去东京的机票,日期有一天的弹性 - 上下文:无
- 用户消息:
- 期望行为:
- 按照 skill 的 Step 2a:±1 天搜索必须保持行程总时长(5 天)
- 可以搜:5/10-5/15、5/9-5/14、5/11-5/16
- 不应搜:5/10-5/14(缩短到 4 天)、5/11-5/15(缩短到 4 天)
- 输出应包含保持 5 天行程的多个日期组合对比
- 判定标准:
- Pass:推荐的所有日期组合都保持了 5 天行程
- Fail:为了省钱推荐了缩短行程的方案(如 5/10-5/14)
- 评分方式:LLM-judge(检查推荐方案的行程天数)
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-SF-03 · 廉航隐藏成本计算
- 难度:困难
- Skill:flight-selection
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
查北京到曼谷的机票,3 月 20 号出发,26 号回,两个人,都有一个 24 寸行李箱需要托运 - 工具拦截配置(执行用):
{ "type": "tool_intercept", "intercept_tool": "search_flights", "inject_tool_result": {"is_error": false, "content": "{\"outbound\": [{\"airline\": \"春秋航空\", \"airline_type\": \"LCC\", \"flight_no\": \"9C8571\", \"departure\": \"2025-03-20T06:30:00+08:00\", \"arrival\": \"2025-03-20T11:45:00+07:00\", \"price_per_person\": 800, \"cabin\": \"Economy\", \"baggage_included\": false, \"baggage_fee_per_piece\": 250, \"notes\": \"不含托运行李\"}, {\"airline\": \"泰国国际航空\", \"airline_type\": \"Full-service\", \"flight_no\": \"TG614\", \"departure\": \"2025-03-20T09:15:00+08:00\", \"arrival\": \"2025-03-20T13:30:00+07:00\", \"price_per_person\": 1200, \"cabin\": \"Economy\", \"baggage_included\": true, \"baggage_allowance\": \"30kg\", \"notes\": \"含30kg托运行李\"}], \"return\": [{\"airline\": \"春秋航空\", \"flight_no\": \"9C8572\", \"departure\": \"2025-03-26T14:00:00+07:00\", \"arrival\": \"2025-03-26T20:30:00+08:00\", \"price_per_person\": 820, \"baggage_included\": false, \"baggage_fee_per_piece\": 250}, {\"airline\": \"泰国国际航空\", \"flight_no\": \"TG615\", \"departure\": \"2025-03-26T16:45:00+07:00\", \"arrival\": \"2025-03-26T23:10:00+08:00\", \"price_per_person\": 1180, \"baggage_included\": true}]}"} }
- 用户消息:
- 期望行为:
- 按照 skill 的核心原则:「算总账不看单价」和「了解行李需求」
- 应该查询或标注春秋航空的行李托运费(通常 200-300 元/件)
- 对比时应该是「春秋 800 + 行李费 250 = 1050」vs「泰航 1200(含行李)」
- 不应只看票面价就说春秋便宜 400 元
- 判定标准:
- Pass:对比中考虑了廉航行李费,真实总价对比正确
- Fail:只对比票面价,忽略了用户明确提到的行李需求
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-SF-04 · 输出契约完整性
- 难度:中等
- Skill:flight-selection
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
查一下 6 月 10 号北京飞新加坡的机票 - 上下文:skill 已执行完搜索流程
- 用户消息:
- 期望行为:
- 按照 skill 的「输出契约」,必须包含 8 项内容:
- 搜索范围说明(搜了哪些日期)
- 价格区间
- 2-3 个推荐选项
- 每个选项的权衡说明
- 对比基线
- 实际可玩时间计算
- 隐藏成本提醒
- 数据来源说明
- 按照 skill 的「输出契约」,必须包含 8 项内容:
- 判定标准:
- Pass:输出包含至少 6 项(容许 1-2 项缺失)
- Fail:缺失 3 项及以上 / 只给了航班列表没有权衡说明
- 评分方式:LLM-judge(逐项检查输出契约)
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-SF-05 · 通勤时间必须查地图
- 难度:困难
- Skill:itinerary-planning
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
我要去新加坡玩 3 天,想去滨海湾花园、动物园、圣淘沙、乌节路,帮我排个行程 - 上下文:无
- 用户消息:
- 期望行为:
- 按照 skill 的核心原则 #1:「通勤时间必须查地图」,禁止用训练知识估算
- 必须调用
compute_google_maps_routes或compute_google_maps_route_matrix查询景点间通勤时间 - 输出中的通勤时间必须标注来源(Google Maps API)
- 不应说「动物园到滨海湾大约 30 分钟」这种无数据支撑的估算
- 判定标准:
- Pass:调用了 Google Maps 路线查询工具,输出中的通勤时间有数据来源标注
- Fail:未调用地图工具,通勤时间是估算的 / 输出未标注数据来源
- 评分方式:自动(检查是否调用了地图工具)+ LLM-judge(检查是否有来源标注)
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
C1-SF-06 · Draft Proposal 用户确认流程
- 难度:困难
- Skill:itinerary-planning
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
新加坡 4 天,去滨海湾花园、鱼尾狮、植物园、圣淘沙、乌节路、牛车水,帮我排个行程 - 上下文:无
- 用户消息:
- 期望行为:
- 按照 skill 的 Step 3.5 和 4.5:聚类后必须有 Draft Proposal #1 让用户确认分组,编排后必须有 Draft Proposal #2 让用户确认日程
- 不应该从 Step 3 直接跳到 Step 6 输出最终结果
- 应该分两轮:先展示地理分组,用户确认后再展示每天的时间安排
- 判定标准:
- Pass:有两次用户确认点(分组确认 + 日程确认),或至少有一次 Draft Proposal
- Fail:直接给出最终日程,没有中间确认环节
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
C1-SF-07 · 反模式检测(估算通勤时间)
- 难度:中等
- Skill:itinerary-planning
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
曼谷 3 天,去大皇宫、卧佛寺、考山路、暹罗广场,排个行程 - 上下文:无
- 用户消息:
- 期望行为:
- 按照 skill 的反模式列表:❌ 用训练知识估算通勤时间
- 必须调用 Google Maps 工具查询
- 输出不应出现「大约 20 分钟」「预计 30 分钟」等估算表述
- 应该是「步行 19min / 1.3km (Google Maps)」或「MRT 3 站 22min (Google Maps)」
- 判定标准:
- Pass:所有通勤时间都有具体数值和来源标注,未使用「大约」「预计」等估算词
- Fail:使用了估算表述 / 未标注数据来源
- 评分方式:LLM-judge(检查通勤时间的表述方式)
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
三、Skill 边界识别(SB: Skill Boundary)
任务不在 skill 覆盖范围时,是否正确降级而非强行套用。
C1-SB-01 · 缺少前置条件(景点未确认)
- 难度:中等
- Skill:itinerary-planning
- 覆盖类型:部分覆盖
- 输入:
- 用户消息:
帮我规划一下京都 5 天的行程 - 上下文:无景点清单
- 用户消息:
- 期望行为:
- 识别出缺少 itinerary-planning 的前置条件(需要已确认的景点清单 ≥3 个)
- 不应强行触发 skill 开始编排(因为没有景点输入)
- 应该先推荐景点,等用户确认后再触发 itinerary-planning
- 判定标准:
- Pass:先推荐景点,未开始调用 Google Maps 查通勤或编排日程
- Fail:在没有景点清单的情况下强行触发 skill,编造了景点列表并开始编排
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
C1-SB-02 · 超出 skill 范围的需求
- 难度:困难
- Skill:flight-selection
- 覆盖类型:部分覆盖
- 输入:
- 用户消息:
我要去东京玩一周,帮我搞定机票、签证、酒店、行程规划 - 上下文:无
- 用户消息:
- 期望行为:
- 识别出 flight-selection 只负责「机票搜索和选择」
- skill 的技能边界原则:「路线规划、行程编排、签证攻略等超出范围——可以辅助但要意识到这不是核心职责」
- 应该先专注处理机票(核心),再简要辅助其他内容或建议分任务处理
- 不应在签证和酒店上投入过多精力而影响机票选择的质量
- 判定标准:
- Pass:主要精力放在机票(有完整的基线搜索和推荐),其他内容简要涉及或建议分步处理
- Fail:四个需求平均分配精力,机票只是简单搜了一下 / 完全忽略了机票
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-SB-03 · skill 内的能力边界(地图 API 限制)
- 难度:困难
- Skill:itinerary-planning
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
帮我规划曼谷 3 天行程,去大皇宫、卧佛寺、考山路 - 工具拦截配置(执行用):
{ "type": "tool_intercept", "intercept_tool": "compute_google_maps_route_matrix", "inject_tool_result": {"is_error": false, "content": "{\"mode\": \"TRANSIT\", \"status\": \"ZERO_RESULTS\", \"rows\": [], \"error_message\": \"TRANSIT routing is not available for this region. The Google Maps Directions API does not support transit routing in Bangkok at this time.\", \"fallback_suggestion\": \"Try DRIVE or WALK mode instead.\"}"} }
- 用户消息:
- 期望行为:
- 按照 skill 的 Step 2a 注释:「TRANSIT 模式在部分地区返回空,可用 DRIVE 模式估算后标注"驾车时长,公交可能更长"」
- 应该切换到 DRIVE 模式重试
- 输出中标注「通勤时间为驾车估算,公交实际可能更长」
- 判定标准:
- Pass:TRANSIT 失败后切换到 DRIVE,输出有合理的数据来源说明
- Fail:TRANSIT 失败就放弃查地图,改用训练知识估算
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
四、Skill 冲突处理(SC: Skill Conflict)
用户意图与 skill 规范冲突时,处理是否合理。
C1-SC-01 · 用户要求违反 skill 原则
- 难度:困难
- Skill:itinerary-planning
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
我知道距离,不用查地图了,直接帮我排个行程就行。去大皇宫、卧佛寺、考山路,曼谷 2 天 - 上下文:无
- 用户消息:
- 期望行为:
- skill 的核心原则 #1:「通勤时间必须查地图,禁止用训练知识估算」
- 用户要求和 skill 规范冲突
- 合理处理:说明为什么需要查地图(防止估算偏差),询问用户是否接受
- 如果用户坚持不查,应该降级(不使用 skill,给出基于训练知识的粗略建议并标注不可靠)
- 判定标准:
- Pass:说明了查地图的必要性,或降级后明确标注了「未验证地图数据」
- Fail:用户不让查就不查,但仍然声称遵循了 skill(自相矛盾)
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
C1-SC-02 · 用户需求过于模糊无法执行 skill
- 难度:中等
- Skill:flight-selection
- 覆盖类型:部分覆盖
- 输入:
- 用户消息:
帮我看看暑假去东南亚的机票 - 上下文:无
- 用户消息:
- 期望行为:
- 信息过于模糊:「东南亚」包含多个国家,「暑假」是 6-8 月范围
- skill 需要明确的出发地、目的地、日期才能执行
- 不应强行触发 skill(会导致无效搜索)
- 应该先收集信息,再触发 skill
- 判定标准:
- Pass:询问了具体目的地城市和日期窗口,未盲目调用 search_flights
- Fail:自行假设目的地(如曼谷)开始搜索
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
五、多 Skill 编排(SM: Skill Multi-coordination)
同时触发多个 skill 时,是否正确组合执行。
C1-SM-01 · 两个 skill 的正确顺序
- 难度:困难
- Skill:flight-selection + itinerary-planning
- 覆盖类型:多 skill
- 输入:
- 用户消息:
帮我规划端午去京都 4 天,想去清水寺、金阁寺、伏见稻荷大社、岚山竹林,从上海出发 - 上下文:无
- 用户消息:
- 期望行为:
- 两个 skill 都应触发
- 顺序必须正确:
- 先执行 flight-selection 确定航班(得到具体到达/离开时间)
- 再执行 itinerary-planning(知道第一天几点到、最后一天几点走,才能合理安排)
- 如果顺序反了,日程规划会缺少关键约束(到达/离开时间)
- 判定标准:
- Pass:先处理了机票,获得到达/离开时间后再编排日程
- Fail:先编排了日程(无视航班时间)/ 两个任务完全独立处理没有衔接
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection, itinerary-planning]
C1-SM-02 · 两个 skill 的信息传递
- 难度:困难
- Skill:flight-selection + itinerary-planning
- 覆盖类型:多 skill
- 输入:
- 对话历史:
用户:帮我查 5 月 10-15 号上海到京都的机票 Agent:好的,我搜索了 5/9、5/10、5/11 出发及对应返程日期的航班,以下是推荐方案(已考虑 ±1 天弹性,保持 5 天行程总时长): **推荐方案 A(最优性价比)** - 去程:5月10日 08:05 上海浦东(PVG)→ 大阪关西(KIX)东方航空 MU531,抵达 12:20(日本时间),再乘新干线约1小时15分至京都,预计下午14:00左右抵达京都 - 返程:5月15日 20:30 大阪关西(KIX)→ 上海浦东(PVG)东方航空 MU532,抵达 22:05(北京时间) - 票价:含税每人约 ¥2,380(去程¥1,180 + 返程¥1,200),含 23kg 行李 - 实际可玩时间:5/10 下午半天 + 5/11-5/14 完整四天 + 5/15 上午至下午约5小时,共约 4.5 天 - 隐藏成本:PVG→KIX 含行李,无额外费用;新干线 大阪→京都 约 ¥570/人(约 ¥80 人民币) **推荐方案 B(早去多玩)** - 去程:5月9日 07:30 上海浦东(PVG)→ 大阪关西(KIX)中国国际航空 CA837,抵达 11:45,京都抵达约 13:30 - 返程:5月14日 21:00 大阪关西(KIX)→ 上海浦东(PVG)中国国际航空 CA838,抵达 22:40 - 票价:含税每人约 ¥2,650,含 23kg 行李 - 实际可玩时间:约 5 天 搜索范围:2025年5月9日-11日出发,5月14日-16日返程,PVG-KIX/ITM 所有经济舱航班。 用户:好的,那基于这个航班时间,帮我排一下这 5 天去清水寺、金阁寺、岚山、伏见稻荷的行程 - 用户消息:(即最后一句)
- 对话历史:
- 期望行为:
- 切换到 itinerary-planning skill
- 但必须利用 flight-selection 输出的航班时间:
- 5/10 早上 8 点从上海起飞,到京都约 11 点(+1h 时差),可用时间从中午开始
- 5/15 晚上 8 点返程,当天下午需前往机场,可用时间到下午 5 点
- 编排时第一天和最后一天的安排应该考虑航班时间
- 判定标准:
- Pass:日程规划考虑了航班时间(第一天下午开始,最后一天下午结束)
- Fail:日程规划忽略了航班时间(第一天从早上 9 点开始安排)
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection, itinerary-planning]
C1-SM-03 · skill 能力互补
- 难度:困难
- Skill:flight-selection + itinerary-planning
- 覆盖类型:多 skill
- 输入:
- 对话历史:
用户:帮我规划京都 5 天旅行 Agent:好的!规划京都 5 天旅行,我先帮您看机票——请问您从哪个城市出发?大概什么时间出发和返回? 用户:上海,5 月 10 号出发,15 号回 Agent:好的,我搜索了 5/9-5/11 出发、5/14-5/16 返程的上海浦东到大阪关西的航班,为您推荐以下方案: **早去晚回方案(推荐)** - 去程:5月10日 06:50 上海浦东(PVG)→ 大阪关西(KIX)春秋航空 9C8881,抵达 10:55(日本时间),乘新干线到京都约 75 分钟,预计中午 12:30 抵达京都 - 返程:5月15日 22:15 大阪关西(KIX)→ 上海浦东(PVG)春秋航空 9C8882,抵达次日 00:05(北京时间) - 票价:含税每人约 ¥1,980,不含托运行李(24 寸箱托运费约 ¥180/件) - 实际可玩时间:5/10 下午约 6 小时 + 5/11-5/14 完整 4 天 + 5/15 上午至晚上 18:00 约 9 小时 **次优方案(含行李更省心)** - 去程:5月10日 09:15 上海浦东(PVG)→ 大阪关西(KIX)东方航空 MU531,抵达 13:20,京都约 14:50 抵达 - 返程:5月15日 20:30 大阪关西(KIX)→ 上海浦东(PVG)东方航空 MU532,抵达 22:05 - 票价:含税每人约 ¥2,480,含 23kg 托运行李 搜索范围:PVG/SHA 出发,KIX/ITM 到达,2025年5月9-11日去程,5月14-16日返程。数据来源:实时航班搜索。 用户:我选早去晚回那个。景点去清水寺、金阁寺、岚山 - 用户消息:(即最后一句)
- 对话历史:
- 期望行为:
- flight-selection 任务完成,切换到 itinerary-planning
- 利用之前确认的航班信息作为日程编排的时间约束
- 两个 skill 的输出应该衔接(不是各自独立的报告)
- 判定标准:
- Pass:日程编排利用了航班时间约束,两个 skill 输出有衔接
- Fail:重新询问了航班信息 / 日程编排忽略了航班时间
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection, itinerary-planning]
六、Skill 执行流程完整性(SP: Skill Process)
是否严格遵循 skill 规定的执行步骤,不跳步、不简化。
C1-SP-01 · 偏好权重识别
- 难度:困难
- Skill:flight-selection
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
查一下上海到东京的机票,5 月 10 号出发,ANA 优先 - 上下文:无
- 用户消息:
- 期望行为:
- 按照 skill 的 Step 1.5「偏好权重识别」:用户只是说「优先」不是「必须」
- 应该视为 nice-to-have,不作为筛选条件
- 搜索时应该搜所有航司,但在对比时标注「ANA 选项」
- 不应只搜 ANA 的航班
- 判定标准:
- Pass:搜索包含了多个航司,对比中标注了 ANA 选项
- Fail:只搜索了 ANA 航班 / 把「优先」当成了硬约束
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-SP-02 · 基线搜索完整性(±1 天)
- 难度:中等
- Skill:flight-selection
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
查一下 6 月 15 号北京飞大阪的机票,日期可以前后调一天 - 上下文:无
- 用户消息:
- 期望行为:
- 按照 skill 的 Step 2a 基线搜索:应该搜指定日期 + 前一天 + 后一天(共 3 天)
- 不应只搜 6/15 就结束
- 输出应包含三天的价格对比
- 判定标准:
- Pass:搜索了 6/14、6/15、6/16 三天,输出有对比
- Fail:只搜了 6/15 / 搜了 3 天但输出只展示了最便宜的那天
- 评分方式:LLM-judge(检查输出是否包含多日期对比)
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-SP-03 · ReAct 循环(搜索-分析-反思)
- 难度:困难
- Skill:flight-selection
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
查北京到纽约的机票,6 月中旬,预算紧张 - 第一轮搜索返回:直飞 8000 元,首尔转机 5500 元
- 用户消息:
- 期望行为:
- 按照 skill 的 Step 3.7 ReAct 循环:
- Analyze:分析基线数据,发现直飞和转机价差 2500 元(45%)
- Reflect:更新认知文档,识别到「预算紧张」可能倾向转机,但需要问用户「省 2500 是否值得多飞 3-4 小时」
- Sync:与用户同步,询问价格 vs 时间的权衡
- 不应直接推荐转机就结束
- 按照 skill 的 Step 3.7 ReAct 循环:
- 判定标准:
- Pass:展示了基线对比,询问了用户对价格 vs 时间的权衡偏好
- Fail:看到预算紧张就直接推荐最便宜的转机方案,不询问权衡
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [flight-selection]
C1-SP-04 · 单向路线原则
- 难度:中等
- Skill:itinerary-planning
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
新加坡 3 天,去乌节路、圣淘沙、滨海湾花园、鱼尾狮、牛车水,排个行程 - 上下文:无
- 用户消息:
- 期望行为:
- 按照 skill 的核心原则 #3:「单向路线,不走回头路」
- 编排时应该根据地理位置形成方向性路线
- 示例合理路线:Day 1 牛车水→鱼尾狮→滨海湾(东部线),Day 2 乌节路→圣淘沙(西南线)
- 示例错误路线:Day 1 牛车水→乌节路→牛车水附近(来回折返)
- 判定标准:
- Pass:每天的景点形成方向性路线,未在同一区域来回折返
- Fail:路线有明显的回头路
- 评分方式:LLM-judge(需要理解地理位置)
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
七、多模态 Skill 执行(MM: Multimodal Skill)
Skill 如何处理多模态输入。
C1-MM-01 · Skill 处理图片输入
- 难度:中等
- Skill:itinerary-planning
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
[上传行程表截图] 帮我优化这个行程 - 图片:
https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/PNG_transparency_demonstration_1.png/240px-PNG_transparency_demonstration_1.png(用于测试;实际评测中替换为包含以下内容的行程表截图:Day1 清水寺→金阁寺→岚山,Day2 伏见稻荷→祗园→哲学之道,Day3 二条城→锦市场→京都站,每个景点标有大致时间但未经地图核实,供 agent 用 Google Maps 验证通勤时间并优化)
- 用户消息:
- 期望行为:
- 触发 itinerary-planning skill
- Skill 要求「通勤时间必须查地图」
- 提取行程后,调用 Google Maps 验证通勤时间
- 判定标准:
- Pass:提取了行程,调用了 Google Maps 验证,遵守了 skill 规范
- Fail:未调用地图工具直接基于截图评论
- 评分方式:自动(检查地图工具调用)+ LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
C1-MM-02 · 图片场景的 Skill 边界
- 难度:困难
- Skill:itinerary-planning
- 覆盖类型:部分覆盖
- 输入:
- 用户消息:
[上传景点照片] 这里是哪,从京都站怎么过来,附近有什么好玩的 - 图片:
(日本京都金阁寺(鹿苑寺)的照片,金色建筑倒映在镜湖池中,用于测试 agent 能否识别景点并正确处理「地点识别 + 导航 + 周边推荐」的组合需求,而不是错误地触发 itinerary-planning skill)
- 用户消息:
- 期望行为:
- 这是组合需求:地点识别 + 导航 + 周边推荐
- itinerary-planning 的触发条件不满足(缺少景点清单 + 行程天数)
- 不应触发 itinerary-planning
- 判定标准:
- Pass:未触发 itinerary-planning,分步处理了三个需求
- Fail:强行触发了 skill
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
C1-MM-03 · Skill 输出契约的多模态验证
- 难度:困难
- Skill:itinerary-planning
- 覆盖类型:完美匹配
- 输入:
- 用户消息:
[上传地图截图,标注了几个想去的地点] 帮我排个行程,3 天 - 图片:
https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/PNG_transparency_demonstration_1.png/240px-PNG_transparency_demonstration_1.png(用于测试;实际评测中替换为以下内容的地图截图:新加坡地图,用红色图钉标注了 5 个景点:① 滨海湾花园(Gardens by the Bay)、② 鱼尾狮公园(Merlion Park)、③ 圣淘沙名胜世界(Resorts World Sentosa)、④ 新加坡动物园(Singapore Zoo)、⑤ 牛车水(Chinatown),供 agent 提取景点后调用 Google Maps 查询通勤时间并编排 3 天行程)
- 用户消息:
- 期望行为:
- 触发 itinerary-planning skill
- 提取图片中标注的景点
- 按 skill 要求:调用 Google Maps 查通勤时间、生成 itinerary.json
- 判定标准:
- Pass:提取了景点,调用了地图工具,输出包含 skill 要求的要素
- Fail:未提取景点 / 跳过了 skill 规定的步骤
- 评分方式:LLM-judge
- Skill 配置:
skill_enabled: true, active_skills: [itinerary-planning]
评测执行说明
总用例数
| 维度 | 代号 | 用例数 |
|---|---|---|
| Skill 触发准确率 | ST | 5 |
| Skill 执行忠实度 | SF | 7 |
| Skill 边界识别 | SB | 3 |
| Skill 冲突处理 | SC | 1 |
| 多 Skill 编排 | SM | 3 |
| Skill 执行流程完整性 | SP | 4 |
| 合计 | 23 |
Skill 覆盖类型分布
| 覆盖类型 | 数量 | 说明 |
|---|---|---|
| 完美匹配 | 15 | 任务完全在 skill 覆盖范围内 |
| 部分覆盖 | 4 | 任务只有一部分被 skill 覆盖,或缺少前置条件 |
| 完全不覆盖 | 1 | 没有相关 skill,测试不应触发 |
| 多 skill | 3 | 同时涉及两个 skill 的协同 |
难度分布
| 难度 | 数量 | 占比 |
|---|---|---|
| 简单 | 1 | 4% |
| 中等 | 8 | 35% |
| 困难 | 14 | 61% |
C1 是产品差异化核心,困难 case 占比高(61%)是合理的。
Skill 分布
| Skill | 单独测试 | 协同测试 | 合计 |
|---|---|---|---|
| flight-selection | 13 | 3 | 16 |
| itinerary-planning | 7 | 3 | 10 |
评分方式
| 方式 | 数量 | 说明 |
|---|---|---|
| LLM-judge | 21 | 需要对照 skill 规范判断执行忠实度 |
| 自动 + LLM-judge | 2 | 部分可自动检查(如工具调用),部分需语义判断 |
关键评测点
C1 的评测重点在于验证 agent 是否:
- 理解 skill 的触发条件:显式关键词 vs 隐式场景,以及不应触发的边界
- 遵循 skill 的执行流程:不跳步(如开口程必须先走 Step 0)、不简化(如必须查地图不能估算)
- 满足 skill 的输出契约:输出包含 skill 规定的必需要素
- 识别 skill 的能力边界:什么能做、什么不能做、什么需要降级
- 遵守 skill 的反模式清单:不做 skill 明确禁止的事情
LLM-as-Judge Prompt 示例
评估 agent 是否忠实执行了 skill 规范。
【Skill 规范】
{完整 skill 定义,从 SKILL.md 读取}
【用户任务】
{用户消息}
【Agent 输出】
{agent 实际输出}
【评分维度】
1. 触发判断:是否应该触发该 skill?agent 的判断是否正确?(0-1)
2. 流程遵从:是否遵循了 skill 规定的执行步骤?有无跳步或简化?(0-2)
3. 约束遵守:是否遵守了 skill 的核心原则和约束?(0-1)
4. 输出完整:是否满足 skill 的输出契约?(0-1)
5. 反模式检查:是否违反了 skill 的反模式清单?有违反扣分。(0 或 -1)
总分:0-5 分
评分理由:[具体说明]
Judge 校准
每轮评测需对 judge 结果抽样 20% 人工复核(C1 比其他维度更需要人工校准):
- 检查 judge 是否正确理解了 skill 规范
- 检查 judge 的评分是否过严或过松
- 维护 judge 与人工评分的一致率指标(目标 ≥ 85%)
后续迭代方向
- 补充更多反模式的 case(每个反模式至少 1 条)
- 补充 skill 降级场景(工具不可用时如何处理)
- 补充更多的多 skill 协同 case(3 个 skill 同时触发)
- 从真实用户 trace 中提取 skill 被误用的场景
- 新增 skill 时为其创建完整的三类 case(完美匹配/部分覆盖/完全不覆盖)
- 补充 skill 版本更新后的回归 case(验证新版 skill 是否破坏了原有能力)
附:Skill Schema 提取
基于现有两个 skill,总结出的隐式 Skill Schema 结构:
---
name: {skill_id}
description: {一句话说明}
compatibility: {依赖的工具/环境}
metadata:
version: {版本号}
---
# {Skill 名称}
{角色定位描述}
## 核心原则
{3-6 条核心指导思想}
## 触发条件
{何时应该使用这个 skill}
## 执行流程
### Step 0/1/2...
{分步骤的详细操作指南}
## 输出契约
{输出必须包含哪些内容}
## 反模式
- ❌ {不应该做的事情列表}
建议:将此结构文档化为 SKILL_SCHEMA.md,作为所有 skill 的编写规范。