feat(server-release): 从 main 迁移检索增强(章节聚类提升 + BM25 追加修复)

从 main 分支选择性提取检索质量增强代码,不含端口/API 配置变更:

- knowledge/base.py: BM25Index.add_documents 改为追加+去重模式,
  修复多文件上传后仅保留最后文件切片的覆盖 bug
- core/engine.py: 章节聚类提升(_section_cluster_boost)、词法匹配
  辅助种子资格(_chunk_lexical_score)、扩展参数优化
  (CONTEXT_EXPANSION_AFTER 5→8, MAX_EXPANDED_NEIGHBORS 4→8)
- api/chat_routes.py: 路由层词法匹配救援(_rescue_lexical_match)、
  章节聚类救援安全网(_rescue_section_cluster)

部署后需重建 BM25 索引:KnowledgeBaseManager().rebuild_bm25_index('public_kb')
This commit is contained in:
lacerate551
2026-06-17 17:49:36 +08:00
parent fc11b11dda
commit 87f3fae1aa
3 changed files with 390 additions and 14 deletions

View File

@@ -382,18 +382,34 @@ class BM25Index:
def add_documents(self, ids: List[str], documents: List[str], metadatas: List[dict]) -> None:
"""
添加文档到索引(会覆盖原有索引
添加文档到索引(追加模式,自动去重
如果 ID 已存在则更新对应文档,否则追加新文档。
添加后自动重建 BM25 索引。
Args:
ids: 文档 ID 列表
documents: 文档内容列表
metadatas: 文档元数据列表
"""
self.ids = ids
self.documents = documents
self.metadatas = metadatas
if documents:
tokenized = [self.tokenize(doc) for doc in documents]
# 建立已有 ID -> 索引位置 的映射,用于去重
existing_map = {doc_id: idx for idx, doc_id in enumerate(self.ids)}
for i, doc_id in enumerate(ids):
if doc_id in existing_map:
# 更新已有文档
pos = existing_map[doc_id]
self.documents[pos] = documents[i]
self.metadatas[pos] = metadatas[i]
else:
# 追加新文档
existing_map[doc_id] = len(self.ids)
self.ids.append(doc_id)
self.documents.append(documents[i])
self.metadatas.append(metadatas[i])
if self.documents:
tokenized = [self.tokenize(doc) for doc in self.documents]
self.bm25 = BM25Okapi(tokenized)
def search(self, query: str, top_k: int = 10) -> Tuple[List[str], List[str], List[dict], List[float]]: