fix: 缓存系统全面加固 — 版本失效 + 死代码清理 + 防御性改进
基于缓存审查报告 + Claude Code 交叉审查的反馈: P0+ 语义缓存版本失效: - sync.py: 文档变更后清空语义缓存,防止返回过时的 images/sources - document_routes.py: 删除文档时同步清理缓存 - kb_routes.py: 删除向量库时同步清理缓存 P1.5 cache_type 包含式校验: - intent_analyzer.py: != "rag_answer" 改为 == "intent_analysis" P2+ Rerank Cache 版本失效: - cache.py: increment_kb_version 时同时清空 rerank_cache P1+P6 死代码清理: - agentic.py: 移除未使用的 SemanticCache 实例和相关导入 - agentic_base.py: 移除未使用的语义缓存配置导入 - cache.py: 移除 _compute_doc_hash 和未使用的 doc_ids 参数 - engine.py: 移除 set_query_result 调用中的 doc_ids 参数 P7 缓存质量门槛: - config.py: CACHE_MIN_SCORE 从 0.0 改为 0.3
This commit is contained in:
@@ -189,6 +189,8 @@ class RAGCacheManager:
|
||||
# 失效旧版本缓存
|
||||
self.query_cache.invalidate_by_version(old_version)
|
||||
self.embedding_cache.invalidate_by_version(old_version)
|
||||
# Rerank cache 无 kb_version 字段,文档变更时全量清空以防过时分数
|
||||
self.rerank_cache.clear()
|
||||
|
||||
logger.info(f"知识库 {kb_name} 版本更新: {old_version} -> {new_version}")
|
||||
return new_version
|
||||
@@ -196,87 +198,41 @@ class RAGCacheManager:
|
||||
# ==================== Query Cache 方法 ====================
|
||||
|
||||
@staticmethod
|
||||
def _make_query_cache_key(query: str, kb_name: str, kb_version: int, doc_hash: str = "") -> str:
|
||||
def _make_query_cache_key(query: str, kb_name: str, kb_version: int) -> str:
|
||||
"""
|
||||
生成查询缓存 key
|
||||
|
||||
Args:
|
||||
query: 查询文本
|
||||
kb_name: 知识库名称
|
||||
kb_version: 知识库版本号
|
||||
doc_hash: 相关文档版本哈希(细粒度失效)
|
||||
|
||||
Returns:
|
||||
缓存 key
|
||||
生成查询缓存 key(基于 kb_version 的粗粒度失效)
|
||||
"""
|
||||
if doc_hash:
|
||||
# 细粒度:只失效相关文档的缓存
|
||||
return hashlib.md5(
|
||||
f"query:{query}:{kb_name}:{doc_hash}".encode()
|
||||
).hexdigest()
|
||||
else:
|
||||
# 粗粒度:整个知识库版本变化时失效
|
||||
return hashlib.md5(
|
||||
f"query:{query}:{kb_name}:{kb_version}".encode()
|
||||
).hexdigest()
|
||||
return hashlib.md5(
|
||||
f"query:{query}:{kb_name}:{kb_version}".encode()
|
||||
).hexdigest()
|
||||
|
||||
def get_query_result(self, query: str, kb_name: str, doc_ids: List[str] = None) -> Optional[Dict]:
|
||||
def get_query_result(self, query: str, kb_name: str) -> Optional[Dict]:
|
||||
"""
|
||||
获取查询缓存结果
|
||||
|
||||
始终使用粗粒度 key(基于 kb_version),确保 GET/SET key 一致。
|
||||
|
||||
Args:
|
||||
query: 查询文本
|
||||
kb_name: 知识库名称
|
||||
doc_ids: 保留参数以兼容调用方签名(当前未使用)
|
||||
"""
|
||||
kb_version = self.get_kb_version(kb_name)
|
||||
|
||||
# 使用粗粒度 key,与 SET 保持一致
|
||||
key = self._make_query_cache_key(query, kb_name, kb_version)
|
||||
return self.query_cache.get(key)
|
||||
|
||||
def set_query_result(self, query: str, kb_name: str, result: Dict, doc_ids: List[str] = None) -> None:
|
||||
def set_query_result(self, query: str, kb_name: str, result: Dict) -> None:
|
||||
"""
|
||||
设置查询缓存结果
|
||||
|
||||
始终使用粗粒度 key(基于 kb_version),确保 GET/SET key 一致。
|
||||
kb_version 在文档变更时自增,触发整个知识库的缓存失效。
|
||||
|
||||
Args:
|
||||
query: 查询文本
|
||||
kb_name: 知识库名称
|
||||
result: 缓存结果
|
||||
doc_ids: 保留参数以兼容调用方签名(当前未使用)
|
||||
"""
|
||||
kb_version = self.get_kb_version(kb_name)
|
||||
|
||||
# 使用与 GET 相同的粗粒度 key,确保缓存可命中
|
||||
key = self._make_query_cache_key(query, kb_name, kb_version)
|
||||
self.query_cache.set(key, result, kb_version=kb_version)
|
||||
|
||||
def _compute_doc_hash(self, kb_name: str, doc_ids: List[str]) -> str:
|
||||
"""
|
||||
计算文档版本哈希
|
||||
|
||||
用于细粒度缓存失效:只失效相关文档变化时的缓存
|
||||
"""
|
||||
if not doc_ids:
|
||||
return ""
|
||||
|
||||
# 从文档 ID 中提取 source(文件名)
|
||||
sources = set()
|
||||
for doc_id in doc_ids:
|
||||
# doc_id 格式通常为 "filename_text_0" 或类似
|
||||
parts = doc_id.split('_')
|
||||
if parts:
|
||||
sources.add(parts[0])
|
||||
|
||||
# 生成哈希
|
||||
sources_str = ','.join(sorted(sources))
|
||||
return hashlib.md5(f"docs:{sources_str}".encode()).hexdigest()
|
||||
|
||||
# ==================== Embedding Cache 方法 ====================
|
||||
|
||||
@staticmethod
|
||||
|
||||
Reference in New Issue
Block a user