Compare commits
16 Commits
pipeline
...
e164148c5c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e164148c5c | ||
|
|
b12339ff73 | ||
| 410d2e01e4 | |||
| 070e4f579d | |||
| dd066057b0 | |||
| 59c52f6b99 | |||
| bce9203e01 | |||
| 333fad40ac | |||
| 9538757047 | |||
| ffb9aee730 | |||
| b68883e4e0 | |||
| 5d1c02fb5b | |||
| fb473dcf1a | |||
| 10c5bb5a8a | |||
| 3eba1f962b | |||
| 6f990e645d |
Binary file not shown.
|
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 78 KiB |
BIN
backend_service/src/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
backend_service/src/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
backend_service/src/__pycache__/main.cpython-312.pyc
Normal file
BIN
backend_service/src/__pycache__/main.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,24 +0,0 @@
|
|||||||
你是一个严格的任务分类器。只输出一个JSON对象,不要输出解释或多余文本。
|
|
||||||
根据用户指令与下述可用节点定义,判断其为“简单”或“复杂”。
|
|
||||||
|
|
||||||
- 简单:单一原子动作即可完成(例如“起飞”“飞机自检”“移动到某地(已给定坐标)”“对着某点环绕XY圈(如‘对着学生宿舍环绕三十两圈’)”等),且无需行为树与安全并行监控。
|
|
||||||
- 复杂:需要多步流程、搜索/检测/跟踪/评估、战损确认、或需要模板化任务结构与安全并行监控。
|
|
||||||
|
|
||||||
输出格式(严格遵守):
|
|
||||||
{"mode":"simple"} 或 {"mode":"complex"}
|
|
||||||
|
|
||||||
—— 可用节点定义——
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"actions": [
|
|
||||||
{"name": "takeoff"}, {"name": "land"}, {"name": "fly_to_waypoint"}, {"name": "move_direction"}, {"name": "orbit_around_point"}, {"name": "orbit_around_target"}, {"name": "loiter"},
|
|
||||||
{"name": "object_detect"}, {"name": "strike_target"}, {"name": "battle_damage_assessment"},
|
|
||||||
{"name": "search_pattern"}, {"name": "track_object"}, {"name": "deliver_payload"},
|
|
||||||
{"name": "preflight_checks"}, {"name": "emergency_return"}
|
|
||||||
],
|
|
||||||
"conditions": [
|
|
||||||
{"name": "battery_above"}, {"name": "at_waypoint"}, {"name": "object_detected"},
|
|
||||||
{"name": "target_destroyed"}, {"name": "time_elapsed"}, {"name": "gps_status"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
41
backend_service/src/prompts/partials/common_rules.txt
Normal file
41
backend_service/src/prompts/partials/common_rules.txt
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
## 六、高频错误规避
|
||||||
|
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`: 偏移距离(米)
|
||||||
|
- **中文复合方位**(东南/西北/东北/西南/南偏东10度/北偏西15度等):**必须**先调用工具`calc_offset_esu_direction_text`计算绝对坐标,再使用`fly_to_waypoint`。工具参数:
|
||||||
|
- `base`: 参考地点的ENU坐标(含x/y/z)
|
||||||
|
- `direction_text`: 中文方位原文(如“东南”“南偏东10度”)
|
||||||
|
- `distance`: 偏移距离(米)
|
||||||
|
- **禁止简化**:当出现“东南/西北/东北/西南/南偏东/北偏西”等复合方位时,禁止将其简化为单一方向(如仅“东”或仅“南”)。
|
||||||
|
|
||||||
|
示例(必须遵守):
|
||||||
|
- “飞到广场东南方向100米” → 必须调用 `calc_offset_esu_direction_text`,参数 `direction_text` 为 `"东南"`,`distance` 为 `100`,再使用 `fly_to_waypoint`。
|
||||||
|
- “飞到广场南偏东10度100米” → 必须调用 `calc_offset_esu_direction_text`,参数 `direction_text` 为 `"南偏东10度"`,`distance` 为 `100`。
|
||||||
|
|
||||||
|
当指令只有“方向 + 距离”且**没有具体地点名词**时,**禁止**调用`calc_offset_enu`,必须使用`move_direction`。
|
||||||
|
当指令描述“附近/边上/区域内”等模糊位置且**无方向+距离**时,视为到该地点本身,不做偏移计算。
|
||||||
|
|
||||||
|
## 八、输出要求
|
||||||
|
仅输出1个严格符合上述所有规则的JSON对象。
|
||||||
185
backend_service/src/prompts/partials/core_nodes.json
Normal file
185
backend_service/src/prompts/partials/core_nodes.json
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
{
|
||||||
|
"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": "单一子节点(将子节点的成功结果反转为失败)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
1
backend_service/src/prompts/partials/header.txt
Normal file
1
backend_service/src/prompts/partials/header.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
任务:根据用户任意任务指令,生成结构化可执行的无人机行为树(Pytree)JSON。**仅输出单一JSON对象,无任何自然语言、注释或额外内容**。
|
||||||
8
backend_service/src/prompts/partials/required_fields.txt
Normal file
8
backend_service/src/prompts/partials/required_fields.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
## 二、节点必填字段(后端Schema强制要求,缺一验证失败)
|
||||||
|
每个节点必须包含以下字段,字段名/类型不可自定义:
|
||||||
|
1. **`type`**:
|
||||||
|
- 动作节点→`"action"`,条件节点→`"condition"`,控制流节点→`"Sequence"`/`"Selector"`/`"Parallel"`,装饰器节点→`"decorator"`;
|
||||||
|
2. **`name`**:必须是上述JSON中定义的`name`值;
|
||||||
|
3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数;
|
||||||
|
4. **`children`**:仅控制流节点必含(子节点数组);
|
||||||
|
5. **`child`**:仅装饰器节点必含(单一子节点对象,非数组)。
|
||||||
448
backend_service/src/prompts/partials/scene1_examples.txt
Normal file
448
backend_service/src/prompts/partials/scene1_examples.txt
Normal file
@@ -0,0 +1,448 @@
|
|||||||
|
## 四、场景示例
|
||||||
|
|
||||||
|
#### 场景 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}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
208
backend_service/src/prompts/partials/scene4_examples.txt
Normal file
208
backend_service/src/prompts/partials/scene4_examples.txt
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
## 四、场景示例(请灵活参考)
|
||||||
|
|
||||||
|
#### 场景 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"}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
18
backend_service/src/prompts/partials/standard_template.txt
Normal file
18
backend_service/src/prompts/partials/standard_template.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
## 三、标准任务结构模板(单次起降流程)
|
||||||
|
当无人机在地面时,大多数任务应遵循“起飞 -> 移动 -> 条件判断 -> 执行 -> 返航/降落”的单次闭环流程,参考结构如下:
|
||||||
|
```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环节,直接执行用户任务即可
|
||||||
489
backend_service/src/prompts/partials/system_extra_examples.txt
Normal file
489
backend_service/src/prompts/partials/system_extra_examples.txt
Normal file
@@ -0,0 +1,489 @@
|
|||||||
|
#### 场景 7:空中上升后沿建筑外围侦察(Sequence + Selector)
|
||||||
|
**指令**:“无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有人,看到了就拍照传回来。”
|
||||||
|
**参考信息**:面前的大楼外围四个点东南天坐标系坐标:A(-24.00, 241.80),B(-108.50, 241.80),C(-108.50, 289.80),D(-24.00, 292.80)。
|
||||||
|
**思路**:无人机在空中,无需自检与起飞。先向上移动3米(仅方向+距离,使用`move_direction`)。随后“边飞边判断”:用`Parallel`并行执行`fly_sequence`与持续检测分支。检测分支使用`object_detect` + `object_detected` + `take_photos`,再用`SuccessIsFailure`保证不会提前结束并行;并行策略为`success_on_one`,当巡查飞行完成即结束任务。
|
||||||
|
**结构**:Sequence
|
||||||
|
```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}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 场景 8:地面起飞到楼前12米高度并沿外围查找杂物(Sequence)
|
||||||
|
**指令**:“无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有的杂物堆积并拍照。”
|
||||||
|
**参考信息**:面前的大楼外围四个点东南天坐标系坐标:A(-24.00, 241.80),B(-108.50, 241.80),C(-108.50, 289.80),D(-24.00, 292.80)。
|
||||||
|
**思路**:无人机在地面,需自检后起飞。指令是到具体地点且明确高度,使用`fly_sequence`沿外围巡查,所有航点设置为12米高度(`depth`=12)。为满足“边飞边判断”,使用`Parallel`并行飞行与检测,检测分支持续执行`object_detect` + `object_detected` + `take_photos`,用`SuccessIsFailure`避免提前结束。
|
||||||
|
**结构**:Sequence
|
||||||
|
```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}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 场景 9:地面到12米绕外围查看打开的窗户(Sequence)
|
||||||
|
**指令**:“无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有打开的窗户,发现则进行拍照。”
|
||||||
|
**参考信息**:面前的大楼外围四个点东南天坐标系坐标:A(-24.00, 241.80),B(-108.50, 241.80),C(-108.50, 289.80),D(-24.00, 292.80)。
|
||||||
|
**思路**:无人机在地面,先自检起飞。随后使用`fly_sequence`沿外围绕飞,航点高度为12米(`depth`=12)。同时并行执行检测分支,发现打开窗户就拍照。
|
||||||
|
**结构**:Sequence
|
||||||
|
```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}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 场景 10:地面到12米沿外围查找打开的窗户(Sequence)
|
||||||
|
**指令**:“无人机当前在地面,去面前大楼的12米高处,沿着外围查找所有打开的窗户并拍照。”
|
||||||
|
**参考信息**:面前的大楼外围四个点东南天坐标系坐标:A(-24.00, 241.80),B(-108.50, 241.80),C(-108.50, 289.80),D(-24.00, 292.80)。
|
||||||
|
**思路**:无人机在地面,起飞后使用`fly_sequence`沿外围巡查(`depth`=12),并行持续检测打开的窗户并拍照。
|
||||||
|
**结构**:Sequence
|
||||||
|
```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}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 场景 11:空中上升后绕外围侦察打开窗户(Sequence)
|
||||||
|
**指令**:“无人机当前在空中,再往上飞3米,接着绕这栋楼外围侦察有没有打开的窗户,看到了就拍照传回来。”
|
||||||
|
**参考信息**:面前的大楼外围四个点东南天坐标系坐标:A(-24.00, 241.80),B(-108.50, 241.80),C(-108.50, 289.80),D(-24.00, 292.80)。
|
||||||
|
**思路**:无人机在空中,先上升3米。随后并行执行绕飞巡查与检测,发现打开窗户立即拍照。
|
||||||
|
**结构**:Sequence
|
||||||
|
```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}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 场景 12:地面到12米绕外围巡视杂物堆积(Sequence)
|
||||||
|
**指令**:“无人机当前在地面,去面前大楼的12米高处,绕着外围巡视杂物堆积现象,发现则进行拍照。”
|
||||||
|
**参考信息**:面前的大楼外围四个点东南天坐标系坐标:A(-24.00, 241.80),B(-108.50, 241.80),C(-108.50, 289.80),D(-24.00, 292.80)。
|
||||||
|
**思路**:无人机在地面,起飞后沿外围绕飞(`depth`=12),并行检测杂物堆积并拍照。
|
||||||
|
**结构**:Sequence
|
||||||
|
```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}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 场景 13:空中下降后绕外围侦察杂物堆积(Sequence)
|
||||||
|
**指令**:“无人机当前在空中,往下飞3米,接着绕这栋楼外围侦察有没有杂物堆积,看到了就拍照传回来。”
|
||||||
|
**参考信息**:面前的大楼外围四个点东南天坐标系坐标:A(-24.00, 241.80),B(-108.50, 241.80),C(-108.50, 289.80),D(-24.00, 292.80)。
|
||||||
|
**思路**:无人机在空中,先下降3米。随后并行执行绕飞巡查与检测,发现杂物堆积立即拍照。
|
||||||
|
**结构**:Sequence
|
||||||
|
```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}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 场景 14:地面到12米绕外围查看是否有人(Sequence)
|
||||||
|
**指令**:“无人机当前在地面,去面前大楼的12米高处,绕着外围看有没有人,发现则进行拍照。”
|
||||||
|
**参考信息**:面前的大楼外围四个点东南天坐标系坐标:A(-24.00, 241.80),B(-108.50, 241.80),C(-108.50, 289.80),D(-24.00, 292.80)。
|
||||||
|
**思路**:无人机在地面,起飞后沿外围绕飞(`depth`=12),并行检测人员并拍照。
|
||||||
|
**结构**:Sequence
|
||||||
|
```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}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 场景 15:地面到12米沿外围逆时针查找人员(Sequence)
|
||||||
|
**指令**:“无人机当前在地面,去面前大楼的12米高处,沿着外围逆时针查找所有的人并拍照。”
|
||||||
|
**参考信息**:面前的大楼外围四个点东南天坐标系坐标:A(-24.00, 241.80),B(-108.50, 241.80),C(-108.50, 289.80),D(-24.00, 292.80)。
|
||||||
|
**思路**:无人机在地面,起飞后按逆时针顺序巡查外围(示例航点顺序:A→D→C→B→A),并行检测人员与拍照。
|
||||||
|
**结构**:Sequence
|
||||||
|
```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}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
24
backend_service/src/prompts/prompt_manifest.yaml
Normal file
24
backend_service/src/prompts/prompt_manifest.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
scenes:
|
||||||
|
system:
|
||||||
|
- header.txt
|
||||||
|
- core_nodes.json
|
||||||
|
- required_fields.txt
|
||||||
|
- standard_template.txt
|
||||||
|
- scene4_examples.txt
|
||||||
|
- system_extra_examples.txt
|
||||||
|
- common_rules.txt
|
||||||
|
scene1:
|
||||||
|
- header.txt
|
||||||
|
- core_nodes.json
|
||||||
|
- required_fields.txt
|
||||||
|
- standard_template.txt
|
||||||
|
- scene1_examples.txt
|
||||||
|
scene4:
|
||||||
|
- header.txt
|
||||||
|
- core_nodes.json
|
||||||
|
- required_fields.txt
|
||||||
|
- standard_template.txt
|
||||||
|
- scene4_examples.txt
|
||||||
|
- common_rules.txt
|
||||||
|
simple:
|
||||||
|
- simple_mode_prompt.txt
|
||||||
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米距离拍,拍完可以直接返航。
|
||||||
@@ -9,35 +9,38 @@
|
|||||||
示例:
|
示例:
|
||||||
- “起飞到10米” → {"root":{"type":"action","name":"takeoff","params":{"altitude":10.0}}}
|
- “起飞到10米” → {"root":{"type":"action","name":"takeoff","params":{"altitude":10.0}}}
|
||||||
- “移动到(120,80,20)” → {"root":{"type":"action","name":"fly_to_waypoint","params":{"x":120.0,"y":80.0,"z":20.0,"acceptance_radius":2.0}}}
|
- “移动到(120,80,20)” → {"root":{"type":"action","name":"fly_to_waypoint","params":{"x":120.0,"y":80.0,"z":20.0,"acceptance_radius":2.0}}}
|
||||||
- “飞机自检” → {"root":{"type":"action","name":"preflight_checks","params":{"check_level":"comprehensive"}}}
|
- “飞机自检” → {"root":{"type":"action","name":"system_checks","params":{"check_level":"comprehensive"}}}
|
||||||
|
|
||||||
—— 可用节点定义——
|
—— 可用节点定义——
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"actions": [
|
"actions": [
|
||||||
{"name": "takeoff", "description": "无人机从当前位置垂直起飞到指定的海拔高度。", "params": {"altitude": "float, 目标海拔高度(米),范围[1, 100],默认为2"}},
|
{"name":"takeoff","params":{"altitude":"float[1,100],默认2"}},
|
||||||
{"name": "land", "description": "降落无人机。可选择当前位置或返航点降落。", "params": {"mode": "string, 可选值: 'current'(当前位置), 'home'(返航点)"}},
|
{"name":"land","params":{"mode":"'current'/'home'"}},
|
||||||
{"name": "fly_to_waypoint", "description": "导航至一个指定坐标点。使用相对坐标系(x,y,z),单位为米。", "params": {"x": "float", "y": "float", "z": "float", "acceptance_radius": "float, 可选,默认2.0"}},
|
{"name":"fly_to_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","acceptance_radius":"默认2.0"}},
|
||||||
{"name": "move_direction", "description": "按指定方向直线移动。方向可为绝对方位或相对机体朝向。", "params": {"direction": "string: north|south|east|west|forward|backward|left|right", "distance": "float[1,10000], 可选, 不指定则持续移动"}},
|
{"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": "orbit_around_point", "description": "以给定中心点为中心,等速圆周飞行指定圈数。", "params": {"center_x": "float", "center_y": "float", "center_z": "float", "radius": "float[5,1000]", "laps": "int[1,20]", "clockwise": "boolean, 可选, 默认true", "speed_mps": "float[0.5,15], 可选", "gimbal_lock": "boolean, 可选, 默认true"}},
|
{"name":"move_direction","params":{"direction":"north/south/east/west/forward/backward/left/right/up/down","distance":"[1,10000],缺省持续移动","speed":"float,可选"}},
|
||||||
{"name": "orbit_around_target", "description": "以目标为中心,等速圆周飞行指定圈数(需已有目标)。", "params": {"target_class": "string, 取值同object_detect列表", "description": "string, 可选", "radius": "float[5,1000]", "laps": "int[1,20]", "clockwise": "boolean, 可选, 默认true", "speed_mps": "float[0.5,15], 可选", "gimbal_lock": "boolean, 可选, 默认true"}},
|
{"name":"approach_target","params":{"target_class":"string,要趋近的目标类别","description":"string,可选,目标属性描述","stop_distance":"float,期望的最终停止距离","speed":"float,可选,期望的逼近速度"}},
|
||||||
{"name": "loiter", "description": "在当前位置上空悬停一段时间或直到条件触发。", "params": {"duration": "float, 可选[1,600]", "until_condition": "string, 可选"}},
|
{"name":"rotate","params":{"angle":"float,无人机自身旋转角度(正数逆时针,负数顺时针)","angular_velocity":"rad/s,旋转角速度"}},
|
||||||
{"name": "object_detect", "description": "识别特定目标对象。一般是用户提到的需要检测的目标;如果用户给出了需要探索的目标的优先级,比如蓝色球危险性大于红色球大于绿色球,需要检测最危险的球,此处应给出检测优先级,描述应当为 '蓝>红>绿'", "params": {"target_class": "string, 要识别的目标类别,必须为以下值之一: balloon,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", "description": "string, 可选", "count": "int, 可选, 默认1"}},
|
{"name":"rotate_search","params":{"target_class":"string,要搜寻的目标类别","description":"string,可选,目标属性描述","step_angle":"float,可选,每一步旋转的角度","total_rotation":"float,可选,总共旋转搜索的角度"}},
|
||||||
{"name": "strike_target", "description": "对已识别目标进行打击。", "params": {"target_class": "string", "description": "string, 可选", "count": "int, 可选, 默认1"}},
|
{"name":"manual_confirmation","params":{}},
|
||||||
{"name": "battle_damage_assessment", "description": "战损评估。", "params": {"target_class": "string", "assessment_time": "float[5-60], 默认15.0"}},
|
{"name":"loiter","params":{"duration":"[1,600]秒/until_condition:可选"}},
|
||||||
{"name": "search_pattern", "description": "按模式搜索。", "params": {"pattern_type": "string: spiral|grid", "center_x": "float", "center_y": "float", "center_z": "float", "radius": "float[5,1000]", "target_class": "string", "description": "string, 可选", "count": "int, 可选, 默认1"}},
|
{"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": "track_object", "description": "持续跟踪目标。", "params": {"target_class": "string, 取值同object_detect列表", "description": "string, 可选", "track_time": "float[1,600], 默认30.0", "min_confidence": "float[0.5-1.0], 默认0.7", "safe_distance": "float[2-50], 默认10.0"}},
|
{"name":"strike_target","params":{"target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
|
||||||
{"name": "deliver_payload", "description": "投放物资。", "params": {"payload_type": "string", "release_altitude": "float[2,100], 默认5.0"}},
|
{"name":"battle_damage_assessment","params":{"target_class":"同object_detect","assessment_time":"[5,60],默认15"}},
|
||||||
{"name": "preflight_checks", "description": "飞行前系统自检。", "params": {"check_level": "string: basic|comprehensive"}},
|
{"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": "emergency_return", "description": "执行紧急返航程序。", "params": {"reason": "string"}}
|
{"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"}},
|
||||||
|
{"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": [
|
"conditions": [
|
||||||
{"name": "battery_above", "description": "电池电量高于阈值。", "params": {"threshold": "float[0.0,1.0]"}},
|
{"name":"at_waypoint","params":{"x":"±10000","y":"±10000","z":"[1,5000]","tolerance":"默认3.0"}},
|
||||||
{"name": "at_waypoint", "description": "在指定坐标容差范围内。", "params": {"x": "float", "y": "float", "z": "float", "tolerance": "float, 可选, 默认3.0"}},
|
{"name":"object_detected","params":{"target_class":"同object_detect(必传)","description":"可选,目标属性","count":"默认1"}},
|
||||||
{"name": "object_detected", "description": "检测到特定目标。", "params": {"target_class": "string", "description": "string, 可选", "count": "int, 可选, 默认1"}},
|
{"name":"target_destroyed","params":{"target_class":"同object_detect","description":"可选,目标属性","confidence":"[0.5,1.0]默认0.8"}},
|
||||||
{"name": "target_destroyed", "description": "目标已被摧毁。", "params": {"target_class": "string", "description": "string, 可选", "confidence": "float[0.5-1.0], 默认0.8"}},
|
{"name":"time_elapsed","params":{"duration":"[1,2700]秒"}},
|
||||||
{"name": "time_elapsed", "description": "时间经过。", "params": {"duration": "float[1,2700]"}},
|
{"name":"gps_status","params":{"min_satellites":"int[6,15],必传(如8)"}}
|
||||||
{"name": "gps_status", "description": "GPS状态良好。", "params": {"min_satellites": "int[6,15], 默认10"}}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -48,14 +51,4 @@
|
|||||||
- fly_to_waypoint.x,y: [-10000, 10000]
|
- fly_to_waypoint.x,y: [-10000, 10000]
|
||||||
- search_pattern.radius: [5, 1000]
|
- search_pattern.radius: [5, 1000]
|
||||||
- move_direction.distance: [1, 10000]
|
- move_direction.distance: [1, 10000]
|
||||||
- orbit_around_point.radius: [5, 1000]
|
|
||||||
- orbit_around_target.radius: [5, 1000]
|
|
||||||
- orbit_around_point/target.laps: [1, 20]
|
|
||||||
- orbit_around_point/target.speed_mps: [0.5, 15]
|
|
||||||
- 若参考知识提供坐标,必须使用并裁剪到约束范围内
|
- 若参考知识提供坐标,必须使用并裁剪到约束范围内
|
||||||
|
|
||||||
—— 口令转化规则(环绕类)——
|
|
||||||
- “环绕X米Y圈” → 若有目标上下文则使用 `orbit_around_target`,否则根据是否给出中心坐标选择 `orbit_around_point`;`radius=X`,`laps=Y`,默认 `clockwise=true`,`gimbal_lock=true`
|
|
||||||
- “顺时针/逆时针” → `clockwise=true/false`
|
|
||||||
- “等速” → 若未给速度则 `speed_mps` 采用默认值(例如3.0);若口令指明速度,裁剪到[0.5,15]
|
|
||||||
- “以(x,y,z)为中心”/“当前位置为中心” → 选择 `orbit_around_point` 并填充 `center_x/center_y/center_z`
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
任务:根据用户任意任务指令,生成结构化可执行的无人机行为树(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"}},
|
|
||||||
{"name":"move_direction","params":{"direction":"north/south/east/west/forward/backward/left/right","distance":"[1,10000],缺省持续移动"}},
|
|
||||||
{"name":"orbit_around_point","params":{"center_x":"±10000","center_y":"±10000","center_z":"[1,5000]","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
|
|
||||||
{"name":"orbit_around_target","params":{"target_class":"见object_detect列表","description":"可选,目标属性","radius":"[5,1000]","laps":"[1,20]","clockwise":"默认true","speed_mps":"[0.5,15]","gimbal_lock":"默认true"}},
|
|
||||||
{"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","description":"可选,","count":"默认1"}},
|
|
||||||
{"name":"strike_target","params":{"target_class":"同object_detect","description":"可选,目标属性","count":"默认1"}},
|
|
||||||
{"name":"battle_damage_assessment","params":{"target_class":"同object_detect","assessment_time":"[5,60],默认15"}},
|
|
||||||
{"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":"preflight_checks","params":{"check_level":"basic/comprehensive"}},
|
|
||||||
{"name":"emergency_return","params":{"reason":"string"}}
|
|
||||||
],
|
|
||||||
"conditions": [
|
|
||||||
{"name":"battery_above","params":{"threshold":"[0.0,1.0],必传"}},
|
|
||||||
{"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"}},
|
|
||||||
{"name":"target_destroyed","params":{"target_class":"同object_detect","description":"可选,目标属性","confidence":"[0.5,1.0]默认0.8"}},
|
|
||||||
{"name":"time_elapsed","params":{"duration":"[1,2700]秒"}},
|
|
||||||
{"name":"gps_status","params":{"min_satellites":"int[6,15],必传(如8)"}}
|
|
||||||
],
|
|
||||||
"control_flow": [
|
|
||||||
{"name":"Sequence","params":{},"children":"子节点数组(按序执行,全成功则成功)"},
|
|
||||||
{"name":"Selector","params":{"memory":"默认true"},"children":"子节点数组(执行到成功为止)"},
|
|
||||||
{"name":"Parallel","params":{"policy":"all_success"},"children":"子节点数组(同时执行,严禁用'one_success')"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## 二、节点必填字段(后端Schema强制要求,缺一验证失败)
|
|
||||||
每个节点必须包含以下字段,字段名/类型不可自定义:
|
|
||||||
1. **`type`**:
|
|
||||||
- 动作节点→`"action"`,条件节点→`"condition"`,控制流节点→`"Sequence"`/`"Selector"`/`"Parallel"`(与`name`字段值完全一致);
|
|
||||||
2. **`name`**:必须是上述JSON中`actions`/`conditions`/`control_flow`下的`name`值(如“gps_status”不可错写为“gps_check”);
|
|
||||||
3. **`params`**:严格匹配上述节点的`params`定义,无自定义参数(如优先级排序不可加“priority”字段,仅用`description`);
|
|
||||||
4. **`children`**:仅控制流节点必含(子节点数组),动作/条件节点无此字段。
|
|
||||||
|
|
||||||
|
|
||||||
## 三、行为树固定结构(通用不变,确保安全验证)
|
|
||||||
根节点必须是`Parallel`,`children`含`MainTask`(Sequence)和`SafetyMonitor`(Selector),结构不随任务类型(含优先级排序)修改:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"root": {
|
|
||||||
"type": "Parallel",
|
|
||||||
"name": "MissionWithSafety",
|
|
||||||
"params": {"policy": "all_success"},
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"type": "Sequence",
|
|
||||||
"name": "MainTask",
|
|
||||||
"params": {},
|
|
||||||
"children": [
|
|
||||||
// 通用主任务步骤(含优先级排序任务示例,需按用户指令替换):
|
|
||||||
{"type":"action","name":"preflight_checks","params":{"check_level":"comprehensive"}},
|
|
||||||
{"type":"action","name":"takeoff","params":{"altitude":10.0}},
|
|
||||||
{"type":"action","name":"fly_to_waypoint","params":{"x":200.0,"y":150.0,"z":10.0}}, // 搜索区坐标(用户未给时填合理值)
|
|
||||||
{"type":"action","name":"search_pattern","params":{"pattern_type":"grid","center_x":200.0,"center_y":150.0,"center_z":10.0,"radius":50.0,"target_class":"balloon","description":"红色"}},
|
|
||||||
{"type":"condition","name":"object_detected","params":{"target_class":"balloon","description":"红色"}}, // 确认高优先级目标
|
|
||||||
{"type":"action","name":"track_object","params":{"target_class":"balloon","description":"红色","track_time":30.0}},
|
|
||||||
{"type":"action","name":"strike_target","params":{"target_class":"balloon","description":"红色"}},
|
|
||||||
{"type":"action","name":"land","params":{"mode":"home"}}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "Selector",
|
|
||||||
"name": "SafetyMonitor",
|
|
||||||
"params": {"memory": true},
|
|
||||||
"children": [
|
|
||||||
{"type":"condition","name":"battery_above","params":{"threshold":0.3}},
|
|
||||||
{"type":"condition","name":"gps_status","params":{"min_satellites":8}},
|
|
||||||
{
|
|
||||||
"type":"Sequence",
|
|
||||||
"name":"EmergencyHandler",
|
|
||||||
"params": {},
|
|
||||||
"children": [
|
|
||||||
{"type":"action","name":"emergency_return","params":{"reason":"safety_breach"}},
|
|
||||||
{"type":"action","name":"land","params":{"mode":"home"}}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## 四、优先级排序任务通用示例
|
|
||||||
当用户指令中明确提出有多个待考察且具有优先级关系的物体时,节点描述须为优先级关系。比如当指令为已知有三个气球,危险级关系为红色气球大于蓝色气球大于绿色气球,要求优先跟踪最危险的气球时,节点的描述参考下表情形。
|
|
||||||
| 用户指令场景 | `target_class` | `description` | 核心节点示例(search_pattern) |
|
|
||||||
|-----------------------------|-----------------|-------------------------|------------------------------------------------------------------------------------------------|
|
|
||||||
| 红气球>蓝气球>绿气球 | `balloon` | `(红>蓝>绿)` | `{"type":"action","name":"search_pattern","params":{"pattern_type":"grid","center_x":200,"center_y":150,"center_z":10,"radius":50,"target_class":"balloon","description":"(红>蓝>绿)"}}` |
|
|
||||||
| 军用卡车>民用卡车>面包车 | `truck` | `(军用卡车>民用卡车>面包车)` | `{"type":"action","name":"object_detect","params":{"target_class":"truck","description":"(军用卡车>民用卡车>面包车)"}}` |
|
|
||||||
|
|
||||||
|
|
||||||
## 五、高频错误规避(确保验证通过)
|
|
||||||
1. 优先级排序不可修改`target_class`:如“民用卡车、面包车与军用卡车中,军用卡车优先”,`target_class`仍为`truck`,仅用`description`填排序规则;
|
|
||||||
2. 在没有明确指出物体之间的优先级关系情况下,`description`字段只描述物体属性本身,严禁与用户指令中不存在的物体进行排序;
|
|
||||||
3. `track_object`必传`track_time`:不可用`duration`替代(如跟踪30秒填`"track_time":30.0`);
|
|
||||||
4. `gps_status`的`min_satellites`必须在6-15之间(如8,不可缺省);
|
|
||||||
5. 无自定义节点:“锁定高优先级目标”需通过`object_detect`+`object_detected`实现,不可用“lock_high_risk_target”。
|
|
||||||
|
|
||||||
|
|
||||||
## 六、输出要求
|
|
||||||
仅输出1个严格符合上述所有规则的JSON对象,**确保:1. 优先级排序逻辑正确填入`description`;2. `target_class`匹配预定义列表;3. 行为树结构不变;4. 后端解析与Schema验证无错误**,无任何冗余内容。
|
|
||||||
@@ -10,6 +10,8 @@ from openai import OpenAIError
|
|||||||
import jsonschema
|
import jsonschema
|
||||||
import requests
|
import requests
|
||||||
import platform # 新增:用于选择合适的中文字体
|
import platform # 新增:用于选择合适的中文字体
|
||||||
|
import yaml
|
||||||
|
from .tools.coordinate_tools import calc_offset_enu, calc_offset_esu_direction_text
|
||||||
|
|
||||||
# --- 自定义远程嵌入函数 (与ingest.py中定义一致) ---
|
# --- 自定义远程嵌入函数 (与ingest.py中定义一致) ---
|
||||||
from chromadb.api.types import Documents, EmbeddingFunction, Embeddings, Embeddable
|
from chromadb.api.types import Documents, EmbeddingFunction, Embeddings, Embeddable
|
||||||
@@ -52,7 +54,7 @@ def _parse_allowed_nodes_from_prompt(prompt_text: str) -> tuple[Set[str], Set[st
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 使用更精确的正则表达式匹配节点定义部分
|
# 使用更精确的正则表达式匹配节点定义部分
|
||||||
node_section_pattern = r"#### 2\. 可用节点定义.*?```json\s*({.*?})\s*```"
|
node_section_pattern = r"#### 1\. 可用节点定义.*?```json\s*({.*?})\s*```"
|
||||||
match = re.search(node_section_pattern, prompt_text, re.DOTALL | re.IGNORECASE)
|
match = re.search(node_section_pattern, prompt_text, re.DOTALL | re.IGNORECASE)
|
||||||
|
|
||||||
if not match:
|
if not match:
|
||||||
@@ -144,51 +146,12 @@ def _fallback_parse_nodes(prompt_text: str) -> tuple[Set[str], Set[str]]:
|
|||||||
logging.error("在所有JSON代码块中都没有找到有效的节点定义结构。")
|
logging.error("在所有JSON代码块中都没有找到有效的节点定义结构。")
|
||||||
return set(), set()
|
return set(), set()
|
||||||
|
|
||||||
def _find_nodes_by_name(node: Dict, target_name: str) -> List[Dict]:
|
|
||||||
"""递归查找所有指定名称的节点"""
|
|
||||||
nodes_found = []
|
|
||||||
|
|
||||||
if node.get("name") == target_name:
|
|
||||||
nodes_found.append(node)
|
|
||||||
|
|
||||||
# 递归搜索子节点
|
|
||||||
for child in node.get("children", []):
|
|
||||||
nodes_found.extend(_find_nodes_by_name(child, target_name))
|
|
||||||
|
|
||||||
return nodes_found
|
|
||||||
|
|
||||||
def _validate_safety_monitoring(pytree_instance: dict) -> bool:
|
|
||||||
"""验证行为树是否包含必要的安全监控"""
|
|
||||||
root_node = pytree_instance.get("root", {})
|
|
||||||
|
|
||||||
# 查找所有电池监控节点
|
|
||||||
battery_nodes = _find_nodes_by_name(root_node, "battery_above")
|
|
||||||
|
|
||||||
# 检查是否包含安全监控结构
|
|
||||||
safety_monitors = _find_nodes_by_name(root_node, "SafetyMonitor")
|
|
||||||
|
|
||||||
if not battery_nodes and not safety_monitors:
|
|
||||||
logging.warning("⚠️ 安全警告: 行为树中没有发现电池监控节点或安全监控器")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 检查电池阈值设置是否合理
|
|
||||||
for battery_node in battery_nodes:
|
|
||||||
threshold = battery_node.get("params", {}).get("threshold")
|
|
||||||
if threshold is not None:
|
|
||||||
if threshold < 0.25:
|
|
||||||
logging.warning(f"⚠️ 安全警告: 电池阈值设置过低 ({threshold}),建议不低于0.25")
|
|
||||||
elif threshold > 0.5:
|
|
||||||
logging.warning(f"⚠️ 安全警告: 电池阈值设置过高 ({threshold}),可能影响任务执行")
|
|
||||||
|
|
||||||
logging.info("✅ 安全监控验证通过")
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> dict:
|
def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> dict:
|
||||||
"""
|
"""
|
||||||
根据允许的行动和条件节点,动态生成一个JSON Schema。
|
根据允许的行动和条件节点,动态生成一个JSON Schema。
|
||||||
"""
|
"""
|
||||||
# 所有可能的节点类型
|
# 所有可能的节点类型
|
||||||
node_types = ["action", "condition", "Sequence", "Selector", "Parallel"]
|
node_types = ["action", "condition", "Sequence", "Selector", "Parallel", "decorator"]
|
||||||
|
|
||||||
# 目标检测相关的类别枚举
|
# 目标检测相关的类别枚举
|
||||||
target_classes = [
|
target_classes = [
|
||||||
@@ -201,38 +164,44 @@ def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> di
|
|||||||
"sandwich", "orange", "broccoli", "carrot", "hot_dog", "pizza", "donut", "cake", "chair",
|
"sandwich", "orange", "broccoli", "carrot", "hot_dog", "pizza", "donut", "cake", "chair",
|
||||||
"couch", "potted_plant", "bed", "dining_table", "toilet", "tv", "laptop", "mouse", "remote",
|
"couch", "potted_plant", "bed", "dining_table", "toilet", "tv", "laptop", "mouse", "remote",
|
||||||
"keyboard", "cell_phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book",
|
"keyboard", "cell_phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book",
|
||||||
"clock", "vase", "scissors", "teddy_bear", "hair_drier", "toothbrush","balloon"
|
"clock", "vase", "scissors", "teddy_bear", "hair_drier", "toothbrush","balloon","trash","window","garbage"
|
||||||
]
|
]
|
||||||
|
|
||||||
# 递归节点定义
|
# 递归节点定义
|
||||||
node_definition = {
|
node_definition = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {"type": "string", "enum": node_types},
|
# 修改:手动构造不区分大小写的正则,避免使用不支持的 (?i) 标志
|
||||||
|
# 匹配: action, condition, sequence, selector, parallel, decorator (忽略大小写)
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^([Aa][Cc][Tt][Ii][Oo][Nn]|[Cc][Oo][Nn][Dd][Ii][Tt][Ii][Oo][Nn]|[Ss][Ee][Qq][Uu][Ee][Nn][Cc][Ee]|[Ss][Ee][Ll][Ee][Cc][Tt][Oo][Rr]|[Pp][Aa][Rr][Aa][Ll][Ll][Ee][Ll]|[Dd][Ee][Cc][Oo][Rr][Aa][Tt][Oo][Rr])$"
|
||||||
|
},
|
||||||
"name": {"type": "string"},
|
"name": {"type": "string"},
|
||||||
"params": {"type": "object"},
|
"params": {"type": "object"},
|
||||||
"children": {
|
"children": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {"$ref": "#/definitions/node"}
|
"items": {"$ref": "#/definitions/node"}
|
||||||
}
|
},
|
||||||
|
"child": {"$ref": "#/definitions/node"}
|
||||||
},
|
},
|
||||||
"required": ["type", "name"],
|
"required": ["type", "name"],
|
||||||
"allOf": [
|
"allOf": [
|
||||||
# 动作节点验证
|
# 动作节点验证 (忽略大小写)
|
||||||
{
|
{
|
||||||
"if": {"properties": {"type": {"const": "action"}}},
|
"if": {"properties": {"type": {"pattern": "^[Aa][Cc][Tt][Ii][Oo][Nn]$"}}},
|
||||||
"then": {"properties": {"name": {"enum": sorted(list(allowed_actions))}}}
|
"then": {"properties": {"name": {"enum": sorted(list(allowed_actions))}}}
|
||||||
},
|
},
|
||||||
# 条件节点验证
|
# 条件节点验证 (忽略大小写)
|
||||||
{
|
{
|
||||||
"if": {"properties": {"type": {"const": "condition"}}},
|
"if": {"properties": {"type": {"pattern": "^[Cc][Oo][Nn][Dd][Ii][Tt][Ii][Oo][Nn]$"}}},
|
||||||
"then": {"properties": {"name": {"enum": sorted(list(allowed_conditions))}}}
|
"then": {"properties": {"name": {"enum": sorted(list(allowed_conditions))}}}
|
||||||
},
|
},
|
||||||
# 目标检测动作节点的参数验证
|
# 目标检测动作节点的参数验证 (忽略大小写)
|
||||||
{
|
{
|
||||||
"if": {
|
"if": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {"const": "action"},
|
"type": {"pattern": "^[Aa][Cc][Tt][Ii][Oo][Nn]$"},
|
||||||
"name": {"const": "object_detect"}
|
"name": {"const": "object_detect"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -251,11 +220,11 @@ def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> di
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
# 目标检测条件节点的参数验证
|
# 目标检测条件节点的参数验证 (忽略大小写)
|
||||||
{
|
{
|
||||||
"if": {
|
"if": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {"const": "condition"},
|
"type": {"pattern": "^[Cc][Oo][Nn][Dd][Ii][Tt][Ii][Oo][Nn]$"},
|
||||||
"name": {"const": "object_detected"}
|
"name": {"const": "object_detected"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -274,11 +243,11 @@ def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> di
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
# 电池监控节点的参数验证
|
# 电池监控节点的参数验证 (忽略大小写)
|
||||||
{
|
{
|
||||||
"if": {
|
"if": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {"const": "condition"},
|
"type": {"pattern": "^[Cc][Oo][Nn][Dd][Ii][Tt][Ii][Oo][Nn]$"},
|
||||||
"name": {"const": "battery_above"}
|
"name": {"const": "battery_above"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -295,11 +264,11 @@ def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> di
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
# GPS状态节点的参数验证
|
# GPS状态节点的参数验证 (忽略大小写)
|
||||||
{
|
{
|
||||||
"if": {
|
"if": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {"const": "condition"},
|
"type": {"pattern": "^[Cc][Oo][Nn][Dd][Ii][Tt][Ii][Oo][Nn]$"},
|
||||||
"name": {"const": "gps_status"}
|
"name": {"const": "gps_status"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -315,6 +284,65 @@ def _generate_pytree_schema(allowed_actions: set, allowed_conditions: set) -> di
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
# 飞行序列节点的参数验证
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"type": {"pattern": "^[Aa][Cc][Tt][Ii][Oo][Nn]$"},
|
||||||
|
"name": {"const": "fly_sequence"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"params": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"waypoints": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"x": {"type": "number"},
|
||||||
|
"y": {"type": "number"},
|
||||||
|
"depth": {"type": "number"}
|
||||||
|
},
|
||||||
|
"required": ["x", "y"]
|
||||||
|
},
|
||||||
|
"minItems": 1
|
||||||
|
},
|
||||||
|
"coordinate_frame": {"type": "string", "enum": ["global", "local_enu"]},
|
||||||
|
"speed": {"type": "number"}
|
||||||
|
},
|
||||||
|
"required": ["waypoints", "coordinate_frame"],
|
||||||
|
"additionalProperties": False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
# 抵近目标节点的参数验证
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"type": {"pattern": "^[Aa][Cc][Tt][Ii][Oo][Nn]$"},
|
||||||
|
"name": {"const": "approach_target"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"params": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"target_class": {"type": "string"},
|
||||||
|
"description": {"type": "string"},
|
||||||
|
"stop_distance": {"type": "number"},
|
||||||
|
"speed": {"type": "number"}
|
||||||
|
},
|
||||||
|
"required": ["target_class", "stop_distance"],
|
||||||
|
"additionalProperties": False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -372,10 +400,7 @@ def _validate_pytree_with_schema(pytree_instance: dict, schema: dict) -> bool:
|
|||||||
jsonschema.validate(instance=pytree_instance, schema=schema)
|
jsonschema.validate(instance=pytree_instance, schema=schema)
|
||||||
logging.info("✅ JSON Schema验证成功")
|
logging.info("✅ JSON Schema验证成功")
|
||||||
|
|
||||||
# 额外验证安全监控
|
return True
|
||||||
safety_valid = _validate_safety_monitoring(pytree_instance)
|
|
||||||
|
|
||||||
return True and safety_valid
|
|
||||||
except jsonschema.ValidationError as e:
|
except jsonschema.ValidationError as e:
|
||||||
logging.warning("❌ Pytree验证失败")
|
logging.warning("❌ Pytree验证失败")
|
||||||
logging.warning(f"错误信息: {e.message}")
|
logging.warning(f"错误信息: {e.message}")
|
||||||
@@ -503,6 +528,10 @@ def _add_nodes_and_edges(node: dict, dot, parent_id: str | None = None) -> str:
|
|||||||
shape = 'ellipse'
|
shape = 'ellipse'
|
||||||
style = 'filled'
|
style = 'filled'
|
||||||
fillcolor = '#e1d5e7' # 紫色
|
fillcolor = '#e1d5e7' # 紫色
|
||||||
|
elif node_type == 'decorator':
|
||||||
|
shape = 'doubleoctagon'
|
||||||
|
style = 'filled'
|
||||||
|
fillcolor = '#f8cecc' # 浅红
|
||||||
|
|
||||||
# 特别标记安全相关节点
|
# 特别标记安全相关节点
|
||||||
if node.get('name') in ['battery_above', 'gps_status', 'SafetyMonitor']:
|
if node.get('name') in ['battery_above', 'gps_status', 'SafetyMonitor']:
|
||||||
@@ -515,11 +544,14 @@ def _add_nodes_and_edges(node: dict, dot, parent_id: str | None = None) -> str:
|
|||||||
if parent_id:
|
if parent_id:
|
||||||
dot.edge(parent_id, current_id)
|
dot.edge(parent_id, current_id)
|
||||||
|
|
||||||
# 递归处理子节点
|
# 递归处理子节点 (Sequence, Selector, Parallel 等)
|
||||||
children = node.get("children", [])
|
children = node.get("children", [])
|
||||||
if not children:
|
|
||||||
return current_id
|
|
||||||
|
|
||||||
|
# 兼容 decorator 类型的 child 字段 (处理为单元素列表以便统一逻辑)
|
||||||
|
if node_type == 'decorator' and 'child' in node:
|
||||||
|
children = [node['child']]
|
||||||
|
|
||||||
|
if children:
|
||||||
# 记录所有子节点的ID
|
# 记录所有子节点的ID
|
||||||
child_ids = []
|
child_ids = []
|
||||||
|
|
||||||
@@ -535,8 +567,10 @@ def _add_nodes_and_edges(node: dict, dot, parent_id: str | None = None) -> str:
|
|||||||
for cid in child_ids:
|
for cid in child_ids:
|
||||||
s.node(cid)
|
s.node(cid)
|
||||||
|
|
||||||
# 行为树中,所有类型的节点都只是父连子,不需要子节点间的额外连接
|
# 递归处理单子节点 (Decorator) - 已合并到 children 处理逻辑中,此处删除旧逻辑
|
||||||
# Sequence、Selector、Parallel 的执行逻辑由行为树引擎处理,不需要在可视化中体现
|
# child = node.get("child")
|
||||||
|
# if child:
|
||||||
|
# _add_nodes_and_edges(child, dot, current_id)
|
||||||
|
|
||||||
return current_id
|
return current_id
|
||||||
|
|
||||||
@@ -547,6 +581,8 @@ class PyTreeGenerator:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.base_dir = os.path.dirname(os.path.abspath(__file__))
|
self.base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
self.prompts_dir = os.path.join(self.base_dir, 'prompts')
|
self.prompts_dir = os.path.join(self.base_dir, 'prompts')
|
||||||
|
self._prompt_manifest_cache = None
|
||||||
|
self._prompt_manifest_mtime = None
|
||||||
|
|
||||||
# Updated output directory for visualizations
|
# Updated output directory for visualizations
|
||||||
self.vis_dir = os.path.abspath(os.path.join(self.base_dir, '..', 'generated_visualizations'))
|
self.vis_dir = os.path.abspath(os.path.join(self.base_dir, '..', 'generated_visualizations'))
|
||||||
@@ -561,10 +597,13 @@ class PyTreeGenerator:
|
|||||||
self.reasoning_preview_lines = int(os.getenv("REASONING_PREVIEW_LINES", "20"))
|
self.reasoning_preview_lines = int(os.getenv("REASONING_PREVIEW_LINES", "20"))
|
||||||
except Exception:
|
except Exception:
|
||||||
self.reasoning_preview_lines = 20
|
self.reasoning_preview_lines = 20
|
||||||
# 加载提示词:复杂模式复用现有 system_prompt.txt;简单模式与分类器独立提示词
|
# 加载提示词:优先使用清单拼接,失败回退到单文件
|
||||||
self.complex_prompt = self._load_prompt("system_prompt.txt")
|
self.complex_prompt = self._load_prompt_from_manifest("system", "system_prompt.txt")
|
||||||
self.simple_prompt = self._load_prompt("simple_mode_prompt.txt")
|
self.scene1_prompt = self._load_prompt_from_manifest("scene1", "scene1_prompt.txt")
|
||||||
|
self.scene4_prompt = self._load_prompt_from_manifest("scene4", "scene4_prompt.txt")
|
||||||
|
self.simple_prompt = self._load_prompt_from_manifest("simple", "simple_mode_prompt.txt")
|
||||||
self.classifier_prompt = self._load_prompt("classifier_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
|
self.system_prompt = self.complex_prompt
|
||||||
|
|
||||||
@@ -588,7 +627,7 @@ class PyTreeGenerator:
|
|||||||
self.complex_llm_client = openai.OpenAI(api_key=self.api_key, base_url=self.complex_base_url)
|
self.complex_llm_client = openai.OpenAI(api_key=self.api_key, base_url=self.complex_base_url)
|
||||||
|
|
||||||
# --- ChromaDB Client Setup ---
|
# --- ChromaDB Client Setup ---
|
||||||
vector_store_path = os.path.abspath(os.path.join(self.base_dir, '..', '..', 'tools', 'vector_store'))
|
vector_store_path = os.path.abspath(os.path.join(self.base_dir, '..', '..', 'tools', 'rag','vector_store'))
|
||||||
self.chroma_client = chromadb.PersistentClient(path=vector_store_path)
|
self.chroma_client = chromadb.PersistentClient(path=vector_store_path)
|
||||||
|
|
||||||
# Explicitly use the remote embedding function for queries
|
# Explicitly use the remote embedding function for queries
|
||||||
@@ -612,6 +651,219 @@ class PyTreeGenerator:
|
|||||||
logging.error(f"提示词文件未找到 -> {file_name}")
|
logging.error(f"提示词文件未找到 -> {file_name}")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def _load_prompt_manifest(self) -> Optional[dict]:
|
||||||
|
manifest_path = os.path.join(self.prompts_dir, "prompt_manifest.yaml")
|
||||||
|
try:
|
||||||
|
manifest_mtime = os.path.getmtime(manifest_path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if (
|
||||||
|
self._prompt_manifest_cache is not None
|
||||||
|
and self._prompt_manifest_mtime == manifest_mtime
|
||||||
|
):
|
||||||
|
return self._prompt_manifest_cache
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(manifest_path, "r", encoding="utf-8") as f:
|
||||||
|
manifest = yaml.safe_load(f) or {}
|
||||||
|
except Exception as exc:
|
||||||
|
logging.error(f"提示词清单加载失败 -> {exc}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not isinstance(manifest, dict):
|
||||||
|
logging.error("提示词清单格式错误:顶层必须为映射")
|
||||||
|
return None
|
||||||
|
|
||||||
|
self._prompt_manifest_cache = manifest
|
||||||
|
self._prompt_manifest_mtime = manifest_mtime
|
||||||
|
return manifest
|
||||||
|
|
||||||
|
def _resolve_prompt_fragment(self, fragment: str) -> str:
|
||||||
|
if os.path.isabs(fragment):
|
||||||
|
return fragment
|
||||||
|
if "/" in fragment:
|
||||||
|
return os.path.join(self.prompts_dir, fragment)
|
||||||
|
partial_path = os.path.join(self.prompts_dir, "partials", fragment)
|
||||||
|
if os.path.exists(partial_path):
|
||||||
|
return partial_path
|
||||||
|
return os.path.join(self.prompts_dir, fragment)
|
||||||
|
|
||||||
|
def _load_fragment_text(self, fragment_path: str) -> str:
|
||||||
|
if fragment_path.lower().endswith(".json"):
|
||||||
|
try:
|
||||||
|
with open(fragment_path, "r", encoding="utf-8") as f:
|
||||||
|
payload = json.load(f)
|
||||||
|
except Exception as exc:
|
||||||
|
raise ValueError(f"JSON片段解析失败: {exc}") from exc
|
||||||
|
|
||||||
|
json_text = json.dumps(payload, ensure_ascii=False, indent=2)
|
||||||
|
if os.path.basename(fragment_path) == "core_nodes.json":
|
||||||
|
return "\n".join(
|
||||||
|
[
|
||||||
|
"## 一、核心节点定义(格式不可修改,确保后端解析)",
|
||||||
|
"#### 1. 可用节点定义 (必须遵守)",
|
||||||
|
"你必须严格从以下JSON定义的列表中选择节点构建行为树,不允许使用未定义节点:",
|
||||||
|
"```json",
|
||||||
|
json_text,
|
||||||
|
"```",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return "\n".join(["```json", json_text, "```"])
|
||||||
|
|
||||||
|
with open(fragment_path, "r", encoding="utf-8") as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
def _load_prompt_from_manifest(self, scene_key: str, fallback_file: str) -> str:
|
||||||
|
manifest = self._load_prompt_manifest()
|
||||||
|
if not manifest:
|
||||||
|
return self._load_prompt(fallback_file)
|
||||||
|
|
||||||
|
scene_map = manifest.get("scenes", manifest)
|
||||||
|
fragments = scene_map.get(scene_key)
|
||||||
|
if not fragments:
|
||||||
|
logging.warning(f"提示词清单缺少场景配置 -> {scene_key}")
|
||||||
|
return self._load_prompt(fallback_file)
|
||||||
|
if not isinstance(fragments, list) or not all(isinstance(item, str) for item in fragments):
|
||||||
|
logging.warning(f"提示词清单场景配置非法 -> {scene_key}")
|
||||||
|
return self._load_prompt(fallback_file)
|
||||||
|
|
||||||
|
contents = []
|
||||||
|
for fragment in fragments:
|
||||||
|
fragment_path = self._resolve_prompt_fragment(fragment)
|
||||||
|
try:
|
||||||
|
contents.append(self._load_fragment_text(fragment_path).strip("\n"))
|
||||||
|
except FileNotFoundError:
|
||||||
|
logging.error(f"提示词片段未找到 -> {fragment_path}")
|
||||||
|
return self._load_prompt(fallback_file)
|
||||||
|
except ValueError as exc:
|
||||||
|
logging.error(f"提示词片段解析失败 -> {exc}")
|
||||||
|
return self._load_prompt(fallback_file)
|
||||||
|
|
||||||
|
return "\n\n".join(contents).strip("\n")
|
||||||
|
|
||||||
|
def _get_tool_definitions(self) -> list[dict]:
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "calc_offset_enu",
|
||||||
|
"description": "根据ENU坐标系基准点、方向和距离计算偏移后的坐标。",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"base": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"x": {"type": "number"},
|
||||||
|
"y": {"type": "number"},
|
||||||
|
"z": {"type": "number"}
|
||||||
|
},
|
||||||
|
"required": ["x", "y", "z"]
|
||||||
|
},
|
||||||
|
"direction": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"east", "west", "north", "south",
|
||||||
|
"up", "down"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"distance": {"type": "number", "minimum": 0}
|
||||||
|
},
|
||||||
|
"required": ["base", "direction", "distance"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "calc_offset_esu_direction_text",
|
||||||
|
"description": "根据ESU坐标系基准点、中文方位与距离计算偏移后的坐标。",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"base": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"x": {"type": "number"},
|
||||||
|
"y": {"type": "number"},
|
||||||
|
"z": {"type": "number"}
|
||||||
|
},
|
||||||
|
"required": ["x", "y", "z"]
|
||||||
|
},
|
||||||
|
"direction_text": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "中文方位,如“南偏东10度”“北偏东10度”“东南”“西北”等"
|
||||||
|
},
|
||||||
|
"distance": {"type": "number", "minimum": 0}
|
||||||
|
},
|
||||||
|
"required": ["base", "direction_text", "distance"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
def _normalize_tool_calls(self, tool_calls: list) -> list[dict]:
|
||||||
|
normalized = []
|
||||||
|
for call in tool_calls:
|
||||||
|
if hasattr(call, "function"):
|
||||||
|
normalized.append(
|
||||||
|
{
|
||||||
|
"id": getattr(call, "id", None),
|
||||||
|
"name": call.function.name,
|
||||||
|
"arguments": call.function.arguments,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
elif isinstance(call, dict):
|
||||||
|
normalized.append(
|
||||||
|
{
|
||||||
|
"id": call.get("id"),
|
||||||
|
"name": (call.get("function") or {}).get("name"),
|
||||||
|
"arguments": (call.get("function") or {}).get("arguments"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return normalized
|
||||||
|
|
||||||
|
def _execute_tool_calls(self, tool_calls: list) -> list[dict]:
|
||||||
|
tool_messages = []
|
||||||
|
normalized = self._normalize_tool_calls(tool_calls)
|
||||||
|
for call in normalized:
|
||||||
|
tool_name = call.get("name")
|
||||||
|
tool_args = call.get("arguments")
|
||||||
|
tool_id = call.get("id")
|
||||||
|
if not tool_name:
|
||||||
|
logging.warning("工具调用缺少名称,已忽略。")
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
args = json.loads(tool_args or "{}")
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
logging.warning(f"工具调用参数解析失败: {tool_args}")
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
if tool_name == "calc_offset_enu":
|
||||||
|
result = calc_offset_enu(**args)
|
||||||
|
elif tool_name == "calc_offset_esu_direction_text":
|
||||||
|
result = calc_offset_esu_direction_text(**args)
|
||||||
|
else:
|
||||||
|
result = {"error": f"unsupported tool: {tool_name}"}
|
||||||
|
tool_messages.append(
|
||||||
|
{
|
||||||
|
"role": "tool",
|
||||||
|
"tool_call_id": tool_id,
|
||||||
|
"content": json.dumps(result, ensure_ascii=False)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
except Exception as exc:
|
||||||
|
logging.warning(f"工具调用执行失败({tool_name}): {exc}")
|
||||||
|
tool_messages.append(
|
||||||
|
{
|
||||||
|
"role": "tool",
|
||||||
|
"tool_call_id": tool_id,
|
||||||
|
"content": json.dumps({"error": str(exc)}, ensure_ascii=False)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return tool_messages
|
||||||
|
|
||||||
def _retrieve_context(self, query: str) -> Optional[str]:
|
def _retrieve_context(self, query: str) -> Optional[str]:
|
||||||
logging.info("--- 开始从向量数据库检索上下文 ---")
|
logging.info("--- 开始从向量数据库检索上下文 ---")
|
||||||
try:
|
try:
|
||||||
@@ -629,19 +881,72 @@ class PyTreeGenerator:
|
|||||||
logging.error(f"从向量数据库检索时发生错误: {e}")
|
logging.error(f"从向量数据库检索时发生错误: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _should_enable_tools(self, user_prompt: str, retrieved_context: Optional[str]) -> bool:
|
||||||
|
if not user_prompt:
|
||||||
|
return False
|
||||||
|
|
||||||
|
direction_patterns = [
|
||||||
|
"东边", "西边", "南边", "北边",
|
||||||
|
"东侧", "西侧", "南侧", "北侧",
|
||||||
|
"往东", "往西", "往南", "往北",
|
||||||
|
"向东", "向西", "向南", "向北",
|
||||||
|
"东南", "西南", "东北", "西北",
|
||||||
|
"南偏东", "南偏西", "北偏东", "北偏西",
|
||||||
|
]
|
||||||
|
has_direction = any(pat in user_prompt for pat in direction_patterns)
|
||||||
|
has_distance = re.search(r"\d+(\.\d+)?\s*(米|m)", user_prompt) is not None
|
||||||
|
if not (has_direction and has_distance):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not retrieved_context:
|
||||||
|
return False
|
||||||
|
|
||||||
|
place_candidates: list[str] = []
|
||||||
|
for line in retrieved_context.splitlines():
|
||||||
|
if "地点:" in line or "别名:" in line:
|
||||||
|
place_candidates.extend(re.findall(r"'([^']+)'", line))
|
||||||
|
if not place_candidates:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return any(place in user_prompt for place in place_candidates)
|
||||||
|
|
||||||
|
def _save_history(self, prompt: str, result_dict: dict):
|
||||||
|
"""保存请求和响应历史记录"""
|
||||||
|
import datetime
|
||||||
|
try:
|
||||||
|
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
|
# 确保history目录存在
|
||||||
|
history_dir = os.path.join(self.base_dir, '..', 'history')
|
||||||
|
os.makedirs(history_dir, exist_ok=True)
|
||||||
|
|
||||||
|
history_file = os.path.join(history_dir, f"{timestamp}_plan.json")
|
||||||
|
|
||||||
|
record = {
|
||||||
|
"timestamp": datetime.datetime.now().isoformat(),
|
||||||
|
"request": prompt,
|
||||||
|
"response": result_dict
|
||||||
|
}
|
||||||
|
|
||||||
|
with open(history_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(record, f, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
|
logging.info(f"💾 历史记录已保存: {history_file}")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"保存历史记录失败: {e}")
|
||||||
|
|
||||||
async def generate(self, user_prompt: str) -> Dict[str, Any]:
|
async def generate(self, user_prompt: str) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Generates a py_tree.json structure based on the user's prompt.
|
Generates a py_tree.json structure based on the user's prompt.
|
||||||
"""
|
"""
|
||||||
logging.info(f"接收到用户请求: {user_prompt}")
|
logging.info(f"接收到用户请求: {user_prompt}")
|
||||||
|
|
||||||
# 第一步:分类(简单/复杂)
|
# 第一步:场景分类(simple/scene1/scene4)
|
||||||
mode = "complex"
|
scene_mode = "scene1"
|
||||||
try:
|
try:
|
||||||
classifier_resp = self.classifier_client.chat.completions.create(
|
classifier_resp = self.classifier_client.chat.completions.create(
|
||||||
model=self.classifier_model,
|
model=self.classifier_model,
|
||||||
messages=[
|
messages=[
|
||||||
{"role": "system", "content": self.classifier_prompt or "你是一个分类器,只输出JSON。"},
|
{"role": "system", "content": self.scene_classifier_prompt or "你是一个分类器,只输出JSON。"},
|
||||||
{"role": "user", "content": user_prompt}
|
{"role": "user", "content": user_prompt}
|
||||||
],
|
],
|
||||||
temperature=0.0,
|
temperature=0.0,
|
||||||
@@ -653,16 +958,23 @@ class PyTreeGenerator:
|
|||||||
)
|
)
|
||||||
class_str = classifier_resp.choices[0].message.content
|
class_str = classifier_resp.choices[0].message.content
|
||||||
class_obj = json.loads(class_str)
|
class_obj = json.loads(class_str)
|
||||||
if isinstance(class_obj, dict) and class_obj.get("mode") in ("simple", "complex"):
|
if isinstance(class_obj, dict) and class_obj.get("mode") in ("simple", "scene1", "scene4"):
|
||||||
mode = class_obj.get("mode")
|
scene_mode = class_obj.get("mode")
|
||||||
logging.info(f"分类结果: {mode}")
|
logging.info(f"场景分类结果: {scene_mode}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.warning(f"分类失败,默认按复杂指令处理: {e}")
|
logging.warning(f"场景分类失败,默认按scene1处理: {e}")
|
||||||
|
|
||||||
# 第二步:根据模式准备提示词与上下文(简单与复杂都执行检索增强)
|
# 第二步:根据模式准备提示词与上下文(简单与复杂都执行检索增强)
|
||||||
# 基于模式选择提示词;复杂模式追加一条强制规则,避免模型误输出简单结构
|
# 基于场景选择提示词;非simple时追加强制规则,避免模型误输出简单结构
|
||||||
use_prompt = self.simple_prompt if mode == "simple" else (
|
if scene_mode == "simple":
|
||||||
(self.complex_prompt or "") +
|
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节点)。"
|
"\n\n【强制规则】仅生成包含root的复杂行为树JSON,不得输出简单模式(不得包含mode字段或仅有action节点)。"
|
||||||
)
|
)
|
||||||
final_user_prompt = user_prompt
|
final_user_prompt = user_prompt
|
||||||
@@ -684,37 +996,92 @@ class PyTreeGenerator:
|
|||||||
# System Prompt: use_prompt(不包含RAG结果)
|
# System Prompt: use_prompt(不包含RAG结果)
|
||||||
# User Prompt: final_user_prompt(包含原始user_prompt + RAG检索结果)
|
# User Prompt: final_user_prompt(包含原始user_prompt + RAG检索结果)
|
||||||
final_prompt = f"=== System Prompt ===\n{use_prompt}\n\n=== User Prompt ===\n{final_user_prompt}"
|
final_prompt = f"=== System Prompt ===\n{use_prompt}\n\n=== User Prompt ===\n{final_user_prompt}"
|
||||||
|
tool_enabled = self._should_enable_tools(user_prompt, retrieved_context)
|
||||||
for attempt in range(3):
|
for attempt in range(3):
|
||||||
logging.info(f"--- 第 {attempt + 1}/3 次尝试生成Pytree ---")
|
logging.info(f"--- 第 {attempt + 1}/3 次尝试生成Pytree ---")
|
||||||
try:
|
try:
|
||||||
# 简单/复杂分流到不同模型与提示词
|
# 简单/复杂分流到不同模型与提示词
|
||||||
client = self.simple_llm_client if mode == "simple" else self.complex_llm_client
|
is_simple = scene_mode == "simple"
|
||||||
model_name = self.simple_model if mode == "simple" else self.complex_model
|
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}
|
||||||
|
]
|
||||||
# 始终强制JSON响应并禁用思考功能
|
# 始终强制JSON响应并禁用思考功能
|
||||||
response_kwargs = {
|
response_kwargs = {
|
||||||
"model": model_name,
|
"model": model_name,
|
||||||
"messages": [
|
"messages": messages,
|
||||||
{"role": "system", "content": use_prompt},
|
"temperature": 0.0 if is_simple else 0.1,
|
||||||
{"role": "user", "content": final_user_prompt}
|
|
||||||
],
|
|
||||||
"temperature": 0.1 if mode == "complex" else 0.0,
|
|
||||||
"response_format": {"type": "json_object"}, # 始终强制JSON输出,禁用思考功能
|
"response_format": {"type": "json_object"}, # 始终强制JSON输出,禁用思考功能
|
||||||
# 禁用 Qwen3 模型的思考功能(通过 extra_body 传递)
|
|
||||||
# 注意:如果 API 服务器不支持此参数,会忽略
|
|
||||||
"extra_body": {"chat_template_kwargs": {"enable_thinking": False}}
|
"extra_body": {"chat_template_kwargs": {"enable_thinking": False}}
|
||||||
}
|
}
|
||||||
|
if tool_enabled:
|
||||||
|
response_kwargs["tools"] = self._get_tool_definitions()
|
||||||
|
response_kwargs["tool_choice"] = "auto"
|
||||||
# 基于模式设定最大输出token数(直接在代码中配置)
|
# 基于模式设定最大输出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)
|
response = client.chat.completions.create(**response_kwargs)
|
||||||
|
|
||||||
|
# 工具调用处理:执行工具并回填后,强制模型输出JSON
|
||||||
|
for tool_round in range(3):
|
||||||
|
try:
|
||||||
|
first_msg = response.choices[0].message
|
||||||
|
tool_calls = getattr(first_msg, "tool_calls", None)
|
||||||
|
except Exception:
|
||||||
|
first_msg = response.choices[0].get("message") if isinstance(response.choices[0], dict) else None
|
||||||
|
tool_calls = (first_msg or {}).get("tool_calls")
|
||||||
|
|
||||||
|
if not tool_calls:
|
||||||
|
break
|
||||||
|
|
||||||
|
logging.info("检测到工具调用,执行第 %d 轮工具回填。", tool_round + 1)
|
||||||
|
tool_messages = self._execute_tool_calls(tool_calls)
|
||||||
|
if not tool_messages:
|
||||||
|
break
|
||||||
|
|
||||||
|
tool_calls_for_messages = []
|
||||||
|
for call in self._normalize_tool_calls(tool_calls):
|
||||||
|
if not call.get("id") or not call.get("name"):
|
||||||
|
continue
|
||||||
|
tool_calls_for_messages.append(
|
||||||
|
{
|
||||||
|
"id": call["id"],
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": call["name"],
|
||||||
|
"arguments": call.get("arguments", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
messages = messages + [
|
||||||
|
{
|
||||||
|
"role": "assistant",
|
||||||
|
"content": getattr(first_msg, "content", "") if first_msg else "",
|
||||||
|
"tool_calls": tool_calls_for_messages
|
||||||
|
}
|
||||||
|
] + tool_messages
|
||||||
|
followup_kwargs = dict(response_kwargs)
|
||||||
|
followup_kwargs["messages"] = messages
|
||||||
|
followup_kwargs.pop("tools", None)
|
||||||
|
followup_kwargs.pop("tool_choice", None)
|
||||||
|
response = client.chat.completions.create(**followup_kwargs)
|
||||||
|
break
|
||||||
# 兼容可能存在的 reasoning_content 字段
|
# 兼容可能存在的 reasoning_content 字段
|
||||||
try:
|
try:
|
||||||
msg = response.choices[0].message
|
msg = response.choices[0].message
|
||||||
msg_content = getattr(msg, "content", None)
|
msg_content = getattr(msg, "content", None)
|
||||||
msg_reasoning = getattr(msg, "reasoning_content", None)
|
msg_reasoning = getattr(msg, "reasoning_content", None)
|
||||||
|
remaining_tool_calls = getattr(msg, "tool_calls", None)
|
||||||
except Exception:
|
except Exception:
|
||||||
msg = response.choices[0]["message"] if isinstance(response.choices[0], dict) else None
|
msg = response.choices[0]["message"] if isinstance(response.choices[0], dict) else None
|
||||||
msg_content = (msg or {}).get("content") if isinstance(msg, dict) else None
|
msg_content = (msg or {}).get("content") if isinstance(msg, dict) else None
|
||||||
msg_reasoning = (msg or {}).get("reasoning_content") if isinstance(msg, dict) else None
|
msg_reasoning = (msg or {}).get("reasoning_content") if isinstance(msg, dict) else None
|
||||||
|
remaining_tool_calls = (msg or {}).get("tool_calls") if isinstance(msg, dict) else None
|
||||||
|
|
||||||
|
if (msg_content is None or str(msg_content).strip() == "") and remaining_tool_calls:
|
||||||
|
logging.warning("模型仍在请求工具调用,未返回JSON内容,重试下一次。")
|
||||||
|
continue
|
||||||
|
|
||||||
combined_text = ""
|
combined_text = ""
|
||||||
if isinstance(msg_reasoning, str) and msg_reasoning.strip():
|
if isinstance(msg_reasoning, str) and msg_reasoning.strip():
|
||||||
@@ -725,7 +1092,7 @@ class PyTreeGenerator:
|
|||||||
pytree_str = combined_text if combined_text else (msg_content or "")
|
pytree_str = combined_text if combined_text else (msg_content or "")
|
||||||
raw_full_text_for_logging = pytree_str # 保存完整原文(含 <think>)以便失败时完整打印
|
raw_full_text_for_logging = pytree_str # 保存完整原文(含 <think>)以便失败时完整打印
|
||||||
|
|
||||||
# 提取 <think> 推理链内容(若存在)
|
# 提取 <think> 推理链内容(若有)
|
||||||
reasoning_text = None
|
reasoning_text = None
|
||||||
try:
|
try:
|
||||||
think_match = re.search(r"<think>([\s\S]*?)</think>", pytree_str)
|
think_match = re.search(r"<think>([\s\S]*?)</think>", pytree_str)
|
||||||
@@ -777,7 +1144,7 @@ class PyTreeGenerator:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# 简单/复杂分别验证与返回
|
# 简单/复杂分别验证与返回
|
||||||
if mode == "simple":
|
if scene_mode == "simple":
|
||||||
try:
|
try:
|
||||||
jsonschema.validate(instance=pytree_dict, schema=self.simple_schema)
|
jsonschema.validate(instance=pytree_dict, schema=self.simple_schema)
|
||||||
# 手动检查:简单模式的root节点不能有children(或children必须是空数组)
|
# 手动检查:简单模式的root节点不能有children(或children必须是空数组)
|
||||||
@@ -825,51 +1192,13 @@ class PyTreeGenerator:
|
|||||||
logging.warning(f"保存推理链Markdown失败: {e}")
|
logging.warning(f"保存推理链Markdown失败: {e}")
|
||||||
# 添加 final_prompt 到返回结果
|
# 添加 final_prompt 到返回结果
|
||||||
pytree_dict['final_prompt'] = final_prompt
|
pytree_dict['final_prompt'] = final_prompt
|
||||||
|
|
||||||
|
# 保存历史记录
|
||||||
|
self._save_history(user_prompt, pytree_dict)
|
||||||
|
|
||||||
return pytree_dict
|
return pytree_dict
|
||||||
|
|
||||||
# 复杂模式回退:若模型误返回简单结构(root是单个action),则自动包装为含安全监控的行为树
|
# 验证生成的复杂行为树
|
||||||
if mode == "complex" and isinstance(pytree_dict, dict) and 'root' in pytree_dict:
|
|
||||||
root_node = pytree_dict.get('root', {})
|
|
||||||
# 检查是否是简单结构(root是单个action节点,没有children)
|
|
||||||
if (root_node.get('type') == 'action' and
|
|
||||||
('children' not in root_node or not root_node.get('children'))):
|
|
||||||
try:
|
|
||||||
jsonschema.validate(instance=pytree_dict, schema=self.simple_schema)
|
|
||||||
logging.warning("⚠️ 复杂模式生成了简单结构(单个action),触发自动包装为完整行为树的回退逻辑。")
|
|
||||||
action_name = root_node.get('name')
|
|
||||||
action_params = root_node.get('params') if isinstance(root_node.get('params'), dict) else {}
|
|
||||||
|
|
||||||
safety_selector = {
|
|
||||||
"type": "Selector",
|
|
||||||
"name": "SafetyMonitor",
|
|
||||||
"params": {"memory": True},
|
|
||||||
"children": [
|
|
||||||
{"type": "condition", "name": "battery_above", "params": {"threshold": 0.3}},
|
|
||||||
{"type": "condition", "name": "gps_status", "params": {"min_satellites": 8}},
|
|
||||||
{"type": "Sequence", "name": "EmergencyHandler", "children": [
|
|
||||||
{"type": "action", "name": "emergency_return", "params": {"reason": "safety_breach"}},
|
|
||||||
{"type": "action", "name": "land", "params": {"mode": "home"}}
|
|
||||||
]}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
main_children = [{"type": "action", "name": action_name, "params": action_params}]
|
|
||||||
if action_name != "land":
|
|
||||||
main_children.append({"type": "action", "name": "land", "params": {"mode": "home"}})
|
|
||||||
|
|
||||||
root_parallel = {
|
|
||||||
"type": "Parallel",
|
|
||||||
"name": "MissionWithSafety",
|
|
||||||
"params": {"policy": "all_success"},
|
|
||||||
"children": [
|
|
||||||
{"type": "Sequence", "name": "MainTask", "children": main_children},
|
|
||||||
safety_selector
|
|
||||||
]
|
|
||||||
}
|
|
||||||
pytree_dict = {"root": root_parallel}
|
|
||||||
except jsonschema.ValidationError:
|
|
||||||
# 不符合简单结构,按正常复杂验证继续
|
|
||||||
pass
|
|
||||||
if _validate_pytree_with_schema(pytree_dict, self.schema):
|
if _validate_pytree_with_schema(pytree_dict, self.schema):
|
||||||
logging.info("✅ 成功生成并验证了Pytree")
|
logging.info("✅ 成功生成并验证了Pytree")
|
||||||
plan_id = str(uuid.uuid4())
|
plan_id = str(uuid.uuid4())
|
||||||
@@ -901,6 +1230,10 @@ class PyTreeGenerator:
|
|||||||
logging.warning(f"保存推理链Markdown失败: {e}")
|
logging.warning(f"保存推理链Markdown失败: {e}")
|
||||||
# 添加 final_prompt 到返回结果
|
# 添加 final_prompt 到返回结果
|
||||||
pytree_dict['final_prompt'] = final_prompt
|
pytree_dict['final_prompt'] = final_prompt
|
||||||
|
|
||||||
|
# 保存历史记录
|
||||||
|
self._save_history(user_prompt, pytree_dict)
|
||||||
|
|
||||||
return pytree_dict
|
return pytree_dict
|
||||||
else:
|
else:
|
||||||
# 打印未通过验证的Pytree以便排查
|
# 打印未通过验证的Pytree以便排查
|
||||||
|
|||||||
1
backend_service/src/tools/__init__.py
Normal file
1
backend_service/src/tools/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
"""工具模块包。"""
|
||||||
BIN
backend_service/src/tools/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
backend_service/src/tools/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
backend_service/src/tools/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
backend_service/src/tools/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
110
backend_service/src/tools/coordinate_tools.py
Normal file
110
backend_service/src/tools/coordinate_tools.py
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
|
import re
|
||||||
|
from typing import Dict, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
_DIRECTION_DELTAS: Dict[str, Tuple[int, int, int]] = {
|
||||||
|
"east": (1, 0, 0),
|
||||||
|
"west": (-1, 0, 0),
|
||||||
|
"north": (0, -1, 0),
|
||||||
|
"south": (0, 1, 0),
|
||||||
|
"up": (0, 0, 1),
|
||||||
|
"down": (0, 0, -1),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def calc_offset_enu(base: Dict[str, float], direction: str, distance: float) -> Dict[str, float]:
|
||||||
|
"""在ENU坐标系下按方向偏移固定距离。"""
|
||||||
|
if distance < 0:
|
||||||
|
raise ValueError("distance must be non-negative")
|
||||||
|
if not isinstance(base, dict):
|
||||||
|
raise ValueError("base must be an object with x/y/z")
|
||||||
|
|
||||||
|
direction_key = (direction or "").strip().lower()
|
||||||
|
if direction_key not in _DIRECTION_DELTAS:
|
||||||
|
raise ValueError(f"unsupported direction: {direction}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
x = float(base["x"])
|
||||||
|
y = float(base["y"])
|
||||||
|
z = float(base["z"])
|
||||||
|
except Exception as exc:
|
||||||
|
raise ValueError("base must contain numeric x/y/z") from exc
|
||||||
|
|
||||||
|
dx, dy, dz = _DIRECTION_DELTAS[direction_key]
|
||||||
|
offset_x = x + dx * distance
|
||||||
|
offset_y = y + dy * distance
|
||||||
|
offset_z = z + dz * distance
|
||||||
|
|
||||||
|
return {"x": offset_x, "y": offset_y, "z": offset_z}
|
||||||
|
|
||||||
|
|
||||||
|
_DIRECTION_TEXT_DIAGONALS_ESU: Dict[str, Tuple[float, float]] = {
|
||||||
|
"东南": (1.0, 1.0),
|
||||||
|
"西南": (-1.0, 1.0),
|
||||||
|
"东北": (1.0, -1.0),
|
||||||
|
"西北": (-1.0, -1.0),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_direction_text_esu(direction_text: str) -> Tuple[float, float]:
|
||||||
|
text = (direction_text or "").strip().replace(" ", "")
|
||||||
|
if not text:
|
||||||
|
raise ValueError("direction_text must be a non-empty string")
|
||||||
|
|
||||||
|
for prefix in ("向", "正"):
|
||||||
|
if text.startswith(prefix):
|
||||||
|
text = text[len(prefix):]
|
||||||
|
|
||||||
|
if text in _DIRECTION_TEXT_DIAGONALS_ESU:
|
||||||
|
x, y = _DIRECTION_TEXT_DIAGONALS_ESU[text]
|
||||||
|
length = math.hypot(x, y)
|
||||||
|
return x / length, y / length
|
||||||
|
|
||||||
|
if text in ("东", "西", "南", "北"):
|
||||||
|
if text == "东":
|
||||||
|
return 1.0, 0.0
|
||||||
|
if text == "西":
|
||||||
|
return -1.0, 0.0
|
||||||
|
if text == "南":
|
||||||
|
return 0.0, 1.0
|
||||||
|
return 0.0, -1.0
|
||||||
|
|
||||||
|
match = re.match(r"^(南|北)偏(东|西)(\d+(?:\.\d+)?)度?$", text)
|
||||||
|
if match:
|
||||||
|
base_dir, toward_dir, angle_str = match.groups()
|
||||||
|
angle_deg = float(angle_str)
|
||||||
|
if angle_deg < 0 or angle_deg > 90:
|
||||||
|
raise ValueError("angle must be between 0 and 90 degrees")
|
||||||
|
angle_rad = math.radians(angle_deg)
|
||||||
|
x_sign = 1.0 if toward_dir == "东" else -1.0
|
||||||
|
if base_dir == "南":
|
||||||
|
return math.sin(angle_rad) * x_sign, math.cos(angle_rad)
|
||||||
|
return math.sin(angle_rad) * x_sign, -math.cos(angle_rad)
|
||||||
|
|
||||||
|
raise ValueError(f"unsupported direction_text: {direction_text}")
|
||||||
|
|
||||||
|
|
||||||
|
def calc_offset_esu_direction_text(
|
||||||
|
base: Dict[str, float], direction_text: str, distance: float
|
||||||
|
) -> Dict[str, float]:
|
||||||
|
"""在ESU坐标系下按中文方位偏移固定距离。"""
|
||||||
|
if distance < 0:
|
||||||
|
raise ValueError("distance must be non-negative")
|
||||||
|
if not isinstance(base, dict):
|
||||||
|
raise ValueError("base must be an object with x/y/z")
|
||||||
|
|
||||||
|
try:
|
||||||
|
x = float(base["x"])
|
||||||
|
y = float(base["y"])
|
||||||
|
z = float(base["z"])
|
||||||
|
except Exception as exc:
|
||||||
|
raise ValueError("base must contain numeric x/y/z") from exc
|
||||||
|
|
||||||
|
dx_unit, dy_unit = _parse_direction_text_esu(direction_text)
|
||||||
|
offset_x = x + dx_unit * distance
|
||||||
|
offset_y = y + dy_unit * distance
|
||||||
|
|
||||||
|
return {"x": offset_x, "y": offset_y, "z": z}
|
||||||
0
backend_service/venv/bin/Activate.ps1
Executable file → Normal file
0
backend_service/venv/bin/Activate.ps1
Executable file → Normal file
4
backend_service/venv/bin/activate
Executable file → Normal file
4
backend_service/venv/bin/activate
Executable file → Normal file
@@ -41,12 +41,12 @@ case "$(uname)" in
|
|||||||
CYGWIN*|MSYS*|MINGW*)
|
CYGWIN*|MSYS*|MINGW*)
|
||||||
# transform D:\path\to\venv to /d/path/to/venv on MSYS and MINGW
|
# transform D:\path\to\venv to /d/path/to/venv on MSYS and MINGW
|
||||||
# and to /cygdrive/d/path/to/venv on Cygwin
|
# and to /cygdrive/d/path/to/venv on Cygwin
|
||||||
VIRTUAL_ENV=$(cygpath /home/huangfukk/DronePlanning/backend_service/venv)
|
VIRTUAL_ENV=$(cygpath /home/a/DronePlanning/backend_service/venv)
|
||||||
export VIRTUAL_ENV
|
export VIRTUAL_ENV
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
# use the path as-is
|
# use the path as-is
|
||||||
export VIRTUAL_ENV=/home/huangfukk/DronePlanning/backend_service/venv
|
export VIRTUAL_ENV=/home/a/DronePlanning/backend_service/venv
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|||||||
2
backend_service/venv/bin/activate.csh
Executable file → Normal file
2
backend_service/venv/bin/activate.csh
Executable file → Normal file
@@ -9,7 +9,7 @@ alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PA
|
|||||||
# Unset irrelevant variables.
|
# Unset irrelevant variables.
|
||||||
deactivate nondestructive
|
deactivate nondestructive
|
||||||
|
|
||||||
setenv VIRTUAL_ENV /home/huangfukk/DronePlanning/backend_service/venv
|
setenv VIRTUAL_ENV /home/a/DronePlanning/backend_service/venv
|
||||||
|
|
||||||
set _OLD_VIRTUAL_PATH="$PATH"
|
set _OLD_VIRTUAL_PATH="$PATH"
|
||||||
setenv PATH "$VIRTUAL_ENV/"bin":$PATH"
|
setenv PATH "$VIRTUAL_ENV/"bin":$PATH"
|
||||||
|
|||||||
2
backend_service/venv/bin/activate.fish
Executable file → Normal file
2
backend_service/venv/bin/activate.fish
Executable file → Normal file
@@ -33,7 +33,7 @@ end
|
|||||||
# Unset irrelevant variables.
|
# Unset irrelevant variables.
|
||||||
deactivate nondestructive
|
deactivate nondestructive
|
||||||
|
|
||||||
set -gx VIRTUAL_ENV /home/huangfukk/DronePlanning/backend_service/venv
|
set -gx VIRTUAL_ENV /home/a/DronePlanning/backend_service/venv
|
||||||
|
|
||||||
set -gx _OLD_VIRTUAL_PATH $PATH
|
set -gx _OLD_VIRTUAL_PATH $PATH
|
||||||
set -gx PATH "$VIRTUAL_ENV/"bin $PATH
|
set -gx PATH "$VIRTUAL_ENV/"bin $PATH
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from coloredlogs.cli import main
|
from coloredlogs.cli import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
|
||||||
import sys
|
|
||||||
from dashscope.cli import main
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if sys.argv[0].endswith('.exe'):
|
|
||||||
sys.argv[0] = sys.argv[0][:-4]
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from distro.distro import main
|
from distro.distro import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from dotenv.__main__ import cli
|
from dotenv.__main__ import cli
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from fastapi.cli import main
|
from fastapi.cli import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
7
backend_service/venv/bin/filetype
Executable file
7
backend_service/venv/bin/filetype
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||||
|
import sys
|
||||||
|
from filetype.__main__ import main
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if sys.argv[0].endswith('.exe'):
|
||||||
|
sys.argv[0] = sys.argv[0][:-4]
|
||||||
|
sys.exit(main())
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from httpx import main
|
from httpx import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from humanfriendly.cli import main
|
from humanfriendly.cli import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from isympy import main
|
from isympy import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
|
||||||
import sys
|
|
||||||
from json_repair.__main__ import cli
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if sys.argv[0].endswith('.exe'):
|
|
||||||
sys.argv[0] = sys.argv[0][:-4]
|
|
||||||
sys.exit(cli())
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from markdown_it.cli.parse import main
|
from markdown_it.cli.parse import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
|
||||||
import sys
|
|
||||||
from mcp.cli import app
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if sys.argv[0].endswith('.exe'):
|
|
||||||
sys.argv[0] = sys.argv[0][:-4]
|
|
||||||
sys.exit(app())
|
|
||||||
7
backend_service/venv/bin/nltk
Executable file
7
backend_service/venv/bin/nltk
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||||
|
import sys
|
||||||
|
from nltk.cli import cli
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if sys.argv[0].endswith('.exe'):
|
||||||
|
sys.argv[0] = sys.argv[0][:-4]
|
||||||
|
sys.exit(cli())
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from charset_normalizer.cli import cli_detect
|
from charset_normalizer.cli import cli_detect
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from onnxruntime.tools.onnxruntime_test import main
|
from onnxruntime.tools.onnxruntime_test import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
7
backend_service/venv/bin/oxmsg
Executable file
7
backend_service/venv/bin/oxmsg
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||||
|
import sys
|
||||||
|
from oxmsg.cli import oxmsg
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if sys.argv[0].endswith('.exe'):
|
||||||
|
sys.argv[0] = sys.argv[0][:-4]
|
||||||
|
sys.exit(oxmsg())
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
from pip._internal.cli.main import main
|
from pip._internal.cli.main import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
if sys.argv[0].endswith('.exe'):
|
||||||
|
sys.argv[0] = sys.argv[0][:-4]
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
from pip._internal.cli.main import main
|
from pip._internal.cli.main import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
if sys.argv[0].endswith('.exe'):
|
||||||
|
sys.argv[0] = sys.argv[0][:-4]
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
from pip._internal.cli.main import main
|
from pip._internal.cli.main import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
if sys.argv[0].endswith('.exe'):
|
||||||
|
sys.argv[0] = sys.argv[0][:-4]
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from pygments.cmdline import main
|
from pygments.cmdline import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
|
||||||
import sys
|
|
||||||
from json5.tool import main
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if sys.argv[0].endswith('.exe'):
|
|
||||||
sys.argv[0] = sys.argv[0][:-4]
|
|
||||||
sys.exit(main())
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from build.__main__ import entrypoint
|
from build.__main__ import entrypoint
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from rsa.cli import decrypt
|
from rsa.cli import decrypt
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from rsa.cli import encrypt
|
from rsa.cli import encrypt
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from rsa.cli import keygen
|
from rsa.cli import keygen
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from rsa.util import private_to_public
|
from rsa.util import private_to_public
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from rsa.cli import sign
|
from rsa.cli import sign
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from rsa.cli import verify
|
from rsa.cli import verify
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
|
||||||
import sys
|
|
||||||
from shortuuid.cli import cli
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if sys.argv[0].endswith('.exe'):
|
|
||||||
sys.argv[0] = sys.argv[0][:-4]
|
|
||||||
sys.exit(cli())
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from tqdm.cli import main
|
from tqdm.cli import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from watchfiles.cli import cli
|
from watchfiles.cli import cli
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from websockets.cli import main
|
from websockets.cli import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/home/huangfukk/DronePlanning/backend_service/venv/bin/python3
|
#!/home/a/DronePlanning/backend_service/venv/bin/python3
|
||||||
import sys
|
import sys
|
||||||
from websocket._wsdump import main
|
from websocket._wsdump import main
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
Copyright (c) 2011, Stavros Korokithakis
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
Neither the name of Stochastic Technologies nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/local/bin/python
|
||||||
|
# -*- coding: latin-1 -*-
|
||||||
|
"""
|
||||||
|
olefile (formerly OleFileIO_PL)
|
||||||
|
|
||||||
|
Module to read/write Microsoft OLE2 files (also called Structured Storage or
|
||||||
|
Microsoft Compound Document File Format), such as Microsoft Office 97-2003
|
||||||
|
documents, Image Composer and FlashPix files, Outlook messages, ...
|
||||||
|
This version is compatible with Python 2.6+ and 3.x
|
||||||
|
|
||||||
|
Project website: http://www.decalage.info/olefile
|
||||||
|
|
||||||
|
olefile is copyright (c) 2005-2015 Philippe Lagadec (http://www.decalage.info)
|
||||||
|
|
||||||
|
olefile is based on the OleFileIO module from the PIL library v1.1.6
|
||||||
|
See: http://www.pythonware.com/products/pil/index.htm
|
||||||
|
|
||||||
|
The Python Imaging Library (PIL) is
|
||||||
|
Copyright (c) 1997-2005 by Secret Labs AB
|
||||||
|
Copyright (c) 1995-2005 by Fredrik Lundh
|
||||||
|
|
||||||
|
See source code and LICENSE.txt for information on usage and redistribution.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# The OleFileIO_PL module is for backward compatibility
|
||||||
|
|
||||||
|
try:
|
||||||
|
# first try to import olefile for Python 2.6+/3.x
|
||||||
|
from olefile.olefile import *
|
||||||
|
# import metadata not covered by *:
|
||||||
|
from olefile.olefile import __version__, __author__, __date__
|
||||||
|
|
||||||
|
except:
|
||||||
|
# if it fails, fallback to the old version olefile2 for Python 2.x:
|
||||||
|
from olefile.olefile2 import *
|
||||||
|
# import metadata not covered by *:
|
||||||
|
from olefile.olefile2 import __doc__, __version__, __author__, __date__
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
Authors
|
|
||||||
=======
|
|
||||||
|
|
||||||
``pyjwt`` is currently written and maintained by `Jose Padilla <https://github.com/jpadilla>`_.
|
|
||||||
Originally written and maintained by `Jeff Lindsay <https://github.com/progrium>`_.
|
|
||||||
|
|
||||||
A full list of contributors can be found on GitHub’s `overview <https://github.com/jpadilla/pyjwt/graphs/contributors>`_.
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2015-2022 José Padilla
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
Metadata-Version: 2.1
|
|
||||||
Name: PyJWT
|
|
||||||
Version: 2.10.1
|
|
||||||
Summary: JSON Web Token implementation in Python
|
|
||||||
Author-email: Jose Padilla <hello@jpadilla.com>
|
|
||||||
License: MIT
|
|
||||||
Project-URL: Homepage, https://github.com/jpadilla/pyjwt
|
|
||||||
Keywords: json,jwt,security,signing,token,web
|
|
||||||
Classifier: Development Status :: 5 - Production/Stable
|
|
||||||
Classifier: Intended Audience :: Developers
|
|
||||||
Classifier: License :: OSI Approved :: MIT License
|
|
||||||
Classifier: Natural Language :: English
|
|
||||||
Classifier: Programming Language :: Python
|
|
||||||
Classifier: Programming Language :: Python :: 3
|
|
||||||
Classifier: Programming Language :: Python :: 3 :: Only
|
|
||||||
Classifier: Programming Language :: Python :: 3.9
|
|
||||||
Classifier: Programming Language :: Python :: 3.10
|
|
||||||
Classifier: Programming Language :: Python :: 3.11
|
|
||||||
Classifier: Programming Language :: Python :: 3.12
|
|
||||||
Classifier: Programming Language :: Python :: 3.13
|
|
||||||
Classifier: Topic :: Utilities
|
|
||||||
Requires-Python: >=3.9
|
|
||||||
Description-Content-Type: text/x-rst
|
|
||||||
License-File: LICENSE
|
|
||||||
License-File: AUTHORS.rst
|
|
||||||
Provides-Extra: crypto
|
|
||||||
Requires-Dist: cryptography>=3.4.0; extra == "crypto"
|
|
||||||
Provides-Extra: dev
|
|
||||||
Requires-Dist: coverage[toml]==5.0.4; extra == "dev"
|
|
||||||
Requires-Dist: cryptography>=3.4.0; extra == "dev"
|
|
||||||
Requires-Dist: pre-commit; extra == "dev"
|
|
||||||
Requires-Dist: pytest<7.0.0,>=6.0.0; extra == "dev"
|
|
||||||
Requires-Dist: sphinx; extra == "dev"
|
|
||||||
Requires-Dist: sphinx-rtd-theme; extra == "dev"
|
|
||||||
Requires-Dist: zope.interface; extra == "dev"
|
|
||||||
Provides-Extra: docs
|
|
||||||
Requires-Dist: sphinx; extra == "docs"
|
|
||||||
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
||||||
Requires-Dist: zope.interface; extra == "docs"
|
|
||||||
Provides-Extra: tests
|
|
||||||
Requires-Dist: coverage[toml]==5.0.4; extra == "tests"
|
|
||||||
Requires-Dist: pytest<7.0.0,>=6.0.0; extra == "tests"
|
|
||||||
|
|
||||||
PyJWT
|
|
||||||
=====
|
|
||||||
|
|
||||||
.. image:: https://github.com/jpadilla/pyjwt/workflows/CI/badge.svg
|
|
||||||
:target: https://github.com/jpadilla/pyjwt/actions?query=workflow%3ACI
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/v/pyjwt.svg
|
|
||||||
:target: https://pypi.python.org/pypi/pyjwt
|
|
||||||
|
|
||||||
.. image:: https://codecov.io/gh/jpadilla/pyjwt/branch/master/graph/badge.svg
|
|
||||||
:target: https://codecov.io/gh/jpadilla/pyjwt
|
|
||||||
|
|
||||||
.. image:: https://readthedocs.org/projects/pyjwt/badge/?version=stable
|
|
||||||
:target: https://pyjwt.readthedocs.io/en/stable/
|
|
||||||
|
|
||||||
A Python implementation of `RFC 7519 <https://tools.ietf.org/html/rfc7519>`_. Original implementation was written by `@progrium <https://github.com/progrium>`_.
|
|
||||||
|
|
||||||
Sponsor
|
|
||||||
-------
|
|
||||||
|
|
||||||
.. |auth0-logo| image:: https://github.com/user-attachments/assets/ee98379e-ee76-4bcb-943a-e25c4ea6d174
|
|
||||||
:width: 160px
|
|
||||||
|
|
||||||
+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
||||||
| |auth0-logo| | If you want to quickly add secure token-based authentication to Python projects, feel free to check Auth0's Python SDK and free plan at `auth0.com/signup <https://auth0.com/signup?utm_source=external_sites&utm_medium=pyjwt&utm_campaign=devn_signup>`_. |
|
|
||||||
+--------------+-----------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
|
||||||
|
|
||||||
Installing
|
|
||||||
----------
|
|
||||||
|
|
||||||
Install with **pip**:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ pip install PyJWT
|
|
||||||
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
.. code-block:: pycon
|
|
||||||
|
|
||||||
>>> import jwt
|
|
||||||
>>> encoded = jwt.encode({"some": "payload"}, "secret", algorithm="HS256")
|
|
||||||
>>> print(encoded)
|
|
||||||
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg
|
|
||||||
>>> jwt.decode(encoded, "secret", algorithms=["HS256"])
|
|
||||||
{'some': 'payload'}
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
-------------
|
|
||||||
|
|
||||||
View the full docs online at https://pyjwt.readthedocs.io/en/stable/
|
|
||||||
|
|
||||||
|
|
||||||
Tests
|
|
||||||
-----
|
|
||||||
|
|
||||||
You can run tests from the project root after cloning with:
|
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
$ tox
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
PyJWT-2.10.1.dist-info/AUTHORS.rst,sha256=klzkNGECnu2_VY7At89_xLBF3vUSDruXk3xwgUBxzwc,322
|
|
||||||
PyJWT-2.10.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
||||||
PyJWT-2.10.1.dist-info/LICENSE,sha256=eXp6ICMdTEM-nxkR2xcx0GtYKLmPSZgZoDT3wPVvXOU,1085
|
|
||||||
PyJWT-2.10.1.dist-info/METADATA,sha256=EkewF6D6KU8SGaaQzVYfxUUU1P_gs_dp1pYTkoYvAx8,3990
|
|
||||||
PyJWT-2.10.1.dist-info/RECORD,,
|
|
||||||
PyJWT-2.10.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
||||||
PyJWT-2.10.1.dist-info/top_level.txt,sha256=RP5DHNyJbMq2ka0FmfTgoSaQzh7e3r5XuCWCO8a00k8,4
|
|
||||||
jwt/__init__.py,sha256=VB2vFKuboTjcDGeZ8r-UqK_dz3NsQSQEqySSICby8Xg,1711
|
|
||||||
jwt/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/algorithms.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/api_jwk.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/api_jws.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/api_jwt.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/exceptions.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/help.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/jwk_set_cache.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/jwks_client.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/types.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/utils.cpython-313.pyc,,
|
|
||||||
jwt/__pycache__/warnings.cpython-313.pyc,,
|
|
||||||
jwt/algorithms.py,sha256=cKr-XEioe0mBtqJMCaHEswqVOA1Z8Purt5Sb3Bi-5BE,30409
|
|
||||||
jwt/api_jwk.py,sha256=6F1r7rmm8V5qEnBKA_xMjS9R7VoANe1_BL1oD2FrAjE,4451
|
|
||||||
jwt/api_jws.py,sha256=aM8vzqQf6mRrAw7bRy-Moj_pjWsKSVQyYK896AfMjJU,11762
|
|
||||||
jwt/api_jwt.py,sha256=OGT4hok1l5A6FH_KdcrU5g6u6EQ8B7em0r9kGM9SYgA,14512
|
|
||||||
jwt/exceptions.py,sha256=bUIOJ-v9tjopTLS-FYOTc3kFx5WP5IZt7ksN_HE1G9Q,1211
|
|
||||||
jwt/help.py,sha256=vFdNzjQoAch04XCMYpCkyB2blaqHAGAqQrtf9nSPkdk,1808
|
|
||||||
jwt/jwk_set_cache.py,sha256=hBKmN-giU7-G37L_XKgc_OZu2ah4wdbj1ZNG_GkoSE8,959
|
|
||||||
jwt/jwks_client.py,sha256=p9b-IbQqo2tEge9Zit3oSPBFNePqwho96VLbnUrHUWs,4259
|
|
||||||
jwt/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
jwt/types.py,sha256=VnhGv_VFu5a7_mrPoSCB7HaNLrJdhM8Sq1sSfEg0gLU,99
|
|
||||||
jwt/utils.py,sha256=hxOjvDBheBYhz-RIPiEz7Q88dSUSTMzEdKE_Ww2VdJw,3640
|
|
||||||
jwt/warnings.py,sha256=50XWOnyNsIaqzUJTk6XHNiIDykiL763GYA92MjTKmok,59
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Wheel-Version: 1.0
|
|
||||||
Generator: setuptools (75.6.0)
|
|
||||||
Root-Is-Purelib: true
|
|
||||||
Tag: py3-none-any
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
jwt
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,547 +0,0 @@
|
|||||||
Metadata-Version: 2.4
|
|
||||||
Name: agentscope
|
|
||||||
Version: 1.0.7
|
|
||||||
Summary: AgentScope: A Flexible yet Robust Multi-Agent Platform.
|
|
||||||
Author-email: SysML team of Alibaba Tongyi Lab <gaodawei.gdw@alibaba-inc.com>
|
|
||||||
License-Expression: Apache-2.0
|
|
||||||
Project-URL: Homepage, https://github.com/agentscope-ai/agentscope
|
|
||||||
Project-URL: Documentation, https://doc.agentscope.io/
|
|
||||||
Project-URL: Repository, https://github.com/agentscope-ai/agentscope
|
|
||||||
Keywords: deep-learning,multi agents,agents
|
|
||||||
Classifier: Development Status :: 4 - Beta
|
|
||||||
Classifier: Programming Language :: Python :: 3
|
|
||||||
Classifier: Programming Language :: Python :: 3.10
|
|
||||||
Classifier: Operating System :: OS Independent
|
|
||||||
Classifier: Intended Audience :: Developers
|
|
||||||
Classifier: Intended Audience :: Science/Research
|
|
||||||
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
||||||
Requires-Python: >=3.10
|
|
||||||
Description-Content-Type: text/markdown
|
|
||||||
License-File: LICENSE
|
|
||||||
Requires-Dist: aioitertools
|
|
||||||
Requires-Dist: anthropic
|
|
||||||
Requires-Dist: dashscope
|
|
||||||
Requires-Dist: docstring_parser
|
|
||||||
Requires-Dist: json5
|
|
||||||
Requires-Dist: json_repair
|
|
||||||
Requires-Dist: mcp>=1.13
|
|
||||||
Requires-Dist: numpy
|
|
||||||
Requires-Dist: openai
|
|
||||||
Requires-Dist: python-datauri
|
|
||||||
Requires-Dist: opentelemetry-api
|
|
||||||
Requires-Dist: opentelemetry-sdk
|
|
||||||
Requires-Dist: opentelemetry-exporter-otlp
|
|
||||||
Requires-Dist: python-socketio
|
|
||||||
Requires-Dist: shortuuid
|
|
||||||
Requires-Dist: tiktoken
|
|
||||||
Requires-Dist: sounddevice
|
|
||||||
Provides-Extra: full
|
|
||||||
Requires-Dist: ollama>=0.5.4; extra == "full"
|
|
||||||
Requires-Dist: google-genai; extra == "full"
|
|
||||||
Requires-Dist: Pillow; extra == "full"
|
|
||||||
Requires-Dist: transformers; extra == "full"
|
|
||||||
Requires-Dist: jinja2; extra == "full"
|
|
||||||
Requires-Dist: ray; extra == "full"
|
|
||||||
Requires-Dist: mem0ai; extra == "full"
|
|
||||||
Requires-Dist: packaging; extra == "full"
|
|
||||||
Requires-Dist: pypdf; extra == "full"
|
|
||||||
Requires-Dist: python-docx; extra == "full"
|
|
||||||
Requires-Dist: nltk; extra == "full"
|
|
||||||
Requires-Dist: qdrant-client; extra == "full"
|
|
||||||
Provides-Extra: dev
|
|
||||||
Requires-Dist: agentscope[full]; extra == "dev"
|
|
||||||
Requires-Dist: pre-commit; extra == "dev"
|
|
||||||
Requires-Dist: pytest; extra == "dev"
|
|
||||||
Requires-Dist: sphinx-gallery; extra == "dev"
|
|
||||||
Requires-Dist: furo; extra == "dev"
|
|
||||||
Requires-Dist: myst_parser; extra == "dev"
|
|
||||||
Requires-Dist: matplotlib; extra == "dev"
|
|
||||||
Requires-Dist: pymilvus[milvus_lite]; extra == "dev"
|
|
||||||
Requires-Dist: reme-ai>=0.1.10.7; python_full_version >= "3.12" and extra == "dev"
|
|
||||||
Dynamic: license-file
|
|
||||||
|
|
||||||
[**中文主页**](https://github.com/agentscope-ai/agentscope/blob/main/README_zh.md) | [**Tutorial**](https://doc.agentscope.io/) | [**Roadmap**](https://github.com/agentscope-ai/agentscope/blob/main/docs/roadmap.md) | [**FAQ**](https://doc.agentscope.io/tutorial/faq.html)
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img
|
|
||||||
src="https://img.alicdn.com/imgextra/i1/O1CN01nTg6w21NqT5qFKH1u_!!6000000001621-55-tps-550-550.svg"
|
|
||||||
alt="AgentScope Logo"
|
|
||||||
width="200"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2 align="center">AgentScope: Agent-Oriented Programming for Building LLM Applications</h2>
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://arxiv.org/abs/2402.14034">
|
|
||||||
<img
|
|
||||||
src="https://img.shields.io/badge/cs.MA-2402.14034-B31C1C?logo=arxiv&logoColor=B31C1C"
|
|
||||||
alt="arxiv"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a href="https://pypi.org/project/agentscope/">
|
|
||||||
<img
|
|
||||||
src="https://img.shields.io/badge/python-3.10+-blue?logo=python"
|
|
||||||
alt="pypi"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a href="https://pypi.org/project/agentscope/">
|
|
||||||
<img
|
|
||||||
src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fpypi.org%2Fpypi%2Fagentscope%2Fjson&query=%24.info.version&prefix=v&logo=pypi&label=version"
|
|
||||||
alt="pypi"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a href="https://doc.agentscope.io/">
|
|
||||||
<img
|
|
||||||
src="https://img.shields.io/badge/Docs-English%7C%E4%B8%AD%E6%96%87-blue?logo=markdown"
|
|
||||||
alt="docs"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a href="https://agentscope.io/">
|
|
||||||
<img
|
|
||||||
src="https://img.shields.io/badge/GUI-AgentScope_Studio-blue?logo=look&logoColor=green&color=dark-green"
|
|
||||||
alt="workstation"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
<a href="./LICENSE">
|
|
||||||
<img
|
|
||||||
src="https://img.shields.io/badge/license-Apache--2.0-black"
|
|
||||||
alt="license"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://trendshift.io/api/badge/repositories/10079" alt="modelscope%2Fagentscope | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## ✨ Why AgentScope?
|
|
||||||
|
|
||||||
Easy for beginners, powerful for experts.
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="./assets/images/agentscope_v1_0822.png" alt="AgentScope Framework" width="80%"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
- **Transparent to Developers**: Transparent is our **FIRST principle**. Prompt engineering, API invocation, agent building, workflow orchestration, all are visible and controllable for developers. No deep encapsulation or implicit magic.
|
|
||||||
- **[Realtime Steering](https://doc.agentscope.io/tutorial/task_agent.html#realtime-steering)**: Native support for realtime interruption and customized handling.
|
|
||||||
- **More Agentic**: Support [agentic tools management](https://doc.agentscope.io/tutorial/task_tool.html), [agentic long-term memory control](https://doc.agentscope.io/tutorial/task_long_term_memory.html) and agentic RAG, etc.
|
|
||||||
- **Model Agnostic**: Programming once, run with all models.
|
|
||||||
- **LEGO-style Agent Building**: All components are **modular** and **independent**.
|
|
||||||
- **Multi-Agent Oriented**: Designed for **multi-agent**, **explicit** message passing and workflow orchestration, NO deep encapsulation.
|
|
||||||
- **Highly Customizable**: Tools, prompt, agent, workflow, third-party libs & visualization, customization is encouraged everywhere.
|
|
||||||
|
|
||||||
Quick overview of important features in **AgentScope 1.0**:
|
|
||||||
|
|
||||||
| Module | Feature | Tutorial |
|
|
||||||
|------------|------------------------------------------------------------------------------------|-------------------------------------------------------------------------|
|
|
||||||
| model | Support async invocation | [Model](https://doc.agentscope.io/tutorial/task_model.html) |
|
|
||||||
| | Support reasoning model | |
|
|
||||||
| | Support streaming/non-streaming returns | |
|
|
||||||
| tool | Support async/sync tool functions | [Tool](https://doc.agentscope.io/tutorial/task_tool.html) |
|
|
||||||
| | Support streaming/non-streaming returns | |
|
|
||||||
| | Support user interruption | |
|
|
||||||
| | Support post-processing | |
|
|
||||||
| | Support group-wise tools management | |
|
|
||||||
| | Support agentic tools management by meta tool | |
|
|
||||||
| MCP | Support streamable HTTP/SSE/StdIO transport | [MCP](https://doc.agentscope.io/tutorial/task_mcp.html) |
|
|
||||||
| | Support both **stateful** and **stateless** mode MCP Client | |
|
|
||||||
| | Support client- & function-level fine-grained control | |
|
|
||||||
| agent | Support async execution | |
|
|
||||||
| | Support parallel tool calls | |
|
|
||||||
| | Support realtime steering interruption and customized handling | |
|
|
||||||
| | Support automatic state management | |
|
|
||||||
| | Support agent-controlled long-term memory | |
|
|
||||||
| | Support agent hooks | |
|
|
||||||
| tracing | Support OpenTelemetry-based tracing in LLM, tools, agent and formatter | [Tracing](https://doc.agentscope.io/tutorial/task_tracing.html) |
|
|
||||||
| | Support connecting to third-party tracing platforms (e.g. Arize-Phoenix, Langfuse) | |
|
|
||||||
| memory | Support long-term memory | [Memory](https://doc.agentscope.io/tutorial/task_long_term_memory.html) |
|
|
||||||
| session | Provide session/application-level automatic state management | [Session](https://doc.agentscope.io/tutorial/task_state.html) |
|
|
||||||
| evaluation | Provide distributed and parallel evaluation | [Evaluation](https://doc.agentscope.io/tutorial/task_eval.html) |
|
|
||||||
| formatter | Support multi-agent prompt formatting with tools API | [Prompt Formatter](https://doc.agentscope.io/tutorial/task_prompt.html) |
|
|
||||||
| | Support truncation-based formatter strategy | |
|
|
||||||
| plan | Support ReAct-based long-term planning | [Plan](https://doc.agentscope.io/tutorial/task_plan.html) |
|
|
||||||
| | Support manual plan specification | |
|
|
||||||
| RAG | Support agentic RAG | [RAG](https://doc.agentscope.io/tutorial/task_rag.html) |
|
|
||||||
| | Support multimodal RAG | |
|
|
||||||
| ... | | |
|
|
||||||
|
|
||||||
## 📢 News
|
|
||||||
- **[2025-11]** [Contributing Guide](./CONTRIBUTING.md) is online now! Welcome to contribute to AgentScope.
|
|
||||||
- **[2025-09]** **RAG** module in AgentScope 1.0 is online now! Check our [tutorial](https://doc.agentscope.io/tutorial/task_rag.html) and [example](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/rag) for more details.
|
|
||||||
- **[2025-09]** **Voice agent** is online! `ReActAgent` supports Qwen-Omni and GPT-Audio natively now, check our [new example](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/voice_agent) and [roadmap](https://github.com/agentscope-ai/agentscope/issues/773).
|
|
||||||
- **[2025-09]** A new powerful 📋**Plan** module is online now! Check out the [tutorial](https://doc.agentscope.io/tutorial/task_plan.html) for more details.
|
|
||||||
- **[2025-09]** **AgentScope Runtime** is open-sourced now! Enabling effective agent deployment with sandboxed tool execution for production-ready AI applications. Check out the [GitHub repo](https://github.com/agentscope-ai/agentscope-runtime).
|
|
||||||
- **[2025-09]** **AgentScope Studio** is open-sourced now! Check out the [GitHub repo](https://github.com/agentscope-ai/agentscope-studio).
|
|
||||||
- **[2025-08]** The new tutorial of v1 is online now! Check out the [tutorial](https://doc.agentscope.io) for more details.
|
|
||||||
- **[2025-08]** 🎉🎉 AgentScope v1 is released now! This version fully embraces the asynchronous execution, providing many new features and improvements. Check out [changelog](https://github.com/agentscope-ai/agentscope/blob/main/docs/changelog.md) for detailed changes.
|
|
||||||
|
|
||||||
## 💬 Contact
|
|
||||||
|
|
||||||
Welcome to join our community on
|
|
||||||
|
|
||||||
| [Discord](https://discord.gg/eYMpfnkG8h) | DingTalk |
|
|
||||||
|----------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| <img src="https://gw.alicdn.com/imgextra/i1/O1CN01hhD1mu1Dd3BWVUvxN_!!6000000000238-2-tps-400-400.png" width="100" height="100"> | <img src="https://img.alicdn.com/imgextra/i1/O1CN01LxzZha1thpIN2cc2E_!!6000000005934-2-tps-497-477.png" width="100" height="100"> |
|
|
||||||
|
|
||||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
||||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
||||||
## 📑 Table of Contents
|
|
||||||
|
|
||||||
- [🚀 Quickstart](#-quickstart)
|
|
||||||
- [💻 Installation](#-installation)
|
|
||||||
- [🛠️ From source](#-from-source)
|
|
||||||
- [🔄 Using uv (recommended for faster installs)](#-using-uv-recommended-for-faster-installs)
|
|
||||||
- [📦 From PyPi](#-from-pypi)
|
|
||||||
- [📝 Example](#-example)
|
|
||||||
- [👋 Hello AgentScope!](#-hello-agentscope)
|
|
||||||
- [🎯 Realtime Steering](#-realtime-steering)
|
|
||||||
- [🛠️ Fine-Grained MCP Control](#-fine-grained-mcp-control)
|
|
||||||
- [🧑🤝🧑 Multi-Agent Conversation](#-multi-agent-conversation)
|
|
||||||
- [💻 AgentScope Studio](#-agentscope-studio)
|
|
||||||
- [📖 Documentation](#-documentation)
|
|
||||||
- [🤝 Contributing](#-contributing)
|
|
||||||
- [⚖️ License](#-license)
|
|
||||||
- [📚 Publications](#-publications)
|
|
||||||
- [✨ Contributors](#-contributors)
|
|
||||||
|
|
||||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
||||||
|
|
||||||
## 🚀 Quickstart
|
|
||||||
|
|
||||||
### 💻 Installation
|
|
||||||
|
|
||||||
> AgentScope requires **Python 3.10** or higher.
|
|
||||||
|
|
||||||
#### 🛠️ From source
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Pull the source code from GitHub
|
|
||||||
git clone -b main https://github.com/agentscope-ai/agentscope.git
|
|
||||||
|
|
||||||
# Install the package in editable mode
|
|
||||||
cd agentscope
|
|
||||||
pip install -e .
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 🔄 Using uv (recommended for faster installs)
|
|
||||||
|
|
||||||
[uv](https://github.com/astral-sh/uv) is a fast Python package installer and resolver, written in Rust.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Clone the repository
|
|
||||||
git clone -b main https://github.com/agentscope-ai/agentscope.git
|
|
||||||
cd agentscope
|
|
||||||
|
|
||||||
# Install with uv
|
|
||||||
uv pip install -e .
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 📦 From PyPi
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install agentscope
|
|
||||||
```
|
|
||||||
|
|
||||||
Or with uv:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
uv pip install agentscope
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📝 Example
|
|
||||||
|
|
||||||
### 👋 Hello AgentScope!
|
|
||||||
|
|
||||||
Start with a conversation between user and a ReAct agent 🤖 named "Friday"!
|
|
||||||
|
|
||||||
```python
|
|
||||||
from agentscope.agent import ReActAgent, UserAgent
|
|
||||||
from agentscope.model import DashScopeChatModel
|
|
||||||
from agentscope.formatter import DashScopeChatFormatter
|
|
||||||
from agentscope.memory import InMemoryMemory
|
|
||||||
from agentscope.tool import Toolkit, execute_python_code, execute_shell_command
|
|
||||||
import os, asyncio
|
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
toolkit = Toolkit()
|
|
||||||
toolkit.register_tool_function(execute_python_code)
|
|
||||||
toolkit.register_tool_function(execute_shell_command)
|
|
||||||
|
|
||||||
agent = ReActAgent(
|
|
||||||
name="Friday",
|
|
||||||
sys_prompt="You're a helpful assistant named Friday.",
|
|
||||||
model=DashScopeChatModel(
|
|
||||||
model_name="qwen-max",
|
|
||||||
api_key=os.environ["DASHSCOPE_API_KEY"],
|
|
||||||
stream=True,
|
|
||||||
),
|
|
||||||
memory=InMemoryMemory(),
|
|
||||||
formatter=DashScopeChatFormatter(),
|
|
||||||
toolkit=toolkit,
|
|
||||||
)
|
|
||||||
|
|
||||||
user = UserAgent(name="user")
|
|
||||||
|
|
||||||
msg = None
|
|
||||||
while True:
|
|
||||||
msg = await agent(msg)
|
|
||||||
msg = await user(msg)
|
|
||||||
if msg.get_text_content() == "exit":
|
|
||||||
break
|
|
||||||
|
|
||||||
asyncio.run(main())
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🎯 Realtime Steering
|
|
||||||
|
|
||||||
Natively support **realtime interruption** in ``ReActAgent`` with robust memory preservation, and convert interruption into an **observable event** for agent to seamlessly resume conversations.
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="./assets/images/realtime_steering_zh.gif" alt="Realtime Steering" width="49%"/>
|
|
||||||
<img src="./assets/images/realtime_steering_en.gif" alt="Realtime Steering" width="49%"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
### 🛠️ Fine-Grained MCP Control
|
|
||||||
|
|
||||||
Developers can obtain the MCP tool as a **local callable function**, and use it anywhere (e.g. call directly, pass to agent, wrap into a more complex tool, etc.)
|
|
||||||
|
|
||||||
```python
|
|
||||||
from agentscope.mcp import HttpStatelessClient
|
|
||||||
from agentscope.tool import Toolkit
|
|
||||||
import os
|
|
||||||
|
|
||||||
async def fine_grained_mcp_control():
|
|
||||||
# Initialize the MCP client
|
|
||||||
client = HttpStatelessClient(
|
|
||||||
name="gaode_mcp",
|
|
||||||
transport="streamable_http",
|
|
||||||
url=f"https://mcp.amap.com/mcp?key={os.environ['GAODE_API_KEY']}",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Obtain the MCP tool as a **local callable function**, and use it anywhere
|
|
||||||
func = await client.get_callable_function(func_name="maps_geo")
|
|
||||||
|
|
||||||
# Option 1: Call directly
|
|
||||||
await func(address="Tiananmen Square", city="Beijing")
|
|
||||||
|
|
||||||
# Option 2: Pass to agent as a tool
|
|
||||||
toolkit = Toolkit()
|
|
||||||
toolkit.register_tool_function(func)
|
|
||||||
# ...
|
|
||||||
|
|
||||||
# Option 3: Wrap into a more complex tool
|
|
||||||
# ...
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🧑🤝🧑 Multi-Agent Conversation
|
|
||||||
|
|
||||||
AgentScope provides ``MsgHub`` and pipelines to streamline multi-agent conversations, offering efficient message routing and seamless information sharing
|
|
||||||
|
|
||||||
```python
|
|
||||||
from agentscope.pipeline import MsgHub, sequential_pipeline
|
|
||||||
from agentscope.message import Msg
|
|
||||||
import asyncio
|
|
||||||
|
|
||||||
async def multi_agent_conversation():
|
|
||||||
# Create agents
|
|
||||||
agent1 = ...
|
|
||||||
agent2 = ...
|
|
||||||
agent3 = ...
|
|
||||||
agent4 = ...
|
|
||||||
|
|
||||||
# Create a message hub to manage multi-agent conversation
|
|
||||||
async with MsgHub(
|
|
||||||
participants=[agent1, agent2, agent3],
|
|
||||||
announcement=Msg("Host", "Introduce yourselves.", "assistant")
|
|
||||||
) as hub:
|
|
||||||
# Speak in a sequential manner
|
|
||||||
await sequential_pipeline([agent1, agent2, agent3])
|
|
||||||
# Dynamic manage the participants
|
|
||||||
hub.add(agent4)
|
|
||||||
hub.delete(agent3)
|
|
||||||
await hub.broadcast(Msg("Host", "Goodbye!", "assistant"))
|
|
||||||
|
|
||||||
asyncio.run(multi_agent_conversation())
|
|
||||||
```
|
|
||||||
|
|
||||||
### 💻 AgentScope Studio
|
|
||||||
|
|
||||||
Use the following command to install and start AgentScope Studio, to trace and visualize your agent application.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install -g @agentscope/studio
|
|
||||||
|
|
||||||
as_studio
|
|
||||||
```
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img
|
|
||||||
src="./assets/images/home.gif"
|
|
||||||
width="49%"
|
|
||||||
alt="home"
|
|
||||||
/>
|
|
||||||
<img
|
|
||||||
src="./assets/images/projects.gif"
|
|
||||||
width="49%"
|
|
||||||
alt="projects"
|
|
||||||
/>
|
|
||||||
<img
|
|
||||||
src="./assets/images/runtime.gif"
|
|
||||||
width="49%"
|
|
||||||
alt="runtime"
|
|
||||||
/>
|
|
||||||
<img
|
|
||||||
src="./assets/images/friday.gif"
|
|
||||||
width="49%"
|
|
||||||
alt="friday"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
## 📖 Documentation
|
|
||||||
|
|
||||||
- Tutorial
|
|
||||||
- [Installation](https://doc.agentscope.io/tutorial/quickstart_installation.html)
|
|
||||||
- [Key Concepts](https://doc.agentscope.io/tutorial/quickstart_key_concept.html)
|
|
||||||
- [Create Message](https://doc.agentscope.io/tutorial/quickstart_message.html)
|
|
||||||
- [ReAct Agent](https://doc.agentscope.io/tutorial/quickstart_agent.html)
|
|
||||||
- Workflow
|
|
||||||
- [Conversation](https://doc.agentscope.io/tutorial/workflow_conversation.html)
|
|
||||||
- [Multi-Agent Debate](https://doc.agentscope.io/tutorial/workflow_multiagent_debate.html)
|
|
||||||
- [Concurrent Agents](https://doc.agentscope.io/tutorial/workflow_concurrent_agents.html)
|
|
||||||
- [Routing](https://doc.agentscope.io/tutorial/workflow_routing.html)
|
|
||||||
- [Handoffs](https://doc.agentscope.io/tutorial/workflow_handoffs.html)
|
|
||||||
- FAQ
|
|
||||||
- [FAQ](https://doc.agentscope.io/tutorial/faq.html)
|
|
||||||
- Task Guides
|
|
||||||
- [Model](https://doc.agentscope.io/tutorial/task_model.html)
|
|
||||||
- [Prompt Formatter](https://doc.agentscope.io/tutorial/task_prompt.html)
|
|
||||||
- [Tool](https://doc.agentscope.io/tutorial/task_tool.html)
|
|
||||||
- [Memory](https://doc.agentscope.io/tutorial/task_memory.html)
|
|
||||||
- [Long-Term Memory](https://doc.agentscope.io/tutorial/task_long_term_memory.html)
|
|
||||||
- [Agent](https://doc.agentscope.io/tutorial/task_agent.html)
|
|
||||||
- [Pipeline](https://doc.agentscope.io/tutorial/task_pipeline.html)
|
|
||||||
- [Plan](https://doc.agentscope.io/tutorial/task_plan.html)
|
|
||||||
- [State/Session Management](https://doc.agentscope.io/tutorial/task_state.html)
|
|
||||||
- [Agent Hooks](https://doc.agentscope.io/tutorial/task_hook.html)
|
|
||||||
- [MCP](https://doc.agentscope.io/tutorial/task_mcp.html)
|
|
||||||
- [AgentScope Studio](https://doc.agentscope.io/tutorial/task_studio.html)
|
|
||||||
- [Tracing](https://doc.agentscope.io/tutorial/task_tracing.html)
|
|
||||||
- [Evaluation](https://doc.agentscope.io/tutorial/task_eval.html)
|
|
||||||
- [Embedding](https://doc.agentscope.io/tutorial/task_embedding.html)
|
|
||||||
- [Token](https://doc.agentscope.io/tutorial/task_token.html)
|
|
||||||
- API
|
|
||||||
- [API Docs](https://doc.agentscope.io/api/agentscope.html)
|
|
||||||
- [Examples](https://github.com/agentscope-ai/agentscope/tree/main/examples)
|
|
||||||
- Functionality
|
|
||||||
- [MCP](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/mcp)
|
|
||||||
- [Plan](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/plan)
|
|
||||||
- [Structured Output](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/structured_output)
|
|
||||||
- [RAG](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/rag)
|
|
||||||
- [Long-Term Memory](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/long_term_memory)
|
|
||||||
- [Session with SQLite](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/session_with_sqlite)
|
|
||||||
- [Stream Printing Messages](https://github.com/agentscope-ai/agentscope/tree/main/examples/functionality/stream_printing_messages)
|
|
||||||
- Agent
|
|
||||||
- [ReAct Agent](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/react_agent)
|
|
||||||
- [Voice Agent](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/voice_agent)
|
|
||||||
- [Deep Research Agent](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/deep_research_agent)
|
|
||||||
- [Browser-use Agent](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/browser_agent)
|
|
||||||
- [Meta Planner Agent](https://github.com/agentscope-ai/agentscope/tree/main/examples/agent/meta_planner_agent)
|
|
||||||
- Game
|
|
||||||
- [Nine-player Werewolves](https://github.com/agentscope-ai/agentscope/tree/main/examples/game/werewolves)
|
|
||||||
- Workflow
|
|
||||||
- [Multi-agent Debate](https://github.com/agentscope-ai/agentscope/tree/main/examples/workflows/multiagent_debate)
|
|
||||||
- [Multi-agent Conversation](https://github.com/agentscope-ai/agentscope/tree/main/examples/workflows/multiagent_conversation)
|
|
||||||
- [Multi-agent Concurrent](https://github.com/agentscope-ai/agentscope/tree/main/examples/workflows/multiagent_concurrent)
|
|
||||||
- Evaluation
|
|
||||||
- [ACEBench](https://github.com/agentscope-ai/agentscope/tree/main/examples/evaluation/ace_bench)
|
|
||||||
- Training
|
|
||||||
- [Reinforcement learning (RL) with Trinity-RFT](https://github.com/agentscope-ai/agentscope/tree/main/examples/training/react_agent)
|
|
||||||
|
|
||||||
|
|
||||||
## 🤝 Contributing
|
|
||||||
|
|
||||||
We welcome contributions from the community! Please refer to our [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines
|
|
||||||
on how to contribute.
|
|
||||||
|
|
||||||
## ⚖️ License
|
|
||||||
|
|
||||||
AgentScope is released under Apache License 2.0.
|
|
||||||
|
|
||||||
## 📚 Publications
|
|
||||||
|
|
||||||
If you find our work helpful for your research or application, please cite our papers.
|
|
||||||
|
|
||||||
- [AgentScope 1.0: A Developer-Centric Framework for Building Agentic Applications](https://arxiv.org/abs/2508.16279)
|
|
||||||
|
|
||||||
- [AgentScope: A Flexible yet Robust Multi-Agent Platform](https://arxiv.org/abs/2402.14034)
|
|
||||||
|
|
||||||
```
|
|
||||||
@article{agentscope_v1,
|
|
||||||
author = {
|
|
||||||
Dawei Gao,
|
|
||||||
Zitao Li,
|
|
||||||
Yuexiang Xie,
|
|
||||||
Weirui Kuang,
|
|
||||||
Liuyi Yao,
|
|
||||||
Bingchen Qian,
|
|
||||||
Zhijian Ma,
|
|
||||||
Yue Cui,
|
|
||||||
Haohao Luo,
|
|
||||||
Shen Li,
|
|
||||||
Lu Yi,
|
|
||||||
Yi Yu,
|
|
||||||
Shiqi He,
|
|
||||||
Zhiling Luo,
|
|
||||||
Wenmeng Zhou,
|
|
||||||
Zhicheng Zhang,
|
|
||||||
Xuguang He,
|
|
||||||
Ziqian Chen,
|
|
||||||
Weikai Liao,
|
|
||||||
Farruh Isakulovich Kushnazarov,
|
|
||||||
Yaliang Li,
|
|
||||||
Bolin Ding,
|
|
||||||
Jingren Zhou}
|
|
||||||
title = {AgentScope 1.0: A Developer-Centric Framework for Building Agentic Applications},
|
|
||||||
journal = {CoRR},
|
|
||||||
volume = {abs/2508.16279},
|
|
||||||
year = {2025},
|
|
||||||
}
|
|
||||||
|
|
||||||
@article{agentscope,
|
|
||||||
author = {
|
|
||||||
Dawei Gao,
|
|
||||||
Zitao Li,
|
|
||||||
Xuchen Pan,
|
|
||||||
Weirui Kuang,
|
|
||||||
Zhijian Ma,
|
|
||||||
Bingchen Qian,
|
|
||||||
Fei Wei,
|
|
||||||
Wenhao Zhang,
|
|
||||||
Yuexiang Xie,
|
|
||||||
Daoyuan Chen,
|
|
||||||
Liuyi Yao,
|
|
||||||
Hongyi Peng,
|
|
||||||
Zeyu Zhang,
|
|
||||||
Lin Zhu,
|
|
||||||
Chen Cheng,
|
|
||||||
Hongzhu Shi,
|
|
||||||
Yaliang Li,
|
|
||||||
Bolin Ding,
|
|
||||||
Jingren Zhou}
|
|
||||||
title = {AgentScope: A Flexible yet Robust Multi-Agent Platform},
|
|
||||||
journal = {CoRR},
|
|
||||||
volume = {abs/2402.14034},
|
|
||||||
year = {2024},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## ✨ Contributors
|
|
||||||
|
|
||||||
All thanks to our contributors:
|
|
||||||
|
|
||||||
<a href="https://github.com/agentscope-ai/agentscope/graphs/contributors">
|
|
||||||
<img src="https://contrib.rocks/image?repo=agentscope-ai/agentscope&max=999&columns=12&anon=1" />
|
|
||||||
</a>
|
|
||||||
@@ -1,315 +0,0 @@
|
|||||||
agentscope-1.0.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
||||||
agentscope-1.0.7.dist-info/METADATA,sha256=HD2a1imJIVJ1oFh55nhcZTP0Li5q-9o1ZDg-K73SVh8,25920
|
|
||||||
agentscope-1.0.7.dist-info/RECORD,,
|
|
||||||
agentscope-1.0.7.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
agentscope-1.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
||||||
agentscope-1.0.7.dist-info/licenses/LICENSE,sha256=QYa8rfNYxgCABgMJdp22sqNScg1zU9gnu1dMYA_umRM,20637
|
|
||||||
agentscope-1.0.7.dist-info/top_level.txt,sha256=uYSDqkiAOqFFfMz9DGnkhn0_nNVwo1uaFYZQikHbWNM,11
|
|
||||||
agentscope/__init__.py,sha256=MkP1MQ4hMFmRQF8qeUUVuBcCGvLS4fa-eqvogl8aj84,3220
|
|
||||||
agentscope/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/__pycache__/_config.cpython-313.pyc,,
|
|
||||||
agentscope/__pycache__/_logging.cpython-313.pyc,,
|
|
||||||
agentscope/__pycache__/_version.cpython-313.pyc,,
|
|
||||||
agentscope/_config.py,sha256=W1Y2lQbTXj1esxwm_sK2yFqztacz-L1OzRJsaei04GM,767
|
|
||||||
agentscope/_logging.py,sha256=XzcUTb7MfRZkc-B3N1IV-jpHaZG0yFirZyfuGa7HOA4,1223
|
|
||||||
agentscope/_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
agentscope/_utils/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/_utils/__pycache__/_common.cpython-313.pyc,,
|
|
||||||
agentscope/_utils/__pycache__/_mixin.cpython-313.pyc,,
|
|
||||||
agentscope/_utils/_common.py,sha256=ghJITFirhNAwTl_ifi9cI6Oc_Fsvlimiv_sxwi4JXZE,8169
|
|
||||||
agentscope/_utils/_mixin.py,sha256=9co2GJyiShSq6HiQ1KwGABr3mfYw2tyvlzCMgI8L0-w,219
|
|
||||||
agentscope/_version.py,sha256=KpA_lRRXOAnkM0n8CqdbV0FanoevNyEft5-YZ-i1-wI,80
|
|
||||||
agentscope/agent/__init__.py,sha256=fxBL1RmxC__kHPRVYkEj03EJ1mYO32vKsbY5wDIV_x8,496
|
|
||||||
agentscope/agent/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/agent/__pycache__/_agent_base.cpython-313.pyc,,
|
|
||||||
agentscope/agent/__pycache__/_agent_meta.cpython-313.pyc,,
|
|
||||||
agentscope/agent/__pycache__/_react_agent.cpython-313.pyc,,
|
|
||||||
agentscope/agent/__pycache__/_react_agent_base.cpython-313.pyc,,
|
|
||||||
agentscope/agent/__pycache__/_user_agent.cpython-313.pyc,,
|
|
||||||
agentscope/agent/__pycache__/_user_input.cpython-313.pyc,,
|
|
||||||
agentscope/agent/_agent_base.py,sha256=gxF0tuQN0XebkWR-uVM-a_RTR6eKoJnJOvJT90UegKI,24299
|
|
||||||
agentscope/agent/_agent_meta.py,sha256=Ilda4Fonq29oeQ3kUDTIs8db655MQqWIhzvxGiGUrSw,5730
|
|
||||||
agentscope/agent/_react_agent.py,sha256=zQKd9L19k3hjJmCRZYp2GjqedHh5-A45k-8xWcGSDoI,28676
|
|
||||||
agentscope/agent/_react_agent_base.py,sha256=haWRx93D7A_zmhVVJLlJ_YD8I2pCM7g77vok761DOug,3707
|
|
||||||
agentscope/agent/_user_agent.py,sha256=50kYNXWSfYE7L0x8D1Vmzsl1-mg20nSaCDYROzEusPI,4219
|
|
||||||
agentscope/agent/_user_input.py,sha256=oXtHQ8XapV0ov_8S40MAt2EWDHmvC-_zAEZsR9lUt8g,13105
|
|
||||||
agentscope/embedding/__init__.py,sha256=aiGzcY4qzX7a-ieseIH86_8zhry5yaII5Wdkg-hKjXY,871
|
|
||||||
agentscope/embedding/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/__pycache__/_cache_base.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/__pycache__/_dashscope_embedding.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/__pycache__/_dashscope_multimodal_embedding.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/__pycache__/_embedding_base.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/__pycache__/_embedding_response.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/__pycache__/_embedding_usage.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/__pycache__/_file_cache.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/__pycache__/_gemini_embedding.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/__pycache__/_ollama_embedding.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/__pycache__/_openai_embedding.cpython-313.pyc,,
|
|
||||||
agentscope/embedding/_cache_base.py,sha256=QV_D9Q1Rbtts1BporJVomFwaLyG6nsy9GxhLQNxh4lY,1800
|
|
||||||
agentscope/embedding/_dashscope_embedding.py,sha256=r0qbxhs1kfNgPkgWIvcPXKDdKfVFhKKERpqW9DyfRtM,5905
|
|
||||||
agentscope/embedding/_dashscope_multimodal_embedding.py,sha256=XQ3Dx7sXC18fTXW6kkudhMwJKqiVSfrPOJrGeYpXFEg,8682
|
|
||||||
agentscope/embedding/_embedding_base.py,sha256=sgt_GsFGiuzSCt1-gzhLKJ3Cn4usYbGfHqliHIWMZg8,1191
|
|
||||||
agentscope/embedding/_embedding_response.py,sha256=naEqlewn6J5UyteBewwknH6HlZVTo2SRhN714JhOk2U,1093
|
|
||||||
agentscope/embedding/_embedding_usage.py,sha256=Z1q5yPXuGR8BpB7yUxcn-vPfmRP7gqnGmBjsSGC2f1w,579
|
|
||||||
agentscope/embedding/_file_cache.py,sha256=2MZpiurcVgqkCTIq2U_8Z0n_D0I1Z87owXY0K-Fqfvk,7126
|
|
||||||
agentscope/embedding/_gemini_embedding.py,sha256=5WgGi9iJK6OSbCO_2mG_JbgSxUotR44grNo9CF6yaL0,3549
|
|
||||||
agentscope/embedding/_ollama_embedding.py,sha256=XRAicJgcD8DDHHy0W5du_Jsio4JC3L6pqvctexUOFKA,3379
|
|
||||||
agentscope/embedding/_openai_embedding.py,sha256=ZWcyLR_a9DuekdmHkxD93ck6Hk3ZmytNsLYognCFacE,3491
|
|
||||||
agentscope/evaluate/__init__.py,sha256=8FWPPEnQh95u9TxN8Forj8-b-in2a4_yxn_5F-yMeV8,861
|
|
||||||
agentscope/evaluate/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/__pycache__/_benchmark_base.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/__pycache__/_metric_base.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/__pycache__/_solution.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/__pycache__/_task.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/__init__.py,sha256=ZtgAiBvYaSJOmUPXX2P5hf_cJdECxJiMgEtyt99pI38,331
|
|
||||||
agentscope/evaluate/_ace_benchmark/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/__pycache__/_ace_benchmark.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/__pycache__/_ace_metric.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/__pycache__/_ace_tools_zh.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_benchmark.py,sha256=8MV9V0FMSV3YfymVKd_ybJRt_dzybKBTJMeivZ393FI,8151
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_metric.py,sha256=6_VBBJ50v7aL6OdwJXRRUrqx2gdWtnpM6jlcZMHP6cQ,4225
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__init__.py,sha256=DFWSvwmPolmgqEbqwmkvO05mTr2QNoneO_eXFjEw7ac,327
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/_food_platform_api.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/_message_api.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/_reminder_api.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/_shared_state.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/__pycache__/_travel_api.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/_food_platform_api.py,sha256=TUQD6gR2VzjtUDK9pZKoWr-H9U0opKcUjvqRmP3q58c,9871
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/_message_api.py,sha256=oJcSfj5Kw_BIMI3eC3LsxB5ZI_nN4o_wd0jOX6OXPGA,11784
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/_reminder_api.py,sha256=ObmgAI4UnpoZmgiRpGvqwXL2Bs5YH1KQG1JVBM9AXmM,7082
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/_shared_state.py,sha256=sLkWasNv57-YxeMEj-GIj6mB6LN0RmsIpOaL3fjImmg,551
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_api/_travel_api.py,sha256=aa5ixysqx6mO3Msueyv_vrJ3yJbdMBKkBmyaKoozJoU,28644
|
|
||||||
agentscope/evaluate/_ace_benchmark/_ace_tools_zh.py,sha256=f10Vu8N82BYe5aBVo8hi2FkC1f0VKMqrNouWEG8DsQM,4052
|
|
||||||
agentscope/evaluate/_benchmark_base.py,sha256=YqFeDn6G-e8njE48Yso5-tRSeE5dZzDRhwvJKCnriQQ,1263
|
|
||||||
agentscope/evaluate/_evaluator/__init__.py,sha256=2g3K8cHhugTwf64ywiF-yLFihpvlrBMX01bUNTQ-yik,280
|
|
||||||
agentscope/evaluate/_evaluator/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_evaluator/__pycache__/_evaluator_base.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_evaluator/__pycache__/_general_evaluator.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_evaluator/__pycache__/_ray_evaluator.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_evaluator/_evaluator_base.py,sha256=Y7LWZDTLmKyiq4WvpLj6dSMJSZw4N80ty-BFEAg5Wxg,7317
|
|
||||||
agentscope/evaluate/_evaluator/_general_evaluator.py,sha256=GSMdijP5a8KPVvc6QrAqOI7pRFyXhd-n3yKekgqSHB0,3817
|
|
||||||
agentscope/evaluate/_evaluator/_ray_evaluator.py,sha256=CS_Hng_j2lY5nlaN5Fb1Uq5hL99dcNyzu2OaGl_HLk0,6075
|
|
||||||
agentscope/evaluate/_evaluator_storage/__init__.py,sha256=bSdhxI83A-2OVMX6L-ZO8EwYytyBQy6XwGIFQbdTod4,262
|
|
||||||
agentscope/evaluate/_evaluator_storage/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_evaluator_storage/__pycache__/_evaluator_storage_base.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_evaluator_storage/__pycache__/_file_evaluator_storage.cpython-313.pyc,,
|
|
||||||
agentscope/evaluate/_evaluator_storage/_evaluator_storage_base.py,sha256=IW4A6WkBGf43uGj59f7Eu5ySTiX1rmPbpjX1iYjCl8A,5459
|
|
||||||
agentscope/evaluate/_evaluator_storage/_file_evaluator_storage.py,sha256=xPBZ6GXCSL3YMJJNsqH0-bzCxo4_FhZDEqLJcGXLexA,11096
|
|
||||||
agentscope/evaluate/_metric_base.py,sha256=ksYBDhjmE8vTv8cMy31HBhbvkGgIYhUBiC8Qw4zpOAE,2663
|
|
||||||
agentscope/evaluate/_solution.py,sha256=CDbGtYOerCd_o2WgKMnFUPrzF51tXeAcMRu2-poyyho,1194
|
|
||||||
agentscope/evaluate/_task.py,sha256=RJw6GbBTZmYN7bZY3DR6qEDKB4bgV3zwNbWt5vZZEhU,1585
|
|
||||||
agentscope/exception/__init__.py,sha256=eaWWszusA4Lm3CaPmyZCpLBkjwxc17IAPq0MioznbQQ,361
|
|
||||||
agentscope/exception/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/exception/__pycache__/_exception_base.cpython-313.pyc,,
|
|
||||||
agentscope/exception/__pycache__/_tool.cpython-313.pyc,,
|
|
||||||
agentscope/exception/_exception_base.py,sha256=o0VAg5seb9GnJNs_eZMrlmxqbI7UEyzwr7B1gwA48oQ,660
|
|
||||||
agentscope/exception/_tool.py,sha256=AsCWmwM7HF5fFKD6JhI6ohRGMZG7i8H1cwWj3xfiPUc,512
|
|
||||||
agentscope/formatter/__init__.py,sha256=mgg0ZCZsk-beTELeVU9HVaU9T38w3u5gMyA4LT-wwag,1184
|
|
||||||
agentscope/formatter/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/formatter/__pycache__/_anthropic_formatter.cpython-313.pyc,,
|
|
||||||
agentscope/formatter/__pycache__/_dashscope_formatter.cpython-313.pyc,,
|
|
||||||
agentscope/formatter/__pycache__/_deepseek_formatter.cpython-313.pyc,,
|
|
||||||
agentscope/formatter/__pycache__/_formatter_base.cpython-313.pyc,,
|
|
||||||
agentscope/formatter/__pycache__/_gemini_formatter.cpython-313.pyc,,
|
|
||||||
agentscope/formatter/__pycache__/_ollama_formatter.cpython-313.pyc,,
|
|
||||||
agentscope/formatter/__pycache__/_openai_formatter.cpython-313.pyc,,
|
|
||||||
agentscope/formatter/__pycache__/_truncated_formatter_base.cpython-313.pyc,,
|
|
||||||
agentscope/formatter/_anthropic_formatter.py,sha256=yJMg6IZX538aKmC6JqYzddhVeLSGz92X9ubjg9MNvaA,8226
|
|
||||||
agentscope/formatter/_dashscope_formatter.py,sha256=FWkX2_zHXCaq4sK_o6NH5b_qcXin_tODDhFqAk0x78A,14548
|
|
||||||
agentscope/formatter/_deepseek_formatter.py,sha256=5Ewi8c99qYL5ZCyE6oKek1x3cqNMfHDtXay43Goohi0,8143
|
|
||||||
agentscope/formatter/_formatter_base.py,sha256=FQKf_3KrydfzuAIL5m5YbC36pfz7lXjnnjG_VI25Cm0,3690
|
|
||||||
agentscope/formatter/_gemini_formatter.py,sha256=n6okME8L623zoLayNXG1uf-UEDgB3xydmpuWipUm4kY,13036
|
|
||||||
agentscope/formatter/_ollama_formatter.py,sha256=fqGKIdhPyMizYSBLj-YwtcbIPBriXolEvrPQuR-ZeiY,10290
|
|
||||||
agentscope/formatter/_openai_formatter.py,sha256=6wrcmO7mqba1X-VWMbYEGjWIv7NfhW-4nctLqvuDaU0,13214
|
|
||||||
agentscope/formatter/_truncated_formatter_base.py,sha256=xKqBL-qiDZSLaHq1ls9fUZZY8xSikdpLqC85hVSWbDM,10211
|
|
||||||
agentscope/hooks/__init__.py,sha256=gn0gD6IUtvlN8fGSy9YZRcS3ANpewvyPjQZuHo2SylU,670
|
|
||||||
agentscope/hooks/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/hooks/__pycache__/_studio_hooks.cpython-313.pyc,,
|
|
||||||
agentscope/hooks/_studio_hooks.py,sha256=fxGjYIwqQ1vs0Yr3zrcfAwO1ZWLyoSvG_0MCmjLnBog,1143
|
|
||||||
agentscope/mcp/__init__.py,sha256=8_x7Loaxt1PVh5h5ubr_RdnyF9wRJOhSsBYMHWaPFRw,587
|
|
||||||
agentscope/mcp/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/mcp/__pycache__/_client_base.cpython-313.pyc,,
|
|
||||||
agentscope/mcp/__pycache__/_http_stateful_client.cpython-313.pyc,,
|
|
||||||
agentscope/mcp/__pycache__/_http_stateless_client.cpython-313.pyc,,
|
|
||||||
agentscope/mcp/__pycache__/_mcp_function.cpython-313.pyc,,
|
|
||||||
agentscope/mcp/__pycache__/_stateful_client_base.cpython-313.pyc,,
|
|
||||||
agentscope/mcp/__pycache__/_stdio_stateful_client.cpython-313.pyc,,
|
|
||||||
agentscope/mcp/_client_base.py,sha256=XzYjrxwSzIEbAVO5IzUlbKTtzdr41fTfBtSUnISpGvY,3274
|
|
||||||
agentscope/mcp/_http_stateful_client.py,sha256=Ekwd1KUJ2RX9oWvv3ZEqDy1FQaXa-hZbSp019K_eR_M,3186
|
|
||||||
agentscope/mcp/_http_stateless_client.py,sha256=LotK9FgzXtSi7VSSGxF0PwYagARBd72P2derYe2Itmg,5223
|
|
||||||
agentscope/mcp/_mcp_function.py,sha256=b_bK9chwTriE7pbncuzG3j46HZkG8BSugvpBr8Z90bI,2604
|
|
||||||
agentscope/mcp/_stateful_client_base.py,sha256=l01VBdAsPNtwR50TnJtwx7NqcIB89V6xpiSN-QUFBeU,5206
|
|
||||||
agentscope/mcp/_stdio_stateful_client.py,sha256=IjDjvha_82RCJgQ8eOitQfPnBVdWzy-ljzzYxnpAgvo,2950
|
|
||||||
agentscope/memory/__init__.py,sha256=PlElb2Rt9lL9JcNZ6ADCvCJwaMPlhPdZIaaBkUlOHfs,555
|
|
||||||
agentscope/memory/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/memory/__pycache__/_in_memory_memory.cpython-313.pyc,,
|
|
||||||
agentscope/memory/__pycache__/_long_term_memory_base.cpython-313.pyc,,
|
|
||||||
agentscope/memory/__pycache__/_mem0_long_term_memory.cpython-313.pyc,,
|
|
||||||
agentscope/memory/__pycache__/_mem0_utils.cpython-313.pyc,,
|
|
||||||
agentscope/memory/__pycache__/_memory_base.cpython-313.pyc,,
|
|
||||||
agentscope/memory/_in_memory_memory.py,sha256=wEpxEqJ0rKui4AVrPz4Bs7JYLc4FmZmp6brUxm9U9nw,3694
|
|
||||||
agentscope/memory/_long_term_memory_base.py,sha256=PQj1W7cLZVyO6gEbaqCeJm_uGG4oa6kRb_3PNgtwbBA,2976
|
|
||||||
agentscope/memory/_mem0_long_term_memory.py,sha256=UsETvCSdwdaP59CphU5SB_BmOvCUHVkmDdFd0POFScs,21243
|
|
||||||
agentscope/memory/_mem0_utils.py,sha256=9cKMy6KUKfAT5CF5oaIrJp90-qFaOZRMbLVg1VZvyMA,7617
|
|
||||||
agentscope/memory/_memory_base.py,sha256=HcM23pIsXULYX6lT1DsGODG72ZWo3EA2TE6kbJEXQG4,1218
|
|
||||||
agentscope/memory/_reme/__init__.py,sha256=mIuY8wRbVVYrQk_S05RBLivY0cnWDfq7Ere-oASf0G0,364
|
|
||||||
agentscope/memory/_reme/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/memory/_reme/__pycache__/_reme_long_term_memory_base.cpython-313.pyc,,
|
|
||||||
agentscope/memory/_reme/__pycache__/_reme_personal_long_term_memory.cpython-313.pyc,,
|
|
||||||
agentscope/memory/_reme/__pycache__/_reme_task_long_term_memory.cpython-313.pyc,,
|
|
||||||
agentscope/memory/_reme/__pycache__/_reme_tool_long_term_memory.cpython-313.pyc,,
|
|
||||||
agentscope/memory/_reme/_reme_long_term_memory_base.py,sha256=o9bvTq1Zz4OESBifog0rX-Pax1N4dkcEgbxMknLCnz4,13747
|
|
||||||
agentscope/memory/_reme/_reme_personal_long_term_memory.py,sha256=y4BpRymoNjw4ZHTYE6ThflwDgKroeHOLotgrpCNd5n8,13818
|
|
||||||
agentscope/memory/_reme/_reme_task_long_term_memory.py,sha256=QHqLJojl98JO9Gv4Q6QrJGtyUvffRAIOkY0w0zNkcVo,14324
|
|
||||||
agentscope/memory/_reme/_reme_tool_long_term_memory.py,sha256=DyKOJQYKm5eAhiqd91Xb7bBl23RO6jf0_k98P_AuK7Q,17675
|
|
||||||
agentscope/message/__init__.py,sha256=Bxh_L9v-eHVe4_vrhXhMfaNsk5TN45i0PwuKiIju1I0,519
|
|
||||||
agentscope/message/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/message/__pycache__/_message_base.cpython-313.pyc,,
|
|
||||||
agentscope/message/__pycache__/_message_block.cpython-313.pyc,,
|
|
||||||
agentscope/message/_message_base.py,sha256=sYw8MiuErVEcqaS6mPAoqTwsrJAyb9UqP-hZyqltNYY,6895
|
|
||||||
agentscope/message/_message_block.py,sha256=oJQsnqm2exxIZjUn3j6CV77rlwL-QIbSf15PCGiTOgg,2651
|
|
||||||
agentscope/model/__init__.py,sha256=BrUp6U4Tn7GwuaKvJ4rC3GIwrNXZe9jxBYxftJV7OZA,603
|
|
||||||
agentscope/model/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/model/__pycache__/_anthropic_model.cpython-313.pyc,,
|
|
||||||
agentscope/model/__pycache__/_dashscope_model.cpython-313.pyc,,
|
|
||||||
agentscope/model/__pycache__/_gemini_model.cpython-313.pyc,,
|
|
||||||
agentscope/model/__pycache__/_model_base.cpython-313.pyc,,
|
|
||||||
agentscope/model/__pycache__/_model_response.cpython-313.pyc,,
|
|
||||||
agentscope/model/__pycache__/_model_usage.cpython-313.pyc,,
|
|
||||||
agentscope/model/__pycache__/_ollama_model.cpython-313.pyc,,
|
|
||||||
agentscope/model/__pycache__/_openai_model.cpython-313.pyc,,
|
|
||||||
agentscope/model/__pycache__/_trinity_model.cpython-313.pyc,,
|
|
||||||
agentscope/model/_anthropic_model.py,sha256=DPPI6WF1MD6ApSpu-tFXjM620GE8X3NqF4fpfuquA6U,18902
|
|
||||||
agentscope/model/_dashscope_model.py,sha256=dCY6Z8xYyyMU2Y3HBUHaNaesBBCUW1FDBy_11VIm7dE,19329
|
|
||||||
agentscope/model/_gemini_model.py,sha256=KUCZZelXec7ZXAo_XM8nyjrus7ATY2OYxXRPX0Uze5Y,17453
|
|
||||||
agentscope/model/_model_base.py,sha256=9lRp9WT-NyOsoHLw2pKvr-aBOqsoFp_PLziXz9Jvsho,2039
|
|
||||||
agentscope/model/_model_response.py,sha256=aER8B2-rg_Uu0MRSxknTIO_J0Q5yzyvH1aKfNdaW35k,1295
|
|
||||||
agentscope/model/_model_usage.py,sha256=o9OvCM4CwYqqfa_w2oz80poIU8a2x9tf4jrkynr0g3o,560
|
|
||||||
agentscope/model/_ollama_model.py,sha256=1l2fSIs2AakdZCV6rFVHANpokpZ0ZjAUFheY4sy6Eq0,12319
|
|
||||||
agentscope/model/_openai_model.py,sha256=DA3LspB1X_Z-z9HNsZK_-df6oJjwvUNso1GzpgiRwhw,20201
|
|
||||||
agentscope/model/_trinity_model.py,sha256=aq0pCGcDZfd3OX2bqM0RLhcsD2Dguom2QrwcB3CRjMw,2362
|
|
||||||
agentscope/module/__init__.py,sha256=zhS2IA0PzSZalXiyu1jUXnz32ESQNn7RJKJJuSInE5o,130
|
|
||||||
agentscope/module/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/module/__pycache__/_state_module.cpython-313.pyc,,
|
|
||||||
agentscope/module/_state_module.py,sha256=nI1cm1Sa2ycFiFxs_tpo9aOnxWSqXGr8gVCTlRw5bVI,5644
|
|
||||||
agentscope/pipeline/__init__.py,sha256=KwzeVx8Ugl0Ljk9B_ziRrR-5YfBHtDW5fjdM3CVJmgc,496
|
|
||||||
agentscope/pipeline/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/pipeline/__pycache__/_class.cpython-313.pyc,,
|
|
||||||
agentscope/pipeline/__pycache__/_functional.cpython-313.pyc,,
|
|
||||||
agentscope/pipeline/__pycache__/_msghub.cpython-313.pyc,,
|
|
||||||
agentscope/pipeline/_class.py,sha256=NQS56cj3eOK2j5F28-V3Sdh1cMaOT3N68y10hqH24MY,2594
|
|
||||||
agentscope/pipeline/_functional.py,sha256=lVtm7UijSV7qyJ9C-aR_4dpmTON88nxZ8oUKxpvOoyU,5903
|
|
||||||
agentscope/pipeline/_msghub.py,sha256=P2QqwvwJeiSE82eI_NDszeKHRHV4bOseisTnLwVUT34,5227
|
|
||||||
agentscope/plan/__init__.py,sha256=TZ48k6DSZh5t9piWMl90R-gCBnY0ipLe875ZMfDtKts,418
|
|
||||||
agentscope/plan/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/plan/__pycache__/_in_memory_storage.cpython-313.pyc,,
|
|
||||||
agentscope/plan/__pycache__/_plan_model.cpython-313.pyc,,
|
|
||||||
agentscope/plan/__pycache__/_plan_notebook.cpython-313.pyc,,
|
|
||||||
agentscope/plan/__pycache__/_storage_base.cpython-313.pyc,,
|
|
||||||
agentscope/plan/_in_memory_storage.py,sha256=I32B4nJCu7BYyb1Tgm4QLRI_K0Q27kMNRt96N-y0wLM,2094
|
|
||||||
agentscope/plan/_plan_model.py,sha256=yb4KK_JL1C3QVoX4gCeiSghHFaE39ijq4lxbGm_viZI,6418
|
|
||||||
agentscope/plan/_plan_notebook.py,sha256=LmZOJxQj862Bp4TR_gZU_lqF14uhPHVnENjVLVIOVas,32621
|
|
||||||
agentscope/plan/_storage_base.py,sha256=M1BFqDIiHthFJQFi3gDZNaO12S9FZ_snTFMbqtTipIw,725
|
|
||||||
agentscope/rag/__init__.py,sha256=ZCXDDkeHqYGyl-HuPpWzVj_5mP24fUXSDLpHRc0Hz-U,674
|
|
||||||
agentscope/rag/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/rag/__pycache__/_document.cpython-313.pyc,,
|
|
||||||
agentscope/rag/__pycache__/_knowledge_base.cpython-313.pyc,,
|
|
||||||
agentscope/rag/__pycache__/_simple_knowledge.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_document.py,sha256=9UvKeKu0WBz2nwNj3cgvx6fouVzBa7LJFcDvpVXxw8A,1199
|
|
||||||
agentscope/rag/_knowledge_base.py,sha256=pswLgq1VPKD9UiHns1I_dlI0m6A-9GNyAI67Pm_aJ2A,4441
|
|
||||||
agentscope/rag/_reader/__init__.py,sha256=IvJ2FAphm5CgWoaI1CEPmJPArveQtZv5-Shfkf3yitg,413
|
|
||||||
agentscope/rag/_reader/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_reader/__pycache__/_image_reader.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_reader/__pycache__/_pdf_reader.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_reader/__pycache__/_reader_base.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_reader/__pycache__/_text_reader.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_reader/__pycache__/_word_reader.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_reader/_image_reader.py,sha256=kY-jLuzaUyILsviOaO4Fzejupa7I_OJGCRVheo-D0YA,1902
|
|
||||||
agentscope/rag/_reader/_pdf_reader.py,sha256=auptyMvJ6CFDOHqF-Z8s6gHoYtA5mldnQsz3k7AfSv8,2758
|
|
||||||
agentscope/rag/_reader/_reader_base.py,sha256=qY5xkACT1H28lWLjUUFB-Dn_xqpUexPwJu-pMViTmVI,900
|
|
||||||
agentscope/rag/_reader/_text_reader.py,sha256=Loq0fFMhj53mhZPcezG_hxIx3LQSD5FaTsxQmXDqZos,5046
|
|
||||||
agentscope/rag/_reader/_word_reader.py,sha256=0eh_7d_Fa5_6g5xsMq7koSWz4Uv6y3fCPY3LoZ958TI,17385
|
|
||||||
agentscope/rag/_simple_knowledge.py,sha256=rMqMEy6QInrjUOX85g8NRlG7LHSrip4hkYVcv17lOMA,2580
|
|
||||||
agentscope/rag/_store/__init__.py,sha256=u7qAWDjacgKxfzIPD7LeDXb9pbvWX6WjgDrdvMyQzJM,305
|
|
||||||
agentscope/rag/_store/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_store/__pycache__/_milvuslite_store.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_store/__pycache__/_qdrant_store.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_store/__pycache__/_store_base.cpython-313.pyc,,
|
|
||||||
agentscope/rag/_store/_milvuslite_store.py,sha256=1FUs6zlVoOjwz3YLc-oFqyXqSQjEdKD_uNhCDjURqHI,9059
|
|
||||||
agentscope/rag/_store/_qdrant_store.py,sha256=04Xsfr9WM7g7MNRyPO1hEd_-hbIqPkvexYKMY9ukR80,6250
|
|
||||||
agentscope/rag/_store/_store_base.py,sha256=RaXNmcGu6kZMJjM7pfSjVWcv4iCxMt9LMbJpSMrI0ZM,1658
|
|
||||||
agentscope/session/__init__.py,sha256=GY2Skir_T7y19pnywNVBZ3H3ePqsnShva-ljgeiCLiQ,196
|
|
||||||
agentscope/session/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/session/__pycache__/_json_session.cpython-313.pyc,,
|
|
||||||
agentscope/session/__pycache__/_session_base.cpython-313.pyc,,
|
|
||||||
agentscope/session/_json_session.py,sha256=4NvJPK4qplKdASSHeu7BugpCSxO8BNHRbSNPzna6g-s,3820
|
|
||||||
agentscope/session/_session_base.py,sha256=pKbEHnOHJuxaccGobPo2z984W3OrZS3Rl9oCwrpibMY,859
|
|
||||||
agentscope/token/__init__.py,sha256=0PyydmrOKp-Al3CUqM_1WiCSZc9hSR3XEXV7mXCv48k,487
|
|
||||||
agentscope/token/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/token/__pycache__/_anthropic_token_counter.cpython-313.pyc,,
|
|
||||||
agentscope/token/__pycache__/_gemini_token_counter.cpython-313.pyc,,
|
|
||||||
agentscope/token/__pycache__/_huggingface_token_counter.cpython-313.pyc,,
|
|
||||||
agentscope/token/__pycache__/_openai_token_counter.cpython-313.pyc,,
|
|
||||||
agentscope/token/__pycache__/_token_base.cpython-313.pyc,,
|
|
||||||
agentscope/token/_anthropic_token_counter.py,sha256=-1c-OrsfaNvSCEHzgRNSFL7HUQCAuoe9q3nNEk4J9YE,1853
|
|
||||||
agentscope/token/_gemini_token_counter.py,sha256=vcWHo8iHR1JLhDTM3pS6-mpxEUWCKceVll_ypq7mKhU,1385
|
|
||||||
agentscope/token/_huggingface_token_counter.py,sha256=ksxFpqPde16VptiSV8RmHasgld1bp_fz16j6t4baWtk,2846
|
|
||||||
agentscope/token/_openai_token_counter.py,sha256=Aq2YCnCOvPUOfr4r5OeQqqom_VRAPyUdckqIbx3giiQ,11365
|
|
||||||
agentscope/token/_token_base.py,sha256=ukxfNg8nBL_MLd9rzkpy5aP8s-uqEKbeZGtAYZyCBzA,388
|
|
||||||
agentscope/tool/__init__.py,sha256=lXMHKD91iPK2rSY53cDg39kMXwQsedG-rf39gFRd0Go,1020
|
|
||||||
agentscope/tool/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/tool/__pycache__/_async_wrapper.cpython-313.pyc,,
|
|
||||||
agentscope/tool/__pycache__/_registered_tool_function.cpython-313.pyc,,
|
|
||||||
agentscope/tool/__pycache__/_response.cpython-313.pyc,,
|
|
||||||
agentscope/tool/__pycache__/_toolkit.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_async_wrapper.py,sha256=tfv6edszdHC03IsL0Z3EvVAII0zEdYavD3wBI__L-zM,3474
|
|
||||||
agentscope/tool/_coding/__init__.py,sha256=e_XNdZZo6-gS7EvY_AEM2h0q3XtYm1voCKbojypfwn4,232
|
|
||||||
agentscope/tool/_coding/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_coding/__pycache__/_python.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_coding/__pycache__/_shell.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_coding/_python.py,sha256=FwnidjGPYBRsLGX0FPICjlApISg7eL4GZoVBvFrObik,2714
|
|
||||||
agentscope/tool/_coding/_shell.py,sha256=pgivhc2CSs8mBWSh5ax9NgWI07q_b7WoKV7hdI8h448,2266
|
|
||||||
agentscope/tool/_multi_modality/__init__.py,sha256=H9VpqWCV0V7WXvqqYWjbpwmafJHtq_pDm-RV7P3vG0s,678
|
|
||||||
agentscope/tool/_multi_modality/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_multi_modality/__pycache__/_dashscope_tools.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_multi_modality/__pycache__/_openai_tools.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_multi_modality/_dashscope_tools.py,sha256=6piJ5fjVaQTYaq4w3UQXGS0ANY29lkCqyc3_keomlbY,8908
|
|
||||||
agentscope/tool/_multi_modality/_openai_tools.py,sha256=UaZOHHAWEi7Y_uG_n23Q8OTh45Cb-hD4t5-oR6o4K_Q,20873
|
|
||||||
agentscope/tool/_registered_tool_function.py,sha256=jI8VMSeWlj-EGq7IKlydBQcC2jjOZEDQTdnkxEm7jng,3449
|
|
||||||
agentscope/tool/_response.py,sha256=3WdPFj1uRdxvkrECfMlUjzPVg-PseeSVNF5SWn1dCOs,938
|
|
||||||
agentscope/tool/_text_file/__init__.py,sha256=tnQP6RCS1wHff65ycZkXE4Fxcw5OXZe50_6dD5hfa9o,276
|
|
||||||
agentscope/tool/_text_file/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_text_file/__pycache__/_utils.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_text_file/__pycache__/_view_text_file.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_text_file/__pycache__/_write_text_file.cpython-313.pyc,,
|
|
||||||
agentscope/tool/_text_file/_utils.py,sha256=vizy7C6rNmp8z5aiNbrrsMdoeX8bws4FnnyEixlo0jU,2645
|
|
||||||
agentscope/tool/_text_file/_view_text_file.py,sha256=MHq0eiNiBMSDY7Dne8Ch6-YqIS0i8alP3dX2gzxi-nA,2280
|
|
||||||
agentscope/tool/_text_file/_write_text_file.py,sha256=zZcafaRg53o2DT1Q1t9en4Z8sRxaRwREAbsfdLfSpOI,7333
|
|
||||||
agentscope/tool/_toolkit.py,sha256=2iSCpI9zRmNgD_g_PVE-N8K060_DU4S9NDzQ7tvnW30,34654
|
|
||||||
agentscope/tracing/__init__.py,sha256=R7Xegg62pD5UDey0w4ZyAJ6LVt6_qSkjlrOIoV3mHpk,382
|
|
||||||
agentscope/tracing/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/tracing/__pycache__/_attributes.cpython-313.pyc,,
|
|
||||||
agentscope/tracing/__pycache__/_setup.cpython-313.pyc,,
|
|
||||||
agentscope/tracing/__pycache__/_trace.cpython-313.pyc,,
|
|
||||||
agentscope/tracing/__pycache__/_types.cpython-313.pyc,,
|
|
||||||
agentscope/tracing/_attributes.py,sha256=-R_z4rI17u4pOyK9RWtWPmKX0uEL1YmffcJhAEJanvM,1774
|
|
||||||
agentscope/tracing/_setup.py,sha256=QwhHf_NyR-4lBJChNa616pze7CV7HPFq0mNoWxUnCQg,874
|
|
||||||
agentscope/tracing/_trace.py,sha256=Iclrx0Uxpjq4OwrGfCvl_TADn7eSm85R2ZhJiwYdG-w,21677
|
|
||||||
agentscope/tracing/_types.py,sha256=EE-Y6btCihsNuC27XiLlTdqLy1C4CCoENthPDerw8mU,528
|
|
||||||
agentscope/tune/__init__.py,sha256=VpKbNhHLr6GAQ4zJJ-hEy9IOCqLB7YQTNt3DKQKbq0g,195
|
|
||||||
agentscope/tune/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/tune/__pycache__/_tune.cpython-313.pyc,,
|
|
||||||
agentscope/tune/__pycache__/_workflow.cpython-313.pyc,,
|
|
||||||
agentscope/tune/_tune.py,sha256=elVcwVuRRlPghcaYQZAYhiwchV4VqIL-PDb86HaV_ws,2520
|
|
||||||
agentscope/tune/_workflow.py,sha256=TLrri2aRfVamTzDK8FaeHUDDSZZnfhos8JvseeFoHiU,2125
|
|
||||||
agentscope/types/__init__.py,sha256=_AX5wH9fPHkNEwCOQb2ycdh62J6IRXqYYcplJOcWjFQ,408
|
|
||||||
agentscope/types/__pycache__/__init__.cpython-313.pyc,,
|
|
||||||
agentscope/types/__pycache__/_hook.cpython-313.pyc,,
|
|
||||||
agentscope/types/__pycache__/_json.cpython-313.pyc,,
|
|
||||||
agentscope/types/__pycache__/_object.cpython-313.pyc,,
|
|
||||||
agentscope/types/__pycache__/_tool.cpython-313.pyc,,
|
|
||||||
agentscope/types/_hook.py,sha256=st--2oBVuLwNaNk5DQXkYA7xp8X4HaqTaXf2lVDAPM0,427
|
|
||||||
agentscope/types/_json.py,sha256=MXTFO_TufiyRy0X_OuEfuoPqWLRUYRRwurKu-o-m5oI,308
|
|
||||||
agentscope/types/_object.py,sha256=dHR84mJvBFesbYj46mQO9ssw38dPuKpJaCbySprLWZE,111
|
|
||||||
agentscope/types/_tool.py,sha256=J22DtLNDoMTZp_cOkGfrjpmG-qFPWgqaKhcXsyomC58,845
|
|
||||||
@@ -1,391 +0,0 @@
|
|||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright 2024 Alibaba
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
Some codes of tests/run.py is modified from
|
|
||||||
https://github.com/alibaba/FederatedScope/blob/master/tests/run.py, which is
|
|
||||||
also licensed under the terms of the Apache 2.0.
|
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Code in src/agentscope/web/static/js/socket.io.js is adapted from
|
|
||||||
https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.3/socket.io.js (MIT License)
|
|
||||||
|
|
||||||
Copyright (c) 2014-2021 Guillermo Rauch
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Code in src/agentscope/web/static/js/jquery-3.3.1.min.js is adapted from
|
|
||||||
https://code.jquery.com/jquery-3.3.1.min.js (MIT License)
|
|
||||||
|
|
||||||
Copyright (c) JS Foundation and other contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Code in src/agentscope/web/static/js/bootstrap.bundle.min.js is adapted from
|
|
||||||
https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.bundle.min.js
|
|
||||||
(MIT License)
|
|
||||||
|
|
||||||
Copyright (c) 2011-2019 The Bootstrap Authors (https://github
|
|
||||||
.com/twbs/bootstrap/graphs/contributors)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Code in src/agentscope/web/static/js/bootstrap-table.min.js is adapted from
|
|
||||||
https://unpkg.com/bootstrap-table@1.18.0/dist/bootstrap-table.min.js (MIT
|
|
||||||
License)
|
|
||||||
|
|
||||||
Copyright (c) wenzhixin <wenzhixin2010@gmail.com> (http://wenzhixin.net.cn/)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Code in src/agentscope/web/static/css/bootstrap.min.css is adapted from
|
|
||||||
https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css (MIT
|
|
||||||
License)
|
|
||||||
|
|
||||||
Copyright 2011-2019 The Bootstrap Authors
|
|
||||||
Copyright 2011-2019 Twitter, Inc.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Fonts in src/agentscope/web/static/fonts/KRYPTON.ttf is adapted from
|
|
||||||
https://github.com/githubnext/monaspace (SIL Open Font License 1.1). These
|
|
||||||
fonts are distributed with their original license. See https://github
|
|
||||||
.com/githubnext/monaspace/blob/main/LICENSE for the full text of the license.
|
|
||||||
The following font families are included:
|
|
||||||
|
|
||||||
- Monaspace (with subfamilies: Krypton)
|
|
||||||
|
|
||||||
Copyright (c) 2023, GitHub https://github.com/githubnext/monaspace
|
|
||||||
with Reserved Font Name "Monaspace", including subfamilies: "Argon", "Neon",
|
|
||||||
"Xenon", "Radon", and "Krypton"
|
|
||||||
|
|
||||||
DISCLAIMER
|
|
||||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
||||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
||||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
||||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
||||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Fonts in src/agentscope/web/static/fonts/OSWALD.ttf is adapted from
|
|
||||||
https://fonts.google.com/specimen/Oswald (SIL Open Font License 1.1). These
|
|
||||||
fonts are distributed with their original license. See https://github
|
|
||||||
.com/googlefonts/OswaldFont/blob/main/OFL.txt for the full text of the license.
|
|
||||||
|
|
||||||
Copyright 2016 The Oswald Project Authors (https://github
|
|
||||||
.com/googlefonts/OswaldFont)
|
|
||||||
|
|
||||||
DISCLAIMER
|
|
||||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
||||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
||||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
||||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
||||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
agentscope
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""The agentscope serialization module"""
|
|
||||||
import os
|
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
from . import exception
|
|
||||||
from . import module
|
|
||||||
from . import message
|
|
||||||
from . import model
|
|
||||||
from . import tool
|
|
||||||
from . import formatter
|
|
||||||
from . import memory
|
|
||||||
from . import agent
|
|
||||||
from . import session
|
|
||||||
from . import embedding
|
|
||||||
from . import token
|
|
||||||
from . import evaluate
|
|
||||||
from . import pipeline
|
|
||||||
from . import tracing
|
|
||||||
from . import rag
|
|
||||||
|
|
||||||
from ._logging import (
|
|
||||||
logger,
|
|
||||||
setup_logger,
|
|
||||||
)
|
|
||||||
from .hooks import _equip_as_studio_hooks
|
|
||||||
from ._version import __version__
|
|
||||||
|
|
||||||
|
|
||||||
def init(
|
|
||||||
project: str | None = None,
|
|
||||||
name: str | None = None,
|
|
||||||
logging_path: str | None = None,
|
|
||||||
logging_level: str = "INFO",
|
|
||||||
studio_url: str | None = None,
|
|
||||||
tracing_url: str | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""Initialize the agentscope library.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
project (`str | None`, optional):
|
|
||||||
The project name.
|
|
||||||
name (`str | None`, optional):
|
|
||||||
The name of the run.
|
|
||||||
logging_path (`str | None`, optional):
|
|
||||||
The path to saving the log file. If not provided, logs will not be
|
|
||||||
saved.
|
|
||||||
logging_level (`str | None`, optional):
|
|
||||||
The logging level. Defaults to "INFO".
|
|
||||||
studio_url (`str | None`, optional):
|
|
||||||
The URL of the AgentScope Studio to connect to.
|
|
||||||
tracing_url (`str | None`, optional):
|
|
||||||
The URL of the tracing endpoint, which can connect to third-party
|
|
||||||
OpenTelemetry tracing platforms like Arize-Phoenix and Langfuse.
|
|
||||||
If not provided and `studio_url` is provided, it will send traces
|
|
||||||
to the AgentScope Studio's tracing endpoint.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from . import _config
|
|
||||||
|
|
||||||
if project:
|
|
||||||
_config.project = project
|
|
||||||
|
|
||||||
if name:
|
|
||||||
_config.name = name
|
|
||||||
|
|
||||||
setup_logger(logging_level, logging_path)
|
|
||||||
|
|
||||||
if studio_url:
|
|
||||||
# Register the run
|
|
||||||
data = {
|
|
||||||
"id": _config.run_id,
|
|
||||||
"project": _config.project,
|
|
||||||
"name": _config.name,
|
|
||||||
"timestamp": _config.created_at,
|
|
||||||
"pid": os.getpid(),
|
|
||||||
"status": "running",
|
|
||||||
# Deprecated fields
|
|
||||||
"run_dir": "",
|
|
||||||
}
|
|
||||||
response = requests.post(
|
|
||||||
url=f"{studio_url}/trpc/registerRun",
|
|
||||||
json=data,
|
|
||||||
)
|
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
from .agent import UserAgent, StudioUserInput
|
|
||||||
|
|
||||||
UserAgent.override_class_input_method(
|
|
||||||
StudioUserInput(
|
|
||||||
studio_url=studio_url,
|
|
||||||
run_id=_config.run_id,
|
|
||||||
max_retries=3,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
_equip_as_studio_hooks(studio_url)
|
|
||||||
|
|
||||||
if tracing_url:
|
|
||||||
endpoint = tracing_url
|
|
||||||
else:
|
|
||||||
endpoint = studio_url.strip("/") + "/v1/traces" if studio_url else None
|
|
||||||
|
|
||||||
if endpoint:
|
|
||||||
from .tracing import setup_tracing
|
|
||||||
|
|
||||||
setup_tracing(endpoint=endpoint)
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
# modules
|
|
||||||
"exception",
|
|
||||||
"module",
|
|
||||||
"message",
|
|
||||||
"model",
|
|
||||||
"tool",
|
|
||||||
"formatter",
|
|
||||||
"memory",
|
|
||||||
"agent",
|
|
||||||
"session",
|
|
||||||
"logger",
|
|
||||||
"embedding",
|
|
||||||
"token",
|
|
||||||
"evaluate",
|
|
||||||
"pipeline",
|
|
||||||
"tracing",
|
|
||||||
"rag",
|
|
||||||
# functions
|
|
||||||
"init",
|
|
||||||
"setup_logger",
|
|
||||||
"__version__",
|
|
||||||
]
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,23 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""The runtime configuration in agentscope.
|
|
||||||
|
|
||||||
.. note:: You should import this module as ``import ._config``, then use the
|
|
||||||
variables defined in this module, instead of ``from ._config import xxx``.
|
|
||||||
Because when the variables are changed, the changes will not be reflected in
|
|
||||||
the imported module.
|
|
||||||
"""
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import shortuuid
|
|
||||||
|
|
||||||
|
|
||||||
def _generate_random_suffix(length: int) -> str:
|
|
||||||
"""Generate a random suffix."""
|
|
||||||
return shortuuid.uuid()[:length]
|
|
||||||
|
|
||||||
|
|
||||||
project = "UnnamedProject_At" + datetime.now().strftime("%Y%m%d")
|
|
||||||
name = datetime.now().strftime("%H%M%S_") + _generate_random_suffix(4)
|
|
||||||
run_id: str = shortuuid.uuid()
|
|
||||||
created_at: str = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
|
|
||||||
trace_enabled: bool = False
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""The logger for agentscope."""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
|
|
||||||
_DEFAULT_FORMAT = (
|
|
||||||
"%(asctime)s | %(levelname)-7s | "
|
|
||||||
"%(module)s:%(funcName)s:%(lineno)s - %(message)s"
|
|
||||||
)
|
|
||||||
|
|
||||||
logger = logging.getLogger("as")
|
|
||||||
|
|
||||||
|
|
||||||
def setup_logger(
|
|
||||||
level: str,
|
|
||||||
filepath: str | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""Set up the agentscope logger.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
level (`str`):
|
|
||||||
The logging level, chosen from "INFO", "DEBUG", "WARNING",
|
|
||||||
"ERROR", "CRITICAL".
|
|
||||||
filepath (`str | None`, optional):
|
|
||||||
The filepath to save the logging output.
|
|
||||||
"""
|
|
||||||
if level not in ["INFO", "DEBUG", "WARNING", "ERROR", "CRITICAL"]:
|
|
||||||
raise ValueError(
|
|
||||||
f"Invalid logging level: {level}. Must be one of "
|
|
||||||
f"'INFO', 'DEBUG', 'WARNING', 'ERROR', 'CRITICAL'.",
|
|
||||||
)
|
|
||||||
logger.handlers.clear()
|
|
||||||
logger.setLevel(level)
|
|
||||||
handler = logging.StreamHandler()
|
|
||||||
handler.setFormatter(logging.Formatter(_DEFAULT_FORMAT))
|
|
||||||
logger.addHandler(handler)
|
|
||||||
|
|
||||||
if filepath:
|
|
||||||
handler = logging.FileHandler(filepath)
|
|
||||||
handler.setFormatter(logging.Formatter(_DEFAULT_FORMAT))
|
|
||||||
logger.addHandler(handler)
|
|
||||||
|
|
||||||
logger.propagate = False
|
|
||||||
|
|
||||||
|
|
||||||
setup_logger("INFO")
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,285 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""The common utilities for agentscope library."""
|
|
||||||
import asyncio
|
|
||||||
import base64
|
|
||||||
import functools
|
|
||||||
import inspect
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import tempfile
|
|
||||||
import types
|
|
||||||
import typing
|
|
||||||
import uuid
|
|
||||||
from datetime import datetime
|
|
||||||
from typing import Union, Any, Callable, Type, Dict
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from json_repair import repair_json
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
from .._logging import logger
|
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
|
||||||
from mcp.types import Tool
|
|
||||||
else:
|
|
||||||
Tool = "mcp.types.Tool"
|
|
||||||
|
|
||||||
|
|
||||||
def _json_loads_with_repair(
|
|
||||||
json_str: str,
|
|
||||||
) -> Union[dict, list, str, float, int, bool, None]:
|
|
||||||
"""The given json_str maybe incomplete, e.g. '{"key', so we need to
|
|
||||||
repair and load it into a Python object.
|
|
||||||
"""
|
|
||||||
repaired = json_str
|
|
||||||
try:
|
|
||||||
repaired = repair_json(json_str)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
return json.loads(repaired)
|
|
||||||
except json.JSONDecodeError as e:
|
|
||||||
raise ValueError(
|
|
||||||
f"Failed to decode JSON string `{json_str}` after repairing it "
|
|
||||||
f"into `{repaired}`. Error: {e}",
|
|
||||||
) from e
|
|
||||||
|
|
||||||
|
|
||||||
def _is_accessible_local_file(url: str) -> bool:
|
|
||||||
"""Check if the given URL is a local URL."""
|
|
||||||
return os.path.isfile(url)
|
|
||||||
|
|
||||||
|
|
||||||
def _get_timestamp(add_random_suffix: bool = False) -> str:
|
|
||||||
"""Get the current timestamp in the format YYYY-MM-DD HH:MM:SS.sss."""
|
|
||||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
|
|
||||||
|
|
||||||
if add_random_suffix:
|
|
||||||
# Add a random suffix to the timestamp
|
|
||||||
timestamp += f"_{os.urandom(3).hex()}"
|
|
||||||
|
|
||||||
return timestamp
|
|
||||||
|
|
||||||
|
|
||||||
async def _is_async_func(func: Callable) -> bool:
|
|
||||||
"""Check if the given function is an async function, including
|
|
||||||
coroutine functions, async generators, and coroutine objects.
|
|
||||||
"""
|
|
||||||
|
|
||||||
return (
|
|
||||||
inspect.iscoroutinefunction(func)
|
|
||||||
or inspect.isasyncgenfunction(func)
|
|
||||||
or isinstance(func, types.CoroutineType)
|
|
||||||
or isinstance(func, types.GeneratorType)
|
|
||||||
and asyncio.iscoroutine(func)
|
|
||||||
or isinstance(func, functools.partial)
|
|
||||||
and await _is_async_func(func.func)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def _execute_async_or_sync_func(
|
|
||||||
func: Callable,
|
|
||||||
*args: Any,
|
|
||||||
**kwargs: Any,
|
|
||||||
) -> Any:
|
|
||||||
"""Execute an async or sync function based on its type.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
func (`Callable`):
|
|
||||||
The function to be executed, which can be either async or sync.
|
|
||||||
*args (`Any`):
|
|
||||||
Positional arguments to be passed to the function.
|
|
||||||
**kwargs (`Any`):
|
|
||||||
Keyword arguments to be passed to the function.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
`Any`:
|
|
||||||
The result of the function execution.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if await _is_async_func(func):
|
|
||||||
return await func(*args, **kwargs)
|
|
||||||
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def _get_bytes_from_web_url(
|
|
||||||
url: str,
|
|
||||||
max_retries: int = 3,
|
|
||||||
) -> str:
|
|
||||||
"""Get the bytes from a given URL.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
url (`str`):
|
|
||||||
The URL to fetch the bytes from.
|
|
||||||
max_retries (`int`, defaults to `3`):
|
|
||||||
The maximum number of retries.
|
|
||||||
"""
|
|
||||||
for _ in range(max_retries):
|
|
||||||
try:
|
|
||||||
response = requests.get(url)
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.content.decode("utf-8")
|
|
||||||
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
return base64.b64encode(response.content).decode("ascii")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.info(
|
|
||||||
"Failed to fetch bytes from URL %s. Error %s. Retrying...",
|
|
||||||
url,
|
|
||||||
str(e),
|
|
||||||
)
|
|
||||||
|
|
||||||
raise RuntimeError(
|
|
||||||
f"Failed to fetch bytes from URL `{url}` after {max_retries} retries.",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _save_base64_data(
|
|
||||||
media_type: str,
|
|
||||||
base64_data: str,
|
|
||||||
) -> str:
|
|
||||||
"""Save the base64 data to a temp file and return the file path. The
|
|
||||||
extension is guessed from the MIME type.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
media_type (`str`):
|
|
||||||
The MIME type of the data, e.g. "image/png", "audio/mpeg".
|
|
||||||
base64_data (`str):
|
|
||||||
The base64 data to be saved.
|
|
||||||
"""
|
|
||||||
extension = "." + media_type.split("/")[-1]
|
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(
|
|
||||||
suffix=f".{extension}",
|
|
||||||
delete=False,
|
|
||||||
) as temp_file:
|
|
||||||
decoded_data = base64.b64decode(base64_data)
|
|
||||||
temp_file.write(decoded_data)
|
|
||||||
temp_file.close()
|
|
||||||
return temp_file.name
|
|
||||||
|
|
||||||
|
|
||||||
def _extract_json_schema_from_mcp_tool(tool: Tool) -> dict[str, Any]:
|
|
||||||
"""Extract JSON schema from MCP tool."""
|
|
||||||
|
|
||||||
return {
|
|
||||||
"type": "function",
|
|
||||||
"function": {
|
|
||||||
"name": tool.name,
|
|
||||||
"description": tool.description,
|
|
||||||
"parameters": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": tool.inputSchema.get(
|
|
||||||
"properties",
|
|
||||||
{},
|
|
||||||
),
|
|
||||||
"required": tool.inputSchema.get(
|
|
||||||
"required",
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _remove_title_field(schema: dict) -> None:
|
|
||||||
"""Remove the title field from the JSON schema to avoid
|
|
||||||
misleading the LLM."""
|
|
||||||
# The top level title field
|
|
||||||
if "title" in schema:
|
|
||||||
schema.pop("title")
|
|
||||||
|
|
||||||
# properties
|
|
||||||
if "properties" in schema:
|
|
||||||
for prop in schema["properties"].values():
|
|
||||||
if isinstance(prop, dict):
|
|
||||||
_remove_title_field(prop)
|
|
||||||
|
|
||||||
# items
|
|
||||||
if "items" in schema and isinstance(schema["items"], dict):
|
|
||||||
_remove_title_field(schema["items"])
|
|
||||||
|
|
||||||
# additionalProperties
|
|
||||||
if "additionalProperties" in schema and isinstance(
|
|
||||||
schema["additionalProperties"],
|
|
||||||
dict,
|
|
||||||
):
|
|
||||||
_remove_title_field(
|
|
||||||
schema["additionalProperties"],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _create_tool_from_base_model(
|
|
||||||
structured_model: Type[BaseModel],
|
|
||||||
tool_name: str = "generate_structured_output",
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
"""Create a function tool definition from a Pydantic BaseModel.
|
|
||||||
This function converts a Pydantic BaseModel class into a tool definition
|
|
||||||
that can be used with function calling API. The resulting tool
|
|
||||||
definition includes the model's JSON schema as parameters, enabling
|
|
||||||
structured output generation by forcing the model to call this function
|
|
||||||
with properly formatted data.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
structured_model (`Type[BaseModel]`):
|
|
||||||
A Pydantic BaseModel class that defines the expected structure
|
|
||||||
for the tool's output.
|
|
||||||
tool_name (`str`, default `"generate_structured_output"`):
|
|
||||||
The tool name that used to force the LLM to generate structured
|
|
||||||
output by calling this function.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
`Dict[str, Any]`: A tool definition dictionary compatible with
|
|
||||||
function calling API, containing type ("function") and
|
|
||||||
function dictionary with name, description, and parameters
|
|
||||||
(JSON schema).
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
:caption: Example usage
|
|
||||||
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
class PersonInfo(BaseModel):
|
|
||||||
name: str
|
|
||||||
age: int
|
|
||||||
email: str
|
|
||||||
|
|
||||||
tool = _create_tool_from_base_model(PersonInfo, "extract_person")
|
|
||||||
print(tool["function"]["name"]) # extract_person
|
|
||||||
print(tool["type"]) # function
|
|
||||||
|
|
||||||
.. note:: The function automatically removes the 'title' field from
|
|
||||||
the JSON schema to ensure compatibility with function calling
|
|
||||||
format. This is handled by the internal ``_remove_title_field()``
|
|
||||||
function.
|
|
||||||
"""
|
|
||||||
schema = structured_model.model_json_schema()
|
|
||||||
|
|
||||||
_remove_title_field(schema)
|
|
||||||
tool_definition = {
|
|
||||||
"type": "function",
|
|
||||||
"function": {
|
|
||||||
"name": tool_name,
|
|
||||||
"description": "Generate the required structured output with "
|
|
||||||
"this function",
|
|
||||||
"parameters": schema,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return tool_definition
|
|
||||||
|
|
||||||
|
|
||||||
def _map_text_to_uuid(text: str) -> str:
|
|
||||||
"""Map the given text to a deterministic UUID string.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
text (`str`):
|
|
||||||
The input text to be mapped to a UUID.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
`str`:
|
|
||||||
A deterministic UUID string derived from the input text.
|
|
||||||
"""
|
|
||||||
return str(uuid.uuid3(uuid.NAMESPACE_DNS, text))
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""The mixin for agentscope."""
|
|
||||||
|
|
||||||
|
|
||||||
class DictMixin(dict):
|
|
||||||
"""The dictionary mixin that allows attribute-style access."""
|
|
||||||
|
|
||||||
__setattr__ = dict.__setitem__
|
|
||||||
__getattr__ = dict.__getitem__
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""The version of agentscope."""
|
|
||||||
|
|
||||||
__version__ = "1.0.7"
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""The agent base class."""
|
|
||||||
from ._agent_base import AgentBase
|
|
||||||
from ._react_agent_base import ReActAgentBase
|
|
||||||
from ._react_agent import ReActAgent
|
|
||||||
from ._user_input import (
|
|
||||||
UserInputBase,
|
|
||||||
UserInputData,
|
|
||||||
TerminalUserInput,
|
|
||||||
StudioUserInput,
|
|
||||||
)
|
|
||||||
from ._user_agent import UserAgent
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"AgentBase",
|
|
||||||
"ReActAgentBase",
|
|
||||||
"ReActAgent",
|
|
||||||
"UserInputData",
|
|
||||||
"UserInputBase",
|
|
||||||
"TerminalUserInput",
|
|
||||||
"StudioUserInput",
|
|
||||||
"UserAgent",
|
|
||||||
]
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user