提示词流程分类
This commit is contained in:
519
backend_service/src/prompts/scene1_prompt.txt
Normal file
519
backend_service/src/prompts/scene1_prompt.txt
Normal file
@@ -0,0 +1,519 @@
|
||||
任务:根据用户任意任务指令,生成结构化可执行的无人机行为树(Pytree)JSON。**仅输出单一JSON对象,无任何自然语言、注释或额外内容**。
|
||||
|
||||
## 一、核心节点定义(格式不可修改,确保后端解析)
|
||||
#### 1. 可用节点定义 (必须遵守)
|
||||
你必须严格从以下JSON定义的列表中选择节点构建行为树,不允许使用未定义节点:
|
||||
```json
|
||||
{
|
||||
"actions": [
|
||||
{"name":"takeoff","params":{"altitude":"float[1,100],默认2"}},
|
||||
{"name":"land","params":{"mode":"'current'/'home'"}},
|
||||
{"name":"fly_to_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","acceptance_radius":"默认2.0","desc":"仅当指令提及具体地点(如'去广场'、'去大门')或需计算明确坐标时使用"}},
|
||||
{"name":"fly_sequence","params":{"waypoints":"list[dict] (e.g. [{'x':10,'y':20,'depth':5}, ...];depth可选,不填则保持当前高度)","coordinate_frame":"'global'/'local_enu'(global:经纬度, local_enu:以起飞点为原点的东南天坐标系)","speed":"float,可选"}},
|
||||
{"name":"move_direction","params":{"direction":"north/south/east/west/forward/backward/left/right","distance":"[1,10000],缺省则持续移动","speed":"float,可选","desc":"当指令仅包含'往东/西...飞xx米'且无具体地点名词时,必须使用此节点"}},
|
||||
{"name":"approach_target","params":{"target_class":"string,要趋近的目标类别","description":"string,可选,目标属性描述","stop_distance":"float,期望的最终停止距离","speed":"float,可选,期望的逼近速度"}},
|
||||
{"name":"rotate","params":{"angle":"float,无人机自身旋转角度(正数逆时针,负数顺时针)","angular_velocity":"rad/s,旋转角速度"}},
|
||||
{"name":"rotate_search","params":{"target_class":"同object_detect","description":"string,可选,目标属性描述","step_angle":"float,可选,每一步旋转的角度","total_rotation":"float,可选,总共旋转搜索的角度"}},
|
||||
{"name":"manual_confirmation","params":{}},
|
||||
{"name":"loiter","params":{"duration":"[1,600]秒/until_condition:可选"}},
|
||||
{"name":"object_detect","params":{"target_class":"person,bicycle,car,motorcycle,airplane,bus,train,truck,boat,traffic_light,fire_hydrant,stop_sign,parking_meter,bench,bird,cat,dog,horse,sheep,cow,elephant,bear,zebra,giraffe,backpack,umbrella,handbag,tie,suitcase,frisbee,skis,snowboard,sports_ball,kite,baseball_bat,baseball_glove,skateboard,surfboard,tennis_racket,bottle,wine_glass,cup,fork,knife,spoon,bowl,banana,apple,sandwich,orange,broccoli,carrot,hot_dog,pizza,donut,cake,chair,couch,potted_plant,bed,dining_table,toilet,tv,laptop,mouse,remote,keyboard,cell_phone,microwave,oven,toaster,sink,refrigerator,book,clock,vase,scissors,teddy_bear,hair_drier,toothbrush,garbage","description":"可选,","count":"默认1"}},
|
||||
{"name":"search_pattern","params":{"pattern_type":"spiral/grid","center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
|
||||
{"name":"track_object","params":{"target_class":"同object_detect","description":"可选,目标属性","track_time":"[1,600]秒(必传,不可用'duration')","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}},
|
||||
{"name":"deliver_payload","params":{"payload_type":"string","release_altitude":"[2,100]默认5"}},
|
||||
{"name":"system_checks","params":{"check_level":"basic/comprehensive,只能在起飞takeoff节点前使用,空中无需使用该节点"}},
|
||||
{"name":"return_emergency","params":{"reason":"string,此节点仅用于【无明确目的地】的立即返航(默认回起飞点)。若指令包含“回到xx地”、“去xx地”(即使包含“紧急”二字),**严禁**使用此节点,必须使用fly_to_waypoint"}},
|
||||
{"name":"take_photos","params":{"target_class":"同object_detect","description":"可选,目标属性","track_time":"[1,600]秒(必传,不可用'duration')","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}}
|
||||
],
|
||||
"conditions": [
|
||||
{"name":"at_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","tolerance":"默认3.0"}},
|
||||
{"name":"object_detected","params":{"target_class":"同object_detect(必传)","description":"可选,目标属性","count":"默认1"}}
|
||||
],
|
||||
"control_flow": [
|
||||
{"name":"Sequence","params":{},"children":"子节点数组(按序执行,全成功则成功)"},
|
||||
{"name":"Selector","params":{"memory":"默认true"},"children":"子节点数组(执行到成功为止)"},
|
||||
{"name":"Parallel","params":{"policy":"all_success/success_on_one"},"children":"子节点数组(同时执行,默认all_success)"}
|
||||
],
|
||||
"decorators": [
|
||||
{"name":"SuccessIsFailure","params":{},"child":"单一子节点(将子节点的成功结果反转为失败)"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 二、节点必填字段(后端Schema强制要求,缺一验证失败)
|
||||
每个节点必须包含以下字段,字段名/类型不可自定义:
|
||||
1. **`type`**:
|
||||
- 动作节点→`"action"`,条件节点→`"condition"`,控制流节点→`"Sequence"`/`"Selector"`/`"Parallel"`,装饰器节点→`"decorator"`;
|
||||
2. **`name`**:必须是上述JSON中定义的`name`值;
|
||||
3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数;
|
||||
4. **`children`**:仅控制流节点必含(子节点数组);
|
||||
5. **`child`**:仅装饰器节点必含(单一子节点对象,非数组)。
|
||||
|
||||
|
||||
## 三、标准任务结构模板(单次起降流程)
|
||||
当无人机在地面时,大多数任务应遵循“起飞 -> 移动 -> 条件判断 -> 执行 -> 返航/降落”的单次闭环流程,参考结构如下:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "MainTask",
|
||||
"children": [
|
||||
{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{"type":"action","name":"fly_to_waypoint","params":{"x":100.0,"y":50.0,"z":10.0}}, // 接近目标区域
|
||||
// --- 核心任务区 (根据指令替换) ---
|
||||
// 默认不需要降落节点,除非用户明确要求
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
而当无人机在空中时,则无需system_checks与takeoff环节,直接执行用户任务即可
|
||||
|
||||
## 四、场景示例
|
||||
|
||||
#### 场景 1:地面到12米绕外围查看打开的窗户(Sequence)
|
||||
**指令**:“无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有打开的窗户,发现则进行拍照。”
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "FlyPerimeterAndPhotoWindows",
|
||||
"children": [
|
||||
{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{
|
||||
"type": "Parallel",
|
||||
"name": "PatrolAndDetectWindows",
|
||||
"params": {"policy": "success_on_one"},
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "fly_sequence",
|
||||
"params": {
|
||||
"waypoints": [
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 241.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 289.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 292.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0}
|
||||
],
|
||||
"coordinate_frame": "local_enu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator",
|
||||
"name": "SuccessIsFailure",
|
||||
"child": {
|
||||
"type": "Sequence",
|
||||
"name": "DetectOpenWindowsWhileFlying",
|
||||
"children": [
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"window","description":"打开的窗户"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"window","description":"打开的窗户"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"window","description":"打开的窗户","track_time":10.0}}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 2:地面到12米沿外围查找打开的窗户(Sequence)
|
||||
**指令**:“无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有打开的窗户并拍照。”
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "FlyPerimeterAndPhotoOpenWindows",
|
||||
"children": [
|
||||
{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{
|
||||
"type": "Parallel",
|
||||
"name": "PatrolAndDetectOpenWindows",
|
||||
"params": {"policy": "success_on_one"},
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "fly_sequence",
|
||||
"params": {
|
||||
"waypoints": [
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 241.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 289.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 292.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0}
|
||||
],
|
||||
"coordinate_frame": "local_enu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator",
|
||||
"name": "SuccessIsFailure",
|
||||
"child": {
|
||||
"type": "Sequence",
|
||||
"name": "DetectAllOpenWindowsWhileFlying",
|
||||
"children": [
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"window","description":"打开的窗户"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"window","description":"打开的窗户"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"window","description":"打开的窗户","track_time":10.0}}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 3:空中上升后绕外围侦察打开窗户(Sequence)
|
||||
**指令**:“无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有打开的窗户,看到了就拍照传回来。”
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "RiseAndDetectOpenWindows",
|
||||
"children": [
|
||||
{"type":"action","name":"move_direction","params":{"direction":"up","distance":3.0}},
|
||||
{
|
||||
"type": "Parallel",
|
||||
"name": "PatrolAndDetectOpenWindows",
|
||||
"params": {"policy": "success_on_one"},
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "fly_sequence",
|
||||
"params": {
|
||||
"waypoints": [
|
||||
{"x": -24.0, "y": 241.8},
|
||||
{"x": -108.5, "y": 241.8},
|
||||
{"x": -108.5, "y": 289.8},
|
||||
{"x": -24.0, "y": 292.8},
|
||||
{"x": -24.0, "y": 241.8}
|
||||
],
|
||||
"coordinate_frame": "local_enu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator",
|
||||
"name": "SuccessIsFailure",
|
||||
"child": {
|
||||
"type": "Sequence",
|
||||
"name": "DetectOpenWindowsWhileFlying",
|
||||
"children": [
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"window","description":"打开的窗户"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"window","description":"打开的窗户"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"window","description":"打开的窗户","track_time":10.0}}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 4:地面到12米绕外围巡视杂物堆积(Sequence)
|
||||
**指令**:“无人机当前在地面,去面前大楼的12米高处,绕着外围巡视杂物堆积现象,发现则进行拍照。”
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "FlyPerimeterAndPhotoGarbageObserve",
|
||||
"children": [
|
||||
{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{
|
||||
"type": "Parallel",
|
||||
"name": "PatrolAndDetectGarbageObserve",
|
||||
"params": {"policy": "success_on_one"},
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "fly_sequence",
|
||||
"params": {
|
||||
"waypoints": [
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 241.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 289.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 292.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0}
|
||||
],
|
||||
"coordinate_frame": "local_enu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator",
|
||||
"name": "SuccessIsFailure",
|
||||
"child": {
|
||||
"type": "Sequence",
|
||||
"name": "DetectGarbageWhileFlying",
|
||||
"children": [
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"garbage","description":"杂物堆积"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"garbage","description":"杂物堆积"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"garbage","description":"杂物堆积","track_time":10.0}}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 5:地面到12米沿外围查找杂物堆积(Sequence)
|
||||
**指令**:“无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的杂物堆积并拍照。”
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "FlyPerimeterAndPhotoGarbage",
|
||||
"children": [
|
||||
{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{
|
||||
"type": "Parallel",
|
||||
"name": "PatrolAndDetectGarbage",
|
||||
"params": {"policy": "success_on_one"},
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "fly_sequence",
|
||||
"params": {
|
||||
"waypoints": [
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 241.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 289.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 292.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0}
|
||||
],
|
||||
"coordinate_frame": "local_enu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator",
|
||||
"name": "SuccessIsFailure",
|
||||
"child": {
|
||||
"type": "Sequence",
|
||||
"name": "DetectGarbageWhileFlying",
|
||||
"children": [
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"garbage","description":"杂物堆积"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"garbage","description":"杂物堆积"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"garbage","description":"杂物堆积","track_time":10.0}}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 6:空中下降后绕外围侦察杂物堆积(Sequence)
|
||||
**指令**:“无人机当前在空中,往下飞3米,接着绕这栋楼外围侦察有没有杂物堆积,看到了就拍照传回来。”
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "DescendAndDetectGarbage",
|
||||
"children": [
|
||||
{"type":"action","name":"move_direction","params":{"direction":"down","distance":3.0}},
|
||||
{
|
||||
"type": "Parallel",
|
||||
"name": "PatrolAndDetectGarbage",
|
||||
"params": {"policy": "success_on_one"},
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "fly_sequence",
|
||||
"params": {
|
||||
"waypoints": [
|
||||
{"x": -24.0, "y": 241.8},
|
||||
{"x": -108.5, "y": 241.8},
|
||||
{"x": -108.5, "y": 289.8},
|
||||
{"x": -24.0, "y": 292.8},
|
||||
{"x": -24.0, "y": 241.8}
|
||||
],
|
||||
"coordinate_frame": "local_enu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator",
|
||||
"name": "SuccessIsFailure",
|
||||
"child": {
|
||||
"type": "Sequence",
|
||||
"name": "DetectGarbageWhileFlying",
|
||||
"children": [
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"garbage","description":"杂物堆积"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"garbage","description":"杂物堆积"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"garbage","description":"杂物堆积","track_time":10.0}}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 7:地面到12米绕外围查看是否有人(Sequence)
|
||||
**指令**:“无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有人,发现则进行拍照。”
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "FlyPerimeterAndPhotoPerson",
|
||||
"children": [
|
||||
{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{
|
||||
"type": "Parallel",
|
||||
"name": "PatrolAndDetectPerson",
|
||||
"params": {"policy": "success_on_one"},
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "fly_sequence",
|
||||
"params": {
|
||||
"waypoints": [
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 241.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 289.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 292.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0}
|
||||
],
|
||||
"coordinate_frame": "local_enu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator",
|
||||
"name": "SuccessIsFailure",
|
||||
"child": {
|
||||
"type": "Sequence",
|
||||
"name": "DetectPersonWhileFlying",
|
||||
"children": [
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"person","description":"人员"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"person","description":"人员"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"person","description":"人员","track_time":10.0}}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 8:地面到12米沿外围逆时针查找人员(Sequence)
|
||||
**指令**:“无人机当前在地面,去面前大楼的12米高处,沿着外围逆时针查找所有的人并拍照。”
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "FlyPerimeterCounterClockwiseAndPhotoPerson",
|
||||
"children": [
|
||||
{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{
|
||||
"type": "Parallel",
|
||||
"name": "PatrolCCWAndDetectPerson",
|
||||
"params": {"policy": "success_on_one"},
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "fly_sequence",
|
||||
"params": {
|
||||
"waypoints": [
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 292.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 289.8, "depth": 12.0},
|
||||
{"x": -108.5, "y": 241.8, "depth": 12.0},
|
||||
{"x": -24.0, "y": 241.8, "depth": 12.0}
|
||||
],
|
||||
"coordinate_frame": "local_enu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator",
|
||||
"name": "SuccessIsFailure",
|
||||
"child": {
|
||||
"type": "Sequence",
|
||||
"name": "DetectPersonWhileFlying",
|
||||
"children": [
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"person","description":"人员"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"person","description":"人员"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"person","description":"人员","track_time":10.0}}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 9:空中上升后沿建筑外围侦察人员(Sequence)
|
||||
**指令**:“无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。”
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "RiseAndPatrolPerimeter",
|
||||
"children": [
|
||||
{"type":"action","name":"move_direction","params":{"direction":"up","distance":3.0}},
|
||||
{
|
||||
"type": "Parallel",
|
||||
"name": "PatrolAndDetect",
|
||||
"params": {"policy": "success_on_one"},
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "fly_sequence",
|
||||
"params": {
|
||||
"waypoints": [
|
||||
{"x": -24.0, "y": 241.8},
|
||||
{"x": -108.5, "y": 241.8},
|
||||
{"x": -108.5, "y": 289.8},
|
||||
{"x": -24.0, "y": 292.8},
|
||||
{"x": -24.0, "y": 241.8}
|
||||
],
|
||||
"coordinate_frame": "local_enu"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator",
|
||||
"name": "SuccessIsFailure",
|
||||
"child": {
|
||||
"type": "Sequence",
|
||||
"name": "DetectAndPhotoWhileFlying",
|
||||
"children": [
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"person","description":"建筑外围人员"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"person","description":"建筑外围人员"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"person","description":"建筑外围人员","track_time":10.0}}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
311
backend_service/src/prompts/scene4_prompt.txt
Normal file
311
backend_service/src/prompts/scene4_prompt.txt
Normal file
@@ -0,0 +1,311 @@
|
||||
任务:根据用户任意任务指令,生成结构化可执行的无人机行为树(Pytree)JSON。**仅输出单一JSON对象,无任何自然语言、注释或额外内容**。
|
||||
|
||||
## 一、核心节点定义(格式不可修改,确保后端解析)
|
||||
#### 1. 可用节点定义 (必须遵守)
|
||||
你必须严格从以下JSON定义的列表中选择节点构建行为树,不允许使用未定义节点:
|
||||
```json
|
||||
{
|
||||
"actions": [
|
||||
{"name":"takeoff","params":{"altitude":"float[1,100],默认2"}},
|
||||
{"name":"land","params":{"mode":"'current'/'home'"}},
|
||||
{"name":"fly_to_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","acceptance_radius":"默认2.0","desc":"仅当指令提及具体地点(如'去广场'、'去大门')或需计算明确坐标时使用"}},
|
||||
{"name":"fly_sequence","params":{"waypoints":"list[dict] (e.g. [{'x':10,'y':20,'depth':5}, ...];depth可选,不填则保持当前高度)","coordinate_frame":"'global'/'local_enu'(global:经纬度, local_enu:以起飞点为原点的东南天坐标系)","speed":"float,可选"}},
|
||||
{"name":"move_direction","params":{"direction":"north/south/east/west/forward/backward/left/right","distance":"[1,10000],缺省则持续移动","speed":"float,可选","desc":"当指令仅包含'往东/西...飞xx米'且无具体地点名词时,必须使用此节点"}},
|
||||
{"name":"approach_target","params":{"target_class":"string,要趋近的目标类别","description":"string,可选,目标属性描述","stop_distance":"float,期望的最终停止距离","speed":"float,可选,期望的逼近速度"}},
|
||||
{"name":"rotate","params":{"angle":"float,无人机自身旋转角度(正数逆时针,负数顺时针)","angular_velocity":"rad/s,旋转角速度"}},
|
||||
{"name":"rotate_search","params":{"target_class":"同object_detect","description":"string,可选,目标属性描述","step_angle":"float,可选,每一步旋转的角度","total_rotation":"float,可选,总共旋转搜索的角度"}},
|
||||
{"name":"manual_confirmation","params":{}},
|
||||
{"name":"loiter","params":{"duration":"[1,600]秒/until_condition:可选"}},
|
||||
{"name":"object_detect","params":{"target_class":"person,bicycle,car,motorcycle,airplane,bus,train,truck,boat,traffic_light,fire_hydrant,stop_sign,parking_meter,bench,bird,cat,dog,horse,sheep,cow,elephant,bear,zebra,giraffe,backpack,umbrella,handbag,tie,suitcase,frisbee,skis,snowboard,sports_ball,kite,baseball_bat,baseball_glove,skateboard,surfboard,tennis_racket,bottle,wine_glass,cup,fork,knife,spoon,bowl,banana,apple,sandwich,orange,broccoli,carrot,hot_dog,pizza,donut,cake,chair,couch,potted_plant,bed,dining_table,toilet,tv,laptop,mouse,remote,keyboard,cell_phone,microwave,oven,toaster,sink,refrigerator,book,clock,vase,scissors,teddy_bear,hair_drier,toothbrush,garbage","description":"可选,","count":"默认1"}},
|
||||
{"name":"search_pattern","params":{"pattern_type":"spiral/grid","center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
|
||||
{"name":"track_object","params":{"target_class":"同object_detect","description":"可选,目标属性","track_time":"[1,600]秒(必传,不可用'duration')","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}},
|
||||
{"name":"deliver_payload","params":{"payload_type":"string","release_altitude":"[2,100]默认5"}},
|
||||
{"name":"system_checks","params":{"check_level":"basic/comprehensive,只能在起飞takeoff节点前使用,空中无需使用该节点"}},
|
||||
{"name":"return_emergency","params":{"reason":"string,此节点仅用于【无明确目的地】的立即返航(默认回起飞点)。若指令包含“回到xx地”、“去xx地”(即使包含“紧急”二字),**严禁**使用此节点,必须使用fly_to_waypoint"}},
|
||||
{"name":"take_photos","params":{"target_class":"同object_detect","description":"可选,目标属性","track_time":"[1,600]秒(必传,不可用'duration')","min_confidence":"[0.5,1.0]默认0.7","safe_distance":"[2,50]默认10"}}
|
||||
],
|
||||
"conditions": [
|
||||
{"name":"at_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","tolerance":"默认3.0"}},
|
||||
{"name":"object_detected","params":{"target_class":"同object_detect(必传)","description":"可选,目标属性","count":"默认1"}}
|
||||
],
|
||||
"control_flow": [
|
||||
{"name":"Sequence","params":{},"children":"子节点数组(按序执行,全成功则成功)"},
|
||||
{"name":"Selector","params":{"memory":"默认true"},"children":"子节点数组(执行到成功为止)"},
|
||||
{"name":"Parallel","params":{"policy":"all_success/success_on_one"},"children":"子节点数组(同时执行,默认all_success)"}
|
||||
],
|
||||
"decorators": [
|
||||
{"name":"SuccessIsFailure","params":{},"child":"单一子节点(将子节点的成功结果反转为失败)"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 二、节点必填字段(后端Schema强制要求,缺一验证失败)
|
||||
每个节点必须包含以下字段,字段名/类型不可自定义:
|
||||
1. **`type`**:
|
||||
- 动作节点→`"action"`,条件节点→`"condition"`,控制流节点→`"Sequence"`/`"Selector"`/`"Parallel"`,装饰器节点→`"decorator"`;
|
||||
2. **`name`**:必须是上述JSON中定义的`name`值;
|
||||
3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数;
|
||||
4. **`children`**:仅控制流节点必含(子节点数组);
|
||||
5. **`child`**:仅装饰器节点必含(单一子节点对象,非数组)。
|
||||
|
||||
|
||||
## 三、标准任务结构模板(单次起降流程)
|
||||
当无人机在地面时,大多数任务应遵循“起飞 -> 移动 -> 条件判断 -> 执行 -> 返航/降落”的单次闭环流程,参考结构如下:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "MainTask",
|
||||
"children": [
|
||||
{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{"type":"action","name":"fly_to_waypoint","params":{"x":100.0,"y":50.0,"z":10.0}}, // 接近目标区域
|
||||
// --- 核心任务区 (根据指令替换) ---
|
||||
// 默认不需要降落节点,除非用户明确要求
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
而当无人机在空中时,则无需system_checks与takeoff环节,直接执行用户任务即可
|
||||
|
||||
## 四、场景示例(请灵活参考)
|
||||
|
||||
#### 场景 1:线性搜索任务(Sequence + Selector)
|
||||
**指令**:“无人机当前在地面,去研究所正大门,搜索扎辫子女子,找到后拍照。”
|
||||
**思路**:无人机在地面,则需要先自检然后起飞;获取研究所正大门坐标,调用fly_to_waypoint节点到达该地;然后调用rotate_search节点搜索目标女子,再使用object_detected条件节点,这样就可以作为take_photos节点的依据。
|
||||
**结构**:Sequence (按顺序执行)
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "MainSearchTask",
|
||||
"children": [
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{"type":"action","name":"fly_to_waypoint","params":{"x":100.0,"y":50.0,"z":10.0}},
|
||||
{"type":"action","name":"rotate_search","params":{"target_class":"person","description":"扎辫子女子"}},
|
||||
{
|
||||
"type": "Selector",
|
||||
"name": "CheckAndPhoto",
|
||||
"children": [
|
||||
{
|
||||
"type": "Sequence",
|
||||
"name": "PhotoIfFound",
|
||||
"children": [
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"person","description":"扎辫子女子"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"person","description":"扎辫子女子","track_time":10.0}}
|
||||
]
|
||||
},
|
||||
{"type":"action","name":"loiter","params":{"duration":5.0}} // 未发现时的备选动作
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 2:带中断逻辑的巡逻(Selector 示例)
|
||||
**指令**:“无人机当前在地面,飞往航点A。如果途中发现可疑人员,则悬停。”
|
||||
**参考知识**:航点A的坐标(x:100.0,y:50.0)
|
||||
**思路**:无人机在地面,则需要先自检然后起飞;获取航点A的坐标,调用fly_to_waypoint节点到达该地;但同时需要注意看到可疑人员需要悬停,意味着一边进行识别,识别到进行悬停,因此要在object_detect节点后有一个object_detected条件节点,作为悬停的条件。
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"children": [
|
||||
{"type":"action","name":"system_checks","params":{"check_level":"basic"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{
|
||||
"type": "Selector",
|
||||
"name": "FlyOrDetect",
|
||||
"children": [
|
||||
{
|
||||
"type": "Sequence",
|
||||
"name": "InterruptionLogic",
|
||||
"children": [
|
||||
{"type":"action","name":"object_detect","params":{"target_class":"person"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"person"}},
|
||||
{"type":"action","name":"loiter","params":{"duration":5.0}}
|
||||
]
|
||||
},
|
||||
{"type":"action","name":"fly_to_waypoint","params":{"x":100.0,"y":50.0,"z":10.0}}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 3:长期监控任务(Parallel 示例)
|
||||
**指令**:“无人机当前在空中,往广场西边飞200米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。”
|
||||
**参考知识**:广场西边200米的坐标(x:50.0,y:50.0,z:10.0)
|
||||
**思路**:无人机在空中,直接前往目标点;到达后需要并行执行两件事:1. 倒计时5分钟(主控时间);2. 持续检测人并拍照(从属任务)。
|
||||
使用`Parallel`节点并设置策略为`success_on_one`,这样当倒计时(loiter)结束返回成功时,整个并行节点就会成功结束,从而强制停止拍照循环。为了让拍照循环不提前结束Parallel,拍照分支使用`decorator`(SuccessIsFailure)或无限重试逻辑。
|
||||
**结构**:
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "MainTask",
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "fly_to_waypoint",
|
||||
"params": {
|
||||
"x": 50.0,
|
||||
"y": 50.0,
|
||||
"z": 10.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Parallel",
|
||||
"name": "MonitorAndPhoto",
|
||||
"params": {
|
||||
"policy": "success_on_one"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "loiter",
|
||||
"params": {
|
||||
"time": 300
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "decorator",
|
||||
"name": "SuccessIsFailure",
|
||||
"child": {
|
||||
"type": "Sequence",
|
||||
"name": "CheckAndPhoto",
|
||||
"children": [
|
||||
{
|
||||
"type": "action",
|
||||
"name": "object_detect",
|
||||
"params": {
|
||||
"target_class": "person"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "condition",
|
||||
"name": "object_detected",
|
||||
"params": {
|
||||
"target_class": "person"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "action",
|
||||
"name": "take_photos",
|
||||
"params": {
|
||||
"target_class": "person"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "action",
|
||||
"name": "return_emergency",
|
||||
"params": {
|
||||
"reason": "任务完成"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 4:交互式确认任务(Sequence + Manual Confirmation)
|
||||
**指令**:“无人机当前在空中,搜索小汽车,搜索到了我确认后再决定要不要拍照。”
|
||||
**思路**:无人机已在空中,无需起飞,直接进行搜索。首先使用`rotate_search`主动搜索目标,配合`object_detected`条件节点确认目标是否被检测到。检测到后,执行`manual_confirmation`节点等待用户确认。只有用户确认通过(返回Success),才会继续执行后续的`take_photos`动作。
|
||||
**结构**:Sequence
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "SearchConfirmPhoto",
|
||||
"children": [
|
||||
{"type":"action","name":"rotate_search","params":{"target_class":"car","description":"小汽车"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"car","description":"小汽车"}},
|
||||
{"type":"action","name":"manual_confirmation","params":{}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"car","description":"小汽车"}}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 5:后置确认任务(Sequence + Manual Confirmation)
|
||||
**指令**:“无人机当前在地面,搜索小汽车,搜索到了拍张照,我确认后再决定要不要返航”
|
||||
**思路**:无人机在地面,需起飞。搜索小汽车(`rotate_search` + `object_detected`)。搜索到后,先执行拍照(`take_photos`)。之后执行人工确认(`manual_confirmation`),确认通过后才执行返航(`return_emergency`)。
|
||||
**结构**:Sequence
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "SearchPhotoConfirmReturn",
|
||||
"children": [
|
||||
{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}},
|
||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
||||
{"type":"action","name":"rotate_search","params":{"target_class":"car","description":"小汽车"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"car","description":"小汽车"}},
|
||||
{"type":"action","name":"take_photos","params":{"target_class":"car","description":"小汽车"}},
|
||||
{"type":"action","name":"manual_confirmation","params":{}},
|
||||
{"type":"action","name":"return_emergency","params":{"reason":"确认后返航"}}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 场景 6:移动后条件降落(Sequence)
|
||||
**指令**:“无人机当前在空中,紧急回到广场,看见了红绿灯之后直接降落。”
|
||||
**参考知识**:广场坐标(x:0.0, y:0.0, z:10.0)
|
||||
**思路**:无人机在空中,无需起飞。首先飞往广场(`fly_to_waypoint`),严禁使用`return_emergency`。到达后,为了满足“看见红绿灯”的条件,必须先执行主动搜索(`rotate_search`)。一旦检测到红绿灯(`object_detected`),即执行降落(`land`)。
|
||||
**结构**:Sequence
|
||||
```json
|
||||
{
|
||||
"root": {
|
||||
"type": "Sequence",
|
||||
"name": "FlySearchLand",
|
||||
"children": [
|
||||
{"type":"action","name":"fly_to_waypoint","params":{"x":0.0,"y":0.0,"z":10.0}},
|
||||
{"type":"action","name":"rotate_search","params":{"target_class":"traffic_light","description":"红绿灯"}},
|
||||
{"type":"condition","name":"object_detected","params":{"target_class":"traffic_light","description":"红绿灯"}},
|
||||
{"type":"action","name":"land","params":{"mode":"current"}}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 六、高频错误规避
|
||||
1. 控制流节点的 `type` 必须是 `"Sequence"`, `"Selector"` 或 `"Parallel"`
|
||||
2. **人工确认节点 (`manual_confirmation`) 使用原则**:
|
||||
- **必须添加**:仅当指令中明确包含“我确认”、“等待确认”、“经允许”、“我通过后”等人工介入关键词时,**必须**在相应动作前添加此节点。
|
||||
- **严禁添加**:若指令未提及上述关键词,**严禁**主动添加此节点(即使是拍照、返航或降落等动作,只要用户没说要确认,就直接执行)。
|
||||
3. 在条件节点 `object_detected` 执行前,必须先安排搜索类动作节点(优先使用 `rotate_search`,仅当需大范围移动时用 `search_pattern`),确保无人机主动寻找目标。
|
||||
4. 当使用rotate_search或者object_detect节点时,必须有object_detected节点
|
||||
5. 用户指令中要求在当前位置执行任务时,无需fly_to_waypoint节点
|
||||
6. **严格区分无人机状态**:当用户指令明确无人机在**空中**时,严禁使用system_checks与takeoff节点;仅当指令明确在**地面**时,才可使用这两个节点
|
||||
7. **重点关注**:fly_to_waypoint与return_emergency节点辨析:当指令包含具体目的地(如“紧急回到广场”、“飞回大门”)时,**必须**使用fly_to_waypoint节点,**绝对禁止**使用return_emergency节点(该节点仅用于无目的地的“返航”指令)。
|
||||
8. 当用户指令中提及“靠近”、“飞近”、“贴近”目标时,**必须**在`take_photos`之前使用`approach_target`节点;若未提及此类关键词,则**严禁**使用`approach_target`节点。
|
||||
9. **方向移动优先原则**:当指令为“快速去往东边100米”,直接使用 `move_direction` 节点+距离参数,严禁使用fly_to_waypoint
|
||||
|
||||
## 七、坐标计算规则(东南天坐标系 ENU)
|
||||
本系统统一使用东南天(ENU)坐标系:
|
||||
- **X轴**:正方向为**东** (East),负方向为**西** (West)
|
||||
- **Y轴**:正方向为**南** (South)向为**北** (North)
|
||||
- **Z轴**:正方向为**天** (Up),负方向为**地** (Down)
|
||||
|
||||
**仅当指令涉及前往“具体地点”(如广场、大门)的偏移位置时,才需计算绝对坐标并使用`fly_to_waypoint`:**
|
||||
|
||||
当指令包含“具体地点 + 方向 + 距离”的偏移(如“广场西边200米”)时,**必须**先调用工具`calc_offset_enu`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
||||
- `base`: 参考地点的ENU坐标(含x/y/z)
|
||||
- `direction`: east/west/north/south/up/down
|
||||
- `distance`: 偏移距离(米)
|
||||
|
||||
当指令只有“方向 + 距离”且**没有具体地点名词**时,**禁止**调用`calc_offset_enu`,必须使用`move_direction`。
|
||||
当指令描述“附近/边上/区域内”等模糊位置且**无方向+距离**时,视为到该地点本身,不做偏移计算。
|
||||
|
||||
## 八、输出要求
|
||||
仅输出1个严格符合上述所有规则的JSON对象。
|
||||
46
backend_service/src/prompts/scene_classifier_prompt.txt
Normal file
46
backend_service/src/prompts/scene_classifier_prompt.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
你是一个严格的指令场景分类器。只输出一个JSON对象,不要输出解释或多余文本。
|
||||
根据用户指令与下述场景定义,判断其属于“simple / scene1 / scene4”之一。
|
||||
|
||||
输出格式(严格遵守):
|
||||
{"mode":"simple"} 或 {"mode":"scene1"} 或 {"mode":"scene4"}
|
||||
|
||||
判定规则(严格遵守):
|
||||
1. 若指令符合 scene1 或 scene4 的特征,必须输出对应模式;
|
||||
2. 若指令不符合 scene1 与 scene4,输出 simple;
|
||||
3. 仅允许以上三种取值,禁止输出其他字段或文本。
|
||||
|
||||
—— 场景定义 ——
|
||||
scene1(大楼外围巡查类):
|
||||
- 关键词特征:面前大楼/这栋楼、外围/沿着外围/绕着外围、12米高处、逆时针等;
|
||||
- 任务类型:绕楼外围巡查、搜索窗户/杂物堆积/人员等并拍照;
|
||||
- 包含上下/下降移动(上升3米/下降3米)后绕楼侦察的也属于 scene1。
|
||||
|
||||
scene4(广场相关复合任务类):
|
||||
- 关键词特征:广场、广场边上、广场南边、施工区域、紧急回到广场、回到广场;
|
||||
- 任务类型:在广场搜索/拍照/监控/返航/降落/靠近拍照等;
|
||||
- 可能包含“确认后拍照/返航”、“持续监控5分钟”、“挟持”等描述。
|
||||
|
||||
—— 场景指令样例 ——
|
||||
scene1 示例:
|
||||
- 无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有打开的窗户,发现则进行拍照。
|
||||
- 无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有打开的窗户并拍照。
|
||||
- 无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有打开的窗户,看到了就拍照传回来。
|
||||
- 无人机当前在地面,去面前大楼的12米高处,绕着外围巡视杂物堆积现象,发现则进行拍照。
|
||||
- 无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的杂物堆积并拍照。
|
||||
- 无人机当前在空中,往下飞3米,接着绕这栋楼外围侦察有没有杂物堆积,看到了就拍照传回来。
|
||||
- 无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有人,发现则进行拍照。
|
||||
- 无人机当前在地面,去面前大楼的12米高处,沿着外围逆时针查找所有的人并拍照。
|
||||
- 无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。
|
||||
|
||||
scene4 示例:
|
||||
- 无人机当前在地面,到广场查找穿红色衣服的人,找到后近距离拍照。
|
||||
- 无人机当前在空中,回到广场,对戴帽子的人进行拍照。
|
||||
- 无人机当前在空中,去广场南边40米,对过往的公交车拍张照,然后返航。
|
||||
- 无人机当前在地面,到广场查找绿色公交车,看见了拍个照片。
|
||||
- 无人机当前在空中,搜索小汽车,搜索到了我确认后再决定要不要拍照。
|
||||
- 无人机当前在空中,搜索小汽车,搜索到了拍张照,我确认后再决定要不要返航。
|
||||
- 无人机当前在空中,往广场南边飞40米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。
|
||||
- 无人机当前在地面,到广场边上的施工区域内,发现有没带安全帽的飞近后拍照。
|
||||
- 无人机当前在空中,紧急回到广场,看见了红绿灯之后直接降落。
|
||||
- 无人机当前在地面,快速去往东边60米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。
|
||||
- 无人机当前在空中,离白色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。
|
||||
@@ -594,10 +594,13 @@ class PyTreeGenerator:
|
||||
self.reasoning_preview_lines = int(os.getenv("REASONING_PREVIEW_LINES", "20"))
|
||||
except Exception:
|
||||
self.reasoning_preview_lines = 20
|
||||
# 加载提示词:复杂模式复用现有 system_prompt.txt;简单模式与分类器独立提示词
|
||||
# 加载提示词:复杂模式复用现有 system_prompt.txt;场景1/4与分类器独立提示词
|
||||
self.complex_prompt = self._load_prompt("system_prompt.txt")
|
||||
self.scene1_prompt = self._load_prompt("scene1_prompt.txt")
|
||||
self.scene4_prompt = self._load_prompt("scene4_prompt.txt")
|
||||
self.simple_prompt = self._load_prompt("simple_mode_prompt.txt")
|
||||
self.classifier_prompt = self._load_prompt("classifier_prompt.txt")
|
||||
self.scene_classifier_prompt = self._load_prompt("scene_classifier_prompt.txt")
|
||||
# 兼容旧变量名
|
||||
self.system_prompt = self.complex_prompt
|
||||
|
||||
@@ -812,13 +815,13 @@ class PyTreeGenerator:
|
||||
"""
|
||||
logging.info(f"接收到用户请求: {user_prompt}")
|
||||
|
||||
# 第一步:分类(简单/复杂)
|
||||
mode = "complex"
|
||||
# 第一步:场景分类(simple/scene1/scene4)
|
||||
scene_mode = "scene1"
|
||||
try:
|
||||
classifier_resp = self.classifier_client.chat.completions.create(
|
||||
model=self.classifier_model,
|
||||
messages=[
|
||||
{"role": "system", "content": self.classifier_prompt or "你是一个分类器,只输出JSON。"},
|
||||
{"role": "system", "content": self.scene_classifier_prompt or "你是一个分类器,只输出JSON。"},
|
||||
{"role": "user", "content": user_prompt}
|
||||
],
|
||||
temperature=0.0,
|
||||
@@ -830,18 +833,25 @@ class PyTreeGenerator:
|
||||
)
|
||||
class_str = classifier_resp.choices[0].message.content
|
||||
class_obj = json.loads(class_str)
|
||||
if isinstance(class_obj, dict) and class_obj.get("mode") in ("simple", "complex"):
|
||||
mode = class_obj.get("mode")
|
||||
logging.info(f"分类结果: {mode}")
|
||||
if isinstance(class_obj, dict) and class_obj.get("mode") in ("simple", "scene1", "scene4"):
|
||||
scene_mode = class_obj.get("mode")
|
||||
logging.info(f"场景分类结果: {scene_mode}")
|
||||
except Exception as e:
|
||||
logging.warning(f"分类失败,默认按复杂指令处理: {e}")
|
||||
logging.warning(f"场景分类失败,默认按scene1处理: {e}")
|
||||
|
||||
# 第二步:根据模式准备提示词与上下文(简单与复杂都执行检索增强)
|
||||
# 基于模式选择提示词;复杂模式追加一条强制规则,避免模型误输出简单结构
|
||||
use_prompt = self.simple_prompt if mode == "simple" else (
|
||||
(self.complex_prompt or "") +
|
||||
"\n\n【强制规则】仅生成包含root的复杂行为树JSON,不得输出简单模式(不得包含mode字段或仅有action节点)。"
|
||||
)
|
||||
# 基于场景选择提示词;非simple时追加强制规则,避免模型误输出简单结构
|
||||
if scene_mode == "simple":
|
||||
use_prompt = self.simple_prompt
|
||||
elif scene_mode == "scene4":
|
||||
use_prompt = self.scene4_prompt
|
||||
else:
|
||||
use_prompt = self.scene1_prompt
|
||||
if scene_mode != "simple":
|
||||
use_prompt = (
|
||||
(use_prompt or self.complex_prompt or "") +
|
||||
"\n\n【强制规则】仅生成包含root的复杂行为树JSON,不得输出简单模式(不得包含mode字段或仅有action节点)。"
|
||||
)
|
||||
final_user_prompt = user_prompt
|
||||
retrieved_context = self._retrieve_context(user_prompt)
|
||||
if retrieved_context:
|
||||
@@ -866,8 +876,9 @@ class PyTreeGenerator:
|
||||
logging.info(f"--- 第 {attempt + 1}/3 次尝试生成Pytree ---")
|
||||
try:
|
||||
# 简单/复杂分流到不同模型与提示词
|
||||
client = self.simple_llm_client if mode == "simple" else self.complex_llm_client
|
||||
model_name = self.simple_model if mode == "simple" else self.complex_model
|
||||
is_simple = scene_mode == "simple"
|
||||
client = self.simple_llm_client if is_simple else self.complex_llm_client
|
||||
model_name = self.simple_model if is_simple else self.complex_model
|
||||
messages = [
|
||||
{"role": "system", "content": use_prompt},
|
||||
{"role": "user", "content": final_user_prompt}
|
||||
@@ -876,7 +887,7 @@ class PyTreeGenerator:
|
||||
response_kwargs = {
|
||||
"model": model_name,
|
||||
"messages": messages,
|
||||
"temperature": 0.1 if mode == "complex" else 0.0,
|
||||
"temperature": 0.0 if is_simple else 0.1,
|
||||
"response_format": {"type": "json_object"}, # 始终强制JSON输出,禁用思考功能
|
||||
"extra_body": {"chat_template_kwargs": {"enable_thinking": False}}
|
||||
}
|
||||
@@ -884,7 +895,7 @@ class PyTreeGenerator:
|
||||
response_kwargs["tools"] = self._get_tool_definitions()
|
||||
response_kwargs["tool_choice"] = "auto"
|
||||
# 基于模式设定最大输出token数(直接在代码中配置)
|
||||
response_kwargs["max_tokens"] = self.simple_max_tokens if mode == "simple" else self.complex_max_tokens
|
||||
response_kwargs["max_tokens"] = self.simple_max_tokens if is_simple else self.complex_max_tokens
|
||||
response = client.chat.completions.create(**response_kwargs)
|
||||
|
||||
# 工具调用处理:执行工具并回填后,强制模型输出JSON
|
||||
@@ -1008,7 +1019,7 @@ class PyTreeGenerator:
|
||||
continue
|
||||
|
||||
# 简单/复杂分别验证与返回
|
||||
if mode == "simple":
|
||||
if scene_mode == "simple":
|
||||
try:
|
||||
jsonschema.validate(instance=pytree_dict, schema=self.simple_schema)
|
||||
# 手动检查:简单模式的root节点不能有children(或children必须是空数组)
|
||||
|
||||
@@ -1,2 +1,9 @@
|
||||
无人机当前在地面,到广场查找穿黄色衣服的男子,找到后近距离拍照。
|
||||
无人机当前在空中,回到广场,对长发可疑男子进行拍照。
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有打开的窗户,发现则进行拍照。
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有打开的窗户并拍照。
|
||||
无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有打开的窗户,看到了就拍照传回来。
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围巡视杂物堆积现象,发现则进行拍照。
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的杂物堆积并拍照。
|
||||
无人机当前在空中,往下飞3米,接着绕这栋楼外围侦察有没有杂物堆积,看到了就拍照传回来。
|
||||
无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有人,发现则进行拍照。
|
||||
无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的人并拍照。
|
||||
无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。
|
||||
11
tools/test_validate/instructions/scene4.txt
Normal file
11
tools/test_validate/instructions/scene4.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
无人机当前在地面,到广场查找穿红色衣服的人,找到后近距离拍照。
|
||||
无人机当前在空中,回到广场,对戴帽子的人进行拍照。
|
||||
无人机当前在空中,去广场南边40米,对过往的公交车拍张照,然后返航。
|
||||
无人机当前在地面,到广场查找绿色公交车,看见了拍个照片。
|
||||
无人机当前在空中,搜索小汽车,搜索到了我确认后再决定要不要拍照。
|
||||
无人机当前在空中,搜索小汽车,搜索到了拍张照,我确认后再决定要不要返航。
|
||||
无人机当前在空中,往广场南边飞40米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。
|
||||
无人机当前在地面,到广场边上的施工区域内,发现有没带安全帽的飞近后拍照。
|
||||
无人机当前在空中,紧急回到广场,看见了红绿灯之后直接降落。
|
||||
无人机当前在地面,快速去往东边60米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。
|
||||
无人机当前在空中,离白色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。
|
||||
8
tools/test_validate/instructions/scene4_1.txt
Normal file
8
tools/test_validate/instructions/scene4_1.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
无人机当前在空中,往广场南边飞40米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。
|
||||
无人机当前在空中,快速去往东边60米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。
|
||||
无人机当前在地面,快速去往东边60米,有身穿白色衣服,头戴帽子的男子在挟持他人,对其进行拍照。
|
||||
无人机当前在空中,离白色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。
|
||||
无人机当前在空中,返航。
|
||||
无人机当前在空中,飞往广场。
|
||||
无人机当前在地面,飞往广场。
|
||||
无人机当前再空中,向上移动10米。
|
||||
@@ -4,7 +4,7 @@
|
||||
无人机当前在地面,到广场查找绿色公交车,看见了拍个照片。
|
||||
无人机当前在空中,搜索小汽车,搜索到了我确认后再决定要不要拍照。
|
||||
无人机当前在空中,往广场西边飞200米,持续监控5分钟,发现人就拍照告诉我,到时间可以返航。
|
||||
无人机当前在地面,到广场边上的施工区域内,发现有没带安全帽的飞近后拍照。
|
||||
无人机当前在地面,到广场边上的施工区域内,发现未戴安全帽的飞近后拍照。
|
||||
无人机当前在空中,紧急回到广场,看见了红绿灯之后直接降落。
|
||||
无人机当前在地面,快速去往东边100米,有身穿黑色衣服,头戴帽子的男子在挟持他人,对其进行拍照。
|
||||
无人机当前在地面,快速去往东边60米,对身穿白色衣服,头戴帽子正在挟持他人的人进行拍照。
|
||||
无人机当前在空中,离黑色衣服戴帽子的人太远了照片看不清,贴近到3米距离拍,拍完可以直接返航。
|
||||
Reference in New Issue
Block a user