fix(workflow): align non-motor accident extraction and evaluations
This commit is contained in:
+64
-5
@@ -1,12 +1,38 @@
|
||||
# Workflow evaluations
|
||||
|
||||
The evaluation runner calls a live FastAPI service backed by FastGPT. For now,
|
||||
each conversation step checks only the SSE `stage_code.nextStageCode` value.
|
||||
During the run it also prints the live dialogue and saves transcripts.
|
||||
The evaluation runner calls a live FastAPI service backed by FastGPT. Each
|
||||
conversation step checks the SSE `stage_code.nextStageCode` value and optional
|
||||
form / reply expectations. During the run it prints the dialogue and saves
|
||||
transcripts. Cases target `workflow/20261021`; import that workflow into FastGPT
|
||||
before running against a service.
|
||||
|
||||
## Case format
|
||||
|
||||
Add YAML files anywhere under `evals/cases/` (e.g. `direct/`, `browser_addon/`, `no_false/` for false-interrupt / false-transfer checks):
|
||||
Add YAML files anywhere under `evals/cases/`:
|
||||
|
||||
- `collection_skip_known_info/`: skip known fields and clarify missing information.
|
||||
- `non_motor_vehicle/`: both client modes, with separate flow and extraction cases.
|
||||
`all_info`, `self_collision`, `no_other_vehicle`, and `explicit_correction`
|
||||
cover conversation flow and known facts. `electric_bicycle` verifies an
|
||||
electric bicycle hitting a fixed object and transferring to `0003` without
|
||||
asking for car counts. These cases accept the described non-motor-vehicle
|
||||
collision as having `vehicle_count: 0` from the first accident description.
|
||||
`zero_count_bundle` / `zero_count_history` check zero extraction and retention.
|
||||
Explicit correction to one car must update the count to `1`.
|
||||
Both collection and extraction prompts in `workflow/20261021` use this policy
|
||||
only for an explicitly described non-motor-vehicle single-party collision with
|
||||
a fixed object; other vehicle involvement or unclear relations do not imply zero.
|
||||
- `time_confirmation/`: mandatory full-date confirmation, retaining supplemental
|
||||
information while confirmation is pending, and confirming corrected times.
|
||||
- `no_false/`: ASR noise must not cause premature transfer.
|
||||
- `photo_button_guidance/`: button help and failure handling.
|
||||
- `photo_skip_plate_confirm/`: current photo transitions without plate confirmation.
|
||||
|
||||
Obsolete scripts requiring repeated time/count confirmations or the removed
|
||||
`2004` / `2016` photo states have been removed. Photo transition cases use a
|
||||
complete accident description, confirm its standardized time, then reach their
|
||||
target branch. Time confirmation is mandatory even when all other information
|
||||
is already known; an unchanged time is confirmed only once.
|
||||
|
||||
```yaml
|
||||
name: direct_initial_stage
|
||||
@@ -26,6 +52,29 @@ steps:
|
||||
`browser_addon`). Steps in one file share the same generated `sessionId`.
|
||||
Different cases always use different session IDs.
|
||||
|
||||
Optional `expect` fields:
|
||||
|
||||
- `form`: partial equality against the cumulative form, including value types.
|
||||
- `formMatches`: field-to-regex mapping for free-text descriptions.
|
||||
- `formAbsent`: fields that must not have been extracted yet.
|
||||
- `replyMatches` / `replyNotMatches`: required / forbidden reply regexes.
|
||||
|
||||
If any step has a form expectation, the runner sends `needFormUpdate: true`
|
||||
throughout that case, merges SSE `formUpdate` deltas across turns, and records
|
||||
both updates and form snapshots. Thus an omitted unchanged field is accepted,
|
||||
while a later incorrect overwrite fails. SSE errors also fail the step.
|
||||
Existing cases without reply expectations still require manual review of their
|
||||
commented wording requirements.
|
||||
|
||||
```yaml
|
||||
- input: 没有人员伤亡。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {has_injury: false, has_non_motor_vehicle_hit: true}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
replyNotMatches: "(有没有|是否).*非机动车"
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
Start the API, then execute:
|
||||
@@ -45,9 +94,19 @@ Run selected cases:
|
||||
```bash
|
||||
python evals/run.py --case direct
|
||||
python evals/run.py --case browser_addon
|
||||
python evals/run.py --case no_false
|
||||
python evals/run.py --case non_motor_vehicle
|
||||
python evals/run.py --case non_motor_vehicle_electric_bicycle
|
||||
python evals/run.py --case non_motor_vehicle_zero_count
|
||||
python evals/run.py --case time_confirmation
|
||||
python evals/run.py --case photo_skip_plate_confirm
|
||||
```
|
||||
|
||||
There are 14 non-motor-vehicle cases: 10 flow cases and 4 zero-count extraction
|
||||
cases. Both groups require `vehicle_count: 0` for the described non-motor-vehicle
|
||||
collisions, while unrelated chatter must leave accident fields absent. Vehicle
|
||||
type corrections, time confirmation, and transfer checks remain active. The
|
||||
runner still stops each case at its first failure.
|
||||
|
||||
## Dialogue and transcripts
|
||||
|
||||
While a case runs, each step prints the user input, bot reply (`text_delta`),
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
name: browser_addon_initial_stage
|
||||
clientMode: browser_addon
|
||||
|
||||
steps:
|
||||
- input: hi
|
||||
expect:
|
||||
stageCode: browser_addon.1001
|
||||
|
||||
- input: 继续办理
|
||||
expect:
|
||||
stageCode: browser_addon.1002
|
||||
|
||||
- input: 十分钟之前两车追尾
|
||||
expect:
|
||||
stageCode: browser_addon.1002
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: browser_addon.1002
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: browser_addon.1002
|
||||
|
||||
- input: 十分钟之前
|
||||
expect:
|
||||
stageCode: browser_addon.1002
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: browser_addon.1002
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: browser_addon.1002
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: browser_addon.2010
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: browser_addon.2011
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: browser_addon.2012
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: browser_addon.2013
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: browser_addon.2014
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: browser_addon.2015
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: browser_addon.2016
|
||||
|
||||
- input: 没错
|
||||
expect:
|
||||
stageCode: browser_addon.0000
|
||||
@@ -1,8 +1,8 @@
|
||||
name: browser_addon_collection_skip_known_info_dual_all_info
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -14,7 +14,13 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 信息齐全,直接引导双车拍照;不得追加任何已知字段的确认问题。
|
||||
# 其他信息齐全,先确认完整时间;确认后直接双车拍照。
|
||||
- input: 十分钟前两辆汽车追尾,没有人员受伤,没有撞到非机动车或行人,我还在事故现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: browser_addon_collection_skip_known_info_dual_bundle_remaining
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -19,7 +19,12 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 本轮同时补齐三个字段,直接分流,不拆成多个确认轮次。
|
||||
# 一次补齐剩余信息,先复述完整时间等待确认。
|
||||
- input: 没有撞到非机动车或行人,十分钟前发生的,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: browser_addon_collection_skip_known_info_dual_fill_missing
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -14,17 +14,24 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 仅询问是否撞到非机动车,不再核对人伤、时间或两辆车的数量。
|
||||
# 先询问是否涉及非机动车,不再核对已知人伤或数量。
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 仅询问是否还在现场,不要求确认十分钟前的标准时间。
|
||||
# 复述换算后的完整事故时间,等待用户确认。
|
||||
- input: 没有撞到非机动车,也没有行人。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 最后补齐在场信息即分流,不再询问或确认车辆数量。
|
||||
|
||||
- input: 在,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: browser_addon_collection_skip_known_info_dual_unclear_injury
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -19,7 +19,13 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 人伤澄清后所有字段齐全,直接双车拍照。
|
||||
# 人伤澄清后确认完整时间,用户确认后直接双车拍照。
|
||||
- input: 看清楚了,没有人受伤。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: browser_addon_collection_skip_known_info_single_all_info
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -14,7 +14,13 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 信息齐全,直接引导拍摄车辆前方;不得再确认时间、数量、人伤或在场情况。
|
||||
# 其他信息齐全,先确认完整时间;确认后直接单车拍照。
|
||||
- input: 十分钟前我倒车撞到护栏,事故只有一辆汽车,没有人受伤,没有撞到非机动车或行人,我还在事故现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2000"
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: browser_addon_collection_skip_known_info_single_no_inferred_count
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 只询问机动车数量,不能从撞护栏推断只有一辆车;不得重问其他字段。
|
||||
# 先确认完整时间,再询问缺失的机动车数量;不能从撞护栏推断只有一辆车。
|
||||
- input: 十分钟前我倒车撞到了护栏,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 明确数量后直接单车拍照,不再要求数量确认。
|
||||
|
||||
- input: 只有一辆汽车。
|
||||
expect:
|
||||
stageCode: "browser_addon.2000"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: direct_collection_skip_known_info_dual_all_info
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -14,7 +14,13 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 信息齐全,直接引导双车拍照;不得追加任何已知字段的确认问题。
|
||||
# 其他信息齐全,先确认完整时间;确认后直接双车拍照。
|
||||
- input: 十分钟前两辆汽车追尾,没有人员受伤,没有撞到非机动车或行人,我还在事故现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: direct_collection_skip_known_info_dual_bundle_remaining
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -19,7 +19,12 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 本轮同时补齐三个字段,直接分流,不拆成多个确认轮次。
|
||||
# 一次补齐剩余信息,先复述完整时间等待确认。
|
||||
- input: 没有撞到非机动车或行人,十分钟前发生的,我还在现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: direct_collection_skip_known_info_dual_fill_missing
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -14,17 +14,24 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 仅询问是否撞到非机动车,不再核对人伤、时间或两辆车的数量。
|
||||
# 先询问是否涉及非机动车,不再核对已知人伤或数量。
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 仅询问是否还在现场,不要求确认十分钟前的标准时间。
|
||||
# 复述换算后的完整事故时间,等待用户确认。
|
||||
- input: 没有撞到非机动车,也没有行人。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 最后补齐在场信息即分流,不再询问或确认车辆数量。
|
||||
|
||||
- input: 在,我还在现场。
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: direct_collection_skip_known_info_dual_unclear_injury
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -19,7 +19,13 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 人伤澄清后所有字段齐全,直接双车拍照。
|
||||
# 人伤澄清后确认完整时间,用户确认后直接双车拍照。
|
||||
- input: 看清楚了,没有人受伤。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: direct_collection_skip_known_info_single_all_info
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -14,7 +14,13 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 信息齐全,直接引导拍摄车辆前方;不得再确认时间、数量、人伤或在场情况。
|
||||
# 其他信息齐全,先确认完整时间;确认后直接单车拍照。
|
||||
- input: 十分钟前我倒车撞到护栏,事故只有一辆汽车,没有人受伤,没有撞到非机动车或行人,我还在事故现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: direct_collection_skip_known_info_single_no_inferred_count
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016 的事故信息收集提示词。
|
||||
# runner 仅校验状态码;以下注释中的提问内容需结合输出对话手动核对。
|
||||
# 对应 workflow/20261021 的事故信息收集提示词。
|
||||
# 时间确认由回复断言检查;其余注释要求结合对话核对。
|
||||
steps:
|
||||
# 新会话返回安全准备提示。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 只询问机动车数量,不能从撞护栏推断只有一辆车;不得重问其他字段。
|
||||
# 先确认完整时间,再询问缺失的机动车数量;不能从撞护栏推断只有一辆车。
|
||||
- input: 十分钟前我倒车撞到了护栏,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 明确数量后直接单车拍照,不再要求数量确认。
|
||||
|
||||
- input: 只有一辆汽车。
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
name: direct_initial_stage
|
||||
clientMode: direct
|
||||
|
||||
steps:
|
||||
- input: 新对话
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: 继续办理
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前两车追尾
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2011"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2012"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2013"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2014"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2015"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2016"
|
||||
|
||||
- input: 没错
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 李四
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 移交完毕
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 刘云
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对的
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 是
|
||||
expect:
|
||||
stageCode: "0000"
|
||||
@@ -1,89 +0,0 @@
|
||||
name: direct_confirm_dual_no_false_0002
|
||||
clientMode: direct
|
||||
|
||||
# During dual-car info confirm (3002 -> external 1002), short/garbled answers
|
||||
# must stay on 1002, not jump to 0002 after a few unclear turns.
|
||||
steps:
|
||||
- input: 新对话
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: 继续办理
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前两车追尾
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2011"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2012"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2013"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2014"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2015"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2016"
|
||||
|
||||
- input: 没错
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 李四
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 这个
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 试试
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 什么意思
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
@@ -1,81 +0,0 @@
|
||||
name: direct_confirm_dual_no_false_0003
|
||||
clientMode: direct
|
||||
|
||||
# During dual-car info confirm, ASR damage/garbled injury-like words must not
|
||||
# jump to 0003; stay on 1002 (closed confirm / continue current question).
|
||||
steps:
|
||||
- input: 新对话
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: 继续办理
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前两车追尾
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2011"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2012"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2013"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2014"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2015"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2016"
|
||||
|
||||
- input: 没错
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 不,刚摧毁了
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 伤……没有吧
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
@@ -1,81 +0,0 @@
|
||||
name: direct_confirm_single_no_false_0002
|
||||
clientMode: direct
|
||||
|
||||
# During single-car info confirm (3001 -> external 1002), short/garbled answers
|
||||
# must stay on 1002, not jump to 0002 after a few unclear turns.
|
||||
steps:
|
||||
- input: 新对话
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: 继续办理
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前一辆车撞到护栏
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2001"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2002"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2003"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2004"
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: "2005"
|
||||
|
||||
- input: 前方
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 张三
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 这个
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 试试
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 什么意思
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
@@ -1,73 +0,0 @@
|
||||
name: direct_confirm_single_no_false_0003
|
||||
clientMode: direct
|
||||
|
||||
# During single-car info confirm, ASR damage/garbled injury-like words must not
|
||||
# jump to 0003; stay on 1002 (closed confirm / continue current question).
|
||||
steps:
|
||||
- input: 新对话
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: 继续办理
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前一辆车撞到护栏
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2001"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2002"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2003"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2004"
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: "2005"
|
||||
|
||||
- input: 前方
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 不,刚摧毁了
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 伤……没有吧
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
@@ -1,77 +0,0 @@
|
||||
name: direct_photo_dual_no_false_0002
|
||||
clientMode: direct
|
||||
|
||||
# At dual-car plate confirm (2016), short/garbled answers must stay on 2016,
|
||||
# not jump to 0002 after a few unclear turns.
|
||||
steps:
|
||||
- input: 新对话
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: 继续办理
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前两车追尾
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2011"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2012"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2013"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2014"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2015"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2016"
|
||||
|
||||
- input: 这个
|
||||
expect:
|
||||
stageCode: "2016"
|
||||
|
||||
- input: 试试
|
||||
expect:
|
||||
stageCode: "2016"
|
||||
|
||||
- input: 什么意思
|
||||
expect:
|
||||
stageCode: "2016"
|
||||
@@ -1,81 +0,0 @@
|
||||
name: direct_photo_single_no_false_0002
|
||||
clientMode: direct
|
||||
|
||||
# At single-car plate/damage confirm, short/garbled answers must stay on 2004/2005,
|
||||
# not jump to 0002 after a few unclear turns.
|
||||
steps:
|
||||
- input: 新对话
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: 继续办理
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前一辆车撞到护栏
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2001"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2002"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2003"
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2004"
|
||||
|
||||
- input: 这个
|
||||
expect:
|
||||
stageCode: "2004"
|
||||
|
||||
- input: 试试
|
||||
expect:
|
||||
stageCode: "2004"
|
||||
|
||||
- input: 是的
|
||||
expect:
|
||||
stageCode: "2005"
|
||||
|
||||
- input: 这个
|
||||
expect:
|
||||
stageCode: "2005"
|
||||
|
||||
- input: 试试
|
||||
expect:
|
||||
stageCode: "2005"
|
||||
|
||||
- input: 什么意思
|
||||
expect:
|
||||
stageCode: "2005"
|
||||
@@ -0,0 +1,24 @@
|
||||
# 流程回归:非机动车撞固定物按本组口径机动车数量为0,检查事实保持、时间确认及0003分流。
|
||||
name: browser_addon_non_motor_vehicle_all_info
|
||||
clientMode: browser_addon
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "browser_addon.1001"
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
- input: "十分钟前我骑非机动车自己撞在路边石墩上,只有我这一辆非机动车,没有其他车辆或行人,没有人员伤亡,我还在现场。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"has_injury":false,"is_on_scene":true,"vehicle_count":0}
|
||||
formMatches: {"accident_cause":"^其他:(?=.*非机动车)(?=.*石墩).+"}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.0003"
|
||||
form: {"vehicle_count":0}
|
||||
replyNotMatches: "[??]"
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# 电动自行车撞固定物:按本组口径机动车数量为0,完成时间确认及现场采集后进入0003,不追问汽车数量。
|
||||
name: browser_addon_non_motor_vehicle_electric_bicycle
|
||||
clientMode: browser_addon
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "browser_addon.1001"
|
||||
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: "我骑的是非机动车,电动自行车,撞到了路边的石墩子上。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
replyMatches: "(有没有|是否).*受伤"
|
||||
|
||||
- input: "没有人员伤亡。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_injury":false,"vehicle_count":0}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
replyNotMatches: "(几辆|数量|是否.*非机动车|有没有.*非机动车)"
|
||||
|
||||
- input: "十分钟前发生的。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: "对的。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "现场"
|
||||
replyNotMatches: "几辆|数量|这个时间对吗"
|
||||
|
||||
- input: "我还在事故现场。"
|
||||
expect:
|
||||
stageCode: "browser_addon.0003"
|
||||
form: {"has_non_motor_vehicle_hit":true,"has_injury":false,"is_on_scene":true,"vehicle_count":0}
|
||||
replyMatches: "转接.*(人工|警员)|转.*人工"
|
||||
replyNotMatches: "几辆|数量|这个时间对吗"
|
||||
@@ -0,0 +1,33 @@
|
||||
# 非机动车撞固定物时机动车数量为0;用户明确更正为一辆汽车后,数量更新为1。
|
||||
name: browser_addon_non_motor_vehicle_explicit_correction
|
||||
clientMode: browser_addon
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "browser_addon.1001"
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
- input: "我这里是一辆非机动车,撞到了路边的石墩子上。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
formMatches: {"accident_cause":"^其他:(?=.*非机动车)(?=.*石墩).+"}
|
||||
formAbsent: ["has_injury","accident_time","is_on_scene"]
|
||||
replyMatches: "(有没有|是否).*受伤"
|
||||
- input: "刚才说错了,我的是汽车,不是非机动车,事故只有我这一辆汽车,没有涉及非机动车或行人。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":false,"vehicle_count":1}
|
||||
replyMatches: "(有没有|是否).*受伤"
|
||||
- input: "没有人员受伤,十分钟前发生的,我还在事故现场。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":false,"vehicle_count":1,"has_injury":false,"is_on_scene":true}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2000"
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# 流程回归:非机动车撞固定物按本组口径机动车数量为0,检查事实保持、时间确认及0003分流。
|
||||
name: browser_addon_non_motor_vehicle_no_other_vehicle
|
||||
clientMode: browser_addon
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "browser_addon.1001"
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
- input: "我现在没有按住说话,为什么也会记录进去?是不是有bug?"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
formAbsent: ["has_injury","has_non_motor_vehicle_hit","vehicle_count","accident_cause","accident_time","is_on_scene"]
|
||||
- input: "我这里是一辆非机动车,撞到了路边的石墩子上。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
formMatches: {"accident_cause":"^其他:(?=.*非机动车)(?=.*石墩).+"}
|
||||
formAbsent: ["has_injury","accident_time","is_on_scene"]
|
||||
replyMatches: "(有没有|是否).*受伤"
|
||||
- input: "没有人员伤亡。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_injury":false,"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
replyNotMatches: "(有没有|是否).*非机动车"
|
||||
- input: "我已经说过了,是撞在石墩子上,没有别的车子,就我自己的车子。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
formMatches: {"accident_cause":"^其他:(?=.*非机动车)(?=.*石墩).+"}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
- input: "十分钟前。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "现场"
|
||||
|
||||
|
||||
- input: "我还在事故现场。"
|
||||
expect:
|
||||
stageCode: "browser_addon.0003"
|
||||
form: {"has_non_motor_vehicle_hit":true,"is_on_scene":true,"vehicle_count":0}
|
||||
@@ -0,0 +1,46 @@
|
||||
# 流程回归:非机动车撞固定物按本组口径机动车数量为0,检查事实保持、时间确认及0003分流。
|
||||
name: browser_addon_non_motor_vehicle_self_collision
|
||||
clientMode: browser_addon
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "browser_addon.1001"
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
- input: "我这个是非机动车,然后自己撞在路边的石墩子上。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
formMatches: {"accident_cause":"^其他:(?=.*非机动车)(?=.*石墩).+"}
|
||||
formAbsent: ["has_injury","accident_time","is_on_scene"]
|
||||
replyMatches: "(有没有|是否).*受伤"
|
||||
- input: "没有人员伤亡。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_injury":false,"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
replyNotMatches: "(有没有|是否).*非机动车"
|
||||
- input: "没有别的车子,就我自己的车子。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
- input: "十分钟前发生的。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "现场"
|
||||
|
||||
|
||||
- input: "我还在事故现场。"
|
||||
expect:
|
||||
stageCode: "browser_addon.0003"
|
||||
form: {"has_non_motor_vehicle_hit":true,"is_on_scene":true,"vehicle_count":0}
|
||||
@@ -0,0 +1,17 @@
|
||||
# 提取专项:明确只有非机动车时必须向前端发送机动车数量0,不能被空值比较吞掉。
|
||||
name: browser_addon_non_motor_vehicle_zero_count_bundle
|
||||
clientMode: browser_addon
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "browser_addon.1001"
|
||||
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: "十分钟前我骑非机动车自己撞在路边石墩上,只有我这一辆非机动车,没有其他车辆或行人,没有人员伤亡,我还在现场。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"vehicle_count":0}
|
||||
@@ -0,0 +1,27 @@
|
||||
# 提取专项:非机动车撞固定物按本组口径记录机动车数量0,后续补充“没有别的车”时保留0和非机动车事实。
|
||||
name: browser_addon_non_motor_vehicle_zero_count_history
|
||||
clientMode: browser_addon
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "browser_addon.1001"
|
||||
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: "我这里是一辆非机动车,撞到了路边的石墩子上。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
|
||||
- input: "没有人员伤亡。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"vehicle_count":0}
|
||||
|
||||
- input: "我已经说过了,是撞在石墩子上,没有别的车子,就我自己的车子。"
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
@@ -0,0 +1,24 @@
|
||||
# 流程回归:非机动车撞固定物按本组口径机动车数量为0,检查事实保持、时间确认及0003分流。
|
||||
name: direct_non_motor_vehicle_all_info
|
||||
clientMode: direct
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
- input: "十分钟前我骑非机动车自己撞在路边石墩上,只有我这一辆非机动车,没有其他车辆或行人,没有人员伤亡,我还在现场。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"has_injury":false,"is_on_scene":true,"vehicle_count":0}
|
||||
formMatches: {"accident_cause":"^其他:(?=.*非机动车)(?=.*石墩).+"}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "0003"
|
||||
form: {"vehicle_count":0}
|
||||
replyNotMatches: "[??]"
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# 电动自行车撞固定物:按本组口径机动车数量为0,完成时间确认及现场采集后进入0003,不追问汽车数量。
|
||||
name: direct_non_motor_vehicle_electric_bicycle
|
||||
clientMode: direct
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: "我骑的是非机动车,电动自行车,撞到了路边的石墩子上。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
replyMatches: "(有没有|是否).*受伤"
|
||||
|
||||
- input: "没有人员伤亡。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_injury":false,"vehicle_count":0}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
replyNotMatches: "(几辆|数量|是否.*非机动车|有没有.*非机动车)"
|
||||
|
||||
- input: "十分钟前发生的。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: "对的。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "现场"
|
||||
replyNotMatches: "几辆|数量|这个时间对吗"
|
||||
|
||||
- input: "我还在事故现场。"
|
||||
expect:
|
||||
stageCode: "0003"
|
||||
form: {"has_non_motor_vehicle_hit":true,"has_injury":false,"is_on_scene":true,"vehicle_count":0}
|
||||
replyMatches: "转接.*(人工|警员)|转.*人工"
|
||||
replyNotMatches: "几辆|数量|这个时间对吗"
|
||||
@@ -0,0 +1,33 @@
|
||||
# 非机动车撞固定物时机动车数量为0;用户明确更正为一辆汽车后,数量更新为1。
|
||||
name: direct_non_motor_vehicle_explicit_correction
|
||||
clientMode: direct
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
- input: "我这里是一辆非机动车,撞到了路边的石墩子上。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
formMatches: {"accident_cause":"^其他:(?=.*非机动车)(?=.*石墩).+"}
|
||||
formAbsent: ["has_injury","accident_time","is_on_scene"]
|
||||
replyMatches: "(有没有|是否).*受伤"
|
||||
- input: "刚才说错了,我的是汽车,不是非机动车,事故只有我这一辆汽车,没有涉及非机动车或行人。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":false,"vehicle_count":1}
|
||||
replyMatches: "(有没有|是否).*受伤"
|
||||
- input: "没有人员受伤,十分钟前发生的,我还在事故现场。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":false,"vehicle_count":1,"has_injury":false,"is_on_scene":true}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# 流程回归:非机动车撞固定物按本组口径机动车数量为0,检查事实保持、时间确认及0003分流。
|
||||
name: direct_non_motor_vehicle_no_other_vehicle
|
||||
clientMode: direct
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
- input: "我现在没有按住说话,为什么也会记录进去?是不是有bug?"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
formAbsent: ["has_injury","has_non_motor_vehicle_hit","vehicle_count","accident_cause","accident_time","is_on_scene"]
|
||||
- input: "我这里是一辆非机动车,撞到了路边的石墩子上。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
formMatches: {"accident_cause":"^其他:(?=.*非机动车)(?=.*石墩).+"}
|
||||
formAbsent: ["has_injury","accident_time","is_on_scene"]
|
||||
replyMatches: "(有没有|是否).*受伤"
|
||||
- input: "没有人员伤亡。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_injury":false,"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
replyNotMatches: "(有没有|是否).*非机动车"
|
||||
- input: "我已经说过了,是撞在石墩子上,没有别的车子,就我自己的车子。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
formMatches: {"accident_cause":"^其他:(?=.*非机动车)(?=.*石墩).+"}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
- input: "十分钟前。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "现场"
|
||||
|
||||
|
||||
- input: "我还在事故现场。"
|
||||
expect:
|
||||
stageCode: "0003"
|
||||
form: {"has_non_motor_vehicle_hit":true,"is_on_scene":true,"vehicle_count":0}
|
||||
@@ -0,0 +1,46 @@
|
||||
# 流程回归:非机动车撞固定物按本组口径机动车数量为0,检查事实保持、时间确认及0003分流。
|
||||
name: direct_non_motor_vehicle_self_collision
|
||||
clientMode: direct
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
- input: "我这个是非机动车,然后自己撞在路边的石墩子上。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
formMatches: {"accident_cause":"^其他:(?=.*非机动车)(?=.*石墩).+"}
|
||||
formAbsent: ["has_injury","accident_time","is_on_scene"]
|
||||
replyMatches: "(有没有|是否).*受伤"
|
||||
- input: "没有人员伤亡。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_injury":false,"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
replyNotMatches: "(有没有|是否).*非机动车"
|
||||
- input: "没有别的车子,就我自己的车子。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
replyMatches: "(什么时候|几点|事故.*时间)"
|
||||
- input: "十分钟前发生的。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"vehicle_count":0}
|
||||
replyMatches: "现场"
|
||||
|
||||
|
||||
- input: "我还在事故现场。"
|
||||
expect:
|
||||
stageCode: "0003"
|
||||
form: {"has_non_motor_vehicle_hit":true,"is_on_scene":true,"vehicle_count":0}
|
||||
@@ -0,0 +1,17 @@
|
||||
# 提取专项:明确只有非机动车时必须向前端发送机动车数量0,不能被空值比较吞掉。
|
||||
name: direct_non_motor_vehicle_zero_count_bundle
|
||||
clientMode: direct
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: "十分钟前我骑非机动车自己撞在路边石墩上,只有我这一辆非机动车,没有其他车辆或行人,没有人员伤亡,我还在现场。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"vehicle_count":0}
|
||||
@@ -0,0 +1,27 @@
|
||||
# 提取专项:非机动车撞固定物按本组口径记录机动车数量0,后续补充“没有别的车”时保留0和非机动车事实。
|
||||
name: direct_non_motor_vehicle_zero_count_history
|
||||
clientMode: direct
|
||||
|
||||
steps:
|
||||
- input: "【开始】"
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: "继续办理"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: "我这里是一辆非机动车,撞到了路边的石墩子上。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
|
||||
- input: "没有人员伤亡。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"vehicle_count":0}
|
||||
|
||||
- input: "我已经说过了,是撞在石墩子上,没有别的车子,就我自己的车子。"
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {"has_non_motor_vehicle_hit":true,"vehicle_count":0}
|
||||
@@ -1,8 +1,8 @@
|
||||
name: browser_addon_photo_button_guidance_dual_failure
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016 拍照提示词;每个文件使用独立会话。
|
||||
# runner 只校验状态码,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
# 对应 workflow/20261021 拍照提示词;每个文件使用独立会话。
|
||||
# runner 校验状态码和时间确认,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 事故信息齐全,直接进入拍照,只输出原有固定指令,不主动追加按钮说明。
|
||||
# 先确认完整事故时间,确认后进入拍照,不主动追加按钮说明。
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
# 说明界面中间的拍照按钮并保留当前固定拍摄指令。
|
||||
|
||||
- input: 拍照按钮在哪?
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: browser_addon_photo_button_guidance_dual_guidance
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016 拍照提示词;每个文件使用独立会话。
|
||||
# runner 只校验状态码,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
# 对应 workflow/20261021 拍照提示词;每个文件使用独立会话。
|
||||
# runner 校验状态码和时间确认,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 事故信息齐全,直接进入拍照,只输出原有固定指令,不主动追加按钮说明。
|
||||
# 先确认完整事故时间,确认后进入拍照,不主动追加按钮说明。
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
# 必须说明可点击手机界面中间的拍照按钮,并完整保留当前固定指令(第一辆车侧前方、看清车牌);不得推进。
|
||||
|
||||
- input: 拍照按钮在哪?
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
@@ -2,7 +2,7 @@ name: browser_addon_photo_button_guidance_dual_no_repeat
|
||||
clientMode: browser_addon
|
||||
|
||||
# 回归:解释一次按钮后,正常推进不再重复;明确再次求助仍可解释。
|
||||
# runner 只校验状态码,按钮说明是否重复必须手动检查输出对话。
|
||||
# runner 校验状态码和时间确认,按钮说明是否重复必须手动检查输出对话。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 只输出原有拍摄指令,不主动附加按钮说明。
|
||||
# 先确认完整事故时间,确认后只输出原有拍摄指令。
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
# 首次笼统求助可说明一次界面中间的拍照按钮,保留固定指令。
|
||||
|
||||
- input: 这个什么
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: browser_addon_photo_button_guidance_single_failure
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016 拍照提示词;每个文件使用独立会话。
|
||||
# runner 只校验状态码,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
# 对应 workflow/20261021 拍照提示词;每个文件使用独立会话。
|
||||
# runner 校验状态码和时间确认,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 事故信息齐全,直接进入拍照,只输出原有固定指令,不主动追加按钮说明。
|
||||
# 先确认完整事故时间,确认后进入拍照,不主动追加按钮说明。
|
||||
- input: 十分钟前我倒车撞到了护栏,事故只有一辆汽车,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2000"
|
||||
|
||||
# 说明界面中间的拍照按钮并保留当前固定拍摄指令。
|
||||
|
||||
- input: 拍照按钮在哪?
|
||||
expect:
|
||||
stageCode: "browser_addon.2000"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: browser_addon_photo_button_guidance_single_guidance
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016 拍照提示词;每个文件使用独立会话。
|
||||
# runner 只校验状态码,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
# 对应 workflow/20261021 拍照提示词;每个文件使用独立会话。
|
||||
# runner 校验状态码和时间确认,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 事故信息齐全,直接进入拍照,只输出原有固定指令,不主动追加按钮说明。
|
||||
# 先确认完整事故时间,确认后进入拍照,不主动追加按钮说明。
|
||||
- input: 十分钟前我倒车撞到了护栏,事故只有一辆汽车,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2000"
|
||||
|
||||
# 必须说明可点击手机界面中间的拍照按钮,并完整保留当前固定指令(车辆前方);不得推进。
|
||||
|
||||
- input: 拍照按钮在哪?
|
||||
expect:
|
||||
stageCode: "browser_addon.2000"
|
||||
|
||||
@@ -2,7 +2,7 @@ name: browser_addon_photo_button_guidance_single_no_repeat
|
||||
clientMode: browser_addon
|
||||
|
||||
# 回归:解释一次按钮后,正常推进不再重复;明确再次求助仍可解释。
|
||||
# runner 只校验状态码,按钮说明是否重复必须手动检查输出对话。
|
||||
# runner 校验状态码和时间确认,按钮说明是否重复必须手动检查输出对话。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
# 只输出原有拍摄指令,不主动附加按钮说明。
|
||||
# 先确认完整事故时间,确认后只输出原有拍摄指令。
|
||||
- input: 十分钟前我倒车撞到护栏,只有一辆汽车,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.2000"
|
||||
|
||||
# 首次笼统求助可说明一次界面中间的拍照按钮,保留固定指令。
|
||||
|
||||
- input: 这个什么
|
||||
expect:
|
||||
stageCode: "browser_addon.2000"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: direct_photo_button_guidance_dual_failure
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016 拍照提示词;每个文件使用独立会话。
|
||||
# runner 只校验状态码,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
# 对应 workflow/20261021 拍照提示词;每个文件使用独立会话。
|
||||
# runner 校验状态码和时间确认,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 事故信息齐全,直接进入拍照,只输出原有固定指令,不主动追加按钮说明。
|
||||
# 先确认完整事故时间,确认后进入拍照,不主动追加按钮说明。
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
# 说明界面中间的拍照按钮并保留当前固定拍摄指令。
|
||||
|
||||
- input: 拍照按钮在哪?
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: direct_photo_button_guidance_dual_guidance
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016 拍照提示词;每个文件使用独立会话。
|
||||
# runner 只校验状态码,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
# 对应 workflow/20261021 拍照提示词;每个文件使用独立会话。
|
||||
# runner 校验状态码和时间确认,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 事故信息齐全,直接进入拍照,只输出原有固定指令,不主动追加按钮说明。
|
||||
# 先确认完整事故时间,确认后进入拍照,不主动追加按钮说明。
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
# 必须说明可点击手机界面中间的拍照按钮,并完整保留当前固定指令(第一辆车侧前方、看清车牌);不得推进。
|
||||
|
||||
- input: 拍照按钮在哪?
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
@@ -2,7 +2,7 @@ name: direct_photo_button_guidance_dual_no_repeat
|
||||
clientMode: direct
|
||||
|
||||
# 回归:解释一次按钮后,正常推进不再重复;明确再次求助仍可解释。
|
||||
# runner 只校验状态码,按钮说明是否重复必须手动检查输出对话。
|
||||
# runner 校验状态码和时间确认,按钮说明是否重复必须手动检查输出对话。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 只输出原有拍摄指令,不主动附加按钮说明。
|
||||
# 先确认完整事故时间,确认后只输出原有拍摄指令。
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
# 首次笼统求助可说明一次界面中间的拍照按钮,保留固定指令。
|
||||
|
||||
- input: 这个什么
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: direct_photo_button_guidance_single_failure
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016 拍照提示词;每个文件使用独立会话。
|
||||
# runner 只校验状态码,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
# 对应 workflow/20261021 拍照提示词;每个文件使用独立会话。
|
||||
# runner 校验状态码和时间确认,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 事故信息齐全,直接进入拍照,只输出原有固定指令,不主动追加按钮说明。
|
||||
# 先确认完整事故时间,确认后进入拍照,不主动追加按钮说明。
|
||||
- input: 十分钟前我倒车撞到了护栏,事故只有一辆汽车,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
# 说明界面中间的拍照按钮并保留当前固定拍摄指令。
|
||||
|
||||
- input: 拍照按钮在哪?
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: direct_photo_button_guidance_single_guidance
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016 拍照提示词;每个文件使用独立会话。
|
||||
# runner 只校验状态码,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
# 对应 workflow/20261021 拍照提示词;每个文件使用独立会话。
|
||||
# runner 校验状态码和时间确认,按钮位置、固定话术及结束后不再提示按钮需结合对话记录手动检查。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 事故信息齐全,直接进入拍照,只输出原有固定指令,不主动追加按钮说明。
|
||||
# 先确认完整事故时间,确认后进入拍照,不主动追加按钮说明。
|
||||
- input: 十分钟前我倒车撞到了护栏,事故只有一辆汽车,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
# 必须说明可点击手机界面中间的拍照按钮,并完整保留当前固定指令(车辆前方);不得推进。
|
||||
|
||||
- input: 拍照按钮在哪?
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
@@ -2,7 +2,7 @@ name: direct_photo_button_guidance_single_no_repeat
|
||||
clientMode: direct
|
||||
|
||||
# 回归:解释一次按钮后,正常推进不再重复;明确再次求助仍可解释。
|
||||
# runner 只校验状态码,按钮说明是否重复必须手动检查输出对话。
|
||||
# runner 校验状态码和时间确认,按钮说明是否重复必须手动检查输出对话。
|
||||
steps:
|
||||
# 新会话。
|
||||
- input: 新对话
|
||||
@@ -14,12 +14,19 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
# 只输出原有拍摄指令,不主动附加按钮说明。
|
||||
# 先确认完整事故时间,确认后只输出原有拍摄指令。
|
||||
- input: 十分钟前我倒车撞到护栏,只有一辆汽车,没有人受伤,没有撞到非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
# 首次笼统求助可说明一次界面中间的拍照按钮,保留固定指令。
|
||||
|
||||
- input: 这个什么
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: browser_addon_photo_skip_plate_confirm_dual
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016;每个案例使用独立会话。
|
||||
# 对应 workflow/20261021;每个案例使用独立会话。
|
||||
# 本人照片完成后直接结束拍照,不经过 2016。
|
||||
# direct 的内部 3001/3002 对外映射为 1002。
|
||||
steps:
|
||||
@@ -13,34 +13,16 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 两辆汽车发生了追尾。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 十分钟之前
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤,没有涉及非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 是的,我还在事故现场
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 两辆汽车
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "browser_addon.2011"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: browser_addon_photo_skip_plate_confirm_single
|
||||
clientMode: browser_addon
|
||||
|
||||
# 对应 workflow/20261016;每个案例使用独立会话。
|
||||
# 对应 workflow/20261021;每个案例使用独立会话。
|
||||
# 本人照片完成后直接进入车损位置确认 2005,不经过 2004。
|
||||
# direct 的内部 3001/3002 对外映射为 1002。
|
||||
steps:
|
||||
@@ -13,34 +13,16 @@ steps:
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 我倒车撞到了护栏,涉及一辆汽车。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 十分钟之前
|
||||
- input: 十分钟前我倒车撞到护栏,只有一辆汽车,没有人受伤,没有涉及非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 是的,我还在事故现场
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 一辆汽车
|
||||
expect:
|
||||
stageCode: "browser_addon.2000"
|
||||
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "browser_addon.2001"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
name: direct_photo_skip_plate_confirm_dual
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016;每个案例使用独立会话。
|
||||
# 对应 workflow/20261021;每个案例使用独立会话。
|
||||
# 本人照片完成后直接结束拍照,不经过 2016。
|
||||
# 手动检查:最后一次拍摄完成的回复同时说明进入信息确认,并询问第一辆车是否由本人驾驶。
|
||||
# 紧接着回答“是的”后应询问姓名,不应再次询问驾驶员身份。
|
||||
# 回答“李四”后应核实身份证后四位;runner 仅校验状态码,以上正文需查看对话记录。
|
||||
# 回答“李四”后应核实身份证后四位;runner 校验状态码和时间确认,身份确认正文需查看对话记录。
|
||||
# direct 的内部 3001/3002 对外映射为 1002。
|
||||
steps:
|
||||
- input: 新对话
|
||||
@@ -16,34 +16,16 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 两辆汽车发生了追尾。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤,没有涉及非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 是的,我还在事故现场
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 两辆汽车
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2011"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: direct_photo_skip_plate_confirm_single
|
||||
clientMode: direct
|
||||
|
||||
# 对应 workflow/20261016;每个案例使用独立会话。
|
||||
# 对应 workflow/20261021;每个案例使用独立会话。
|
||||
# 本人照片完成后直接进入车损位置确认 2005,不经过 2004。
|
||||
# direct 的内部 3001/3002 对外映射为 1002。
|
||||
steps:
|
||||
@@ -13,34 +13,16 @@ steps:
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 我倒车撞到了护栏,涉及一辆汽车。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 没有
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟之前
|
||||
- input: 十分钟前我倒车撞到护栏,只有一辆汽车,没有人受伤,没有涉及非机动车或行人,我还在现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 对
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 是的,我还在事故现场
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 一辆汽车
|
||||
expect:
|
||||
stageCode: "2000"
|
||||
|
||||
|
||||
- input: 【拍摄完成】
|
||||
expect:
|
||||
stageCode: "2001"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# 必须独立确认完整时间;补充在场信息不算确认,更正后重新确认。
|
||||
name: browser_addon_time_confirmation_correction
|
||||
clientMode: browser_addon
|
||||
|
||||
steps:
|
||||
- input: 新对话
|
||||
expect:
|
||||
stageCode: "browser_addon.1001"
|
||||
|
||||
- input: 继续办理
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤,没有涉及非机动车或行人。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
replyNotMatches: "现场|拍照"
|
||||
|
||||
- input: 我还在事故现场。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {is_on_scene: true}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 不对,事故时间是2025年1月1日8点30分。
|
||||
expect:
|
||||
stageCode: "browser_addon.1002"
|
||||
form: {accident_time: "2025年1月1日8点30分"}
|
||||
replyMatches: "我记录的时间是2025年0?1月0?1日0?8点30分.*这个时间对吗"
|
||||
replyNotMatches: "现场|拍照"
|
||||
|
||||
- input: 对,就是这个时间。
|
||||
expect:
|
||||
stageCode: "browser_addon.2010"
|
||||
form: {accident_time: "2025年1月1日8点30分", is_on_scene: true}
|
||||
replyNotMatches: "这个时间对吗|还在.*现场"
|
||||
@@ -0,0 +1,37 @@
|
||||
# 必须独立确认完整时间;补充在场信息不算确认,更正后重新确认。
|
||||
name: direct_time_confirmation_correction
|
||||
clientMode: direct
|
||||
|
||||
steps:
|
||||
- input: 新对话
|
||||
expect:
|
||||
stageCode: "1001"
|
||||
|
||||
- input: 继续办理
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
|
||||
- input: 十分钟前两辆汽车追尾,没有人受伤,没有涉及非机动车或行人。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
replyNotMatches: "现场|拍照"
|
||||
|
||||
- input: 我还在事故现场。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {is_on_scene: true}
|
||||
replyMatches: "我记录的时间是.*年.*月.*日.*点.*分.*这个时间对吗"
|
||||
|
||||
- input: 不对,事故时间是2025年1月1日8点30分。
|
||||
expect:
|
||||
stageCode: "1002"
|
||||
form: {accident_time: "2025年1月1日8点30分"}
|
||||
replyMatches: "我记录的时间是2025年0?1月0?1日0?8点30分.*这个时间对吗"
|
||||
replyNotMatches: "现场|拍照"
|
||||
|
||||
- input: 对,就是这个时间。
|
||||
expect:
|
||||
stageCode: "2010"
|
||||
form: {accident_time: "2025年1月1日8点30分", is_on_scene: true}
|
||||
replyNotMatches: "这个时间对吗|还在.*现场"
|
||||
+78
-5
@@ -25,6 +25,7 @@ class ChatResult:
|
||||
stage_codes: list[str]
|
||||
errors: list[dict]
|
||||
text: str = ""
|
||||
form_update: dict = field(default_factory=dict)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -37,6 +38,9 @@ class TranscriptTurn:
|
||||
errors: list[dict]
|
||||
ok: bool
|
||||
error: str | None = None
|
||||
form_update: dict = field(default_factory=dict)
|
||||
form: dict = field(default_factory=dict)
|
||||
expectations: dict = field(default_factory=dict)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -88,6 +92,25 @@ def load_cases(cases_dir: Path, name_filters: list[str]) -> list[dict]:
|
||||
f"{path}: step {index} expect.stageCode is required"
|
||||
)
|
||||
|
||||
expect = step["expect"]
|
||||
for key in ("form", "formMatches"):
|
||||
if key in expect and not isinstance(expect[key], dict):
|
||||
raise ValueError(f"{path}: step {index} expect.{key} must be an object")
|
||||
for pattern in expect.get("formMatches", {}).values():
|
||||
if not isinstance(pattern, str):
|
||||
raise ValueError(f"{path}: step {index} formMatches values must be regex strings")
|
||||
re.compile(pattern)
|
||||
if "formAbsent" in expect and (
|
||||
not isinstance(expect["formAbsent"], list)
|
||||
or not all(isinstance(key, str) for key in expect["formAbsent"])
|
||||
):
|
||||
raise ValueError(f"{path}: step {index} expect.formAbsent must be a list of keys")
|
||||
for key in ("replyMatches", "replyNotMatches"):
|
||||
if key in expect:
|
||||
if not isinstance(expect[key], str):
|
||||
raise ValueError(f"{path}: step {index} expect.{key} must be a regex string")
|
||||
re.compile(expect[key])
|
||||
|
||||
if name_filters and not any(value in name for value in name_filters):
|
||||
continue
|
||||
|
||||
@@ -103,6 +126,7 @@ def parse_sse(response: httpx.Response) -> ChatResult:
|
||||
stage_codes: list[str] = []
|
||||
errors: list[dict] = []
|
||||
text_parts: list[str] = []
|
||||
form_update: dict = {}
|
||||
event_name = ""
|
||||
data_lines: list[str] = []
|
||||
|
||||
@@ -116,6 +140,10 @@ def parse_sse(response: httpx.Response) -> ChatResult:
|
||||
chunk = payload.get("text")
|
||||
if isinstance(chunk, str) and chunk:
|
||||
text_parts.append(chunk)
|
||||
elif event_name == "formUpdate":
|
||||
if not isinstance(payload, dict):
|
||||
raise ValueError("formUpdate SSE payload must be an object")
|
||||
form_update.update(payload)
|
||||
elif event_name == "error":
|
||||
errors.append(payload)
|
||||
event_name = ""
|
||||
@@ -134,6 +162,7 @@ def parse_sse(response: httpx.Response) -> ChatResult:
|
||||
stage_codes=stage_codes,
|
||||
errors=errors,
|
||||
text="".join(text_parts),
|
||||
form_update=form_update,
|
||||
)
|
||||
|
||||
|
||||
@@ -143,6 +172,7 @@ def run_chat_step(
|
||||
session_id: str,
|
||||
client_mode: str,
|
||||
text: str,
|
||||
need_form_update: bool = False,
|
||||
) -> ChatResult:
|
||||
with client.stream(
|
||||
"POST",
|
||||
@@ -153,7 +183,7 @@ def run_chat_step(
|
||||
"timeStamp": timestamp(),
|
||||
"text": text,
|
||||
"clientMode": client_mode,
|
||||
"needFormUpdate": False,
|
||||
"needFormUpdate": need_form_update,
|
||||
"useTextChunk": False,
|
||||
},
|
||||
) as response:
|
||||
@@ -194,6 +224,10 @@ def print_turn(turn: TranscriptTurn) -> None:
|
||||
f" stage: expected={turn.expected_stage_code} "
|
||||
f"actual={turn.actual_stage_codes}"
|
||||
)
|
||||
if turn.expectations.keys() - {"stageCode"}:
|
||||
print(f" expect: {turn.expectations}")
|
||||
if turn.form_update or turn.form:
|
||||
print(f" formUpdate: {turn.form_update}; form: {turn.form}")
|
||||
if turn.error:
|
||||
print(f" error: {turn.error}")
|
||||
if turn.errors:
|
||||
@@ -224,6 +258,10 @@ def transcript_to_markdown(transcript: CaseTranscript) -> str:
|
||||
f"- actual stageCodes: `{turn.actual_stage_codes}`",
|
||||
]
|
||||
)
|
||||
if turn.expectations.keys() - {"stageCode"}:
|
||||
lines.append(f"- expectations: `{json.dumps(turn.expectations, ensure_ascii=False)}`")
|
||||
lines.append(f"- formUpdate: `{json.dumps(turn.form_update, ensure_ascii=False)}`")
|
||||
lines.append(f"- cumulative form: `{json.dumps(turn.form, ensure_ascii=False)}`")
|
||||
if turn.error:
|
||||
lines.append(f"- error: `{turn.error}`")
|
||||
if turn.errors:
|
||||
@@ -256,6 +294,9 @@ def transcript_to_json(transcript: CaseTranscript) -> dict:
|
||||
"errors": turn.errors,
|
||||
"ok": turn.ok,
|
||||
"error": turn.error,
|
||||
"expectations": turn.expectations,
|
||||
"formUpdate": turn.form_update,
|
||||
"form": turn.form,
|
||||
}
|
||||
for turn in transcript.turns
|
||||
],
|
||||
@@ -280,6 +321,27 @@ def save_transcript(output_dir: Path, transcript: CaseTranscript) -> Path:
|
||||
return md_path
|
||||
|
||||
|
||||
def check_expectations(result: ChatResult, expect: dict, form: dict) -> list[str]:
|
||||
failures = []
|
||||
if result.stage_codes != [expect["stageCode"]]:
|
||||
failures.append("stageCode mismatch")
|
||||
if result.errors:
|
||||
failures.append("SSE errors returned")
|
||||
for key, value in expect.get("form", {}).items():
|
||||
if key not in form or type(form[key]) is not type(value) or form[key] != value:
|
||||
failures.append(f"form.{key}: expected {value!r}, actual {form.get(key)!r}")
|
||||
for key, pattern in expect.get("formMatches", {}).items():
|
||||
if not isinstance(form.get(key), str) or not re.search(pattern, form[key]):
|
||||
failures.append(f"form.{key}: expected /{pattern}/, actual {form.get(key)!r}")
|
||||
for key in expect.get("formAbsent", []):
|
||||
if key in form:
|
||||
failures.append(f"form.{key}: expected absent, actual {form[key]!r}")
|
||||
for key, should_match in (("replyMatches", True), ("replyNotMatches", False)):
|
||||
if key in expect and bool(re.search(expect[key], result.text)) != should_match:
|
||||
failures.append(f"{key}: {expect[key]!r}")
|
||||
return failures
|
||||
|
||||
|
||||
def run_case(client: httpx.Client, case: dict) -> CaseTranscript:
|
||||
session_id = session_id_for(case["name"])
|
||||
transcript = CaseTranscript(
|
||||
@@ -295,6 +357,11 @@ def run_case(client: httpx.Client, case: dict) -> CaseTranscript:
|
||||
f"({case['_path']}) session={session_id} ==="
|
||||
)
|
||||
|
||||
form: dict = {}
|
||||
need_form_update = any(
|
||||
any(key in step["expect"] for key in ("form", "formAbsent", "formMatches"))
|
||||
for step in case["steps"]
|
||||
)
|
||||
try:
|
||||
for step_number, step in enumerate(case["steps"], start=1):
|
||||
expected = step["expect"]["stageCode"]
|
||||
@@ -305,8 +372,9 @@ def run_case(client: httpx.Client, case: dict) -> CaseTranscript:
|
||||
session_id=session_id,
|
||||
client_mode=case["clientMode"],
|
||||
text=user_input,
|
||||
need_form_update=need_form_update,
|
||||
)
|
||||
except (httpx.HTTPError, json.JSONDecodeError, KeyError) as exc:
|
||||
except (httpx.HTTPError, ValueError, KeyError) as exc:
|
||||
turn = TranscriptTurn(
|
||||
step=step_number,
|
||||
input=user_input,
|
||||
@@ -322,7 +390,9 @@ def run_case(client: httpx.Client, case: dict) -> CaseTranscript:
|
||||
print_turn(turn)
|
||||
break
|
||||
|
||||
ok = result.stage_codes == [expected]
|
||||
form.update(result.form_update)
|
||||
failures = check_expectations(result, step["expect"], form)
|
||||
ok = not failures
|
||||
turn = TranscriptTurn(
|
||||
step=step_number,
|
||||
input=user_input,
|
||||
@@ -331,7 +401,10 @@ def run_case(client: httpx.Client, case: dict) -> CaseTranscript:
|
||||
reply=result.text,
|
||||
errors=result.errors,
|
||||
ok=ok,
|
||||
error=None if ok else "stageCode mismatch",
|
||||
error="; ".join(failures) if failures else None,
|
||||
form_update=dict(result.form_update),
|
||||
form=dict(form),
|
||||
expectations=step["expect"],
|
||||
)
|
||||
transcript.turns.append(turn)
|
||||
print_turn(turn)
|
||||
@@ -395,7 +468,7 @@ def main() -> int:
|
||||
args = parse_args()
|
||||
try:
|
||||
cases = load_cases(args.cases_dir, args.case)
|
||||
except (OSError, ValueError, yaml.YAMLError) as exc:
|
||||
except (OSError, ValueError, yaml.YAMLError, re.error) as exc:
|
||||
print(f"ERROR: {exc}", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import json
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
from evals.run import (
|
||||
ChatResult,
|
||||
DEFAULT_CASES_DIR,
|
||||
check_expectations,
|
||||
load_cases,
|
||||
parse_sse,
|
||||
run_case,
|
||||
transcript_to_json,
|
||||
)
|
||||
|
||||
|
||||
def sse_response(*events):
|
||||
body = "".join(
|
||||
f"event: {name}\ndata: {json.dumps(payload, ensure_ascii=False)}\n\n"
|
||||
for name, payload in events
|
||||
)
|
||||
return httpx.Response(200, text=body)
|
||||
|
||||
|
||||
def test_parse_form_deltas_and_text():
|
||||
result = parse_sse(sse_response(
|
||||
("stage_code", {"nextStageCode": "1002"}),
|
||||
("text_delta", {"text": "请问事故"}),
|
||||
("formUpdate", {"has_non_motor_vehicle_hit": True}),
|
||||
("text_delta", {"text": "是什么时候发生的?"}),
|
||||
("formUpdate", {"vehicle_count": 0}),
|
||||
))
|
||||
assert result.stage_codes == ["1002"]
|
||||
assert result.text == "请问事故是什么时候发生的?"
|
||||
assert result.form_update == {"has_non_motor_vehicle_hit": True, "vehicle_count": 0}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("update,reply,error", [
|
||||
({"has_non_motor_vehicle_hit": False}, "事故什么时候发生的?", "has_non_motor_vehicle_hit"),
|
||||
({"vehicle_count": 1}, "事故什么时候发生的?", "vehicle_count"),
|
||||
({"vehicle_count": False}, "事故什么时候发生的?", "vehicle_count"),
|
||||
({}, "有没有涉及非机动车?", "replyMatches"),
|
||||
({"is_on_scene": True}, "事故什么时候发生的?", "is_on_scene"),
|
||||
])
|
||||
def test_regression_assertions_reject_bad_extraction_and_repeated_questions(update, reply, error):
|
||||
form = {"has_non_motor_vehicle_hit": True, "vehicle_count": 0, **update}
|
||||
failures = check_expectations(ChatResult(["1002"], [], reply), {
|
||||
"stageCode": "1002",
|
||||
"form": {"has_non_motor_vehicle_hit": True, "vehicle_count": 0},
|
||||
"formAbsent": ["is_on_scene"],
|
||||
"replyMatches": "(什么时候|几点|事故.*时间)",
|
||||
"replyNotMatches": "(有没有|是否).*非机动车",
|
||||
}, form)
|
||||
assert any(error in failure for failure in failures)
|
||||
|
||||
|
||||
def test_description_assertion_and_sse_error():
|
||||
expect = {"stageCode": "1002", "formMatches": {
|
||||
"accident_cause": "^其他:(?=.*非机动车)(?=.*石墩).+",
|
||||
}}
|
||||
form = {"accident_cause": "其他:非机动车自行撞到路边石墩"}
|
||||
assert not check_expectations(ChatResult(["1002"], []), expect, form)
|
||||
assert check_expectations(ChatResult(["1002"], [{"message": "failed"}]), expect, form)
|
||||
assert check_expectations(ChatResult(["1002"], []), expect, {"accident_cause": "其他"})
|
||||
|
||||
|
||||
@pytest.mark.parametrize("last_update,passed", [
|
||||
({}, True),
|
||||
({"has_non_motor_vehicle_hit": False, "vehicle_count": 1}, False),
|
||||
])
|
||||
def test_run_case_checks_cumulative_form_and_requests_extraction(last_update, passed):
|
||||
calls = []
|
||||
responses = iter([
|
||||
{"has_non_motor_vehicle_hit": True},
|
||||
{"vehicle_count": 0},
|
||||
last_update,
|
||||
])
|
||||
|
||||
def handler(request):
|
||||
payload = json.loads(request.content)
|
||||
calls.append((request.method, payload))
|
||||
if request.method == "DELETE":
|
||||
return httpx.Response(200, json={"code": "200"})
|
||||
assert payload["needFormUpdate"] is True
|
||||
return sse_response(
|
||||
("stage_code", {"nextStageCode": "1002"}),
|
||||
("formUpdate", next(responses)),
|
||||
("text_delta", {"text": "事故什么时候发生的?"}),
|
||||
)
|
||||
|
||||
case = {"name": "cumulative", "_path": "mock.yaml", "clientMode": "direct", "steps": [
|
||||
{"input": "非机动车撞石墩", "expect": {"stageCode": "1002", "form": {"has_non_motor_vehicle_hit": True}}},
|
||||
{"input": "没有别的车", "expect": {"stageCode": "1002", "form": {"vehicle_count": 0}}},
|
||||
{"input": "没有人员伤亡", "expect": {"stageCode": "1002", "form": {"has_non_motor_vehicle_hit": True, "vehicle_count": 0}}},
|
||||
]}
|
||||
with httpx.Client(base_url="http://eval.test", transport=httpx.MockTransport(handler)) as client:
|
||||
transcript = run_case(client, case)
|
||||
assert transcript.passed is passed
|
||||
assert calls[-1][0] == "DELETE"
|
||||
assert transcript.turns[0].form == {"has_non_motor_vehicle_hit": True}
|
||||
saved = transcript_to_json(transcript)
|
||||
assert saved["turns"][1]["form"]["vehicle_count"] == 0
|
||||
assert saved["turns"][2]["formUpdate"] == last_update
|
||||
|
||||
|
||||
def test_explicit_correction_can_replace_prior_fact():
|
||||
form = {"has_non_motor_vehicle_hit": True}
|
||||
form.update({"has_non_motor_vehicle_hit": False, "vehicle_count": 1})
|
||||
assert not check_expectations(ChatResult(["1002"], []), {
|
||||
"stageCode": "1002", "form": {"has_non_motor_vehicle_hit": False, "vehicle_count": 1},
|
||||
}, form)
|
||||
|
||||
|
||||
def test_current_cases_load_without_removed_photo_states():
|
||||
cases = load_cases(DEFAULT_CASES_DIR, [])
|
||||
assert len({case["name"] for case in cases}) == len(cases)
|
||||
regressions = [case for case in cases if "non_motor_vehicle" in case["name"]]
|
||||
assert {case["clientMode"] for case in regressions} == {"direct", "browser_addon"}
|
||||
for case in cases:
|
||||
for step in case["steps"]:
|
||||
assert step["expect"]["stageCode"].split(".")[-1] not in {"2004", "2016"}
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user