Initial commit: 无人机行为规划后端系统

Made-with: Cursor
This commit is contained in:
2026-03-17 10:51:32 +08:00
commit 3ddc2e1ff4
35 changed files with 3219 additions and 0 deletions

391
docs/项目流程详解.md Normal file
View File

@@ -0,0 +1,391 @@
# 无人机行为规划系统 - 项目流程详解
---
## 1. 整体架构
```mermaid
flowchart TB
subgraph Input [输入]
UserText[用户自然语言指令]
end
subgraph Layer1 [Layer 1 - Router]
Router[意图路由]
FastPath{Fast-Path?}
end
subgraph RAG [RAG 检索]
MapDB[map_db]
RuleDB[rule_db]
FewShotDB[few_shot_db]
Retriever[RAGRetriever]
end
subgraph Layer2 [Layer 2 - Composer]
Composer[动态组装 Prompt]
end
subgraph Layer3 [Layer 3 - Planner]
Planner[LLM 规划]
ToolCall[Function Calling]
MCPCalc[calculate_relative_coordinate]
end
subgraph Layer4 [Layer 4 - Execution]
Parse[parse_json_to_tree]
Wrap[wrap_and_build_tree]
Tree[py_trees 行为树]
end
UserText --> Router
Router --> FastPath
FastPath -->|是| Output1[直接返回原子意图]
FastPath -->|否| Retriever
Retriever --> MapDB
Retriever --> RuleDB
Retriever --> FewShotDB
Retriever --> Composer
Composer --> Planner
Planner --> ToolCall
ToolCall --> MCPCalc
MCPCalc --> Planner
Planner --> Parse
Parse --> Wrap
Wrap --> Tree
```
---
## 2. 数据流与各 Stage 总览
| Stage | 模块 | 对应代码 | 是否调用 RAG | 是否调用工具 | 是否调用 LLM |
|-------|------|----------|--------------|--------------|--------------|
| Layer 1 | Router | `pipeline/router.py` | 否 | 否 | 是 |
| RAG | Retriever | `rag/retriever.py` | 是map/rule/few_shot | 否 | 否 |
| Layer 2 | Composer | `pipeline/composer.py` | 否(消费 RAG 结果) | 否 | 否 |
| Layer 3 | Planner | `pipeline/planner.py` | 否(消费 Composer 输出) | 是LLM 调用 mcp | 是 |
| Layer 4 | Execution | `execution/tree_wrapper.py` | 否 | 否 | 否 |
---
## 3. Stage 1Layer 1 - Router意图路由
### 3.1 职责
- 对用户自然语言做意图分类和实体抽取
- 判断是否为 Fast-Path仅原子意图起飞/降落/悬停)
- 冲突处理:同时含原子+业务意图时,保留业务意图
### 3.2 对应代码
- **入口函数**`route(user_text: str) -> RouterResult`
- **文件**[`src/drone_planning/pipeline/router.py`](../src/drone_planning/pipeline/router.py)
### 3.3 是否调用 RAG
**否**。Router 仅依赖 LLM不访问 RAG。
### 3.4 是否调用工具
**否**。仅调用 LLM 的 `chat_completion_json`,无 Function Calling。
### 3.5 提示词组织
**System Prompt**`ROUTER_SYSTEM_PROMPT`
- 角色:指令意图分类器
- 意图集合原子意图atomic_takeoff/atomic_land/atomic_hover、业务意图fly_task/search_task/track_task/photo_task/interact_task
- 实体要求locations、targets、direction、distance
- 规则相对描述如「广场东边500米」必须拆分为 `locations=["广场"]`, `direction="东"`, `distance=500`
**User Message**:用户原始指令。
**输出 Schema**`ROUTER_JSON_SCHEMA`
```json
{
"intents": ["string"],
"entities": {
"locations": ["string"],
"targets": ["string"],
"direction": "string",
"distance": number
}
}
```
### 3.6 输出与短路逻辑
- `RouterResult.intents`:解析后的意图列表
- `RouterResult.entities`:实体字典
- `RouterResult.is_fast_path`:若 `intents` 非空且全部属于 `ATOMIC_INTENTS`,则为 `True`,后续 RAG/Composer/Planner/Execution 不执行
---
## 4. Stage 2RAG 检索
### 4.1 职责
- 根据 Router 的 `intents``entities``user_text` 检索上下文
- 地图坐标热表优先冷库ChromaDB map_db兜底
- 规则约束:按 intent 查 rule_db
- Few-shot 示例:用 user_text 向量检索 few_shot_db
- **仅提供基准点坐标**`base_location_coords`),不负责相对坐标计算;相对描述由 LLM 通过 mcp 工具计算
### 4.2 对应代码
- **类**`RAGRetriever`
- **方法**`retrieve_context(intents, entities, user_text) -> dict`
- **文件**[`src/drone_planning/rag/retriever.py`](../src/drone_planning/rag/retriever.py)
### 4.3 调用的 RAG 库
| 库名 | 用途 | 检索方式 |
|------|------|----------|
| **map_db** | 基准点坐标 | metadata 精确匹配 `where={"location": base_loc}` |
| **rule_db** | 规则约束 | metadata 精确匹配 `where={"intent": intent}` |
| **few_shot_db** | Few-shot 示例 | 向量相似度 `query(query_texts=[user_text], n_results=2)` |
### 4.4 是否调用工具
**否**。RAG 不调用 mcp_calc仅提供 `base_location_coords``relative_descriptions`,坐标计算由 LLM 通过 Function Calling 完成。
### 4.5 输出结构
```python
{
"map_context": str,
"rule_context": str,
"few_shot_examples": [...],
"base_location_coords": {loc: {x,y,z}}, # 基准点坐标,不计算相对位置
"relative_descriptions": [ # 相对描述,供 LLM 调用工具
{"target": "广场东边500米", "base": "广场", "direction": "", "distance": 500},
...
]
}
```
---
## 5. Stage 3Layer 2 - Composer动态组装
### 5.1 职责
- 根据 `intents` 裁剪 `node_schema.json`,只保留相关 actions
- 将 RAG 的 `base_location_coords``relative_descriptions``map_context``rule_context``few_shot_examples` 拼入 System Prompt
- 生成发给 Planner LLM 的精简 Prompt
### 5.2 对应代码
- **函数**`build_system_prompt(intents, entities, schema_json, rag_context) -> (str, dict)`
- **文件**[`src/drone_planning/pipeline/composer.py`](../src/drone_planning/pipeline/composer.py)
### 5.3 是否调用 RAG
**否**。Composer 不直接调用 RAG只消费 Retriever 返回的 `rag_context`
### 5.4 是否调用工具
**否**
### 5.5 提示词组织
Prompt 由以下部分顺序拼接:
1. **指令**`_instruction`(来自 node_schema
2. **基准点坐标**:若 `base_location_coords` 非空,输出 `## 基准点坐标 base_location_coordsENU单位米`
3. **可用节点**:裁剪后的 schema JSONactions、conditions、control_flow、decorators
4. **RAG 地图上下文**`rag_context["map_context"]`
5. **RAG 规则约束**`rag_context["rule_context"]`
6. **RAG 示例行为树**`rag_context["few_shot_examples"]` 前 2 条
7. **坐标计算规则**:若用户只说绝对地点,可直接使用 base_location_coords若用户说相对位置必须调用 calculate_relative_coordinate禁止心算
### 5.6 意图到 Actions 映射
```python
INTENT_TO_ACTIONS = {
"fly_task": ["fly_to_waypoint", "fly_sequence", "move_direction"],
"search_task": ["search_pattern", "rotate_search"],
"track_task": ["track_object"],
"photo_task": ["take_photos"],
"interact_task": ["report_message", "manual_confirmation"],
}
```
---
## 6. Stage 4Layer 3 - Planner宏观规划
### 6.1 职责
- 根据 Composer 的 System Prompt 和用户文本,生成行为树 JSON
- 支持 Function CallingLLM 可自主调用 `calculate_relative_coordinate` 计算相对坐标
- 最多 5 轮 Tool 循环,无工具调用时解析最终 JSON 返回
### 6.2 对应代码
- **函数**`plan(system_prompt, user_text, tool_call_log) -> dict`
- **文件**[`src/drone_planning/pipeline/planner.py`](../src/drone_planning/pipeline/planner.py)
### 6.3 是否调用 RAG
**否**。Planner 只消费 Composer 输出的 `system_prompt`,其中已包含 RAG 上下文。
### 6.4 是否调用工具
**是**。坐标计算**仅由 LLM 负责**,通过 OpenAI Function Calling 调用 `calculate_relative_coordinate`mcp 工具。Planner 执行工具并追加结果到 messages继续下一轮推理。
**工具定义**`CALC_COORDINATE_TOOL`
```json
{
"type": "function",
"function": {
"name": "calculate_relative_coordinate",
"description": "根据基准点坐标和方向、距离,计算目标点的绝对 ENU 坐标...",
"parameters": {
"base_x": "number",
"base_y": "number",
"direction_str": "string",
"distance": "number"
}
}
}
```
**工具实现**[`src/drone_planning/tools/mcp_calc.py`](../src/drone_planning/tools/mcp_calc.py) 中的 `calculate_relative_coordinate`
### 6.5 提示词组织
- **System**Composer 生成的完整 Prompt含 schema、坐标、RAG 上下文、工具说明)
- **User**:用户原始指令
- 若 LLM 返回 `tool_calls`:追加 assistant message + 各 tool 结果,继续调用 `chat_completion_with_tools`
- 若 LLM 返回纯文本:解析 JSON 作为行为树
### 6.6 回退逻辑
- 若模型不支持 tools使用 `chat_completion_json` + `PLANNER_JSON_SCHEMA` 无工具模式
- 若 JSON 解析失败:使用 `chat_completion` + `response_format={"type": "json_object"}`
---
## 7. Stage 5Layer 4 - Execution执行包装
### 7.1 职责
- 将 Planner 的 JSON 递归解析为 py_trees 对象
- 根据 Blackboard `is_in_air` 判断:若在地面,自动在业务树前插入 `[SystemCheck -> Takeoff]` 子树
- 输出 ASCII 树结构供展示
### 7.2 对应代码
- **函数**`parse_json_to_tree`, `wrap_and_build_tree`, `tree_to_ascii`
- **文件**[`src/drone_planning/execution/tree_wrapper.py`](../src/drone_planning/execution/tree_wrapper.py)
- **依赖**[`core/blackboard.py`](../src/drone_planning/core/blackboard.py)、[`execution/nodes.py`](../src/drone_planning/execution/nodes.py)
### 7.3 是否调用 RAG
**否**
### 7.4 是否调用工具
**否**
### 7.5 节点映射
| JSON type | py_trees 实现 |
|-----------|---------------|
| Sequence | `py_trees.composites.Sequence` |
| Selector | `py_trees.composites.Selector` |
| Parallel | `py_trees.composites.Parallel` |
| fly_to_waypoint | `FlyToWaypointAction` |
| 其他 action | `GenericAction` |
---
## 8. 坐标计算流程(仅 LLM 负责)
```mermaid
flowchart LR
subgraph RAG [RAG 仅提供基准点]
Router1[Router 抽取 direction+distance]
Retriever1[Retriever 解析复合地点]
MapDB1[查 map_db 得基准坐标]
Composer1[Composer 将 base_location_coords 写入 Prompt]
end
subgraph LLM [LLM 调用 mcp 计算]
Planner1[Planner 收到 Prompt]
LLM1[LLM 调用 calculate_relative_coordinate]
Tool1[mcp 工具]
Result1[工具结果写回 messages]
end
Router1 --> Retriever1
Retriever1 --> MapDB1
MapDB1 --> Composer1
Composer1 --> Planner1
Planner1 --> LLM1
LLM1 --> Tool1
Tool1 --> Result1
```
- **RAG**:仅提供 `base_location_coords`(基准点坐标)和 `relative_descriptions`(相对描述列表),不调用 mcp_calc
- **LLM**:若用户说绝对地点,直接使用 base_location_coords若用户说相对位置必须调用 calculate_relative_coordinate禁止心算
---
## 9. RAG 数据格式
### 9.1 map_db.jsonl
每行一个 JSON字段示例
```json
{"document": "大门位于入口处,坐标 x=0, y=0", "location": "大门", "x": 0, "y": 0, "z": 0}
```
### 9.2 rule_db.jsonl
```json
{"document": "起飞必须先做系统检查", "intent": "fly_task", "priority": "high"}
```
### 9.3 few_shot_db.jsonl
```json
{"document": "飞到大门然后拍照", "intent": "fly_task", "tree_json": "{\"root\": {...}}"}
```
---
## 10. 环境变量与配置
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `LLM_CHAT_BASE_URL` | `http://localhost:8081/v1` | Chat API |
| `LLM_EMBEDDING_BASE_URL` | `http://localhost:8090/v1` | Embedding APIRAG |
| `ENABLE_THINKING` | `false` | 模型思考模式 |
| `CHROMA_PERSIST_PATH` | `./data/chroma` | ChromaDB 存储路径 |
---
## 11. 文件索引
| 功能 | 文件路径 |
|------|----------|
| Router | `src/drone_planning/pipeline/router.py` |
| Composer | `src/drone_planning/pipeline/composer.py` |
| Planner | `src/drone_planning/pipeline/planner.py` |
| RAG Retriever | `src/drone_planning/rag/retriever.py` |
| RAG 向量存储 | `src/drone_planning/rag/vector_store.py` |
| RAG 灌入 | `src/drone_planning/rag/ingestion.py` |
| 坐标计算工具 | `src/drone_planning/tools/mcp_calc.py` |
| 执行包装 | `src/drone_planning/execution/tree_wrapper.py` |
| 节点实现 | `src/drone_planning/execution/nodes.py` |
| 黑板 | `src/drone_planning/core/blackboard.py` |
| LLM 客户端 | `src/drone_planning/llm_client/client.py` |
| API 路由 | `src/drone_planning/api/routes.py` |
| 节点 Schema | `config/node_schema.json` |
| 知识库 | `data/knowledge/*.jsonl` |