一款面向专业用户的桌面端深度调研 Agent,类似 Cursor 的交互体验,但核心能力是:自动拆解调研任务 → 多源并行搜索 → 数据提取与验证 → 沙箱分析与绘图 → 生成带溯源引用的研究报告。
核心差异化:不是简单的"搜索+总结",而是一个具备自我优化指令、循环审校、长期记忆、全链路可观测的工业级系统。
| 层级 | 职责 | 主选方案 | 备选方案 | 选型理由 |
|---|---|---|---|---|
| 桌面客户端 | PC 端交互界面 | Electron + React + Monaco Editor | Tauri + Vue | 类 Cursor 体验,生态成熟,插件丰富 |
| 逻辑编排 | Agent 状态机与工作流 | LangGraph | PydanticAI / CrewAI | 支持循环、检查点、回滚,唯一支持复杂有向图的框架 |
| 深度搜索 | 多源并行调研 | GPT Researcher | Open Deep Research (LangChain) | 最成熟的开源深度调研 Agent,17k+ stars,支持递归树状探索 |
| 指令优化 | Prompt 自动编译 | DSPy (GEPA 优化器) | Arize Prompt Learning / TextGrad | 编译时优化,自动生成最优 prompt,样本效率极高 |
| 工具连接 | 外部系统对接 | MCP + LangChain Tools 降级 | 纯 LangChain Tools | MCP 是 2025 新标准,LangChain Tools 作为成熟降级方案 |
| 结构化提取 | 数据抽取与验证 | Instructor (Pydantic) | — | 模型无关,社区最活跃,类型安全 |
| 溯源高亮 | 证据定位与可视化 | LangExtract | — | 字符级精确溯源,交互式高亮可视化 |
| 代码沙箱 | 安全执行分析代码 | E2B Code Interpreter | Docker 隔离沙箱 | 云端隔离,支持任意 Python 库,完成后回传结果 |
| 长期记忆 | 用户偏好与经验积累 | Mem0 (轻量) / Zep (企业级) | Letta (MemGPT) | Mem0 部署快准确率高;Zep 有时序知识图谱 |
| 可观测性 | 全链路追踪与评估 | Langfuse | LangWatch / LangSmith | 开源,支持 token/延迟/成本追踪,自托管 |
| 安全护栏 | 输出验证与过滤 | Guardrails AI | NeMo Guardrails | 灵活的验证规则引擎,支持自定义 validator |
| 后端服务 | API 与任务调度 | FastAPI + Celery + Redis | — | 异步任务队列,支持长时间运行的调研任务 |
| 数据库 | 持久化存储 | PostgreSQL + pgvector | — | 关系数据 + 向量搜索一体化 |
| 消息通信 | 前后端实时通信 | WebSocket (Socket.IO) | SSE | 双向通信,实时推送调研进度 |
┌─────────────────────────────────────────────────────────────────┐
│ Electron Desktop Client │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
│ │ 对话面板 │ │ 报告预览 │ │ 知识库 │ │ 设置/偏好面板 │ │
│ │ (Chat) │ │ (Report) │ │ (KB) │ │ (Settings) │ │
│ └─────┬────┘ └─────┬────┘ └─────┬────┘ └───────┬────────┘ │
│ └──────────────┴──────────────┴──────────────┘ │
│ │ WebSocket / REST │
└───────────────────────────┼──────────────────────────────────────┘
│
┌───────────────────────────┼──────────────────────────────────────┐
│ Backend Service Layer │
│ │ │
│ ┌────────────────────────▼─────────────────────────────────┐ │
│ │ FastAPI Gateway + Auth │ │
│ └────────────────────────┬─────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────▼─────────────────────────────────┐ │
│ │ LangGraph Orchestrator (状态机) │ │
│ │ │ │
│ │ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌───────────┐ │ │
│ │ │ DSPy │ │ GPT │ │ E2B │ │ Instructor│ │ │
│ │ │ Prompt │→ │Researcher│→ │ Sandbox │→ │ +Lang │ │ │
│ │ │ Compile │ │ Search │ │ Analyze │ │ Extract │ │ │
│ │ └─────────┘ └──────────┘ └─────────┘ └───────────┘ │ │
│ │ │ │ │ │
│ │ ▼ ┌──────────┐ ▼ │ │
│ │ ┌─────────┐ │ Guard- │ ┌───────────────┐ │ │
│ │ │ Mem0/ │ │ rails AI │ │ Review Agent │ │ │
│ │ │ Zep │ │ 安全过滤 │ │ 质量审校循环 │ │ │
│ │ │ Memory │ └──────────┘ └───────────────┘ │ │
│ │ └─────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────▼─────────────────────────────────┐ │
│ │ Langfuse (全链路 Trace & Eval) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌────────────┐ ┌─────────────┐ │
│ │PostgreSQL│ │ Redis │ │ Celery │ │
│ │+pgvector │ │ (Cache/MQ) │ │ (Task Queue)│ │
│ └──────────┘ └────────────┘ └─────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
┌───────┴────────┐
│ MCP Protocol │
│ ┌────┐ ┌────┐ │
│ │本地 │ │远程 │ │
│ │文件 │ │API │ │
│ │DB │ │搜索 │ │
│ └────┘ └────┘ │
└────────────────┘
用户输入 → DSPy GEPA 编译器 → 生成最优 Prompt → 传入 LangGraph
DSPy 配置:
import dspy
# 定义调研任务的 Signature
class ResearchTaskDecomposition(dspy.Signature):
"""将用户的调研需求拆解为可执行的子任务列表"""
user_query: str = dspy.InputField(desc="用户的原始调研需求")
context: str = dspy.InputField(desc="用户历史偏好和上下文")
subtasks: list[str] = dspy.OutputField(desc="拆解后的子任务列表")
search_queries: list[str] = dspy.OutputField(desc="每个子任务对应的搜索关键词")
output_format: str = dspy.OutputField(desc="推荐的报告格式")
# 使用 GEPA 优化器自动编译最优指令
optimizer = dspy.GEPA(
metric=research_quality_metric,
max_iterations=50,
num_candidates=10,
)
compiled_module = optimizer.compile(
ResearchTaskDecomposition(),
trainset=training_examples,
valset=validation_examples,
)from langgraph.graph import StateGraph, END
from langgraph.checkpoint.postgres import PostgresSaver
# 定义全局状态
class ResearchState(TypedDict):
query: str # 原始查询
subtasks: list[str] # 拆解后的子任务
raw_sources: list[Document] # 原始搜索结果
extracted_data: list[Evidence] # 结构化提取数据
charts: list[ChartOutput] # E2B 生成的图表
draft_report: str # 草稿报告
review_score: float # 审校评分
review_feedback: str # 审校反馈
iteration: int # 当前迭代次数
final_report: str # 最终报告
# 构建状态图
graph = StateGraph(ResearchState)
graph.add_node("decompose", decompose_task) # DSPy 任务拆解
graph.add_node("search", deep_research) # GPT Researcher 搜索
graph.add_node("extract", extract_evidence) # Instructor + LangExtract
graph.add_node("analyze", sandbox_analysis) # E2B 沙箱分析
graph.add_node("draft", generate_report) # 报告生成
graph.add_node("review", quality_review) # 审校 Agent
graph.add_node("personalize", apply_preferences) # Mem0 个性化
# 编排边
graph.add_edge("decompose", "search")
graph.add_edge("search", "extract")
graph.add_edge("extract", "analyze")
graph.add_edge("analyze", "draft")
graph.add_edge("draft", "review")
# 条件边:审校不通过则回滚
graph.add_conditional_edges(
"review",
lambda state: "search" if state["review_score"] < 0.8
and state["iteration"] < 3
else "personalize",
)
graph.add_edge("personalize", END)
# 持久化检查点
checkpointer = PostgresSaver.from_conn_string(DATABASE_URL)
app = graph.compile(checkpointer=checkpointer)from gpt_researcher import GPTResearcher
async def deep_research(state: ResearchState) -> ResearchState:
all_sources = []
# 为每个子任务并行调研
tasks = []
for subtask in state["subtasks"]:
researcher = GPTResearcher(
query=subtask,
report_type="research_report",
config_path="./research_config.json",
# 可配置搜索引擎:Tavily, Serper, Bing, Google
# 可配置 LLM:GPT-4, Claude, 本地模型
)
tasks.append(researcher.conduct_research())
# 并行执行所有子任务的调研
results = await asyncio.gather(*tasks)
for result in results:
all_sources.extend(result.sources)
state["raw_sources"] = deduplicate(all_sources)
return stateimport instructor
from pydantic import BaseModel, Field
import langextract as lx
# --- 第一层:Instructor 做结构化提取 ---
class ResearchEvidence(BaseModel):
"""从原文中提取的结构化证据"""
claim: str = Field(description="核心论断")
metric: str | None = Field(description="关键数据指标,如增长率、金额")
source_title: str = Field(description="来源标题")
source_url: str = Field(description="来源 URL")
confidence: float = Field(ge=0, le=1, description="置信度")
client = instructor.from_anthropic(anthropic_client)
evidences = client.chat.completions.create(
model="claude-sonnet-4-5-20250929",
response_model=list[ResearchEvidence],
messages=[{
"role": "user",
"content": f"从以下文档中提取关键证据:\n{source_text}"
}]
)
# --- 第二层:LangExtract 做字符级溯源高亮 ---
model = lx.GoogleGenAI(model_name="gemini-2.0-flash")
# 或使用 Ollama 本地模型
# model = lx.Ollama(model_name="gemma3:12b", url="http://localhost:11434")
prompt = lx.Prompt(
description="提取研究报告中的关键数据指标及其原文出处",
examples=[example_input_output], # few-shot 示例
)
results = lx.extract(
text=source_text,
prompt=prompt,
model=model,
num_passes=2, # 多次扫描提高召回率
)
# results 包含每个提取项的 char_offset,可在前端高亮显示from e2b_code_interpreter import Sandbox
async def sandbox_analysis(state: ResearchState) -> ResearchState:
sandbox = Sandbox()
# 上传数据到沙箱
for data in state["extracted_data"]:
sandbox.files.write(f"/data/{data.filename}", data.content)
# 执行分析代码
execution = sandbox.run_code("""
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('Agg')
# 读取数据
df = pd.read_csv('/data/metrics.csv')
# 生成趋势图
fig, ax = plt.subplots(figsize=(12, 6))
ax.plot(df['date'], df['value'], marker='o')
ax.set_title('行业趋势分析', fontsize=16)
ax.set_xlabel('时间')
ax.set_ylabel('指标值')
plt.tight_layout()
plt.savefig('/output/trend.png', dpi=150)
print("CHART_GENERATED: /output/trend.png")
""")
# 取回生成的图表
charts = []
for file_path in execution.output_files:
content = sandbox.files.read(file_path)
charts.append(ChartOutput(path=file_path, data=content))
state["charts"] = charts
sandbox.close()
return statefrom guardrails import Guard
from guardrails.hub import (
DetectPII,
ToxicLanguage,
RestrictToTopic,
ProvenanceV1,
)
# 配置安全护栏
guard = Guard().use_many(
DetectPII(pii_entities=["EMAIL", "PHONE", "SSN"], on_fail="fix"),
ToxicLanguage(threshold=0.8, on_fail="reask"),
RestrictToTopic(
valid_topics=state["subtasks"], # 只允许讨论调研主题
on_fail="reask"
),
ProvenanceV1( # 验证报告内容可以溯源到原文
threshold=0.7,
on_fail="reask"
),
)
# 对最终报告进行校验
validated_report = guard.validate(state["draft_report"])from mem0 import Memory
memory = Memory.from_config({
"graph_store": {
"provider": "neo4j",
"config": {
"url": "neo4j://localhost:7687",
"username": "neo4j",
"password": "password",
}
},
"vector_store": {
"provider": "pgvector",
"config": {
"connection_string": DATABASE_URL,
}
}
})
async def apply_preferences(state: ResearchState) -> ResearchState:
user_id = state["user_id"]
# 检索用户偏好
preferences = memory.search(
query="report format preferences",
user_id=user_id,
limit=10,
)
# 例如:用户偏好柱状图、喜欢简洁风格、讨厌折线图...
# 根据偏好微调报告
state["final_report"] = adjust_report(
report=state["draft_report"],
preferences=preferences,
)
# 记录本次经验
memory.add(
messages=[{
"role": "system",
"content": f"用户对'{state['query']}'的调研任务,"
f"审校 {state['iteration']} 次后通过,"
f"最终评分 {state['review_score']}"
}],
user_id=user_id,
)
return statefrom langfuse import Langfuse
from langfuse.decorators import observe
langfuse = Langfuse(
public_key="pk-...",
secret_key="sk-...",
host="http://localhost:3000", # 自托管
)
# 每个节点都被自动追踪
@observe(name="deep_research")
async def deep_research(state: ResearchState) -> ResearchState:
# Langfuse 自动记录:
# - 输入/输出
# - Token 消耗
# - 延迟
# - 成本
# - 自定义 metadata
...
# 评估打分
langfuse.score(
trace_id=current_trace_id,
name="report_quality",
value=state["review_score"],
comment=state["review_feedback"],
)| 组件 | 技术 | 说明 |
|---|---|---|
| 桌面框架 | Electron 33+ | 跨平台桌面应用,与 Cursor 同技术栈 |
| 前端框架 | React 19 + TypeScript | 组件化开发,类型安全 |
| 状态管理 | Zustand | 轻量级,适合复杂 Agent 状态展示 |
| UI 组件库 | shadcn/ui + Radix | 高质量无样式组件,完全可定制 |
| 代码/文本编辑 | Monaco Editor | VS Code 同款编辑器,支持 Markdown 渲染 |
| 样式方案 | Tailwind CSS 4 | 原子化 CSS,快速构建深色主题 |
| 图表渲染 | Recharts / D3.js | Agent 生成的图表在客户端预览 |
| Markdown 渲染 | react-markdown + remark-gfm | 报告预览与实时渲染 |
| 实时通信 | Socket.IO Client | 与后端 WebSocket 双向通信 |
| 本地存储 | SQLite (better-sqlite3) | 本地缓存历史任务与报告 |
| 进程通信 | Electron IPC | 主进程与渲染进程安全通信 |
┌──────────────────────────────────────────────────────────────────┐
│ 菜单栏:DeepResearch Agent [最小化] [最大化] [关闭] │
├────────────┬──────────────────────────┬──────────────────────────┤
│ │ │ │
│ 左侧栏 │ 主编辑区 │ 右侧栏 │
│ (240px) │ (flex-1) │ (360px, 可折叠) │
│ │ │ │
│ ┌────────┐ │ ┌──────────────────┐ │ ┌──────────────────┐ │
│ │历史任务│ │ │ 对话 / 指令输入 │ │ │ 实时调研进度 │ │
│ │列表 │ │ │ │ │ │ ┌──────────┐ │ │
│ │ │ │ │ [用户]: 帮我分析 │ │ │ │ 任务拆解 ✓│ │ │
│ │ > 低空 │ │ │ 2024低空经济趋势 │ │ │ │ 搜索中.. ◉│ │ │
│ │ 经济 │ │ │ │ │ │ │ 提取 ○│ │ │
│ │ > AI │ │ │ [Agent]: 正在 │ │ │ │ 分析 ○│ │ │
│ │ 芯片 │ │ │ 调研中... │ │ │ │ 审校 ○│ │ │
│ │ │ │ │ │ │ │ └──────────┘ │ │
│ ├────────┤ │ │ ████░░░ 47% │ │ ├──────────────────┤ │
│ │知识库 │ │ │ │ │ │ 源文档列表 │ │
│ │ │ │ └──────────────────┘ │ │ ┌──────────┐ │ │
│ │ 📁本地 │ │ │ │ │ 📄 source1│ │ │
│ │ 📁云端 │ │ ┌──────────────────┐ │ │ │ 📄 source2│ │ │
│ │ │ │ │ 报告预览区 │ │ │ │ 📄 source3│ │ │
│ ├────────┤ │ │ (Monaco Editor │ │ │ └──────────┘ │ │
│ │MCP连接 │ │ │ / Markdown) │ │ ├──────────────────┤ │
│ │ │ │ │ │ │ │ 溯源高亮面板 │ │
│ │ ✓Notion│ │ │ # 2024低空经济 │ │ │ 点击报告中的 │ │
│ │ ✓Drive │ │ │ ## 市场规模 │ │ │ 数据,自动高亮 │ │
│ │ ○SQL │ │ │ ... │ │ │ 原文出处 │ │
│ │ │ │ │ [图表] [引用] │ │ │ │ │
│ └────────┘ │ └──────────────────┘ │ └──────────────────┘ │
│ │ │ │
├────────────┴──────────────────────────┴──────────────────────────┤
│ 底部栏:[Token消耗: 12.4k] [耗时: 3m 22s] [成本: $0.38] │
│ [Langfuse Trace ↗] [导出 PDF] [导出 DOCX] │
└──────────────────────────────────────────────────────────────────┘
- 输入区:支持自然语言输入调研需求,支持 @ 引用本地文件和知识库
- 流式响应:Agent 的思考过程实时流式输出(类 ChatGPT)
- 进度条:多阶段进度展示(拆解→搜索→提取→分析→审校)
- 中断/重试:用户可随时中断、修改方向、重新开始某个阶段
- Monaco Editor:支持 Markdown 实时编辑与预览
- 溯源高亮:点击报告中的任何数据/结论,右侧自动展示原文出处并高亮
- 内嵌图表:E2B 生成的图表内嵌在报告中,支持交互式缩放
- 导出格式:PDF / DOCX / Markdown / HTML
- 本地文件:导入 PDF、Excel、Word 等作为调研背景资料
- MCP 连接:配置 Notion、Google Drive、SQL 数据库等外部数据源
- 向量索引:自动对导入文件建立 pgvector 索引
- LLM 配置:选择调研用 LLM(Claude / GPT-4 / 本地模型)
- 搜索引擎:配置 Tavily / Serper / Bing API Key
- 报告偏好:图表风格、语气、长度、引用格式
- MCP Server 管理:添加/移除 MCP 工具服务器
- Mem0 记忆管理:查看/编辑/清除 Agent 积累的记忆
deepresearch-desktop/
├── electron/
│ ├── main.ts # Electron 主进程
│ ├── preload.ts # 预加载脚本(IPC Bridge)
│ ├── ipc/
│ │ ├── research.ts # 调研任务 IPC 处理
│ │ ├── files.ts # 文件系统操作
│ │ └── mcp.ts # MCP 连接管理
│ ├── updater.ts # 自动更新 (electron-updater)
│ └── tray.ts # 系统托盘(后台任务提醒)
│
├── src/ # React 渲染进程
│ ├── app/
│ │ ├── App.tsx
│ │ ├── routes.tsx
│ │ └── providers.tsx
│ │
│ ├── components/
│ │ ├── chat/
│ │ │ ├── ChatPanel.tsx # 对话面板
│ │ │ ├── MessageBubble.tsx # 消息气泡(支持流式)
│ │ │ ├── InputBar.tsx # 输入栏(支持 @ 引用)
│ │ │ └── ProgressTracker.tsx # 多阶段进度追踪
│ │ │
│ │ ├── editor/
│ │ │ ├── ReportEditor.tsx # Monaco Markdown 编辑器
│ │ │ ├── ProvenanceHighlight.tsx # 溯源高亮组件
│ │ │ ├── ChartEmbed.tsx # 内嵌图表组件
│ │ │ └── ExportMenu.tsx # 导出菜单
│ │ │
│ │ ├── sidebar/
│ │ │ ├── HistoryList.tsx # 历史任务列表
│ │ │ ├── KnowledgeBase.tsx # 知识库管理
│ │ │ ├── MCPConnections.tsx # MCP 连接状态
│ │ │ └── SourcePanel.tsx # 源文档列表
│ │ │
│ │ ├── settings/
│ │ │ ├── LLMConfig.tsx # LLM 模型配置
│ │ │ ├── SearchConfig.tsx # 搜索引擎配置
│ │ │ ├── MemoryManager.tsx # 记忆管理
│ │ │ └── PreferencesForm.tsx # 报告偏好设置
│ │ │
│ │ └── shared/
│ │ ├── StatusBar.tsx # 底部状态栏
│ │ ├── CommandPalette.tsx # Cmd+K 命令面板
│ │ └── ThemeProvider.tsx # 主题切换
│ │
│ ├── stores/
│ │ ├── researchStore.ts # 调研任务状态(Zustand)
│ │ ├── chatStore.ts # 对话历史状态
│ │ ├── settingsStore.ts # 设置状态
│ │ └── socketStore.ts # WebSocket 连接状态
│ │
│ ├── services/
│ │ ├── api.ts # REST API 客户端
│ │ ├── socket.ts # Socket.IO 客户端
│ │ └── localDB.ts # SQLite 本地缓存
│ │
│ └── styles/
│ ├── globals.css # Tailwind + 自定义变量
│ └── themes/
│ ├── dark.css # 深色主题(默认)
│ └── light.css # 浅色主题
│
├── package.json
├── electron-builder.yml # 打包配置(Windows/Mac/Linux)
├── tailwind.config.ts
├── tsconfig.json
└── vite.config.ts # Vite 构建(比 webpack 更快)
类似 Cursor / VS Code 的命令面板,快速操作:
┌─────────────────────────────────────┐
│ 🔍 输入命令或搜索... │
├─────────────────────────────────────┤
│ 📋 新建调研任务 │
│ 📂 打开知识库 │
│ 🔌 管理 MCP 连接 │
│ 📊 查看 Langfuse 追踪 │
│ ⚙️ 打开设置 │
│ 📤 导出当前报告 │
│ 🧠 查看 Agent 记忆 │
│ 🔄 重新运行当前任务 │
└─────────────────────────────────────┘
┌─────────────────────────────┐
│ 🔬 调研进度 - 迭代 #1/3 │
├─────────────────────────────┤
│ │
│ ✅ 任务拆解 (0.8s) │
│ → 生成 5 个子任务 │
│ │
│ ◉ 深度搜索 (进行中) │
│ ├ 子任务1: ✅ 12 篇 │
│ ├ 子任务2: ◉ 搜索中... │
│ ├ 子任务3: ○ 等待中 │
│ ├ 子任务4: ○ 等待中 │
│ └ 子任务5: ○ 等待中 │
│ │
│ ○ 数据提取 │
│ ○ 沙箱分析 │
│ ○ 报告生成 │
│ ○ 质量审校 │
│ ○ 个性化调整 │
│ │
├─────────────────────────────┤
│ Token: 8.2k | 耗时: 1m 12s│
│ [暂停] [中断] [跳到下一步] │
└─────────────────────────────┘
deepresearch-backend/
├── app/
│ ├── main.py # FastAPI 入口
│ ├── config.py # 环境配置
│ │
│ ├── api/
│ │ ├── routes/
│ │ │ ├── research.py # 调研任务 API
│ │ │ ├── knowledge.py # 知识库 API
│ │ │ ├── memory.py # 记忆管理 API
│ │ │ ├── export.py # 报告导出 API
│ │ │ └── settings.py # 设置 API
│ │ ├── websocket.py # WebSocket 端点
│ │ └── middleware.py # 认证、限流、CORS
│ │
│ ├── agents/
│ │ ├── graph.py # LangGraph 状态机定义
│ │ ├── nodes/
│ │ │ ├── decompose.py # 任务拆解节点
│ │ │ ├── search.py # GPT Researcher 调研节点
│ │ │ ├── extract.py # Instructor + LangExtract 提取节点
│ │ │ ├── analyze.py # E2B 沙箱分析节点
│ │ │ ├── draft.py # 报告生成节点
│ │ │ ├── review.py # 审校节点
│ │ │ └── personalize.py # Mem0 个性化节点
│ │ ├── prompts/
│ │ │ ├── compiled/ # DSPy 编译后的 prompt (自动生成)
│ │ │ └── templates/ # 基础模板
│ │ └── tools/
│ │ ├── mcp_client.py # MCP 协议客户端
│ │ └── search_tools.py # 搜索工具封装
│ │
│ ├── services/
│ │ ├── dspy_compiler.py # DSPy GEPA 编译服务
│ │ ├── e2b_sandbox.py # E2B 沙箱服务
│ │ ├── langextract_svc.py # LangExtract 溯源服务
│ │ ├── guardrails_svc.py # Guardrails 安全校验服务
│ │ ├── langfuse_svc.py # Langfuse 追踪服务
│ │ ├── memory_svc.py # Mem0/Zep 记忆服务
│ │ └── export_svc.py # 报告导出服务 (PDF/DOCX)
│ │
│ ├── models/
│ │ ├── research.py # 调研任务 ORM
│ │ ├── report.py # 报告 ORM
│ │ ├── source.py # 源文档 ORM
│ │ └── user.py # 用户 ORM
│ │
│ ├── db/
│ │ ├── postgres.py # PostgreSQL 连接
│ │ ├── redis.py # Redis 连接
│ │ └── migrations/ # Alembic 迁移
│ │
│ └── workers/
│ ├── celery_app.py # Celery 配置
│ └── tasks.py # 异步任务定义
│
├── dspy_training/
│ ├── datasets/ # 训练数据集
│ ├── metrics.py # 评估指标
│ └── compile.py # 编译脚本
│
├── tests/
├── docker-compose.yml
├── Dockerfile
├── pyproject.toml
└── .env.example
# docker-compose.yml
services:
backend:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@postgres:5432/deepresearch
- REDIS_URL=redis://redis:6379
- LANGFUSE_HOST=http://langfuse:3000
depends_on:
- postgres
- redis
- langfuse
celery-worker:
build: .
command: celery -A app.workers.celery_app worker -l info -c 4
depends_on:
- redis
- postgres
postgres:
image: pgvector/pgvector:pg16
environment:
POSTGRES_DB: deepresearch
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
langfuse:
image: langfuse/langfuse:2
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://user:pass@postgres:5432/langfuse
- NEXTAUTH_SECRET=your-secret
- SALT=your-salt
neo4j: # 用于 Mem0 图存储
image: neo4j:5
ports:
- "7474:7474"
- "7687:7687"
environment:
NEO4J_AUTH: neo4j/password
volumes:
pgdata:{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/data/knowledge-base"]
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://..."]
},
"google-drive": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-google-drive"]
},
"notion": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-notion"],
"env": { "NOTION_TOKEN": "..." }
},
"browser": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-puppeteer"]
},
"tavily-search": {
"command": "npx",
"args": ["-y", "tavily-mcp-server"],
"env": { "TAVILY_API_KEY": "..." }
}
}
}- LangGraph 状态机 + GPT Researcher 搜索
- Instructor 结构化提取
- FastAPI 后端 + WebSocket
- Electron 基础框架 + 对话面板 + 报告预览
- 基础 Markdown 报告导出
- DSPy GEPA 指令优化集成
- LangExtract 溯源高亮
- E2B 沙箱分析与图表
- Mem0 长期记忆
- MCP 工具连接配置界面
- Langfuse 全链路追踪
- Guardrails AI 安全护栏
- 报告导出 PDF/DOCX
- 命令面板 (Cmd+K)
- 自动更新机制
- 多模型支持 (Claude / GPT / 本地 Ollama)
- 插件系统(自定义 MCP 工具)
- 团队协作功能
- 多语言报告生成
- 性能优化与离线模式
| 决策点 | 选择 | 理由 |
|---|---|---|
| Electron vs Tauri | Electron | 生态成熟、Monaco Editor 原生支持、与 Cursor 同栈 |
| Vite vs Webpack | Vite | HMR 速度快 10x+,Electron 社区已有成熟模板 |
| Zustand vs Redux | Zustand | Agent 状态结构复杂但不需要 Redux 的 boilerplate |
| PostgreSQL vs MongoDB | PostgreSQL + pgvector | 关系查询 + 向量搜索一体化,减少运维负担 |
| Celery vs 内置 async | Celery | 调研任务可能运行 5-30 分钟,需要持久化队列和失败重试 |
| Mem0 vs Zep | 默认 Mem0,企业版 Zep | Mem0 开箱即用;Zep 的时序知识图谱适合大规模企业 |
| GPT Researcher vs 自研 | GPT Researcher | 17k stars,递归搜索成熟度高,MCP 支持完善 |