196 lines
6.3 KiB
Markdown
196 lines
6.3 KiB
Markdown
# 无人机行为规划后端系统
|
||
|
||
从自然语言指令到行为树 JSON 的四层流水线系统,支持 RAG 检索、Function Calling 坐标计算、Fast-Path 短路等能力。
|
||
|
||
## 功能概览
|
||
|
||
- **Layer 1 (Router)**:意图分类与实体抽取,支持原子指令(起飞/降落/悬停)Fast-Path 短路
|
||
- **RAG 检索**:地图基准点坐标、规则约束、Few-shot 示例(不负责相对坐标计算)
|
||
- **Layer 2 (Composer)**:根据意图裁剪 schema,组装精简 System Prompt
|
||
- **Layer 3 (Planner)**:LLM 生成行为树 JSON,**仅 LLM 通过 mcp 工具计算坐标**(绝对地点用 base_location_coords,相对位置必须调用工具,禁止心算)
|
||
- **Layer 4 (Execution)**:解析 JSON 为 py_trees,根据 `is_in_air` 自动插入起飞逻辑
|
||
|
||
## 环境要求
|
||
|
||
- Python 3.10+
|
||
- 本地 LLM 服务(llama-server 或兼容 OpenAI API 的服务):
|
||
- **Chat**:默认 `http://localhost:8081/v1`
|
||
- **Embedding**:默认 `http://localhost:8090/v1`(RAG 用)
|
||
|
||
## 快速部署
|
||
|
||
### 1. 克隆与依赖
|
||
|
||
```bash
|
||
cd DronePlanningV2
|
||
pip install -e .
|
||
# 或
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
### 2. 配置 LLM 服务
|
||
|
||
确保 Chat 和 Embedding 服务已启动。可通过环境变量覆盖默认地址:
|
||
|
||
```bash
|
||
export LLM_CHAT_BASE_URL="http://localhost:8081/v1"
|
||
export LLM_EMBEDDING_BASE_URL="http://localhost:8090/v1"
|
||
export OPENAI_API_KEY="not-needed" # 本地部署通常不需要
|
||
```
|
||
|
||
可选:开启模型思考模式(默认关闭以降低延迟):
|
||
|
||
```bash
|
||
export ENABLE_THINKING=true
|
||
```
|
||
|
||
### 3. RAG 知识库灌入
|
||
|
||
**必须先启动 Embedding 服务**(默认 `http://localhost:8090/v1`)。灌入会向该地址请求向量;未启动会出现 `Connection refused`。可与 Chat 一并启动:
|
||
|
||
```bash
|
||
bash run_api.sh # 含 8081 Chat + 8090 Embedding,待终端出现 listening 后再灌入
|
||
```
|
||
|
||
**包位于 `src/` 下**,灌入命令任选其一:
|
||
|
||
```bash
|
||
# 方式 A:已执行 pip install -e . 时
|
||
python -m drone_planning.rag.ingestion
|
||
|
||
# 方式 B:未安装包时,需指定 PYTHONPATH(与 run_api.sh 一致)
|
||
PYTHONPATH=src python -m drone_planning.rag.ingestion
|
||
```
|
||
|
||
Embedding 地址可通过环境变量覆盖:`export LLM_EMBEDDING_BASE_URL=http://主机:端口/v1`
|
||
|
||
知识库文件位于 `data/knowledge/`:
|
||
|
||
- `map_db.jsonl`:地点坐标(location, x, y, z)
|
||
- `rule_db.jsonl`:规则约束(intent, document)
|
||
- `few_shot_db.jsonl`:Few-shot 示例(instruction, tree_json)
|
||
|
||
### 4. 启动 API 服务
|
||
|
||
项目根目录下需让 Python 能找到 `src/drone_planning`(已 `pip install -e .` 可省略):
|
||
|
||
```bash
|
||
PYTHONPATH=src python -m uvicorn main:app --reload --host 0.0.0.0 --port 8000
|
||
```
|
||
|
||
### 5. 启动 Playground 测试台
|
||
|
||
```bash
|
||
streamlit run playground.py
|
||
```
|
||
|
||
## 使用方式
|
||
|
||
### API 调用
|
||
|
||
```bash
|
||
# 复杂任务(走完整流水线)
|
||
curl -X POST http://localhost:8000/api/plan \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"text": "飞到大门然后拍照"}'
|
||
|
||
# 原子指令(Fast-Path 短路)
|
||
curl -X POST http://localhost:8000/api/plan \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"text": "起飞"}'
|
||
|
||
# 相对描述(RAG 提供基准点,LLM 调用 mcp 计算)
|
||
curl -X POST http://localhost:8000/api/plan \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"text": "飞到广场东边500米"}'
|
||
```
|
||
|
||
响应示例(含各环节耗时 `timing_ms`):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"fast_path": false,
|
||
"intents": ["fly_task", "photo_task"],
|
||
"entities": {"locations": ["大门"], "targets": []},
|
||
"rag_context": {...},
|
||
"tool_call_log": [...],
|
||
"tree_json": {"root": {...}},
|
||
"tree_ascii": "...",
|
||
"timing_ms": {
|
||
"Layer1_Router": 120,
|
||
"RAG_检索": 45,
|
||
"Layer2_Composer": 2,
|
||
"Layer3_Planner": 3500,
|
||
"Layer4_Execution": 1
|
||
}
|
||
}
|
||
```
|
||
|
||
### Playground 测试
|
||
|
||
1. 打开 `http://localhost:8501`
|
||
2. 左侧边栏:切换「是否在空中」模拟起飞状态
|
||
3. 主界面:输入自然语言指令,点击「执行规划」
|
||
4. 查看:各环节耗时、Layer 1~4 输出、RAG 检索结果、LLM Tool Call 日志(坐标仅由 LLM 通过 mcp 计算)
|
||
|
||
### 命令行测试 Router
|
||
|
||
```bash
|
||
python -m drone_planning.pipeline.router "飞到大门然后拍照"
|
||
```
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
DronePlanningV2/
|
||
├── config/
|
||
│ └── node_schema.json # 行为树节点定义
|
||
├── data/
|
||
│ └── knowledge/ # RAG 知识库 jsonl
|
||
│ ├── map_db.jsonl
|
||
│ ├── rule_db.jsonl
|
||
│ └── few_shot_db.jsonl
|
||
├── src/drone_planning/
|
||
│ ├── api/ # FastAPI 路由
|
||
│ ├── core/ # Blackboard 黑板
|
||
│ ├── execution/ # py_trees 解析与包装
|
||
│ ├── llm_client/ # Chat / Embedding 客户端
|
||
│ ├── pipeline/ # Router / Composer / Planner
|
||
│ ├── rag/ # 向量存储、检索、灌入
|
||
│ └── tools/ # mcp_calc 坐标计算
|
||
├── main.py # API 入口
|
||
├── playground.py # Streamlit 测试台
|
||
├── requirements.txt
|
||
└── pyproject.toml
|
||
```
|
||
|
||
## 环境变量汇总
|
||
|
||
| 变量 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `LLM_CHAT_BASE_URL` | `http://localhost:8081/v1` | Chat API 地址 |
|
||
| `LLM_EMBEDDING_BASE_URL` | `http://localhost:8090/v1` | Embedding API 地址 |
|
||
| `OPENAI_API_KEY` | `not-needed` | API Key |
|
||
| `ENABLE_THINKING` | `false` | 是否开启模型思考模式 |
|
||
| `CHROMA_PERSIST_PATH` | `./data/chroma` | ChromaDB 持久化路径 |
|
||
| `EMBEDDING_MODEL` | `qwen3-embedding` | Embedding 模型名 |
|
||
|
||
## 常见问题
|
||
|
||
**Q: ChromaDB 报错?**
|
||
A: 确保已安装 `chromadb>=0.4.0`,首次运行需执行 `python -m drone_planning.rag.ingestion`。
|
||
|
||
**Q: LLM 调用超时?**
|
||
A: 检查 `LLM_CHAT_BASE_URL` 是否可达,模型是否支持 `json_schema` / `tools`。
|
||
|
||
**Q: 相对坐标未计算?**
|
||
A: 确保 `map_db.jsonl` 中有基准点(如「广场」),Router 正确抽取 `direction`、`distance`,且 LLM 支持 Function Calling 调用 `calculate_relative_coordinate`。
|
||
|
||
**Q: 如何扩展知识库?**
|
||
A: 编辑 `data/knowledge/*.jsonl` 后重新执行 `python -m drone_planning.rag.ingestion`。
|
||
|
||
## 详细流程文档
|
||
|
||
完整项目流程、各 Stage 对应代码、RAG 调用、工具调用、提示词组织等详见:[docs/项目流程详解.md](docs/项目流程详解.md)
|