- AgentConfig/LlmClient 新增 enable_thinking 参数,前端 SSE 请求传递 thinking 开关,仅千问/DashScope 时启用 - 完善权限系统,支持细粒度的权限控制和用户权限申请 - delegate_research 工具重命名为 subagent,SubAgentTool/SubAgentRunner 重构 - 子代理消息(system/user/assistant/tool)持久化到 agent_messages 表,带 agent_name 标识 - 子代理活动日志(工具调用列表+思考摘要)注入返回结果,Hooks 获得正确 session_id 和 subagent_name - LLM 工具调用 ID 回退生成 UUID(llm.rs),ToolCall/ToolResult SSE 事件增加 id/tool_call_id 双字段 - ToolContext 扩展 session_id/sse_tx/enable_thinking 字段,executor 统一注入而非构造函数传参 - agent_messages 新增 metadata+raw_json 列,agent_sessions 暴露 summary 字段 - 删除文件级 transcript 快照(compact.rs),改为依赖 DB 持久化 - ResearchAgentPanel 重写:TimelineItem 类型替代 StreamStep,支持会话历史回放 - 新增 AgentMetricsPanel/AskUserQuestionCard/AuditLogViewer 三个前端组件,types.ts 完整类型定义 - docs/architecture/ 分层重组:概览/核心模块/核心工作流 + agent/ 子目录 11 篇专题文档 - docs/api.md 补充 RAG/Target/Agent 接口,docs/development.md 新建开发指南 - .env.example 完全重写,补充 FALLBACK_MODEL 等变量说明
8.5 KiB
8.5 KiB
AstroResearch Architecture / 架构设计
AstroResearch 是一个集成了天文学文献检索、多通道下载(含防爬绕过与手动上传)、下载错误诊断、结构化解析、中英学术对比翻译、引文星系图谱以及馆藏健康度诊断的天文科研辅助系统。
2. 核心工作流 (Core Workflows)
2.1 文献下载流程 (Download Flow)
本流程实现了文献的多通道流式下载,支持多级回退、错误诊断记录以及安全反爬防线绕过:
sequenceDiagram
participant U as 用户 (React 前端)
participant H as 处理器 (papers.rs)
participant D as 下载器 (download.rs)
participant DB as 本地数据库 (SQLite)
U->>H: 1. 发起下载请求 (POST /api/download, 含 bibcode, force)
H->>DB: 2. 查询文献元数据 (获取 arxiv_id, doi 等)
alt force == true
H->>DB: 3. 重置本地下载路径字段为 NULL
end
H->>D: 4. 调度下载器执行物理拉取
alt 文献含有 arxiv_id (通道 A:arXiv 直连优先)
D->>D: 5a. 去除版本号 (strip_arxiv_version, v2 -> 无版本)
D->>D: 5b. 随机延时 (maybe_delay: 500-2000ms) 并伪装 UA
D->>D: 5c. 下载 PDF 并校验文件头 (%PDF + %%EOF)
D->>D: 5d. 优先请求官方 HTML (arxiv.org/html/)
note over D: 若官方 HTML 返回 404/错误
D->>D: 5e. 自动降级回退请求 ar5iv HTML (ar5iv.labs.arxiv.org)
D->>D: 5f. 校验 HTML 内容 (detect_anti_bot 检测反爬)
else 无 arxiv_id (通道 B:ADS 路由回退)
D->>D: 6a. 跟踪 ADS Link Gateway 重定向路由
note over D: 若遇到 validate.perfdrive.com 拦截
D->>D: 6b. 自动解析并解码 ssc 参数提取直链
note over D: 若指向 IOPscience / Springer
D->>D: 6c. IOP 专属策略:预热主页写入 Cookie,带 Referer 下载 PDF
D->>D: 6d. Springer 专属策略:使用 Chrome 头下载 HTML 页
note over D: 若网关均失败且存在 DOI
D->>D: 6e. CrossRef 兜底:请求 CrossRef API 获取 PDF URL 并直连下载
end
alt 下载成功
D-->>H: 7a. 返回下载好的本地物理 PDF & HTML 路径
H->>DB: 8a. 更新 pdf_path & html_path 记录
H-->>U: 9a. 返回最新文献状态 (is_downloaded: true)
else 下载失败
D-->>H: 7b. 返回失败原因
H->>DB: 8b. 以 error: 前缀记录诊断信息
H-->>U: 9b. 返回文献状态 (pdf_error / html_error 已填充)
end
详细下载说明:
- 指令接收与校验:后端
download_paper接口在force参数为true时,会强行擦除数据库中已下载的文件路径,启动无缓存的物理文件重新拉取。 - 下载反爬伪装:下载器
Downloader请求时采用动态生成的 Firefox/Chrome 轮换 User-Agent,并在每次 HTTP 访问前强制加入随机休眠机制(500ms - 2000ms),模拟人类自然阅读行为。 - 内容完整性校验:
- 对 PDF 严格校验前四个字节(必须是
%PDF)以及尾部检索(必须包含%%EOF终止符),排查登录墙、错误页伪装成 PDF 导致下载坏文件的问题。 - 对 HTML 文本利用
detect_anti_bot流水线过滤 "cloudflare"、"captcha"、"robot check" 等拦截特征。
- 对 PDF 严格校验前四个字节(必须是
- 错误诊断记录:下载失败时,系统会将具体的失败原因(如 "Cloudflare 拦截"、"404 Not Found" 等)以
error:前缀存入数据库的pdf_path/html_path字段。前端通过pdf_error/html_error字段读取并向用户展示。
2.2 手动上传流程 (Upload Flow)
当自动下载受防爬或人机验证阻碍时,用户可手动上传文献文件:
sequenceDiagram
participant U as 用户 (React 前端 / 浏览器书签)
participant H as 处理器 (papers.rs)
participant DB as 本地数据库 (SQLite)
participant FS as 本地文件系统
U->>H: 1. 上传文件 (POST /api/upload, Multipart: bibcode + type + file)
H->>H: 2. 解析 Multipart 字段
alt bibcode 未直接匹配数据库
H->>DB: 3a. 尝试通过 DOI 匹配
H->>DB: 3b. 尝试通过 arXiv ID 匹配(自动去除版本号)
end
H->>H: 4. 校验文件格式 (PDF 校验 %PDF 文件头)
H->>FS: 5. 写入物理文件 (library/PDF/ 或 library/HTML/)
H->>DB: 6. 更新 pdf_path / html_path,清除 error: 诊断记录
H-->>U: 7. 返回更新后的文献元数据 (is_downloaded: true)
2.3 文献解析流程 (Parse Flow)
本流程负责将本地下载的 HTML 或 PDF 转换为高保真的 Markdown:
sequenceDiagram
participant U as 用户 (React 前端)
participant H as 处理器 (papers.rs)
participant P as 解析器 (parser.rs)
participant M as MinerU (PDF解析服务)
participant Q as 七牛云 (对象存储)
participant DB as 本地数据库 (SQLite)
U->>H: 1. 发起解析请求 (POST /api/parse, 含 bibcode, force)
H->>DB: 2. 查询文献物理路径 (pdf_path, html_path, markdown_path)
alt force == false 且本地已存在 Markdown 物理缓存
H->>H: 3. 读取本地 Markdown 物理文件
H-->>U: 4. 直接返回缓存 Markdown,流程结束
end
H->>P: 5. 触发结构化文献解析
alt 本地存在 HTML 文件
P->>P: 6a. 剥离广告/导航栏与尾页页脚噪声
P->>P: 6b. 公式保护:利用占位符隔离 MathJax/LaTeX 公式段
P->>P: 6c. 标签规范:还原 LaTeXML 特定 span 为标准 table/tr/td,修正上下标
P->>P: 6d. 插图处理:把相对图像路径替换为绝对 CDN 外链地址
P->>P: 6e. 转换 GFM Markdown 并恢复 LaTeX 公式
P->>P: 6f. 后处理:清除冗余的 margin 空白与前导缩进
else 仅有 PDF 文件 (PDF 降级解析)
P->>M: 7a. 获取批量预签名上传 URL (POST /file-urls/batch/)
M-->>P: 7b. 返回预签名上传 URL 与 Batch ID
P->>M: 7c. 上传 PDF 二进制字节流 (PUT 至预签名 URL)
loop 轮询任务状态 (每 10s 一次,最多 45 次)
P->>M: 7d. 查询提取进度与结果 (GET /extract-results/batch/{id})
M-->>P: 7e. 返回处理状态 ("done"/"error"等)
end
P->>P: 7f. 下载解析结果的 ZIP 压缩包并解压提取
loop 遍历每一个提取的插图
P->>Q: 7g. 上传插图文件并获取七牛云 CDN 域名外链
end
P->>P: 7h. 在 Markdown 中重写插图链接为七牛云 CDN 绝对路径
end
P-->>H: 8. 返回清洗转换出的标准英文 Markdown 文本
H->>P: 9. 写入本地物理缓存 Markdown/ 目录
H->>DB: 10. 更新数据库 markdown_path 记录
H-->>U: 11. 返回标准 Markdown 内容渲染展示
2.4 智能对照翻译流程 (Translation Flow)
本流程实现了基于天文学专属词汇表的 LLM 专业对比翻译:
sequenceDiagram
participant U as 用户 (React 前端)
participant H as 处理器 (papers.rs)
participant T as 翻译器 (translation.rs)
participant D as 天文词典 (Trie 树)
participant L as 大模型 (LLM API)
participant DB as 本地数据库 (SQLite)
U->>H: 1. 请求文献对比翻译 (POST /api/translate, 含 bibcode, force)
H->>DB: 2. 查询文献路径及状态
alt force == false 且本地已存在翻译缓存文件
H->>H: 3. 读取本地 Translation/{bibcode}_zh.md 物理文件
H-->>U: 4. 直接返回缓存译文,流程结束
end
H->>H: 5. 读取对应的英文解析 Markdown 物理文件
H->>T: 6. 调度翻译器执行翻译工作流
T->>D: 7. 加载本地 dictionary.txt 并初始化 Trie 树结构
T->>D: 8. 执行英文 Markdown 文本分词匹配
D->>D: 9a. 进行前缀匹配检索
D->>D: 9b. 遵循"最长匹配优先"原则,过滤子词去重
D-->>T: 10. 返回该篇文献提取出的天文学名词对照 (Glossary)
loop 针对英文 Markdown 进行段落分块 (Token 长度控制)
T->>L: 11. 携带 Glossary + 英文原文段落发送 Prompt 请求
note over L: LLM 遵循系统 Prompt 约束:<br>1. 专业词汇严格对应 Glossary 译出<br>2. 严禁改变 LaTeX 公式及 Markdown 标签<br>3. 保持中英段落高度对齐
L-->>T: 12. 返回学术级双语对照翻译段落
end
T->>T: 13. 拼接所有段落,生成完整的对照 Markdown
T->>H: 14. 写入本地物理缓存 Translation/ 目录
H->>DB: 15. 更新数据库中的 translation_path 字段
H-->>U: 16. 返回翻译后 Markdown 渲染展示