Files
DronePlanningV2/docs/项目流程详解.md
2026-03-17 10:51:32 +08:00

392 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 无人机行为规划系统 - 项目流程详解
---
## 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` |