20 KiB
DronePlanning 处理 Pipeline 说明
本文档说明当前后端从自然语言输入到计划 JSON 输出的完整处理流程,以及可自定义修改点。
1. 总体流程
入口为 POST /generate_plan,主链路由 GenerationOrchestrator 编排:
flowchart LR
api[main.py /generate_plan] --> gen[py_tree_generator.generate]
gen --> orch[GenerationOrchestrator]
orch --> s1[Stage1 TaskUnderstanding]
orch --> s2[Stage2 ContextBinding]
orch --> s3[Stage3 MacroPlanning]
s3 --> simple{simple?}
simple -->|是| s6[Stage6 Validate]
simple -->|否| s4[Stage4 Middleware]
s4 --> s5[Stage5 MicroFilling]
s5 --> s6
s6 --> out[返回 py_tree JSON]
对应代码:
backend_service/src/main.pybackend_service/src/py_tree_generator.pybackend_service/src/pipeline/orchestrator.pybackend_service/src/pipeline/stages.py
1.1 各 Stage 提示词模板一览
| Stage | 是否调用 LLM | System 模板/片段(按组合顺序) | User 内容 |
|---|---|---|---|
| Stage1 | 是 | prompts/scene_classifier_prompt.txt |
原始 user_prompt |
| Stage2 | 否 | — | — |
| Stage3 | 是 | simple:simple_mode_prompt.txt;complex:macro_header.txt → 裁剪的 core_nodes.json → template_ground.txt / template_air.txt → common_rules.txt → 可选 system_extra_examples.txt → 意图标签 |
user_prompt + 参考知识(地点/模式/规则) |
| Stage4 | 否 | — | — |
| Stage5 | 是 | micro_header.txt → macro_tree JSON → resolved_data JSON → 裁剪的 atomic/nodes_schema.json |
固定句:「请直接输出完整的带有 params 参数的 JSON 树结构。」 |
| Stage6 | 否 | — | — |
各阶段模板的详细组合顺序与条件见对应小节(如 2.3、3.3、4.3、5.3、6.3、7.3)。
1.2 提示词分配流程图
下图按 Stage 标出各阶段使用的提示词模板及组合关系(仅含涉及 LLM 的 Stage):
flowchart TB
subgraph S1["Stage1 任务理解"]
direction TB
P1_sys["system: scene_classifier_prompt.txt"]
P1_usr["user: user_prompt"]
end
subgraph S2["Stage2 上下文绑定"]
P2["无 LLM / 无提示词"]
end
subgraph S3["Stage3 宏观规划"]
direction TB
P3a["simple: system = simple_mode_prompt.txt"]
P3b["complex: system = macro_header → core_nodes → template_ground/air → common_rules → 可选 system_extra_examples → 意图标签"]
P3_usr["user: user_prompt + 参考知识"]
end
subgraph S4["Stage4 中间层解析"]
P4["无 LLM / 无提示词"]
end
subgraph S5["Stage5 微观填参"]
direction TB
P5_sys["system: micro_header → macro_tree JSON → resolved_data JSON → atomic/nodes_schema 裁剪"]
P5_usr["user: 固定句"]
end
subgraph S6["Stage6 校验与后处理"]
P6["无 LLM / 无提示词"]
end
S1 --> S2 --> S3
S3 --> S4 --> S5 --> S6
- Stage1 / Stage3 / Stage5 会调用 LLM,其 System/User 内容由上图对应框内模板或片段组合而成。
- Stage2 / Stage4 / Stage6 不调用 LLM,无提示词分配。
2. Stage1:任务理解(TaskUnderstanding)
功能:
- 场景分类:
simple / scene1 / scene4 - 意图推断:
intent_type - 风险标记:
risk_flags(例如是否需要人工确认、是否涉及相对方位)
核心代码:
backend_service/src/llm/gateway.py::classify_scene()backend_service/src/pipeline/stages.py::_infer_intent_type()backend_service/src/pipeline/stages.py::_extract_risk_flags()- 数据契约:
backend_service/src/pipeline/contracts.py::TaskUnderstanding
说明:
- 分类模型可启用 thinking(由
STAGE1_ENABLE_THINKING控制)。 - 该阶段不依赖节点字典,避免循环依赖。
2.1 输入格式
stage1_task_understanding(user_prompt: str) 仅接受原始用户指令字符串。
示例输入:
{
"user_prompt": "无人机当前在地面,到广场查找绿色公交车,找到后拍照。"
}
2.2 输出格式(TaskUnderstanding)
{
"scene_mode": "scene4",
"intent_type": "search_and_photo",
"requires_relative_target": false,
"entities": {
"raw_prompt": "无人机当前在地面,到广场查找绿色公交车,找到后拍照。"
},
"risk_flags": [],
"constraints": {}
}
字段说明:
scene_mode:simple | scene1 | scene4intent_type: 当前规则推导出的任务意图标签requires_relative_target: 是否检测到相对方位需求entities: 当前为轻量占位(最小包含raw_prompt)risk_flags: 风险标记列表(如needs_manual_confirmation)constraints: 约束占位(当前为空对象)
2.3 本阶段组合的提示词模板
| 角色 | 模板文件 | 路径 | 说明 |
|---|---|---|---|
| system | 场景分类 | prompts/scene_classifier_prompt.txt |
唯一 system 提示词,定义 simple/scene1/scene4 判定规则与示例 |
| user | 用户原文 | 调用方传入的 user_prompt |
不做拼接,直接作为 user 消息 |
组合方式:messages = [ { "role": "system", "content": scene_classifier_prompt }, { "role": "user", "content": user_prompt } ]。分类结果解析为 scene_mode,其余 intent_type、risk_flags 由本阶段规则函数从 user_prompt 推断,不读模板。
3. Stage2:上下文绑定(ContextBinding)
功能:
- 按场景动态决定检索范围(location/pattern/rules)
- 从多知识库并行检索并汇总
- 相对目标提取(
relative_refs) - 预计算航点(
precomputed_waypoints,MVP) - 基于意图与风险推导
required_actions
核心代码:
backend_service/src/retrieval/retriever.py::UnifiedRetrieverbackend_service/src/retrieval/adapters/chroma_adapter.pybackend_service/src/llm/tool_runtime.pybackend_service/src/pipeline/stages.py::stage2_context_binding()- 数据契约:
backend_service/src/pipeline/contracts.py::ContextBinding
多知识库策略:
- 主集合:
location_kb、pattern_kb、rules_kb - 兼容集合:
drone_docs - 若主集合无结果,会尝试从
drone_docs+kb_type过滤回退查询
3.1 输入格式
该阶段接收:
user_prompt: str- Stage1 输出
TaskUnderstanding
示例输入:
{
"user_prompt": "无人机当前在空中,去广场南边40米,持续监控5分钟,发现人就拍照。",
"understanding": {
"scene_mode": "scene4",
"intent_type": "patrol_or_monitor",
"requires_relative_target": false,
"risk_flags": [],
"entities": {"raw_prompt": "无人机当前在空中,去广场南边40米,持续监控5分钟,发现人就拍照。"},
"constraints": {}
}
}
3.2 输出格式(ContextBinding)
{
"location_context": "地点:广场,坐标(x=120,y=30,z=0)...",
"pattern_context": "示例:先到达命名地点,再监控,再条件触发拍照...",
"rules_context": "",
"citations": {
"location": ["..."],
"pattern": ["..."],
"rules": []
},
"resolved_refs": {},
"precomputed_waypoints": [
{"x": 160.0, "y": 30.0, "z": 10.0}
],
"relative_refs": [],
"required_actions": [
"Sequence",
"fly_to_waypoint",
"loiter",
"object_detect",
"object_detected",
"take_photos"
]
}
字段说明:
*_context: 分知识域拼接后的文本上下文citations: 每个知识域的原始命中文档片段precomputed_waypoints: Stage2 静态可解析时的预计算坐标relative_refs: 相对目标结构化描述required_actions: 后续用于节点裁剪注入的动作白名单
3.3 本阶段组合的提示词模板
本阶段不调用 LLM,无提示词模板。仅做检索(Location/Pattern/Rules)、规则推导(required_actions、relative_refs)、预计算航点。
4. Stage3:宏观规划(Macro Planning,Round 1)
功能:
- 组装 prompt(骨架 + 节点裁剪 + 模板 + 规则 + 检索结果)
- 调用对应模型生成宏观树(及可选的 parameter_requests)
- 解析模型响应(含 reasoning 提取)
核心代码:
backend_service/src/prompting/composer.py::PromptComposer.compose_macro()backend_service/src/llm/gateway.py::generate_json()backend_service/src/pipeline/stages.py::stage3_macro_planning()- 数据契约:
backend_service/src/pipeline/contracts.py::BTDraft
关键行为:
- simple 模式与复杂模式使用不同客户端/模型配置;Stage3 强制关闭 thinking,强制
response_format=json_object;节点定义采用裁剪注入(非全量注入)。
4.1 输入格式(Stage3)
该阶段接收:
user_prompt: strTaskUnderstandingContextBinding
核心输入(示例):
{
"scene_mode": "scene4",
"intent_type": "search_and_photo",
"required_actions": ["Sequence", "fly_to_waypoint", "rotate_search", "object_detected", "take_photos"],
"risk_flags": [],
"context_blocks": {
"location": "地点:广场...",
"pattern": "示例:先到达再搜索...",
"rules": ""
}
}
4.2 输出格式(BTDraft)
{
"system_prompt": "...(裁剪后的系统提示词)...",
"user_prompt": "原始指令 + 参考知识增强段",
"allowed_nodes": {
"actions": ["fly_to_waypoint", "rotate_search", "take_photos"],
"conditions": ["object_detected"]
},
"llm_raw_json": {
"root": {
"type": "Sequence",
"name": "Sequence",
"children": [
{"type": "action", "name": "fly_to_waypoint", "params": {"x": 120, "y": 30, "z": 10, "acceptance_radius": 2}},
{"type": "action", "name": "rotate_search", "params": {"target_class": "bus"}},
{"type": "condition", "name": "object_detected", "params": {"target_class": "bus"}},
{"type": "action", "name": "take_photos", "params": {"target_class": "bus", "track_time": 8}}
]
}
},
"reasoning_text": null,
"final_prompt": "=== System Prompt === ... === User Prompt === ..."
}
字段说明:
system_prompt/user_prompt: 实际发给模型的提示词allowed_nodes: 节点裁剪结果(用于调试与复盘)llm_raw_json: 模型返回并解析后的原始计划 JSONreasoning_text: 可选推理文本(若模型返回)final_prompt: 完整组合记录(便于离线排查)
4.3 本阶段组合的提示词模板
simple 模式(单轮,直接出最终树):
| 角色 | 模板/内容 | 路径 | 说明 |
|---|---|---|---|
| system | 简单模式全文 | prompts/simple_mode_prompt.txt |
直接作为 system,无拼接 |
| user | 用户原文 + 参考知识 | 动态 | user_prompt + _build_user_augmentation(context_blocks) |
复杂模式(scene1/scene4,宏观树 Round 1):
System 按顺序拼接以下内容(来自 prompting/composer.py::compose_macro()):
| 顺序 | 模板/内容 | 路径 | 说明 |
|---|---|---|---|
| 1 | 宏观任务头 | prompts/partials/macro_header.txt |
任务定义与输出要求 |
| 2 | 节点定义(裁剪后) | prompts/partials/core_nodes.json |
按 required_actions + risk_flags 裁剪,最多 30 个 action/condition,格式化为「## 一、核心节点定义」+ JSON 代码块 |
| 3 | 任务模板(二选一) | prompts/partials/template_ground.txt 或 prompts/partials/template_air.txt |
由 drone_state(on_ground / in_air)决定 |
| 4 | 通用规则 | prompts/partials/common_rules.txt |
若文件存在则追加 |
| 5 | 额外示例(可选) | prompts/partials/system_extra_examples.txt |
仅当 intent_type == "generic_mission" 时追加 |
| 6 | 意图标签 | 代码生成 | 固定段落:## 任务意图标签\n- intent_type: \{intent_type}`` |
User 消息:
- 内容 =
user_prompt+ 参考知识增强段。 - 参考知识增强段由
_build_user_augmentation(context_blocks)生成:若context_blocks中location/pattern/rules非空,则按顺序拼接为「【地点知识】…」「【任务模式】…」「【规则知识】…」,整体包在---\n参考知识:\n…\n---中。
5. Stage4:中间层解析(Middleware Resolution)
功能:
- 读取 Stage3 输出的
parameter_requests - 对含
landmark等实体的请求做位置检索与航点预计算,写入resolved_data - 其他实体透传为
{node}_entities,供 Stage5 使用
核心代码:
backend_service/src/pipeline/stages.py::stage4_middleware_resolution()- 复用
retriever.retrieve(scopes=["location"])与tool_runtime.build_precomputed_waypoint()
5.3 本阶段组合的提示词模板
本阶段不调用 LLM,无提示词模板。仅做依赖解析与数据绑定。
6. Stage5:微观参数填空(Micro Parameter Filling,Round 2)
功能:
- 从
prompts/atomic/nodes_schema.json按宏观树中用到的节点名裁剪出atomic_schema - 调用
PromptComposer.compose_micro()组装 Round 2 的 system 提示词 - 再次调用模型,输出带完整
params的 JSON 树
核心代码:
backend_service/src/prompting/composer.py::compose_micro()backend_service/src/pipeline/stages.py::stage5_micro_filling()
6.3 本阶段组合的提示词模板
| 角色 | 模板/内容 | 路径 | 说明 |
|---|---|---|---|
| system | 微观任务头 | prompts/partials/micro_header.txt |
第一段 |
| system | 宏观骨架树 | 运行时 | ## 1. 原宏观骨架树 (macro_tree) + draft.macro_tree 的 JSON |
| system | 确切数据字典 | 运行时 | ## 2. 确切数据字典 (resolved_data) + Stage4 输出的 resolved_data JSON |
| system | 原子节点规范 | prompts/atomic/nodes_schema.json(按需裁剪) |
## 3. 原子节点规范 (atomic_schema);仅保留宏观树中出现的 action/condition 的 schema |
| user | 固定指令 | 代码写死 | "请直接输出完整的带有 params 参数的 JSON 树结构。" |
组合方式:system = 上述四段用 \n\n 拼接;user = 固定字符串。Round 2 不再注入 RAG 检索块。
7. Stage6:校验与后处理(ValidateAndPostprocess)
功能:
- JSON Schema 校验(simple / complex)
- 注入
plan_id、visualization_url、final_prompt - 保存推理链与历史记录
- 在复杂场景下注入
context.relative_refs(及可选context.resolved_refs)
核心代码:
backend_service/src/validation/validator.pybackend_service/src/validation/schema_provider.pybackend_service/src/pipeline/stages.py::stage6_validate_and_postprocess()backend_service/src/py_tree_generator.py::render_visualization()backend_service/src/py_tree_generator.py::_save_history()
7.1 输入格式
该阶段接收:
user_prompt: strTaskUnderstandingContextBindingBTDraft- 复杂模式下还有 Stage5 的
final_tree;simple 模式下为draft.llm_raw_json
7.2 输出格式(最终 API 返回)
复杂模式示例:
{
"root": {
"type": "Sequence",
"name": "Sequence",
"children": [
{"type": "action", "name": "fly_to_waypoint", "params": {"x": 120, "y": 30, "z": 10, "acceptance_radius": 2}},
{"type": "action", "name": "rotate_search", "params": {"target_class": "bus"}},
{"type": "condition", "name": "object_detected", "params": {"target_class": "bus"}},
{"type": "action", "name": "take_photos", "params": {"target_class": "bus", "track_time": 8}}
]
},
"context": {
"relative_refs": [
{"anchor": "front_building", "relation": "left", "distance_m": 20.0}
],
"resolved_refs": {
"strategy": "backend_static_resolution",
"waypoints": [{"x": 120.0, "y": 30.0, "z": 10.0}]
}
},
"plan_id": "6a924d0d-f1a7-4ef1-a9fa-31f73f3115ce",
"visualization_url": "/static/py_tree.png",
"final_prompt": "=== System Prompt === ... === User Prompt === ..."
}
simple 模式示例:
{
"root": {
"type": "action",
"name": "move_direction",
"params": {"direction": "north", "distance": 50}
},
"plan_id": "0f0e5e5f-b9a2-4e6f-95f5-c95e9e6280a5",
"visualization_url": "/static/py_tree.png",
"final_prompt": "=== System Prompt === ... === User Prompt === ..."
}
字段说明:
root: 通过 schema 校验后的行为树根节点context: 仅在复杂模式且命中相对目标时追加plan_id: 每次生成唯一 IDvisualization_url: 最新可视化图访问路径final_prompt: 生成时使用的完整提示词记录
7.3 本阶段组合的提示词模板
本阶段不调用 LLM,无提示词模板。仅做校验、注入元数据与写盘。
8. 数据入库(RAG Ingestion)逻辑
入库脚本:
tools/rag/ingest.py
行为:
- 扫描
tools/rag/knowledge_base/ - 根据子目录推断
kb_type(location/pattern/rules) - 同时写入:
drone_docs(兼容)location_kb/pattern_kb/rules_kb(新检索路径)
9. 可自定义修改点(推荐按优先级)
9.1 场景与意图逻辑
可改文件:
backend_service/src/pipeline/stages.py
可改内容:
_infer_intent_type():扩展意图类别_extract_risk_flags():新增风险规则_derive_required_actions():调整规则推导的动作集合
9.2 Prompt 策略
可改文件:
backend_service/src/prompting/composer.pybackend_service/src/prompts/prompt_manifest.yamlbackend_service/src/prompts/partials/*
可改内容:
- 骨架片段选择
- 节点裁剪规则(当前上限 30)
- 示例注入策略(何时注入 extra examples)
- 用户侧检索增强格式
9.3 模型路由与推理参数
可改文件:
backend_service/src/llm/gateway.py
可改内容:
- 分类模型与生成模型分流策略
temperature、max_tokens、重试次数- thinking 开关策略(Stage1/Stage3)
9.4 检索策略
可改文件:
backend_service/src/retrieval/retriever.pybackend_service/src/retrieval/adapters/chroma_adapter.pytools/rag/ingest.py
可改内容:
- 检索并发策略与
top_k - 回退策略(主集合与兼容集合)
- kb_type 划分方式
- 文档切分与 metadata 设计
9.5 相对目标解析
可改文件:
backend_service/src/pipeline/stages.pybackend_service/src/llm/tool_runtime.py
可改内容:
relative_refs抽取规则- 静态解析能力(何时生成
resolved_refs) - 与 UAV 端协议字段兼容策略
9.6 校验与输出协议
可改文件:
backend_service/src/validation/validator.pybackend_service/src/validation/schema_provider.pybackend_service/src/py_tree_generator.py(schema 来源)
可改内容:
- simple/complex schema 约束强度
- 顶层
context字段的可选校验 - 失败错误信息与恢复策略
10. 关键环境变量
ORIN_IPOPENAI_API_KEYCLASSIFIER_MODEL/SIMPLE_MODEL/COMPLEX_MODELCLASSIFIER_BASE_URL/SIMPLE_BASE_URL/COMPLEX_BASE_URLSTAGE1_ENABLE_THINKINGENABLE_REASONING_CAPTUREREASONING_PREVIEW_LINES
11. 自定义改造建议(实践顺序)
- 先改 Stage1 规则推导(低风险,收益快)
- 再改 PromptComposer 的裁剪与注入(控制长度与稳定性)
- 再改检索策略(top_k、回退、metadata)
- 最后改 schema 与输出协议(需联动执行端)
12. 变更后最小回归清单
每次改造后至少验证:
- simple 指令:返回
root.action,且无 children - scene4 指令:有复合树结构,JSON 可解析
- relative 指令:复杂模式下出现
context.relative_refs /generate_plan不变更接口字段(兼容外部调用)python tools/rag/ingest.py可完成入库(或输出可定位错误)