feat(knowledge): 新增 query_keywords 工具,基于关键词命中的 BM25 检索#769
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new query_keywords tool to the knowledge base toolkit, enabling keyword-based (BM25) searches as a complement to semantic search. The changes include the definition of the QueryKeywordsInputSchema input model, comprehensive unit tests for the new tool, and updates to the project's changelog and roadmap. The feedback suggests improving the robustness of the query_keywords tool by filtering out empty or whitespace-only strings from the keywords list before performing validation.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if not keywords: | ||
| return "请提供关键词列表" |
There was a problem hiding this comment.
为了提高工具的鲁棒性,建议在检查 keywords 之前先过滤掉空字符串或仅包含空格的无效关键词。否则,如果传入 ["", " "] 这样的参数,虽然能绕过 if not keywords 的检查,但后续拼接出的 query_text 将为空或仅包含空格,从而导致检索异常。
通过列表推导式过滤无效关键词可以有效避免这一问题。
| if not keywords: | |
| return "请提供关键词列表" | |
| keywords = [k.strip() for k in keywords if k.strip()] | |
| if not keywords: | |
| return "请提供关键词列表" |
- 新增 QueryKeywordsInputSchema,接收 keywords 列表 - 新增 query_keywords 工具函数,强制 search_mode=keyword 走 BM25 通道 - 过滤空字符串和纯空格关键词,避免检索异常 - 注册到 get_common_kb_tools(),Agent 可自动发现 - 更新 changelog 和 roadmap
5f4945f to
faccf70
Compare
|
关键词检索其实不仅仅是这个意思,这里想要弥补的短板是精准匹配,类似于 grep 这种,但是知识场景和代码场景不同,又要有一定的模糊匹配。所以我初步的设想就是:
这里 bm25 是由 milvus 本身支持的,不需要做太多工作。但是精准匹配我不确定 milvus 是否支持,如果不支持,如何保证性能的同时完成检索,也需要考虑进去。 |
|
感谢反馈,你说得对,当前 BM25 确实无法保证精准子串匹配排在前面。 我查了一下,Milvus 2.6+ 新增了 # slop=0 精准短语匹配,作为 filter 筛选出包含完整短语的 chunk
filter = "PHRASE_MATCH(content, \"扭转减振器\", 0)"
# 配合 BM25 做排序
collection.search(
data=[query_text],
anns_field="content_sparse",
param=bm25_search_params,
limit=50,
expr=filter,
output_fields=output_fields,
)对应你的三个需求:
但目前项目用的 Milvus 是 v2.5.6, 所以这个功能的完整实现需要升级 Milvus 到 2.6+,想听听你的想法。 |
|
版本升级是没关系的,只要正常的功能都还在就行 |
按作者评审反馈,query_keywords 此前纯 BM25 无法保证精准命中排前。改为基于 Milvus 2.6 PHRASE_MATCH 实现「精准优先 + BM25 兜底」检索策略: - 升级 Milvus v2.5.6 -> v2.6.16(etcd v3.5.25 / minio RELEASE.2024-05-28), 同步更新 compose 与镜像拉取/打包脚本;客户端 pymilvus 已锁 3.0.0 无需动。 - KB 与图谱 content 字段新增 enable_match=True 以支持 PHRASE_MATCH。 - _collection_supports_bm25 增加 enable_match 自检:存量 KB 集合首次访问时 自动 drop 重建+重索引(懒触发、按 KB);图谱集合仅对新建生效(图谱检索纯 向量、不用 PHRASE_MATCH,重建需重跑 LLM 抽取,成本不成比例)。 - aquery keyword 分支重写:PHRASE_MATCH 过滤的精准命中在前(BM25 降序), 不足 final_top_k 时纯 BM25 兜底,按 chunk_id 去重;新增 expr 构造 helper (转义防注入、多关键词 or 连接)、_merge_precise_and_backfill。 - _build_chunk_from_hit 新增 is_precise_match 标记写入 metadata(build_search_output 仅透传 metadata,故标记须放 metadata 才能存活到工具输出)。 - query_keywords 传 precise_match/phrase_match_terms,并过滤空/纯空白关键词。
|
按 @xerrors 老师的反馈重做了 本次改动检索策略:精准优先 + BM25 兜底(对应老师三条要求)
多关键词走 Milvus 升级 2.5.6 → 2.6.16(etcd v3.5.25 / minio RELEASE.2024-05-28),6 个文件(2 compose + 2 init 脚本 + 2 打包脚本)同步。客户端 pymilvus 本就锁 3.0.0,升级服务端是补齐而非引入错配。已起 2.6 实测: schema + 存量自动重建:KB 与图谱 content 字段加
|
|
关于 embedding 重建这里需要慎重考虑,对于大型系统来说,自动触发重建的成本开销。需要确认重建是否需要重新计算 embedding?为什么不是从原始的 embedding 迁移过去?这个需要确认。 另外是 Codex 发现的问题:
|
按评审反馈调整存量集合升级策略并修复 Codex 指出的正确性问题: - 向量迁移替代空重建:存量集合自检缺 enable_match 时,drop 前用 query_iterator 读出全量 embedding 原样回灌新集合,不重算; content_sparse 由新集合 BM25 Function 自动生成,迁移后 flush 保证 PHRASE_MATCH 倒排可见。embedding 模型变更分支仍走重算不迁移。 - 修复 or/and 优先级:多关键词 PHRASE_MATCH 的 or 子句整体加括号, 避免与 file_name 的 and 拼接时 file_name 仅约束首个关键词。 - 修复重排前截断:keyword 分支 _merge_precise_and_backfill 改传 recall_top_k 而非 final_top_k,开启重排/图检索时候选池不再失效。 - 补齐 enable_match 自检单测 fixture,新增迁移/优先级/截断单测, 新增精准匹配集成测试。 测试:test_milvus_kb 22 + test_kbs_tools 12 + 集成精准匹配 2 全绿
|
@xerrors 老师反馈已按你的思路重做,commit 改动1. 向量迁移替代空重建(回应「为什么不从原始 embedding 迁移」) 2. Codex 指出的三处已修
单测 34(milvus_kb 22 + kbs_tools 12)+ 集成精准匹配 2 全绿。
|
|
关于这个迁移,需要判断,如果升级后不执行迁移带来的后果是(a)系统发现 有问题,无法正常完成 KB 检索。(b)关键词检索无法生效,但是原有的检索仍可以正常使用? 如果是 A,则需要考虑更妥善的方法,这种就需要在系统启动的时候就完成检查并在日志给出提示,开发者确认后执行迁移命令。对于后者作为可以在知识库页面给出一个提示,手动完成迁移,并显示进度(tasker)。由于迁移脚本是临时的,因此建议放到一个独立的service 文件里面。 另:建议不要直接使用 Agent 提交 Comment,不然我像是在和 Agent 对话 |
变更描述
实现 roadmap v0.7.1 中的「知识库工具新增 query_keywords 工具,专门用于基于关键词命中的排序」。
新增
query_keywordsAgent 工具,接收关键词列表,走 BM25 通道检索,与query_kb的语义检索互为补充。改动内容:
knowledge/schemas.py:新增QueryKeywordsInputSchema(kb_id + keywords + file_name)agents/toolkits/kbs/tools.py:新增query_keywords工具函数,强制search_mode="keyword"走 BM25 通道,注册到get_common_kb_tools()test/unit/toolkits/test_kbs_tools.py:新增 6 个单元测试,修复旧测试_patch_retrievers的 monkeypatch 方式docs/develop-guides/changelog.md:v0.7.1 开发记录docs/develop-guides/roadmap.md:勾选已完成项测试验证:
在 Docker 环境中通过对话让 Agent 调用
query_keywords,搜索关键词「扭转减振器」,BM25 排序结果准确:精确命中的段落 score 最高,上下文提及次之,远端关联最低。{ "kb_id": "kb_om6wjcmnr1", "results": [ { "id": "file_005d51_chunk_5", "metadata": { "score": 7.05 } }, { "id": "file_005d51_chunk_0", "metadata": { "score": 3.96 } }, { "id": "file_005d51_chunk_1", "metadata": { "score": 0.97 } } ] }单元测试全部通过(16/16)。
变更类型
测试
相关日志或者截图
Agent 工具调用截图已在对话中验证通过。
说明
后续可以考虑给
query_kb也暴露search_mode参数(vector/keyword/hybrid),这样 Agent 只需选一个工具,通过参数选模式,比选两个工具的决策成本更低。底层 Milvus/Dify/Notion 已经支持这三种模式了,只是当前 schema 没暴露出来。