MINARA

深度研究流水线

生成结构化市场报告的隔离式六步流水线

深度研究是一条专用流水线,与主 Agent 循环并行运行,但相互独立。主 Agent 循环以对话形式推进,并受权限管控;深度研究流水线则是一个六步状态机,最终产出一份结构化报告。实现位于 apps/agent/src/deep-research/pipeline.ts

为何单独设计流水线,而不让 Agent 循环迭代? 多源研究需要并行采集数据(扇出后合并)、LLM-as-Judge 质量检查,以及重试逻辑。这些需求与对话式 plan → call → observe 节奏不符。专用流水线还能保证研究输出的确定性与可溯源性,这是对话循环无法做到的。

查看实际效果功能 → 深度研究 介绍了面向用户的一侧,包含报告输出示例。

适用场景

当目标是生成书面产物而非聊天回答时,使用此流水线:

  • 针对特定资产或主题的长篇市场分析。
  • 需要为每项论断注明来源的多源综合报告。
  • 定时研究任务,希望获得可通过 id 查阅的产物。

对于快速对话问题("BTC 现价是多少"、"这里应该做多吗"),请使用 Agent 循环。深度研究流水线延迟更高、工具调用预算固定,且不保留当前对话的上下文。

六个步骤

deep-research diagram

collectData 外,每个步骤都是单次 LLM 调用。collectData 会针对每个目标,在工具注册表上运行一个子 Agent 循环。

与主 Agent 循环的隔离

流水线刻意保持隔离

  • 不读取聊天的对话历史。
  • 不消耗技能系统的激活状态。
  • 为数据采集自行构建一套精简工具子集,而不使用当前激活的技能。
  • 不触发学习记录(review-engine 不会在流水线轮次中运行)。

隔离带来两项收益:确定性(每次研究任务从相同状态出发);成本管控(长会话的历史不会渗入研究成本)。

模式

interface ResearchRequest {
  chatId: string;
  userMessage: string;
  mode?: "light" | "heavy";
  language?: string;
}
  • light(默认)。2 个并行采集目标,较小的最大迭代数,单遍报告生成。典型延迟:30–60 秒。
  • heavy。4 个并行采集目标,更大的迭代预算,综合分析更深入。典型延迟:2–5 分钟。

定时/cron 研究任务选 light;用户明确要求深度报告时选 heavy

场景

报告围绕场景组织,即预定义的分析角度,例如"多方观点"、"空方观点"、"基准情形"、"监管风险"、"宏观背景"。metaPlan 步骤根据研究主题,从 apps/agent/src/deep-research/scenarios.ts 的目录中选取 1–4 个场景。

场景选择对报告质量至关重要:缺少"宏观"场景的 BTC 研究报告往往遗漏最重要的背景信息;缺少"空方观点"则会产生确认偏差。目录刻意保持精简,以确保 LLM 场景选择器的可靠性。

输出产物

结果以 report 类型产物存储在 ArtifactStore 中:

interface ResearchResult {
  report_id: string;
  status: "completed" | "error" | "waiting_for_input";
  title: string | null;
  research_topic: string | null;
  scenarios: string[];
  summary: string | null;
  key_findings: string[];
  report_markdown: string | null;
  error?: string;
  tokens: { input: number; output: number };
}

主 Agent 可通过 report://{id} URI 方案将已完成的报告引用给用户。这就是将研究与对话结合的方式:用户请求研究,获得 report_id,随后在聊天中提出引用该报告的后续问题。

报告正文为 Markdown 格式,包含场景标题、行内引用(通过 [text](url)),以及由 summarize 步骤生成的"关键发现"要点列表。

运行方式

在 REPL 中运行

主 Agent 激活 deep-research 领域技能,调用 deep_research_run 工具:

> write me a report on ETH staking yields this quarter
assistant: [activates deep-research skill]
assistant: [calls deep_research_run with mode=heavy]
assistant: ✓ report_id: r_abc123 — here's the summary…

使用 CLI 子命令运行

完全绕过 REPL:

minara research "BTC ETF flows this quarter"
minara research "macro risks for Solana" --mode heavy

完整参数列表见 子命令 → minara research

通过 HTTP 请求运行

curl -X POST http://localhost:8080/research \
  -H 'content-type: application/json' \
  -d '{"topic": "BTC ETF flows", "mode": "light"}'

请求与响应结构见 API → /research

成本与可观测性

每个步骤都会在审计日志中以 source: "deep-research" 记录 {provider, model, tokens}ResearchResult 上的 tokens 字段是用于快速核算成本的汇总估算值。如需精确的成本归因,可查询审计日志:

SELECT model, SUM(input_tokens), SUM(output_tokens), COUNT(*)
  FROM audit
 WHERE source = 'deep-research'
   AND trace_id = ?
 GROUP BY model;

深度研究流水线是大多数 Minara 部署中单次 LLM 成本最高的环节。若账单异常偏高,通常先运行此查询排查。

扩展流水线

流水线刻意保持精简(pipeline.ts 约 700 行)。常见扩展方式:

  • 新增场景:在 scenarios.ts 中追加到目录。元计划提示词在运行时读取目录,无需修改提示词。
  • 调整采集并发数:在 PipelineConfig 中设置 collectConcurrency。默认值为 4,与 v1 上限一致。
  • 调整每个目标的最大迭代数:设置 collectMaxIterations。默认值为 8,即每个数据采集子 Agent 的 LLM 轮次预算。
  • 新增后处理步骤:在流水线类中追加一个方法,在 summarize 与返回之间调用。不要将逻辑内联到已有步骤中;步骤边界是流水线可调试性的保障。

不要将流水线接入主 Agent 循环的历史记录。隔离是设计特性;一旦破坏,聊天成本将渗入研究成本。

不适合放入研究的内容

  • 依赖实时价格的决策。 流水线耗时数分钟,价格随时变动。任何依赖当前执行条件的操作,请使用 Agent 循环。
  • 涉及资金的工具调用。 数据采集使用的精简工具子集排除了所有涉及资金的工具。若工具子集意外包含此类工具,流水线将拒绝运行。
  • 用户私人上下文。 流水线不读取用户的钱包余额或历史记录,仅面向公开市场数据。若报告需要考虑用户的具体仓位,请在 bootstrap 阶段将仓位信息放入用户消息;流水线会将其传递至后续步骤。

本页目录