10 KiB
无人机行为规划后端系统(重建版)需求说明
目标:基于端侧 Qwen3-4B(llama-server)和行为树,重建一个从自然语言到无人机行为树 JSON 的后端系统,支持未来扩展 RAG 和动态语义地图。
一、总体架构理念(务必遵守)
-
大小脑解耦
- 大模型(4B,小模型) = 「大脑」:只做语义理解、意图拆解、行为树结构生成,不直接管起飞/降落/避障。
- Python + py_trees + PX4/仿真 = 「小脑」:负责状态机管理、物理安全、控制执行(起飞、悬停、返航等)。
-
四层流水线结构
-
🔴 Layer 0:感知层(Perception & State)
纯代码。维护一个全局状态黑板DroneStateBlackboard,至少包含:is_in_air: boolposition: {x, y, z}(ENU)- 后续可扩展电量、模式等。
-
🟡 Layer 1:意图路由层(Stage 1 Intent Router)
调用 LLM 做极简意图分类和实体抽取,只输出:intents: list[str]entities: dict并实现 Fast-Path 短路机制:- 若指令是纯原子控制(如“起飞”、“降落”、“悬停”),直接由代码执行,不进入规划阶段。
-
🟢 Layer 2:动态组装与外部计算(Dynamic Composer & MCP/RAG)
纯代码。- 根据
intents和entities,从本地node_schema.json裁剪出最小必要的节点定义(行为树节点)。 - 使用工具(后续接 RAG)解析地点到坐标(ENU),大模型不做算术。
- 生成发给 Stage 2 LLM 的 精简 System Prompt。
- 根据
-
🔵 Layer 3:宏观行为规划(Stage 2 Macro Planner)
调用 LLM(Qwen3-4B):- 输入:Layer 2 生成的 System Prompt + 用户原文(含 RAG 上下文)。
- 输出:业务行为树 JSON(不包含起飞/降落)。
-
🟣 Layer 4:执行包装与安全逻辑(Execution Wrapper)
纯代码 + py_trees:- 将业务树解析为 py_trees 对象。
- 如果
is_in_air == False,自动在业务树前面插入[SystemCheck -> Takeoff]子树。 - 提供 tick 循环和未来的中断(用户打断、动态重规划)预留。
二、节点定义(给 LLM 的行为树节点池)
请在 config/node_schema.json 定义一个简洁的行为节点池(LLM 可见的动作),结构类似:
{
"_instruction": "作为行为树规划器,你只能使用以下定义的节点和参数。",
"actions": {
"fly_to_waypoint": { "desc": "...", "params": { "x": "float", "y": "float", "z": "float" } },
"fly_sequence": { "desc": "...", "params": { "waypoints": "array of {x,y,z}" } },
"move_direction": { "desc": "...", "params": { "direction": "front|back|left|right|up|down", "distance": "float" } },
"search_pattern": { "desc": "...", "params": { "pattern_type": "spiral|grid", "radius": "float", "target_class": "string" } },
"rotate_search": { "desc": "...", "params": { "target_class": "string" } },
"track_object": { "desc": "...", "params": { "target_class": "string", "track_time": "float" } },
"take_photos": { "desc": "...", "params": { "target_class": "string", "count": "int" } },
"report_message": { "desc": "...", "params": { "message": "string" } },
"manual_confirmation": { "desc": "...", "params": { "prompt_message": "string" } }
},
"conditions": {
"object_detected": { "desc": "...", "params": { "target_class": "string" } }
},
"control_flow": {
"Sequence": { "desc": "...", "params": {}, "requires_children": true },
"Selector": { "desc": "...", "params": {}, "requires_children": true },
"Parallel": { "desc": "...", "params": { "policy": "success_on_one|success_on_all" }, "requires_children": true }
},
"decorators": {
"Timeout": { "desc": "...", "params": { "max_time": "float" }, "requires_child": true },
"Repeat": { "desc": "...", "params": { "times": "int" }, "requires_child": true }
}
}
注意:起飞/降落等底层动作不要出现在这里,由 Layer 4 包装硬编码处理。
三、Stage 1 Intent Router 的设计(重点)
1. LLM 提示词(Router System Prompt)
要求使用简洁、正交的 Intent 集合(避免同义词过多):
-
原子意图(Atomic Intents):仅用于 Fast-Path
atomic_takeoffatomic_landatomic_hover
-
业务意图(Business Intents)
fly_task:所有涉及空间移动/路径/巡逻search_task:搜索/侦查track_task:跟踪photo_task:拍照interact_task:上报/请求确认
实体提取要求:
-
地点实体统一用
"locations",且必须为列表:{"locations": ["大门"]}{"locations": ["大门", "广场"]}(支持“先去A再去B”)
-
目标实体用
"targets"列表:{"targets": ["汽车", "行人"]}
-
其他参数如
"direction","distance"直接提取。
2. Python 层的“硬编码冲突处理”逻辑
在 pipeline/router.py 中:
- 定义集合:
ATOMIC_INTENTS = {"atomic_takeoff", "atomic_land", "atomic_hover"}
BUSINESS_INTENTS = {"fly_task", "search_task", "track_task", "photo_task", "interact_task"}
-
处理流程:
-
若
intents非空且 全部属于 ATOMIC_INTENTS:
→ 允许 Fast-Path(直接执行原子命令)。 -
若
intents同时包含 atomic 和 business(如["atomic_takeoff", "fly_task"]):
→ 删除所有 atomic,仅保留 business,走正常规划(起飞由 Layer 4 自动包装)。 -
若
intents为空或包含未识别标签(小模型幻觉):
→ 兜底为["fly_task", "search_task"],保证系统不崩。
-
四、RAG 模块设计(Layer 2 可选扩展)
1. 目录结构
src/drone_planning/rag/:
embedding_client.py:封装 Qwen Embedding(llama-server 8090)。vector_store.py:ChromaDB 客户端,管理三个 Collection:map_dbrule_dbfew_shot_db
retriever.py:RAGRetriever:dynamic_memory:热数据表占位(未来语义地图)。retrieve_context(intents, entities, user_text) -> dict
ingestion.py:从data/knowledge/*.jsonl读 NDJSON 灌入 ChromaDB。schemas.py(可选):约定 JSONL 字段结构。
2. JSONL 格式约定(统一用 .jsonl,一行一 JSON)
data/knowledge/map_db.jsonl:
{"document": "喷泉在广场正中央,坐标 x=10, y=20", "location": "喷泉", "x": 10, "y": 20, "z": 0}
{"document": "A区是禁飞区,不得进入", "location": "A区", "zone_type": "no_fly"}
data/knowledge/rule_db.jsonl:
{"document": "夜间巡逻必须开启热成像", "intent": "search_task", "scene": "night"}
{"document": "起飞必须先做系统检查", "intent": "fly_task", "priority": "high"}
data/knowledge/few_shot_db.jsonl:
{"document": "飞到大门然后拍照", "intent": "fly_task", "tree_json": "{\"root\": {...}}"}
3. 检索策略(在 retriever.py)
-
热数据优先(Dynamic Semantic Map):
dynamic_memory = {"locations": {...}, "targets": {...}}- 若某 location 在热内存中有坐标,直接返回,不要查 ChromaDB。
-
冷库次之(ChromaDB):
- 根据
entities["locations"]和intents用 metadata + 向量检索,从map_db和rule_db获取上下文。 - 使用
user_text在few_shot_db中查 1–2 个相似任务的行为树,作为 few-shot 示例。
- 根据
RAG 返回统一结构:
{
"map_context": "若干行文本或结构化信息",
"rule_context": "规则文本汇总",
"few_shot_examples": [
{"instruction": "...", "tree_json": {...}},
...
]
}
4. 与 Composer 集成(pipeline/composer.py)
-
为
build_system_prompt(...)增加参数rag_context: dict | None。 -
在 Prompt 中插入三个区块(若非空):
## RAG 地图上下文## RAG 规则约束## RAG 示例行为树
-
坐标解析优先级:
- 动态内存(语义地图,未来接入)。
- RAG 地图(map_db 的 x,y,z)。
- geo.py 的硬编码
landmark_to_enu()(兜底,不删除,作为最后一层 fallback)。
五、执行包装层(Layer 4,execution)
1. 行为节点实现(execution/nodes.py)
实现继承自 py_trees.behaviour.Behaviour 的 Mock 节点:
SystemCheckConditionTakeoffActionLandActionFlyToWaypointActionGenericAction(兜底)
目前只打印日志并返回 SUCCESS,后续预留 ROS2/PX4 接口。
2. 树包装与 Tick 循环(execution/tree_wrapper.py)
parse_json_to_tree(node_dict):递归将 Planner 的 JSON 转换为 py_trees 树。wrap_and_build_tree(business_tree):- 读取
DroneStateBlackboard.is_in_air:- 若
False:创建Sequence("Safe_Execution"),依次添加:SystemCheckCondition()TakeoffAction()business_tree
- 若
True:直接返回business_tree。
- 若
- 读取
六、API 接口与 Orchestrator
- 使用 FastAPI 暴露
POST /api/plan:- 输入:
{"text": "用户自然语言指令"}。 - 调用顺序:
- Layer 1 Router:若 Fast-Path,直接返回执行结果。
- 否则,调用 RAG → Composer → Planner → Tree Wrapper,返回行为树 JSON 和日志。
- 输入:
七、请 Cursor 的工作顺序建议
- 生成项目目录和基础依赖(
requirements.txt,pyproject.toml)。 - 实现:
core/blackboard.pyllm_client/client.py(指向http://localhost:8080/v1for chat,http://localhost:8090/v1for embeddings 可在 embedding_client 中配置)
- 实现
config/node_schema.json。 - 实现
pipeline/router.py(含 intents/entities 提取与 Fast-Path 短路 + 冲突处理)。 - 实现
tools/geo.py(仅作为 fallback 静态坐标表)。 - 实现
rag/*(embedding_client, vector_store, ingestion, retriever)。 - 实现
pipeline/composer.py和pipeline/planner.py(加入 rag_context)。 - 实现
execution/nodes.py和execution/tree_wrapper.py。 - 实现
api/routes.py和main.py。 - 最后补充简单的
tests/或手动 curl 示例。
请从目录结构 + 模块职责开始规划,确认后再逐步生成代码。