@lzhzzzzwill/cofos 1.0.2 → 1.1.0
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.
- package/README.md +36 -10
- package/RUNTIME.md +38 -0
- package/bin/cofos.js +80 -20
- package/package.json +16 -4
- package/requirements.txt +0 -3
- package/runtime/config/config.yaml +73 -260
- package/runtime/config/prompt_templates.yaml +73 -369
- package/runtime/src/data_processing/__init__.py +2 -27
- package/runtime/src/data_processing/utils.py +22 -1
- package/runtime/src/inference/__init__.py +2 -6
- package/runtime/src/inference/query_router.py +23 -11
- package/runtime/src/inference/student_adapter_inference.py +312 -61
- package/runtime/src/retrieval/__init__.py +14 -7
- package/runtime/src/retrieval/retrieve_evidence.py +84 -25
- package/scripts/chat.py +91 -28
- package/scripts/sync_runtime.py +45 -0
- package/runtime/config/qwen3_5_config.md +0 -46
- package/runtime/src/data_processing/clean_json_records.py +0 -387
- package/runtime/src/data_processing/parse_wos_xlsx.py +0 -255
- package/runtime/src/data_processing/schema_utils.py +0 -56
- package/runtime/src/inference/run_kg_grounded_inference.py +0 -370
- package/runtime/src/retrieval/build_faiss_index.py +0 -328
|
@@ -1,403 +1,107 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Your task is to extract structured information from scientific literature about COF-catalyzed ROS generation reactions.
|
|
8
|
-
|
|
9
|
-
Follow these rules STRICTLY:
|
|
10
|
-
1. ONLY extract information that is explicitly stated or clearly implied in the provided text
|
|
11
|
-
2. DO NOT infer or guess species that are not mentioned in the text
|
|
12
|
-
3. If evidence is insufficient, return status: "insufficient_evidence"
|
|
13
|
-
4. H2O2 should be categorized as "oxygen-derived target product" in 2e- ORR or photoproduction systems, NOT as a radical ROS
|
|
14
|
-
5. All JSON fields must be filled with actual content - never use empty strings
|
|
15
|
-
|
|
16
|
-
Schema specification:
|
|
17
|
-
- material_context: material_type, active_site, structural_feature
|
|
18
|
-
- reaction_environment: phase, oxidant_source, driving_force, notes
|
|
19
|
-
- dominant_ros_or_product: array of objects with species, category, role, basis, evidence
|
|
20
|
-
- secondary_or_intermediate_ros: array of objects with species, role, basis, evidence
|
|
21
|
-
- mechanism_intermediates: array of objects with species, notation_in_paper, role, evidence
|
|
22
|
-
- mechanism: array of strings describing the mechanism steps
|
|
23
|
-
|
|
24
|
-
extraction_user_prompt: |
|
|
25
|
-
Paper Title: {paper_title}
|
|
26
|
-
DOI: {doi}
|
|
27
|
-
Abstract: {abstract}
|
|
28
|
-
|
|
29
|
-
Text chunk to extract from:
|
|
30
|
-
{chunk_text}
|
|
31
|
-
|
|
32
|
-
Please extract COF-ROS mechanism information following this exact JSON schema:
|
|
33
|
-
|
|
34
|
-
{{
|
|
35
|
-
"material_context": {{
|
|
36
|
-
"material_type": "donor-acceptor COF, donor-only COF, acceptor-only COF, or other",
|
|
37
|
-
"active_site": "TEMPO, carbazole, triazine, triazine, etc.",
|
|
38
|
-
"structural_feature": "pore size, layer spacing, etc."
|
|
39
|
-
}},
|
|
40
|
-
"reaction_environment": {{
|
|
41
|
-
"phase": "aqueous, organic, mixed, or gas-phase",
|
|
42
|
-
"oxidant_source": "O2, air, H2O2, PMS, PDS, H2O, or none",
|
|
43
|
-
"driving_force": "visible light, UV light, sunlight, dark condition, or electrochemical",
|
|
44
|
-
"notes": "any additional relevant conditions"
|
|
45
|
-
}},
|
|
46
|
-
"dominant_ros_or_product": [
|
|
47
|
-
{{
|
|
48
|
-
"species": "normalized ROS or product name (e.g., ·OH, O2·-, 1O2, H2O2, SO4·-)",
|
|
49
|
-
"category": "radical ROS, non-radical ROS, or oxygen-derived target product",
|
|
50
|
-
"role": "dominant species, major contributor, or main product",
|
|
51
|
-
"basis": "why this species is considered dominant",
|
|
52
|
-
"evidence": "specific evidence from the text supporting this claim"
|
|
53
|
-
}}
|
|
54
|
-
],
|
|
55
|
-
"secondary_or_intermediate_ros": [
|
|
56
|
-
{{
|
|
57
|
-
"species": "normalized ROS or intermediate name",
|
|
58
|
-
"role": "intermediate, auxiliary species, or participant",
|
|
59
|
-
"basis": "why this species is considered secondary",
|
|
60
|
-
"evidence": "specific evidence from the text"
|
|
61
|
-
}}
|
|
62
|
-
],
|
|
63
|
-
"mechanism_intermediates": [
|
|
64
|
-
{{
|
|
65
|
-
"species": "surface or solution intermediate (e.g., *O2, *OOH, *HOOH)",
|
|
66
|
-
"notation_in_paper": "how it's denoted in the paper",
|
|
67
|
-
"role": "reaction intermediate",
|
|
68
|
-
"evidence": "evidence from text"
|
|
69
|
-
}}
|
|
70
|
-
],
|
|
71
|
-
"mechanism": [
|
|
72
|
-
"step-by-step mechanism explanation"
|
|
73
|
-
]
|
|
74
|
-
}}
|
|
75
|
-
|
|
76
|
-
OR if insufficient evidence:
|
|
77
|
-
{{
|
|
78
|
-
"status": "insufficient_evidence",
|
|
79
|
-
"reason": "reason why evidence is insufficient"
|
|
80
|
-
}}
|
|
81
|
-
|
|
82
|
-
IMPORTANT: Do NOT include any text before or after the JSON. Only output valid JSON.
|
|
83
|
-
|
|
84
|
-
validation_system_prompt: |
|
|
85
|
-
You are an expert validator for COF-ROS mechanism extraction results.
|
|
86
|
-
|
|
87
|
-
Your task is to validate the extracted JSON against the original text and check for:
|
|
88
|
-
1. JSON validity and completeness
|
|
89
|
-
2. Evidence consistency
|
|
90
|
-
3. Species normalization
|
|
91
|
-
4. Reasonable mechanistic claims
|
|
92
|
-
|
|
93
|
-
Validation rules:
|
|
94
|
-
1. All required fields must be present and non-empty
|
|
95
|
-
2. Species must be standard ROS names
|
|
96
|
-
3. Evidence must be directly supported by the text
|
|
97
|
-
4. If EPR/ESR/quenching is claimed, the text must contain related keywords
|
|
98
|
-
5. H2O2 in 2e- ORR should NOT be labeled as radical ROS
|
|
99
|
-
6. Species not mentioned in text should be marked as inferred, not confirmed
|
|
100
|
-
|
|
101
|
-
Output format:
|
|
102
|
-
{{
|
|
103
|
-
"is_valid": true/false,
|
|
104
|
-
"validation_errors": ["list of errors"],
|
|
105
|
-
"evidence_level": "high/medium/low",
|
|
106
|
-
"support_status": "supported/partially_supported/unsupported",
|
|
107
|
-
"suggestions": ["list of suggestions"]
|
|
108
|
-
}}
|
|
109
|
-
|
|
110
|
-
teacher_distillation_prompt: |
|
|
111
|
-
You are the 35B teacher model for COF-ROS-Reasoner.
|
|
112
|
-
|
|
113
|
-
Your task is to rewrite a draft SFT target into a high-quality answer that a smaller 4B student model can learn from.
|
|
114
|
-
|
|
115
|
-
Domain:
|
|
116
|
-
- COF / covalent organic framework photocatalysis, oxygen reduction, ROS generation, photodynamic therapy, PMS/PDS activation, and related mechanisms.
|
|
117
|
-
- The answer should directly satisfy the instruction while preserving scientifically relevant conditions and uncertainty.
|
|
118
|
-
|
|
119
|
-
Non-negotiable rules:
|
|
120
|
-
1. Stay strictly within the information provided in the Instruction, Input, and Draft answer.
|
|
121
|
-
2. Do not invent materials, ROS species, products, reaction conditions, mechanisms, papers, evidence methods, yields, rates, or citations.
|
|
122
|
-
3. Preserve condition dependence. Do not describe a ROS/product as generally produced unless the input supports that condition.
|
|
123
|
-
4. Distinguish dominant products/species from secondary ROS, intermediates, probes, spin adducts, and scavenger results.
|
|
124
|
-
5. In H2O2 photoproduction or 2e- ORR contexts, describe H2O2 as an oxygen-derived target product, not as a radical ROS.
|
|
125
|
-
6. Do not claim SO4·- unless PMS, PDS, persulfate, or sulfate-radical evidence is present.
|
|
126
|
-
7. Do not claim EPR/ESR/DMPO/TEMP/scavenger/DRIFTS/DFT evidence unless it appears in the provided content.
|
|
127
|
-
8. If the provided content is incomplete or ambiguous, state the uncertainty explicitly and avoid overclaiming.
|
|
128
|
-
9. Do not output chain-of-thought. Provide only the final student-training answer.
|
|
129
|
-
|
|
130
|
-
Style requirements:
|
|
131
|
-
- Write natural scientific QA prose rather than an extraction report.
|
|
132
|
-
- Match the requested depth and format; prefer a compact paragraph unless the instruction asks for a judgment, correction, list, or detailed explanation.
|
|
133
|
-
- Include the key condition if available: phase, oxidant source, and driving force.
|
|
134
|
-
- Treat the input and draft as private working context. Do not say "provided evidence", "the record", "the paper", or similar source-attribution phrases unless the instruction explicitly asks for evidence or citations.
|
|
135
|
-
- Avoid filler phrases, fixed numbered sections, and unnecessary headings.
|
|
136
|
-
|
|
137
|
-
Instruction:
|
|
138
|
-
{instruction}
|
|
139
|
-
|
|
140
|
-
Input:
|
|
141
|
-
{input}
|
|
142
|
-
|
|
143
|
-
Draft answer:
|
|
144
|
-
{draft_output}
|
|
145
|
-
|
|
146
|
-
Return only the improved answer text.
|
|
147
|
-
|
|
148
|
-
kg_rag_system_prompt: |
|
|
149
|
-
You are COF-ROS-Reasoner, a domain assistant specialized in COF (Covalent Organic Framework)-catalyzed ROS generation mechanisms.
|
|
150
|
-
|
|
151
|
-
Guidelines:
|
|
152
|
-
1. Answer the user's actual question directly in one or two compact paragraphs.
|
|
153
|
-
2. Use the supplied context for accuracy, but do not expose retrieval mechanics or present an extraction report.
|
|
154
|
-
3. Do not use numbered sections, fixed field labels, or headings unless the user asks for a list or comparison.
|
|
155
|
-
4. Mention conditions, secondary species, mechanism, and uncertainty only when they help answer the question.
|
|
156
|
-
5. Do not fabricate ROS, products, conditions, mechanisms, or evidence.
|
|
157
|
-
6. If H2O2 is the main product in a 2e- ORR system, do not call it a radical ROS.
|
|
158
|
-
7. If information is insufficient, say so briefly and do not guess.
|
|
159
|
-
8. Do not mention papers, records, retrieved evidence, provided text, or excerpts unless the user explicitly asks for sources or evidence.
|
|
160
|
-
9. By default, state supported facts directly instead of saying they are reported, shown, or described by a source.
|
|
161
|
-
|
|
162
|
-
Return only the final answer in natural scientific prose.
|
|
163
|
-
|
|
164
|
-
kg_rag_user_prompt: |
|
|
165
|
-
User question:
|
|
166
|
-
{question}
|
|
1
|
+
# COFOS standalone student prompt templates.
|
|
2
|
+
# This file is generated by scripts/sync_fwdemo_runtime.py for the npm CLI.
|
|
3
|
+
student_qa_system_prompt: 'You are COF-ROS-Reasoner, a scientific question-answering
|
|
4
|
+
assistant specializing in covalent organic frameworks, photocatalysis, reactive
|
|
5
|
+
oxygen species, and oxygen-reduction products.
|
|
167
6
|
|
|
168
|
-
Private knowledge-graph context:
|
|
169
|
-
{kg_facts}
|
|
170
7
|
|
|
171
|
-
|
|
172
|
-
|
|
8
|
+
Answer the user''s actual question in the same language as the question unless the
|
|
9
|
+
user requests another language. Start with the useful conclusion and let the depth
|
|
10
|
+
and format follow the request: use natural prose by default, explain further when
|
|
11
|
+
asked, and use bullets or comparisons only when the user asks for them.
|
|
173
12
|
|
|
174
|
-
Answer the question naturally. Use only relevant context, do not expose internal context labels, and do not follow a fixed report template. If no context is relevant, give a general answer without inventing study-specific details.
|
|
175
13
|
|
|
176
|
-
|
|
177
|
-
|
|
14
|
+
Keep H2O2 correctly classified as an oxygen-derived product rather than a radical
|
|
15
|
+
ROS. Do not invent materials, species, conditions, mechanisms, measurements, or
|
|
16
|
+
citations. Use background details silently: state the scientific conclusion directly,
|
|
17
|
+
and discuss sources or measurement methods only when the user asks for them.
|
|
178
18
|
|
|
179
|
-
Answer the user's actual question in the same language as the question unless the user requests another language. Start with the useful conclusion and let the depth and format follow the request: use natural prose by default, explain further when asked, and use bullets or comparisons only when the user asks for them.
|
|
180
19
|
|
|
181
|
-
|
|
20
|
+
When a detail is missing or uncertain, express that as a natural scientific limitation.
|
|
21
|
+
Use wording like "the exact secondary ROS is unclear", "the pathway remains uncertain",
|
|
22
|
+
or "I cannot determine that reliably". Avoid meta-comments about what the assistant
|
|
23
|
+
was given internally.
|
|
182
24
|
|
|
183
|
-
|
|
25
|
+
'
|
|
26
|
+
student_qa_user_prompt: 'User question:
|
|
184
27
|
|
|
185
|
-
student_qa_user_prompt: |
|
|
186
|
-
User question:
|
|
187
28
|
{question}
|
|
188
29
|
|
|
189
|
-
Answer naturally and directly. If the question is broad, provide a useful general explanation rather than pretending it refers to a specific study or material.
|
|
190
30
|
|
|
191
|
-
|
|
192
|
-
|
|
31
|
+
Answer naturally and directly. If the question is broad, provide a useful general
|
|
32
|
+
explanation rather than pretending it refers to a specific study or material.
|
|
33
|
+
|
|
34
|
+
'
|
|
35
|
+
student_qa_no_evidence_user_prompt: 'User question:
|
|
36
|
+
|
|
193
37
|
{question}
|
|
194
38
|
|
|
195
|
-
The retrieval system found no high-confidence COFOS knowledge-graph or BM25 context for this turn. Answer naturally from general scientific knowledge. If the user asks for a specific material result or record-level claim, say that it cannot be determined reliably from the current COFOS knowledge base instead of guessing. Do not mention retrieval, provided text, excerpts, records, or papers unless the user explicitly asks for sources.
|
|
196
39
|
|
|
197
|
-
|
|
198
|
-
|
|
40
|
+
The retrieval system found no high-confidence COFOS knowledge-graph or BM25 context
|
|
41
|
+
for this turn. Answer naturally from general scientific knowledge. If the user asks
|
|
42
|
+
for a specific material result or record-level claim, say that it cannot be determined
|
|
43
|
+
reliably from the current COFOS knowledge base instead of guessing. Do not mention
|
|
44
|
+
retrieval, provided text, excerpts, records, or papers unless the user explicitly
|
|
45
|
+
asks for sources.
|
|
46
|
+
|
|
47
|
+
'
|
|
48
|
+
student_rag_user_prompt: 'User question:
|
|
49
|
+
|
|
199
50
|
{question}
|
|
200
51
|
|
|
52
|
+
|
|
201
53
|
Internal facts for answering, not for citation:
|
|
54
|
+
|
|
202
55
|
{kg_facts}
|
|
203
56
|
|
|
57
|
+
|
|
204
58
|
Internal notes for answering, not for citation:
|
|
59
|
+
|
|
205
60
|
{evidence}
|
|
206
61
|
|
|
207
|
-
Use these internal details only to answer the scientific question. Do not say the answer is based on information, context, notes, records, snippets, evidence, or excerpts. Do not add support-status language such as "confirmed by", "backed by", or "supported by" unless the user explicitly asks for evidence. If a claim is uncertain, state the scientific limitation directly, for example "the secondary ROS is unclear" or "the exact pathway cannot be determined reliably". Do not fill a fixed report template.
|
|
208
62
|
|
|
209
|
-
|
|
210
|
-
|
|
63
|
+
Use these internal details only to answer the scientific question. Do not say the
|
|
64
|
+
answer is based on information, context, notes, records, snippets, evidence, or
|
|
65
|
+
excerpts. Do not add support-status language such as "confirmed by", "backed by",
|
|
66
|
+
or "supported by" unless the user explicitly asks for evidence. If a claim is uncertain,
|
|
67
|
+
state the scientific limitation directly, for example "the secondary ROS is unclear"
|
|
68
|
+
or "the exact pathway cannot be determined reliably". Do not fill a fixed report
|
|
69
|
+
template.
|
|
70
|
+
|
|
71
|
+
'
|
|
72
|
+
student_answer_refinement_system_prompt: 'You are COF-ROS-Reasoner''s final-answer
|
|
73
|
+
renderer.
|
|
74
|
+
|
|
211
75
|
|
|
212
76
|
Output contract:
|
|
77
|
+
|
|
213
78
|
- Output exactly one user-facing answer.
|
|
79
|
+
|
|
214
80
|
- Start immediately with the answer content.
|
|
215
|
-
|
|
216
|
-
- Do not
|
|
217
|
-
|
|
81
|
+
|
|
82
|
+
- Do not write analysis, reasoning steps, planning, checklists, labels, or a "Thinking
|
|
83
|
+
Process" section.
|
|
84
|
+
|
|
85
|
+
- Do not mention prompts, drafts, context, retrieval, snippets, records, or internal
|
|
86
|
+
evidence.
|
|
87
|
+
|
|
88
|
+
- Preserve the draft''s scientific meaning, condition dependence, uncertainty, material
|
|
89
|
+
names, and species names.
|
|
90
|
+
|
|
218
91
|
- Do not add new facts, citations, mechanisms, measurements, or claims.
|
|
92
|
+
|
|
219
93
|
- Prefer direct prose. Use bullets only when answering a multi-item list question.
|
|
220
94
|
|
|
221
|
-
|
|
222
|
-
|
|
95
|
+
'
|
|
96
|
+
student_answer_refinement_user_prompt: 'Question: {question}
|
|
97
|
+
|
|
223
98
|
|
|
224
99
|
Draft to render, not to discuss:
|
|
100
|
+
|
|
225
101
|
{draft_answer}
|
|
226
102
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
# Each key mirrors the generating method name so the correspondence is easy to trace.
|
|
233
|
-
sft_generation:
|
|
234
|
-
instruction_sample:
|
|
235
|
-
instruction: >
|
|
236
|
-
Given a COF material and reaction environment, identify the dominant
|
|
237
|
-
ROS or oxygen-derived product and explain the mechanism.
|
|
238
|
-
input_format: >
|
|
239
|
-
Material: {material_desc}. Condition: {phase}, oxidant source: {oxidant},
|
|
240
|
-
driving force: {driving}.
|
|
241
|
-
material_with_site: "{material_type} with {active_site} active site"
|
|
242
|
-
output:
|
|
243
|
-
dominant_line: "Dominant ROS or product: {species_list}"
|
|
244
|
-
secondary_line: "Secondary ROS: {sec_list}"
|
|
245
|
-
intermediates_line: "Mechanism intermediates: {int_list}"
|
|
246
|
-
mechanism_line: "Mechanism: {mechanism_text}"
|
|
247
|
-
join_separator: ". "
|
|
248
|
-
end_punctuation: "."
|
|
249
|
-
|
|
250
|
-
judgment_sample:
|
|
251
|
-
instruction: "Determine whether the statement is supported by the evidence."
|
|
252
|
-
input_format: "Statement: {statement}"
|
|
253
|
-
statement_format: "{material_type} mainly generates {species} as the dominant ROS."
|
|
254
|
-
output:
|
|
255
|
-
radical: "Correct. {species} is the dominant ROS generated by {material_type}."
|
|
256
|
-
product: >
|
|
257
|
-
Correct. {species} is the main oxygen-derived target product in this system,
|
|
258
|
-
not a radical ROS.
|
|
259
|
-
|
|
260
|
-
correction_sample:
|
|
261
|
-
instruction: "Correct the overclaim in the statement based on the evidence."
|
|
262
|
-
input_format: "Statement: {statement}"
|
|
263
|
-
scenarios:
|
|
264
|
-
h2o2_as_radical:
|
|
265
|
-
statement: "{material_type} mainly generates ·OH as the dominant ROS."
|
|
266
|
-
answer: >
|
|
267
|
-
Incorrect. In this system, H2O2 is the main oxygen-derived target product
|
|
268
|
-
(categorized as oxygen-derived target product, not radical ROS), not ·OH.
|
|
269
|
-
secondary_as_dominant:
|
|
270
|
-
statement: "{material_type} mainly generates {sec_species} as the dominant ROS."
|
|
271
|
-
answer: >
|
|
272
|
-
Incorrect. {dominant_species} is the dominant ROS, while {sec_species}
|
|
273
|
-
is only an auxiliary or secondary species.
|
|
274
|
-
no_conditions:
|
|
275
|
-
statement: "{material_type} generates ROS without any specific conditions."
|
|
276
|
-
answer: >
|
|
277
|
-
Incorrect. ROS generation requires specific conditions including reaction
|
|
278
|
-
phase, oxidant source, and driving force.
|
|
279
|
-
|
|
280
|
-
mechanism_sample:
|
|
281
|
-
instruction: "Explain the mechanism of ROS generation for the given COF material."
|
|
282
|
-
input_format: "Material: {material_type}. Explain the ROS generation mechanism."
|
|
283
|
-
|
|
284
|
-
negative_sample:
|
|
285
|
-
instruction: "Determine whether the statement is supported by the evidence."
|
|
286
|
-
input_format: "Statement: {statement}"
|
|
287
|
-
statement_format: "{material_type} mainly generates {other_species} as the dominant ROS."
|
|
288
|
-
output_format: >
|
|
289
|
-
Not supported. {material_type} mainly generates {correct_species},
|
|
290
|
-
not {other_species}.
|
|
291
|
-
|
|
292
|
-
wrong_ros:
|
|
293
|
-
instruction: "Determine whether the statement is supported by the evidence."
|
|
294
|
-
input_format: "Statement: {statement}"
|
|
295
|
-
statement_format: "{material_type} mainly generates {wrong_species} as the dominant ROS."
|
|
296
|
-
output_format: >
|
|
297
|
-
Not supported. {material_type} mainly generates {correct_species},
|
|
298
|
-
not {wrong_species}.
|
|
299
|
-
|
|
300
|
-
wrong_condition:
|
|
301
|
-
instruction: "Correct the false statement about reaction conditions."
|
|
302
|
-
input_format: "Statement: {statement}"
|
|
303
|
-
statement_format: >
|
|
304
|
-
{material_type} generates ROS under {wrong_phase} with {wrong_driving}.
|
|
305
|
-
output_format: >
|
|
306
|
-
Incorrect. The documented conditions are {correct_phase} with
|
|
307
|
-
{correct_driving}, not {wrong_phase} with {wrong_driving}.
|
|
308
|
-
wrong_pairs:
|
|
309
|
-
- [dark condition, thermal catalysis]
|
|
310
|
-
- [UV light, photocatalysis]
|
|
311
|
-
- [high pressure, normal pressure]
|
|
312
|
-
- [organic phase, aqueous phase]
|
|
313
|
-
|
|
314
|
-
overclaim:
|
|
315
|
-
instruction: "Correct the overclaim in the statement."
|
|
316
|
-
input_format: "Statement: {statement}"
|
|
317
|
-
statement_format: "{material_type} mainly generates {sec_species} as the primary ROS."
|
|
318
|
-
output_format: >
|
|
319
|
-
Incorrect. {dominant_species} is the primary ROS, not {sec_species}.
|
|
320
|
-
|
|
321
|
-
h2o2_radical:
|
|
322
|
-
instruction: "Correct the false statement about ROS classification."
|
|
323
|
-
input_format: "Statement: {statement}"
|
|
324
|
-
statement: "{material_type} generates ·OH as the main ROS during H2O2 production."
|
|
325
|
-
answer: >
|
|
326
|
-
Incorrect. H2O2 is the main oxygen-derived target product
|
|
327
|
-
(categorized as oxygen-derived target product, not radical ROS), not ·OH.
|
|
328
|
-
|
|
329
|
-
condition_omission:
|
|
330
|
-
instruction: "Correct the statement by including the missing oxidant."
|
|
331
|
-
input_format: "Statement: {statement}"
|
|
332
|
-
statement: "{material_type} generates ROS without an oxidant source."
|
|
333
|
-
answer: "Incorrect. The reaction requires {oxidant} as the oxidant source."
|
|
334
|
-
|
|
335
|
-
absent_evidence:
|
|
336
|
-
instruction: "Determine whether the evidence claim is supported."
|
|
337
|
-
input_format: "Statement: {statement}"
|
|
338
|
-
statement: >
|
|
339
|
-
EPR studies with DMPO spin trap confirmed ·OH generation over {material_type}.
|
|
340
|
-
answer: >
|
|
341
|
-
Unsupported. The record does not mention EPR, DMPO, or any spin trapping
|
|
342
|
-
evidence for ·OH.
|
|
343
|
-
|
|
344
|
-
cross_cof:
|
|
345
|
-
instruction: "Determine whether the mechanism can be generalized to another COF."
|
|
346
|
-
input_format: "Statement: {statement}"
|
|
347
|
-
statement: "{other_material} follows the same ROS generation mechanism as {material_type}."
|
|
348
|
-
answer: >
|
|
349
|
-
Not supported. Different COFs may have different ROS generation mechanisms.
|
|
350
|
-
{material_type} generates {dominant_species}, while {other_material}
|
|
351
|
-
may generate different ROS.
|
|
352
|
-
|
|
353
|
-
uncertainty:
|
|
354
|
-
instruction: "Answer with uncertainty if evidence is insufficient."
|
|
355
|
-
input_format: "Statement: {statement}"
|
|
356
|
-
statement: "{material_type} generates ROS through a well-established mechanism."
|
|
357
|
-
answer: >
|
|
358
|
-
Uncertain. The available evidence does not provide detailed mechanistic information.
|
|
359
|
-
|
|
360
|
-
# ── RAG-SFT templates ──
|
|
361
|
-
rag_sft:
|
|
362
|
-
question_format: >
|
|
363
|
-
What ROS or oxygen-derived product does {material} generate under {conditions}?
|
|
364
|
-
answer_openings:
|
|
365
|
-
- "Under {conditions}, {material} primarily produces {dominant}."
|
|
366
|
-
- "{material} mainly yields {dominant} under {conditions}."
|
|
367
|
-
- "For {material}, the main ROS or oxygen-derived product under {conditions} is {dominant}."
|
|
368
|
-
secondary_sentence: "Secondary ROS or participating species include {secondary}."
|
|
369
|
-
intermediates_sentence: "Relevant mechanistic intermediates include {intermediates}."
|
|
370
|
-
instruction: >
|
|
371
|
-
Answer the COF-ROS question naturally using the supplied context. Give the
|
|
372
|
-
conclusion directly, preserve condition dependence, distinguish dominant
|
|
373
|
-
products from secondary ROS, and do not call H2O2 a radical ROS.
|
|
374
|
-
input_format: |
|
|
375
|
-
Question:
|
|
376
|
-
{question}
|
|
377
|
-
|
|
378
|
-
Private knowledge-graph context:
|
|
379
|
-
{kg_facts}
|
|
380
|
-
|
|
381
|
-
Private retrieved context:
|
|
382
|
-
{evidence}
|
|
383
|
-
|
|
384
|
-
# ── Interaction and demo ──
|
|
385
|
-
interaction:
|
|
386
|
-
greetings:
|
|
387
|
-
hi: "Hello! What would you like to know about COFs or reactive oxygen species?"
|
|
388
|
-
hello: "Hello! What would you like to know about COFs or reactive oxygen species?"
|
|
389
|
-
hey: "Hello! What would you like to know about COFs or reactive oxygen species?"
|
|
390
|
-
你好: "你好!你想了解 COF、光催化还是活性氧相关问题?"
|
|
391
|
-
您好: "您好!你想了解 COF、光催化还是活性氧相关问题?"
|
|
392
|
-
嗨: "你好!你想了解 COF、光催化还是活性氧相关问题?"
|
|
393
|
-
在吗: "在的。你想了解哪方面的 COF 或活性氧问题?"
|
|
394
|
-
thanks: "You're welcome."
|
|
395
|
-
thank you: "You're welcome."
|
|
396
|
-
谢谢: "不客气。"
|
|
397
|
-
感谢: "不客气。"
|
|
398
|
-
|
|
399
|
-
demo:
|
|
400
|
-
questions:
|
|
401
|
-
- "What ROS does TT-T-COF generate under visible light photocatalysis?"
|
|
402
|
-
- "Which COF materials are reported to generate H2O2 as the main product?"
|
|
403
|
-
- "What is the mechanism of ROS generation in donor-acceptor COFs?"
|
|
103
|
+
|
|
104
|
+
Write only the final natural answer. Do not include any preface, analysis, plan,
|
|
105
|
+
checklist, or explanation of how you rewrote it.
|
|
106
|
+
|
|
107
|
+
'
|
|
@@ -1,31 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
2
|
+
"""COFOS data-processing package."""
|
|
3
3
|
|
|
4
4
|
from .utils import ensure_directory, load_config, setup_logging
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
def __getattr__(name):
|
|
8
|
-
"""Lazy-load optional parser dependencies only when needed."""
|
|
9
|
-
if name == "JSONCleaner":
|
|
10
|
-
from .clean_json_records import JSONCleaner
|
|
11
|
-
|
|
12
|
-
return JSONCleaner
|
|
13
|
-
if name == "WoSParser":
|
|
14
|
-
from .parse_wos_xlsx import WoSParser
|
|
15
|
-
|
|
16
|
-
return WoSParser
|
|
17
|
-
if name == "PDFParser":
|
|
18
|
-
from .parse_pdf_text import PDFParser
|
|
19
|
-
|
|
20
|
-
return PDFParser
|
|
21
|
-
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
__all__ = [
|
|
25
|
-
"JSONCleaner",
|
|
26
|
-
"WoSParser",
|
|
27
|
-
"PDFParser",
|
|
28
|
-
"setup_logging",
|
|
29
|
-
"ensure_directory",
|
|
30
|
-
"load_config",
|
|
31
|
-
]
|
|
6
|
+
__all__ = ["setup_logging", "ensure_directory", "load_config"]
|
|
@@ -5,7 +5,28 @@ COF-ROS-Reasoner: 数据处理工具函数
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Dict, Any
|
|
8
|
+
from typing import Dict, Any, Optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def project_root() -> Path:
|
|
12
|
+
"""Return the tree root that owns ``config/`` and ``src/``.
|
|
13
|
+
|
|
14
|
+
This file lives at ``<root>/src/data_processing/utils.py`` in both the main
|
|
15
|
+
project and the ``fwdemo/runtime`` bundle, so the root is two levels up.
|
|
16
|
+
"""
|
|
17
|
+
return Path(__file__).resolve().parents[2]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def resolve_under_root(value: Any, root: Optional[Path] = None) -> Path:
|
|
21
|
+
"""Resolve *value* against the project root when it is a relative path.
|
|
22
|
+
|
|
23
|
+
Callers used to open ``config/prompt_templates.yaml`` directly, which only
|
|
24
|
+
worked when the process happened to be started from the project root.
|
|
25
|
+
"""
|
|
26
|
+
path = Path(value).expanduser()
|
|
27
|
+
if path.is_absolute():
|
|
28
|
+
return path
|
|
29
|
+
return ((root or project_root()) / path).resolve()
|
|
9
30
|
|
|
10
31
|
|
|
11
32
|
def setup_logging(config: Dict[str, Any]) -> None:
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
"""Minimal conversational routing before domain retrieval."""
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
|
-
from pathlib import Path
|
|
5
4
|
from typing import Optional
|
|
6
5
|
|
|
7
6
|
import yaml
|
|
8
7
|
|
|
8
|
+
from data_processing.utils import resolve_under_root
|
|
9
|
+
|
|
10
|
+
# Keep letters, digits and CJK; collapse everything else to a single space.
|
|
11
|
+
# The character class previously read ``[^a-z0一-鿿]`` which kept only the digit
|
|
12
|
+
# ``0`` and silently dropped 1-9, so greetings were normalised inconsistently.
|
|
13
|
+
_NORMALIZE_RE = re.compile(r"[^a-z0-9一-鿿]+")
|
|
14
|
+
|
|
9
15
|
|
|
10
16
|
class QueryRouter:
|
|
11
17
|
"""Handle only turns that should not invoke either retrieval or generation."""
|
|
@@ -16,18 +22,24 @@ class QueryRouter:
|
|
|
16
22
|
def _load_responses(cls) -> dict:
|
|
17
23
|
if cls._RESPONSES is not None:
|
|
18
24
|
return cls._RESPONSES
|
|
19
|
-
prompt_path =
|
|
25
|
+
prompt_path = resolve_under_root("config/prompt_templates.yaml")
|
|
26
|
+
responses = {}
|
|
20
27
|
if prompt_path.exists():
|
|
21
|
-
with open(prompt_path, "r", encoding="utf-8") as
|
|
22
|
-
prompt_config = yaml.safe_load(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
with open(prompt_path, "r", encoding="utf-8") as handle:
|
|
29
|
+
prompt_config = yaml.safe_load(handle) or {}
|
|
30
|
+
raw = prompt_config.get("interaction", {}).get("greetings", {}) or {}
|
|
31
|
+
# Normalise the keys the same way queries are normalised so that a
|
|
32
|
+
# template key like "Hello!" still matches the user typing "hello".
|
|
33
|
+
responses = {
|
|
34
|
+
cls._normalize(key): value for key, value in raw.items()
|
|
35
|
+
}
|
|
36
|
+
cls._RESPONSES = responses
|
|
26
37
|
return cls._RESPONSES
|
|
27
38
|
|
|
39
|
+
@staticmethod
|
|
40
|
+
def _normalize(text: str) -> str:
|
|
41
|
+
return _NORMALIZE_RE.sub(" ", str(text).lower()).strip()
|
|
42
|
+
|
|
28
43
|
@classmethod
|
|
29
44
|
def quick_response(cls, question: str) -> Optional[str]:
|
|
30
|
-
|
|
31
|
-
r"[^a-z0一-鿿]+", " ", question.lower()
|
|
32
|
-
).strip()
|
|
33
|
-
return cls._load_responses().get(normalized)
|
|
45
|
+
return cls._load_responses().get(cls._normalize(question))
|