deepresearch-flow 0.5.1__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. deepresearch_flow/paper/cli.py +63 -0
  2. deepresearch_flow/paper/config.py +87 -12
  3. deepresearch_flow/paper/db.py +1041 -34
  4. deepresearch_flow/paper/db_ops.py +124 -19
  5. deepresearch_flow/paper/extract.py +1546 -152
  6. deepresearch_flow/paper/prompt_templates/deep_read_phi_system.j2 +2 -0
  7. deepresearch_flow/paper/prompt_templates/deep_read_phi_user.j2 +5 -0
  8. deepresearch_flow/paper/prompt_templates/deep_read_system.j2 +2 -0
  9. deepresearch_flow/paper/prompt_templates/deep_read_user.j2 +272 -40
  10. deepresearch_flow/paper/prompt_templates/eight_questions_phi_system.j2 +1 -0
  11. deepresearch_flow/paper/prompt_templates/eight_questions_phi_user.j2 +2 -0
  12. deepresearch_flow/paper/prompt_templates/eight_questions_system.j2 +2 -0
  13. deepresearch_flow/paper/prompt_templates/eight_questions_user.j2 +4 -0
  14. deepresearch_flow/paper/prompt_templates/simple_phi_system.j2 +2 -0
  15. deepresearch_flow/paper/prompt_templates/simple_system.j2 +2 -0
  16. deepresearch_flow/paper/prompt_templates/simple_user.j2 +2 -0
  17. deepresearch_flow/paper/providers/azure_openai.py +45 -3
  18. deepresearch_flow/paper/providers/openai_compatible.py +45 -3
  19. deepresearch_flow/paper/schemas/deep_read_phi_schema.json +1 -0
  20. deepresearch_flow/paper/schemas/deep_read_schema.json +1 -0
  21. deepresearch_flow/paper/schemas/default_paper_schema.json +6 -0
  22. deepresearch_flow/paper/schemas/eight_questions_schema.json +1 -0
  23. deepresearch_flow/paper/snapshot/__init__.py +4 -0
  24. deepresearch_flow/paper/snapshot/api.py +941 -0
  25. deepresearch_flow/paper/snapshot/builder.py +965 -0
  26. deepresearch_flow/paper/snapshot/identity.py +239 -0
  27. deepresearch_flow/paper/snapshot/schema.py +245 -0
  28. deepresearch_flow/paper/snapshot/tests/__init__.py +2 -0
  29. deepresearch_flow/paper/snapshot/tests/test_identity.py +123 -0
  30. deepresearch_flow/paper/snapshot/text.py +154 -0
  31. deepresearch_flow/paper/template_registry.py +1 -0
  32. deepresearch_flow/paper/templates/deep_read.md.j2 +4 -0
  33. deepresearch_flow/paper/templates/deep_read_phi.md.j2 +4 -0
  34. deepresearch_flow/paper/templates/default_paper.md.j2 +4 -0
  35. deepresearch_flow/paper/templates/eight_questions.md.j2 +4 -0
  36. deepresearch_flow/paper/web/app.py +10 -3
  37. deepresearch_flow/recognize/cli.py +380 -103
  38. deepresearch_flow/recognize/markdown.py +31 -7
  39. deepresearch_flow/recognize/math.py +47 -12
  40. deepresearch_flow/recognize/mermaid.py +320 -10
  41. deepresearch_flow/recognize/organize.py +29 -7
  42. deepresearch_flow/translator/cli.py +71 -20
  43. deepresearch_flow/translator/engine.py +220 -81
  44. deepresearch_flow/translator/prompts.py +19 -2
  45. deepresearch_flow/translator/protector.py +15 -3
  46. {deepresearch_flow-0.5.1.dist-info → deepresearch_flow-0.6.0.dist-info}/METADATA +407 -33
  47. {deepresearch_flow-0.5.1.dist-info → deepresearch_flow-0.6.0.dist-info}/RECORD +51 -43
  48. {deepresearch_flow-0.5.1.dist-info → deepresearch_flow-0.6.0.dist-info}/WHEEL +1 -1
  49. {deepresearch_flow-0.5.1.dist-info → deepresearch_flow-0.6.0.dist-info}/entry_points.txt +0 -0
  50. {deepresearch_flow-0.5.1.dist-info → deepresearch_flow-0.6.0.dist-info}/licenses/LICENSE +0 -0
  51. {deepresearch_flow-0.5.1.dist-info → deepresearch_flow-0.6.0.dist-info}/top_level.txt +0 -0
@@ -3,4 +3,6 @@ Output language: {{ output_language }}.
3
3
  Extract structured data from the provided markdown document.
4
4
  Return ONLY valid JSON that conforms to the given JSON Schema.
5
5
  The field "paper_authors" MUST be an array of strings (each author name as one item).
6
+ If affiliations are available, extract them into "paper_institutions" as a list of institution names.
7
+ Ensure JSON strings escape newlines and code blocks properly.
6
8
  If a field is unknown, use an empty string or empty list per schema.
@@ -12,6 +12,11 @@ Template: deep_read_phi
12
12
  关键结论需要注明来自论文的定位(章节/图/表/公式编号)。
13
13
  每轮末尾要求输出的三行仍需保留,但不要中途停止输出。
14
14
  输出语言:{{ output_language }}。请使用该语言输出(zh 时使用中文,保留必要英文术语)。
15
+
16
+ 图示要求(仅在内容触发时输出,使用 mermaid/markmap 代码块,不要臆造):
17
+ - 模块 M1:若论文结构清晰,输出 markmap 思维导图。
18
+ - 模块 M2/M4/M5:若出现清晰的论证结构或概念结构,可用 flowchart TD/LR 表达。
19
+ - 若论文包含架构/流程/数据流/性能对比等内容,按内容选择合适的 flowchart。
15
20
  {% endif %}
16
21
 
17
22
  ---
@@ -3,4 +3,6 @@ Output language: {{ output_language }}.
3
3
  Extract structured data from the provided markdown document.
4
4
  Return ONLY valid JSON that conforms to the given JSON Schema.
5
5
  The field "paper_authors" MUST be an array of strings (each author name as one item).
6
+ If affiliations are available, extract them into "paper_institutions" as a list of institution names.
7
+ Ensure JSON strings escape newlines and code blocks properly.
6
8
  If a field is unknown, use an empty string or empty list per schema.
@@ -10,6 +10,74 @@ Template: deep_read
10
10
  每个模块字段内部使用 Markdown 编排(标题、列表等)。
11
11
  禁止第一人称(不出现“我/我们/本人”)。
12
12
  关键结论需要注明来自论文的定位(章节/图/表/公式编号)。
13
+
14
+ 图示要求(使用 mermaid/markmap 代码块,必须按论文类型输出对应图示):
15
+ - 如果图示为推断(非原文明确给出),标题前加前缀 [Inferred]。
16
+ - Mermaid 语法要求:节点 ID 只用简单字母数字(如 NodeA/step1),描述文字放在标签里(如 NodeA["复杂描述 (含括号)"]),避免 ID 含空格或特殊字符。
17
+ - 图示用于补充文字而非替代,图后仍要有文字说明。
18
+ - 模块 B:必须给出全文结构的 markmap 导图(无论是否明确提纲)。
19
+ - 综述/调研类论文:必须给出“分类体系 + 代表工作/方法”的图(mermaid flowchart TD),用于总结分类与代表工作。
20
+ - 算法方法类论文:必须给出流程图(flowchart TD)和数据流图(flowchart LR)。
21
+ - 硬件/系统类论文:必须给出架构图(flowchart LR)和数据流图(flowchart LR)。
22
+ - 模块 C3:算法流程图(flowchart TD)。
23
+ - 模块 D:硬件/系统架构图(flowchart LR)。
24
+ - 模块 C4/C5:数据流图(flowchart LR)。
25
+ - 模块 E:性能-精度权衡图(flowchart TD)。
26
+ - 模块 H:实验设置图(flowchart TD)。
27
+
28
+ 示例(每个小结都必须参照,严格遵守代码块与语法,节点 ID 简单):
29
+ 1) 全文结构导图(markmap):
30
+ ```markmap
31
+ # Paper Overview
32
+ ## Introduction
33
+ ## Method
34
+ ### Pipeline
35
+ ### Modules
36
+ ## Experiments
37
+ ## Conclusion
38
+ ```
39
+ 2) 综述/调研分类图(mermaid flowchart TD):
40
+ ```mermaid
41
+ flowchart TD
42
+ CatA["Category A"]
43
+ CatB["Category B"]
44
+ CatC["Category C"]
45
+ W1["Work 1"]
46
+ W2["Work 2"]
47
+ W3["Work 3"]
48
+ CatA --> W1
49
+ CatB --> W2
50
+ CatC --> W3
51
+ ```
52
+ 3) 算法流程图(mermaid flowchart TD):
53
+ ```mermaid
54
+ flowchart TD
55
+ NodeA["Input Data"]
56
+ NodeB["Preprocessing"]
57
+ NodeC["Model"]
58
+ NodeD["Evaluation"]
59
+ NodeA --> NodeB --> NodeC --> NodeD
60
+ ```
61
+ 4) 数据流图(mermaid flowchart LR):
62
+ ```mermaid
63
+ flowchart LR
64
+ Step1["Raw Data"] --> Step2["Feature Extractor"] --> Step3["Fusion"] --> Step4["Output"]
65
+ ```
66
+ 5) 硬件/系统架构图(mermaid flowchart LR):
67
+ ```mermaid
68
+ flowchart LR
69
+ Host["Host"] --> FPGA["FPGA/Accelerator"] --> Mem["Memory/IO"]
70
+ ```
71
+ 6) 性能-精度权衡图(mermaid flowchart TD):
72
+ ```mermaid
73
+ flowchart TD
74
+ Fast["Fast/Low Accuracy"] --> Balanced["Balanced"] --> Accurate["Accurate/Slow"]
75
+ ```
76
+ 7) 实验设置图(mermaid flowchart TD):
77
+ ```mermaid
78
+ flowchart TD
79
+ Dataset["Datasets"] --> Metrics["Metrics"] --> Baselines["Baselines"] --> Results["Results"]
80
+ ```
13
81
  {% endif %}
14
82
 
15
83
  ---
@@ -34,49 +102,213 @@ Template: deep_read
34
102
  - 可选模块 G:联网核验与引用校对
35
103
  - 模块 H:图表与表格的客观抽取
36
104
 
37
- ## 2) 模块内容规范
38
- ### 模块 A:阅读对齐与输入校验
39
- - 明确用户目的与背景
40
- - 检查输入材料:PDF/附录/代码链接/补充材料/数据集
41
- - 输出阅读路线图
42
-
43
- ### 模块 B:第一遍(鸟瞰扫描)
44
- 必须给出 5 项产出:类别、上下文、正确性直觉检查、贡献、清晰度,并给出继续/放弃建议。
45
-
46
- ### 模块 C1~C8:八个问题
47
- 问题1:论文试图解决什么问题?
48
- 问题2:有哪些相关研究?(最强基线/最相近思路/正交方向)
49
- 问题3:论文如何解决这个问题?(流程图文字版)
50
- 问题4:实验数据集与实现设置:用了哪些数据集/场景?为什么选它们?验证哪些关键特性?
51
- 问题5:指标与结果:有哪些指标?实验结果是什么?这些指标分别体现了哪些创新点?尽力抽取全部结果指标。
52
- 问题6:有什么可以进一步探索的点?(理论/工程/数据/评测)
53
- 问题7:现实场景如何体现/实现?(部署约束、算力、延迟、鲁棒性)
54
- 问题8:总结主要内容(一段摘要 + 5 条要点 + 1 个核心公式/机制)
55
-
56
- ### 模块 D:第二遍(内容理解)
57
- - 给出结构树
58
- - 拆解核心方法:输入/输出/模块/损失/训练或推理流程
59
- - 关键图表说明
60
- - 实验部分:数据集、指标、对比方法、公平性、消融充分性
61
-
62
- ### 模块 E:第三遍(深度审视)
63
- 必须包含:可复现重建(伪代码)、假设清单、失败模式、强弱点评估、下一步研究。
64
-
65
- ### 模块 F:术语表(可选)
66
- - 15-40 个关键词,包含中英文名、定义、直觉解释、作用、前置知识
67
- - 术语依赖图(文字版)
68
-
69
- ### 模块 G:联网核验(可选)
70
- - 关键事实提供至少 2 个独立来源
71
- - 冲突要显式说明,无法核验要标记
72
- - 输出引用列表
73
-
74
- ### 模块 H:图表与表格抽取
75
- - 全量索引、打分、TOP 深读
76
- - 需要明确图表位置、图注、类型、支撑的 claim
105
+ ## 2) 模块内容规范(强制格式 + 详细模板)
106
+ {% if stage_name %}
107
+ ### 当前阶段:{{ stage_name }}
108
+ #### 非当前模块摘要(仅摘要,不写细节)
109
+ - 模块 A:基本信息与输入校验
110
+ - 模块 B:鸟瞰扫描 + 结构导图
111
+ - 模块 C1~C8:八问深读(问题/方法/数据/结果/展望)
112
+ - 模块 D:结构树 + 方法拆解 + 图表说明 + 实验细节
113
+ - 模块 E:伪代码 + 假设 + 失败模式 + 强弱点评 + 下一步
114
+ - 模块 F:术语表 + 依赖关系
115
+ - 模块 G:事实核验 + 冲突说明 + 引用列表
116
+ - 模块 H:图表索引 + 深读 + 图表关系说明
117
+
118
+ #### 当前模块详细规范(必须严格遵守)
119
+ {% if stage_name == "module_a" %}
120
+ ### 模块 A:阅读对齐与输入校验(强制格式)
121
+ 必须包含以下小节(按顺序输出):
122
+ 1) 论文基本信息
123
+ - 标题:
124
+ - 作者(姓名 / 单位 / 简历或背景〔若文中提供〕):
125
+ - 发表信息(期刊/会议/年份/级别〔如有〕):
126
+ 2) 研究定位
127
+ - 研究领域:
128
+ - 具体任务:
129
+ - 目标用户/应用场景:
130
+ 3) 输入材料清单
131
+ - PDF:
132
+ - 附录/补充材料:
133
+ - 代码链接:
134
+ - 数据集链接:
135
+ 4) 缺失材料与风险
136
+ - 缺失项:
137
+ - 可能影响:
138
+ 5) 阅读路线图(3-6 步)
139
+ - Step 1:
140
+ - Step 2:
141
+ - Step 3:
142
+ 示例(仅参考格式):
143
+ 【论文基本信息】标题: ...;作者: ...;发表: ...
144
+ 【研究定位】领域/任务/场景...
145
+ 【输入材料清单】PDF: 有/无;代码: ...
146
+ 【缺失材料与风险】...
147
+ 【阅读路线图】Step 1...Step 2...
148
+ {% elif stage_name == "module_b" %}
149
+ ### 模块 B:第一遍鸟瞰扫描(强制格式)
150
+ 必须包含以下小节(按顺序输出):
151
+ 1) 论文类型与类别
152
+ 2) 上下文与研究背景
153
+ 3) 正确性直觉检查(关键假设与合理性)
154
+ 4) 核心贡献(3-5 条,逐条)
155
+ 5) 清晰度评估(结构/图表/公式可读性)
156
+ 6) 继续/放弃建议(给出明确建议 + 依据)
157
+ 7) 结构导图(必须包含 markmap 代码块)
158
+ 示例(仅参考格式):
159
+ 【论文类型与类别】...
160
+ 【上下文】...
161
+ 【贡献】1) ... 2) ...
162
+ ```markmap
163
+ # Paper Overview
164
+ ## Introduction
165
+ ## Method
166
+ ## Experiments
167
+ ## Conclusion
168
+ ```
169
+ {% elif stage_name == "module_c1" %}
170
+ ### 模块 C1:论文试图解决什么问题?(强制格式)
171
+ 必须包含以下小节:
172
+ 1) 问题定义(一句话)
173
+ 2) 痛点/不足(2-4 条)
174
+ 3) 形式化目标或优化目标(如有公式)
175
+ 4) 成功判据(指标或性质)
176
+ 示例:问题定义/痛点/目标/判据逐条说明。
177
+ {% elif stage_name == "module_c2" %}
178
+ ### 模块 C2:相关研究(强制格式)
179
+ 必须包含以下小节:
180
+ 1) 最强基线(1-2 个)+ 对比点
181
+ 2) 最相近思路(1-2 个)+ 区别点
182
+ 3) 正交方向(2-3 个)
183
+ 4) 本文相对位置(一句话定位)
184
+ 示例:使用“方法名 -> 核心思想 -> 局限”结构。
185
+ 例:BaselineX -> 关键机制 -> 局限;ClosestY -> 区别点 -> 适用场景。
186
+ {% elif stage_name == "module_c3" %}
187
+ ### 模块 C3:论文如何解决问题?(强制格式)
188
+ 必须包含以下小节:
189
+ 1) 核心机制概述(1-2 段)
190
+ 2) 步骤拆解(逐步)
191
+ 3) 关键公式/模块作用
192
+ 4) 流程图(mermaid flowchart TD)
193
+ 示例(流程图必须出现):
194
+ ```mermaid
195
+ flowchart TD
196
+ Step1["Input"] --> Step2["Process"] --> Step3["Output"]
197
+ ```
198
+ {% elif stage_name == "module_c4" %}
199
+ ### 模块 C4:实验数据集与设置(强制格式)
200
+ 必须包含以下小节:
201
+ 1) 数据集列表(名称/规模/场景)
202
+ 2) 预处理与划分
203
+ 3) 训练/推理环境(硬件/软件)
204
+ 4) 选择理由与验证目标
205
+ 示例:DatasetA(规模/场景);Split=Train/Val/Test;GPU/驱动/框架版本。
206
+ {% elif stage_name == "module_c5" %}
207
+ ### 模块 C5:指标与结果(强制格式)
208
+ 必须包含以下小节:
209
+ 1) 指标列表(含定义或解释)
210
+ 2) 主要结果(尽量给具体数值)
211
+ 3) 与基线对比(提升/下降)
212
+ 4) 消融/敏感性(若有)
213
+ 示例:Metric=Acc/F1;Result=XX;Baseline=YY;提升=+ZZ%。
214
+ {% elif stage_name == "module_c6" %}
215
+ ### 模块 C6:进一步探索(强制格式)
216
+ 必须包含:理论方向、工程方向、数据/评测方向各至少 1 条。
217
+ 示例:理论=新损失;工程=推理加速;数据=更难场景评测。
218
+ {% elif stage_name == "module_c7" %}
219
+ ### 模块 C7:现实场景体现(强制格式)
220
+ 必须包含:部署约束、算力/延迟、鲁棒性/安全性、可维护性。
221
+ 示例:约束=边缘设备;延迟<XXms;鲁棒性=遮挡/噪声;可维护=更新频率。
222
+ {% elif stage_name == "module_c8" %}
223
+ ### 模块 C8:总结(强制格式)
224
+ 必须包含:
225
+ 1) 一段摘要(6-8 句)
226
+ 2) 5 条要点
227
+ 3) 1 个核心公式/机制(LaTeX)
228
+ 示例:摘要...;要点1..5;公式:$E=mc^2$。
229
+ {% elif stage_name == "module_d" %}
230
+ ### 模块 D:第二遍内容理解(强制格式)
231
+ 必须包含以下小节:
232
+ 1) 结构树(层级列表)
233
+ 2) 方法拆解(输入/输出/模块/损失/训练或推理流程)
234
+ 3) 关键图表说明(至少 2 个)
235
+ 4) 实验细节(数据集/指标/对比方法/公平性/消融)
236
+ 5) 图示(算法类:流程图+数据流图;硬件/系统类:架构图+数据流图)
237
+ 示例:先给结构树,再给流程图,图后解释关键步骤与实验结论关联。
238
+ {% elif stage_name == "module_e" %}
239
+ ### 模块 E:第三遍深度审视(强制格式)
240
+ 必须包含:
241
+ 1) 可复现重建(伪代码)
242
+ 2) 假设清单(3-6 条)
243
+ 3) 失败模式(2-4 条)
244
+ 4) 强弱点评估(优点/缺点)
245
+ 5) 下一步研究(2-4 条)
246
+ 示例:伪代码块 + 假设1/2 + 失败模式A/B。
247
+ {% elif stage_name == "module_f" %}
248
+ ### 模块 F:术语表(强制格式)
249
+ 必须输出 15-40 个条目,每条包含:中英文名/定义/直觉/作用/前置知识。
250
+ 最后追加“术语依赖图(文字版)”。
251
+ 示例:Term(EN/中): 定义... 直觉... 作用... 前置...
252
+ {% elif stage_name == "module_g" %}
253
+ ### 模块 G:联网核验(强制格式)
254
+ 必须包含:
255
+ 1) 关键事实清单(每条至少 2 个来源)
256
+ 2) 冲突与不确定性说明
257
+ 3) 引用列表(按条列出)
258
+ 示例:Claim1 -> sourceA/sourceB;冲突=...;引用=[1][2]。
259
+ {% elif stage_name == "module_h" %}
260
+ ### 模块 H:图表与表格抽取(强制格式)
261
+ 必须包含以下小节:
262
+ 1) 全量索引(表格:编号/图注/类型/位置/支撑 claim/评分)
263
+ 2) TOP 深读(3-5 项,逐条解释)
264
+ 3) 图表关系或实验设置图(mermaid)
265
+ 4) 图与结论对应关系说明
266
+ 示例:表格索引 + Top1 深读 + mermaid 图 + 对应结论说明。
267
+ {% endif %}
268
+ {% else %}
269
+ ### 单次输出模式:所有模块均需详细完成
270
+ 请按以下“强制格式模板”逐模块输出,每个模块必须覆盖其必填项与示例要求。
271
+
272
+ #### 模块 A(模板)
273
+ 【论文基本信息】标题/作者/单位/简历/发表信息/级别
274
+ 【研究定位】领域/任务/场景
275
+ 【输入材料清单】PDF/附录/代码/数据
276
+ 【缺失材料与风险】
277
+ 【阅读路线图】Step 1..Step N
278
+
279
+ #### 模块 B(模板)
280
+ 【论文类型与类别】...【上下文】...【正确性直觉】...【贡献】...【清晰度】...【继续/放弃建议】...
281
+ 结构导图(markmap 代码块)
282
+
283
+ #### 模块 C1~C8(模板)
284
+ 按 C1..C8 小节逐条回答,至少包含“问题定义/关键点/证据定位”。
285
+
286
+ #### 模块 D(模板)
287
+ 结构树 + 方法拆解 + 关键图表说明 + 实验细节 + 必要图示。
288
+
289
+ #### 模块 E(模板)
290
+ 伪代码 + 假设清单 + 失败模式 + 强弱点评 + 下一步研究。
291
+
292
+ #### 模块 F(模板)
293
+ 15-40 术语条目 + 术语依赖图(文字版)。
294
+
295
+ #### 模块 G(模板)
296
+ 关键事实清单(双来源)+ 冲突说明 + 引用列表。
297
+
298
+ #### 模块 H(模板)
299
+ 全量索引 + TOP 深读 + 图表关系/实验设置图 + 图与结论关系说明。
300
+ {% endif %}
77
301
 
78
302
  Document content:
79
303
  {{ content }}
80
304
 
81
305
  JSON Schema:
82
306
  {{ schema }}
307
+
308
+ {% if stage_name %}
309
+ ---
310
+ Critical Instructions for Stage {{ stage_name }}:
311
+ 1) OUTPUT FORMAT: STRICT JSON only. No markdown fences outside the JSON.
312
+ 2) COMPLETENESS: You must cover ALL requirements listed for Module {{ stage_name }} above, in detail.
313
+ 3) NEGATIVE CONSTRAINT: Do NOT generate fields for other modules.
314
+ {% endif %}
@@ -3,4 +3,5 @@ Output language: {{ output_language }}.
3
3
  Extract structured data from the provided markdown document.
4
4
  Return ONLY valid JSON that conforms to the given JSON Schema.
5
5
  The field "paper_authors" MUST be an array of strings (each author name as one item).
6
+ If affiliations are available, extract them into "paper_institutions" as a list of institution names.
6
7
  If a field is unknown, use an empty string or empty list per schema.
@@ -42,6 +42,7 @@ Output language: {{ output_language }}. Use that language in all answers (if zh,
42
42
  5) 防幻觉:超出原文必须标【推测】;原文未给证据/范围必须写“论文未给出”或【证据不足】。
43
43
  6) 输出顺序严格按 Q1→Q8。除 Q8 的“5 bullets”外,不要堆长列表;保持信息密度。
44
44
  7) 输出语言以 {{ output_language }} 为准(zh 时使用中文)。
45
+ 8) 图示要求:仅在内容触发时输出 Mermaid 架构图。触发词:architecture/module/pipeline/stage/system/flow 或明确模块描述。图放在 Q3 内。
45
46
 
46
47
  ========================
47
48
  Mermaid/流程图要求(避免中文报错)
@@ -73,6 +74,7 @@ Q3) 作者如何解决这个问题?(必须含文字流程图)
73
74
  - 必须提供一个“文字流程图(ASCII)”,示例格式:
74
75
  [争点] -> [主论题] -> [关键概念界定] -> [论证路线A] -> [关键反对] -> [回应] -> [结论/含义]
75
76
  - 若用户要求 Mermaid,再额外输出 Mermaid-safe 版本(遵守避坑规则)。
77
+ - 若触发图示要求,请在 Q3 中同时给出 Mermaid-safe 版本。
76
78
 
77
79
  Q4) 论文使用了哪些“证据载体/材料/设定”?为什么这些材料能验证/支撑主张?
78
80
  (哲学版替代“数据集与实现设置”)
@@ -3,4 +3,6 @@ Output language: {{ output_language }}.
3
3
  Extract structured data from the provided markdown document.
4
4
  Return ONLY valid JSON that conforms to the given JSON Schema.
5
5
  The field "paper_authors" MUST be an array of strings (each author name as one item).
6
+ If affiliations are available, extract them into "paper_institutions" as a list of institution names.
7
+ Ensure JSON strings escape newlines and code blocks properly.
6
8
  If a field is unknown, use an empty string or empty list per schema.
@@ -9,6 +9,10 @@ Previously completed outputs (JSON): {{ previous_outputs }}
9
9
  Answer each question in the corresponding JSON field question1 through question8.
10
10
  Use Markdown in each answer if helpful.
11
11
  Output language: {{ output_language }}. Use that language in all answers (if zh, use Chinese).
12
+
13
+ Diagram guidance (only when relevant; do not invent):
14
+ - In question3, include a mermaid architecture diagram when the paper describes system/model architecture or algorithm flow.
15
+ - Triggers: "architecture", "module", "pipeline", "stage", "system", "flow" or explicit block/module descriptions.
12
16
  {% endif %}
13
17
 
14
18
  Questions:
@@ -3,4 +3,6 @@ Output language: {{ output_language }}.
3
3
  Extract structured data from the provided markdown document.
4
4
  Return ONLY valid JSON that conforms to the given JSON Schema.
5
5
  The field "paper_authors" MUST be an array of strings (each author name as one item).
6
+ If affiliations are available, extract them into "paper_institutions" as a list of institution names.
7
+ Ensure JSON strings escape newlines and code blocks properly.
6
8
  If a field is unknown, use an empty string or empty list per schema.
@@ -3,4 +3,6 @@ Output language: {{ output_language }}.
3
3
  Extract structured data from the provided markdown document.
4
4
  Return ONLY valid JSON that conforms to the given JSON Schema.
5
5
  The field "paper_authors" MUST be an array of strings (each author name as one item).
6
+ If affiliations are available, extract them into "paper_institutions" as a list of institution names.
7
+ Ensure JSON strings escape newlines and code blocks properly.
6
8
  If a field is unknown, use an empty string or empty list per schema.
@@ -15,6 +15,8 @@ Write a single-paragraph summary that covers:
15
15
  - real-world scenarios and constraints
16
16
  - the main content summary with one core formula/mechanism
17
17
  Output language: {{ output_language }}. Use that language in all answers (if zh, use Chinese).
18
+
19
+ If affiliations are present, include them in paper_institutions.
18
20
  {% endif %}
19
21
 
20
22
  Document content:
@@ -8,6 +8,40 @@ import httpx
8
8
  from deepresearch_flow.paper.providers.base import ProviderError
9
9
 
10
10
 
11
+ def _extract_error_message(response: httpx.Response) -> str:
12
+ parts: list[str] = []
13
+ try:
14
+ data = response.json()
15
+ except ValueError:
16
+ data = None
17
+ if isinstance(data, dict):
18
+ error = data.get("error")
19
+ if isinstance(error, dict):
20
+ for key in ("code", "type", "message"):
21
+ value = error.get(key)
22
+ if isinstance(value, str):
23
+ value = value.strip()
24
+ if value and value not in parts:
25
+ parts.append(value)
26
+ elif isinstance(error, str):
27
+ value = error.strip()
28
+ if value and value not in parts:
29
+ parts.append(value)
30
+ for key in ("code", "type", "message"):
31
+ value = data.get(key)
32
+ if isinstance(value, str):
33
+ value = value.strip()
34
+ if value and value not in parts:
35
+ parts.append(value)
36
+ if parts:
37
+ return " | ".join(parts)
38
+ text = (response.text or "").strip()
39
+ if text:
40
+ return text
41
+ reason = response.reason_phrase or "HTTP error"
42
+ return f"{response.status_code} {reason}".strip()
43
+
44
+
11
45
  async def chat(
12
46
  client: httpx.AsyncClient,
13
47
  endpoint: str,
@@ -48,12 +82,20 @@ async def chat(
48
82
  raise ProviderError(str(exc), retryable=True) from exc
49
83
 
50
84
  if response.status_code == 429:
51
- raise ProviderError(response.text, status_code=429, retryable=True)
85
+ raise ProviderError(_extract_error_message(response), status_code=429, retryable=True)
52
86
  if response.status_code >= 500:
53
- raise ProviderError(response.text, status_code=response.status_code, retryable=True)
87
+ raise ProviderError(
88
+ _extract_error_message(response),
89
+ status_code=response.status_code,
90
+ retryable=True,
91
+ )
54
92
  if response.status_code >= 400:
55
93
  structured_error = structured_mode in ("json_schema", "json_object")
56
- raise ProviderError(response.text, status_code=response.status_code, structured_error=structured_error)
94
+ raise ProviderError(
95
+ _extract_error_message(response),
96
+ status_code=response.status_code,
97
+ structured_error=structured_error,
98
+ )
57
99
 
58
100
  data = response.json()
59
101
  choices = data.get("choices") or []
@@ -8,6 +8,40 @@ import httpx
8
8
  from deepresearch_flow.paper.providers.base import ProviderError
9
9
 
10
10
 
11
+ def _extract_error_message(response: httpx.Response) -> str:
12
+ parts: list[str] = []
13
+ try:
14
+ data = response.json()
15
+ except ValueError:
16
+ data = None
17
+ if isinstance(data, dict):
18
+ error = data.get("error")
19
+ if isinstance(error, dict):
20
+ for key in ("code", "type", "message"):
21
+ value = error.get(key)
22
+ if isinstance(value, str):
23
+ value = value.strip()
24
+ if value and value not in parts:
25
+ parts.append(value)
26
+ elif isinstance(error, str):
27
+ value = error.strip()
28
+ if value and value not in parts:
29
+ parts.append(value)
30
+ for key in ("code", "type", "message"):
31
+ value = data.get(key)
32
+ if isinstance(value, str):
33
+ value = value.strip()
34
+ if value and value not in parts:
35
+ parts.append(value)
36
+ if parts:
37
+ return " | ".join(parts)
38
+ text = (response.text or "").strip()
39
+ if text:
40
+ return text
41
+ reason = response.reason_phrase or "HTTP error"
42
+ return f"{response.status_code} {reason}".strip()
43
+
44
+
11
45
  async def chat(
12
46
  client: httpx.AsyncClient,
13
47
  base_url: str,
@@ -42,12 +76,20 @@ async def chat(
42
76
  raise ProviderError(str(exc), retryable=True) from exc
43
77
 
44
78
  if response.status_code == 429:
45
- raise ProviderError(response.text, status_code=429, retryable=True)
79
+ raise ProviderError(_extract_error_message(response), status_code=429, retryable=True)
46
80
  if response.status_code >= 500:
47
- raise ProviderError(response.text, status_code=response.status_code, retryable=True)
81
+ raise ProviderError(
82
+ _extract_error_message(response),
83
+ status_code=response.status_code,
84
+ retryable=True,
85
+ )
48
86
  if response.status_code >= 400:
49
87
  structured_error = structured_mode in ("json_schema", "json_object")
50
- raise ProviderError(response.text, status_code=response.status_code, structured_error=structured_error)
88
+ raise ProviderError(
89
+ _extract_error_message(response),
90
+ status_code=response.status_code,
91
+ structured_error=structured_error,
92
+ )
51
93
 
52
94
  data = response.json()
53
95
  choices = data.get("choices") or []
@@ -25,6 +25,7 @@
25
25
  "module_m4": {"type": "string"},
26
26
  "module_m5": {"type": "string"},
27
27
  "module_m6": {"type": "string"},
28
+ "paper_institutions": {"type": "array", "items": {"type": "string"}},
28
29
  "output_language": {"type": "string"}
29
30
  }
30
31
  }
@@ -41,6 +41,7 @@
41
41
  "module_f": {"type": "string"},
42
42
  "module_g": {"type": "string"},
43
43
  "module_h": {"type": "string"},
44
+ "paper_institutions": {"type": "array", "items": {"type": "string"}},
44
45
  "output_language": {"type": "string"}
45
46
  }
46
47
  }
@@ -40,6 +40,12 @@
40
40
  "summary": {
41
41
  "type": "string"
42
42
  },
43
+ "paper_institutions": {
44
+ "type": "array",
45
+ "items": {
46
+ "type": "string"
47
+ }
48
+ },
43
49
  "output_language": {
44
50
  "type": "string"
45
51
  }
@@ -29,6 +29,7 @@
29
29
  "question6": {"type": "string"},
30
30
  "question7": {"type": "string"},
31
31
  "question8": {"type": "string"},
32
+ "paper_institutions": {"type": "array", "items": {"type": "string"}},
32
33
  "output_language": {"type": "string"}
33
34
  }
34
35
  }
@@ -0,0 +1,4 @@
1
+ """Snapshot build + API utilities for production deployments."""
2
+
3
+ from __future__ import annotations
4
+