@
sillydaddy 不要指望一次向量召回就“选中全部关键句子”,而是让模型自己在“看结果”的过程中,决定要不要扩大范围、补充召回、重新提问。
一个典型的 ReAct 交互轨迹可以长这样(简化版,伪日志):
Thought 1:
任务是抽取“中国人民银行的职责”。先用检索工具看看跟该机构和“职责”相关的片段。
Action 1:
使用 tool_search_chunks
参数:query = "中国人民银行 职责 主要职责"
top_k = 20
检索方式:向量 + 关键词 BM25 混合
Observation 1:
返回了若干句子:
- [chunk_101] ……中国人民银行是国务院组成部门,负责……(开头介绍)
- [chunk_102] ……主要职责是:(一)拟定和执行货币政策……
- [chunk_103] ……(二)防范和化解金融风险……
- [chunk_104] ……(三)维护金融稳定……
- [chunk_205] ……编制情况为机关行政编制若干名……
其中一些句子被分得很碎,看起来每条职责是一小句。
Thought 2:
目前召回里已经出现了一些典型“主要职责是:(一)(二)(三)……”结构。
但这些 chunk 可能只覆盖了前几条,后面可能还有(四)(五)(六)。
我应该基于这些 chunk 的位置,再向前向后扩展一小段上下文,以免漏掉枚举条款。
Action 2:
使用 tool_expand_window
参数:chunk_ids = [101,102,103,104]
window_size = 3 # 每个句子向前、向后各扩 3 句
Observation 2:
得到了一个更完整的段落:
- 段落 P1:包含从“主要职责是:”到“(六)……”的全部条款;
- 同时保留了段首“主要职责是:”这句,方便后续抽取。
Thought 3:
P1 里已经包含了完整的“职责”枚举条款。
接下来可以不再扩展检索范围,而是专注于信息抽取。
我将调用一个专门的抽取工具,把职责条款提成结构化列表。
Action 3:
使用 tool_extract_duties
参数:text = 段落 P1 的完整文本
Observation 3:
抽取结果 duty_list:
1. 拟定和执行货币政策,防止通货膨胀和通货紧缩,保持货币币值稳定。
2. 防范和化解金融风险,维护国家金融安全。
3. 维护金融稳定,推进金融改革和发展。
4. 负责金融市场的监管和发展工作。
5. ……
(略)
Thought 4:
抽取结果看起来已经覆盖了所有枚举条目,且结构化良好。
为保险起见,可以再做一次“职责相关性检查”,确认没有某条“职责”散落在别处被我漏掉。
Action 4:
使用 tool_search_chunks
参数:query = "中国人民银行 职责 负责 主要职责"
top_k = 50
并过滤掉已经在 P1 中的语句,只看其它位置的命中。
Observation 4:
新检索命中的其它片段大多是对上述职责的解释、扩展说明或引用,
而不是新的“主要职责”条目。
Thought 5:
没有观察到新的“职责枚举”,当前 duty_list 可以视为基本完整。
接下来,将其写入 govmap 的结构化数据。
Action 5:
使用 tool_save_structured_result
参数:
entity = "中国人民银行"
type = "职责"
data = duty_list
Observation 5:
保存成功。
Final Answer:
已完成对“中国人民银行”的职责抽取,得到 N 条职责,写入 govmap 。