From dc3ee9bc27acb625bf9403a438ea1969e796057f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=9B=A6?= <2584059816@qq.com> Date: Thu, 27 Nov 2025 17:26:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0=20LPMM=20=E7=9F=A5?= =?UTF-8?q?=E8=AF=86=E5=88=B7=E6=96=B0=E8=84=9A=E6=9C=AC=E5=B9=B6=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 引入脚本 scripts/refresh_lpmm_knowledge.py,用于从磁盘手动重新加载并验证 LPMM 知识库。更新用户指南和参数指南,明确说明在导入或删除 LPMM 数据后,需要重新启动或重新初始化主程序。为导入和删除脚本添加面向用户的提示,提醒用户在操作后需要重新启动或重新初始化,以使变更生效。 --- docs-src/lpmm_parameters_guide.md | 6 +++ docs-src/lpmm_user_guide.md | 22 +++++++++-- scripts/delete_lpmm_items.py | 5 +++ scripts/import_openie.py | 5 +++ scripts/refresh_lpmm_knowledge.py | 66 +++++++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 scripts/refresh_lpmm_knowledge.py diff --git a/docs-src/lpmm_parameters_guide.md b/docs-src/lpmm_parameters_guide.md index 8ea0cee6..fc96a87c 100644 --- a/docs-src/lpmm_parameters_guide.md +++ b/docs-src/lpmm_parameters_guide.md @@ -2,6 +2,8 @@ > 本文是对 `config/bot_config.toml` 中 `[lpmm_knowledge]` 段的补充说明。 > 如果你只想使用默认配置,可以不改这些参数,脚本仍然可以正常工作。 +> +> 重要提醒:无论是修改 `[lpmm_knowledge]` 段的参数,还是通过脚本导入 / 删除 LPMM 知识库数据,主程序都需要重启(或在内部调用一次 `lpmm_start_up()`)后,新的参数和知识才会真正生效到聊天侧。 所有与 LPMM 相关的参数,都集中在: @@ -111,6 +113,10 @@ ppr_relation_cap = 50 # 命中关系数超过该值时自动跳过PPR > - 或暂时将 `enable_ppr = false` (除非真的出现问题,否则不建议禁用此项,大幅影响检索效果) > - 调整后重新执行导入或检索,观察日志与系统资源占用。 +> 小提示:每次大改参数或批量删除知识后,建议用 +> - `scripts/test_lpmm_retrieval.py` 看回答风格是否如预期; +> - 如需确认当前磁盘数据能否正常初始化,可执行 `scripts/refresh_lpmm_knowledge.py` 做一次快速自检。 + --- ## 三、开启/关闭 LPMM 与模式说明 diff --git a/docs-src/lpmm_user_guide.md b/docs-src/lpmm_user_guide.md index d98959bf..147ebcab 100644 --- a/docs-src/lpmm_user_guide.md +++ b/docs-src/lpmm_user_guide.md @@ -7,8 +7,11 @@ - 导入 / 删除后的自检与检索效果验证 > 说明:本文默认你已经完成 MaiBot 的基础安装,并能在项目根目录打开命令行终端。 +> 重要提醒:每次使用导入 / 删除相关脚本(如 `import_openie.py`、`delete_lpmm_items.py`)修改 LPMM 知识库后,聊天机器人 / WebUI 端要想看到最新知识,需要重启主程序,或在主程序内部显式调用一次 `lpmm_start_up()` 重新初始化 LPMM --- +。 + ## 一、需要用到的脚本一览 @@ -21,11 +24,9 @@ 调用大模型,从每个段落里抽取实体和三元组,生成中间的 OpenIE JSON 文件。 - `scripts/import_openie.py` 把 `data/openie` 目录中的 OpenIE JSON 文件导入到 LPMM 知识库(向量库 + 知识图)。 - - 删除相关: - `scripts/delete_lpmm_items.py` LPMM 知识库删除入口,支持按批次、按原始文本段落、按哈希列表、按关键字模糊搜索删除。 - - 自检相关: - `scripts/inspect_lpmm_global.py` 查看整个知识库的当前状态:段落/实体/关系条数、知识图节点/边数量、示例内容等。 @@ -33,6 +34,8 @@ 针对某个 OpenIE JSON 批次,检查它在向量库和知识图中的“残留情况”(导入与删除前后对比)。 - `scripts/test_lpmm_retrieval.py` 使用几条预设问题测试 LPMM 检索能力,帮助你判断知识库是否正常工作。 + - `scripts/refresh_lpmm_knowledge.py` + 手动重新加载 `data/embedding` 和 `data/rag` 到内存,用来确认当前磁盘上的 LPMM 知识库能正常初始化。 > 注意:所有命令示例都假设你已经在虚拟环境中,命令行前缀类似 `(.venv)`,并且当前目录是项目根目录。 @@ -209,7 +212,7 @@ ```bash .\.venv\Scripts\python.exe scripts/inspect_lpmm_batch.py ^ --openie-file data/openie/.json - + .\.venv\Scripts\python.exe scripts/inspect_lpmm_global.py ``` @@ -346,8 +349,21 @@ 通过对比不同时间点的输出,你可以判断: - 某些知识是否已经被成功删除(不再出现在回答中); + - 新增的知识是否已经能被检索到。 +### 4.4 进阶:一键刷新(可选) + +- 想简单确认“现在这份 data/embedding + data/rag 是否健康”?执行: + + `.\.venv\Scripts\python.exe scripts/refresh_lpmm_knowledge.py ` + + 它会尝试初始化 LPMM,并打印当前段落/实体/关系条数和图大小。 + + + + + --- ## 五、常见提示与注意事项 diff --git a/scripts/delete_lpmm_items.py b/scripts/delete_lpmm_items.py index 9882aed7..2714297b 100644 --- a/scripts/delete_lpmm_items.py +++ b/scripts/delete_lpmm_items.py @@ -354,6 +354,11 @@ def main(): ) logger.info("删除流程完成") + print( + "\n[NOTICE] 删除脚本执行完毕。如主程序(聊天 / WebUI)已在运行," + "请重启主程序,或在主程序内部调用一次 lpmm_start_up() 以应用最新 LPMM 知识库。" + ) + print("[NOTICE] 如果不清楚 lpmm_start_up 是什么,直接重启主程序即可。") if __name__ == "__main__": diff --git a/scripts/import_openie.py b/scripts/import_openie.py index f9405f59..6698e218 100644 --- a/scripts/import_openie.py +++ b/scripts/import_openie.py @@ -258,6 +258,11 @@ def main(): try: # 在新的事件循环中运行异步主函数 loop.run_until_complete(main_async()) + print( + "\n[NOTICE] OpenIE 导入脚本执行完毕。如主程序(聊天 / WebUI)已在运行," + "请重启主程序,或在主程序内部调用一次 lpmm_start_up() 以应用最新 LPMM 知识库。" + ) + print("[NOTICE] 如果不清楚 lpmm_start_up 是什么,直接重启主程序即可。") finally: # 确保事件循环被正确关闭 if not loop.is_closed(): diff --git a/scripts/refresh_lpmm_knowledge.py b/scripts/refresh_lpmm_knowledge.py new file mode 100644 index 00000000..e70093a8 --- /dev/null +++ b/scripts/refresh_lpmm_knowledge.py @@ -0,0 +1,66 @@ +import os +import sys + +try: + if hasattr(sys.stdout, "reconfigure"): + sys.stdout.reconfigure(encoding="utf-8") + if hasattr(sys.stderr, "reconfigure"): + sys.stderr.reconfigure(encoding="utf-8") +except Exception: + pass + +# 确保能导入 src.* +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + +from src.common.logger import get_logger +from src.config.config import global_config +from src.chat.knowledge import lpmm_start_up, get_qa_manager + +logger = get_logger("refresh_lpmm_knowledge") + + +def main() -> None: + logger.info("开始刷新 LPMM 知识库(重新加载向量库与 KG)...") + + if not global_config.lpmm_knowledge.enable: + logger.warning( + "当前配置中 lpmm_knowledge.enable = false,本次仅刷新磁盘数据与内存结构," + "但聊天侧如未启用 LPMM 仍不会在问答中使用知识库。" + ) + + # 调用标准启动逻辑,内部会加载 data/embedding 与 data/rag + lpmm_start_up() + + qa_manager = get_qa_manager() + if qa_manager is None: + logger.error("刷新后 qa_manager 仍为 None,请检查是否已经成功导入过 LPMM 知识库。") + return + + # 简要输出当前知识库规模,方便人工确认 + embed_manager = qa_manager.embed_manager + kg_manager = qa_manager.kg_manager + + para_vec = len(embed_manager.paragraphs_embedding_store.store) + ent_vec = len(embed_manager.entities_embedding_store.store) + rel_vec = len(embed_manager.relation_embedding_store.store) + nodes = len(kg_manager.graph.get_node_list()) + edges = len(kg_manager.graph.get_edge_list()) + + logger.info("LPMM 知识库刷新完成,当前规模:") + logger.info( + "段落向量=%d, 实体向量=%d, 关系向量=%d, KG节点=%d, KG边=%d", + para_vec, + ent_vec, + rel_vec, + nodes, + edges, + ) + + print("\n[REFRESH] 刷新完成,请注意:") + print("- 本脚本是在独立进程内执行的,用于验证磁盘数据可以正常加载。") + print("- 若主程序已在运行且未在内部调用 lpmm_start_up() 重新初始化,仍需重启或新增管理入口来热刷新。") + print("- 如果不清楚 lpmm_start_up 是什么,只需要重启主程序即可。") + + +if __name__ == "__main__": + main()