ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

知识检索系统评审,先守住权限和引用边界

知识检索系统评审,先守住权限和引用边界 知识检索系统评审先守住权限和引用边界1. 代码评审里的暗坑为什么 Vector DB 不会提示 403在企业级知识库 RAG 系统的开发与代码评审Code Review中常见的隐患示例代码如下# 隐患示例直接拿用户 Prompt 转 embedding 后调用 vector_db.search query_vector embedder.encode(user_prompt) docs vector_db.search(collectioncompany_kb, vectorquery_vector, top_k5)这段代码在单租户测试中可以运行但多租户环境需要明确验证数据隔离。向量检索是否支持过滤、过滤是否由服务端强制执行、缓存键是否包含租户和权限版本都应根据所用存储和访问层逐项确认。不能把检索结果天然当成已经鉴权的数据。在 RAG 工程落地中类似这种“能跑通但极其危险”的代码比比皆是。为了防止盲目上线拖垮系统需制定严格的 RAG Code Review 门禁机制。2. 核心门禁从向量鉴权到召回熔断在 Code Review 阶段应当强制执行三层硬性拦截规则2.1 强制硬隔离过滤 (Mandatory Tenant Filter)所有针对 Vector DB 的 Query 操作必须接受tenant_id和user_role参数。代码中不得出现无filter条件的纯高维近邻搜索。2.2 Score Threshold 语义熔断召回分数的含义依赖模型、距离度量和索引配置不能把单一数值当成通用门槛。应使用带人工标注的查询集校准阈值并在低置信结果时返回不足以回答或要求补充信息回答阶段还要保留可核对的引用。2.3 Context Window 挤压防护限制注入 Prompt 的总 Token 数。当 Chunk 拼装后的总长度超出预算时必须按 Score 降序进行 Truncate而不是抛出 Exception 或者让请求直接在 LLM API 端被截断。3. 生产级 RAG 检索校验管线实现以下使用 Python 编写了一套贴合生产实践的 RAG Pipeline 校验与安全门禁组件import time import logging from typing import List, Dict, Any, Optional from pydantic import BaseModel, Field logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) class UserContext(BaseModel): user_id: str tenant_id: str roles: List[str] class RetrievedChunk(BaseModel): chunk_id: str content: str score: float tenant_id: str class RAGSecurityException(Exception): pass class RAGQualityGate: RAG 质量与安全审查门禁组件 def __init__(self, score_threshold: float 0.65, max_context_tokens: int 2000): self.score_threshold score_threshold self.max_context_tokens max_context_tokens def validate_and_filter_retrieval( self, user_ctx: UserContext, raw_chunks: List[RetrievedChunk] ) - List[RetrievedChunk]: 门禁校验 1: 验证租户隔离防线 门禁校验 2: 低质 Score 过滤 valid_chunks: List[RetrievedChunk] [] for chunk in raw_chunks: # 租户越权检测 if chunk.tenant_id ! user_ctx.tenant_id: logging.error(f[SECURITY ALARM] 检测到越权 Chunk 召回! Task Tenant: {user_ctx.tenant_id}, Chunk Tenant: {chunk.tenant_id}) raise RAGSecurityException(检索链路安全越权请求被强制阻断) # 得分熔断检测 if chunk.score self.score_threshold: logging.warning(f[QUALITY GATE] Chunk {chunk.chunk_id} 得分低于阈值 ({chunk.score:.3f} {self.score_threshold}), 剔除) continue valid_chunks.append(chunk) # 按得分降序 valid_chunks.sort(keylambda x: x.score, reverseTrue) return valid_chunks def assemble_prompt_context(self, chunks: List[RetrievedChunk]) - str: 门禁校验 3: Token 上限截断与 Context 组装 assembled_text current_token_count 0 for chunk in chunks: # 粗略计算 Token 数量生产中建议使用 tiktoken estimated_tokens len(chunk.content) // 2 if current_token_count estimated_tokens self.max_context_tokens: logging.info(f[PROMPT LIMIT] Context 达到上限 {self.max_context_tokens} Token触发截断) break assembled_text f\n--- 参考文档段落 (Relevance: {chunk.score:.2f}) ---\n{chunk.content}\n current_token_count estimated_tokens return assembled_text class SecureRAGPipeline: def __init__(self, gate: RAGQualityGate): self.gate gate def mock_vector_db_search(self, query: str, tenant_id: str) - List[RetrievedChunk]: # 模拟检索返回数据 return [ RetrievedChunk(chunk_idC-101, contentMySQL 主从同步延迟排查指引..., score0.88, tenant_idtenant_id), RetrievedChunk(chunk_idC-102, contentGo 协程池参数调优实战..., score0.61, tenant_idtenant_id), # 得分较低 RetrievedChunk(chunk_idC-999, content机密薪酬数据..., score0.95, tenant_idOTHER_TENANT) # 越权测试数据 ] def execute_query(self, user_prompt: str, user_ctx: UserContext) - str: logging.info(f收到用户 Query: {user_prompt}, Tenant: {user_ctx.tenant_id}) # 1. 模拟向量检索生产中需在 DB 查询语句中拼入 tenant_id filter raw_results self.mock_vector_db_search(user_prompt, tenant_iduser_ctx.tenant_id) # 安全测试模拟移除非法越权数据 safe_results [r for r in raw_results if r.tenant_id user_ctx.tenant_id] # 2. 门禁检查 filtered_chunks self.gate.validate_and_filter_retrieval(user_ctx, safe_results) if not filtered_chunks: return 抱歉检索到的相关知识库内容匹配度较低无法回答该问题。 # 3. Prompt 组装 context_str self.gate.assemble_prompt_context(filtered_chunks) final_prompt f基于以下参考信息回答用户问题:\n{context_str}\n问题: {user_prompt} return final_prompt if __name__ __main__: gate RAGQualityGate(score_threshold0.65, max_context_tokens1000) pipeline SecureRAGPipeline(gate) user UserContext(user_idU-882, tenant_idTENANT_A, roles[developer]) print( 测试场景: 正常检索与门禁过滤 ) prompt_res pipeline.execute_query(如何排查 MySQL 同步延迟, user) print(prompt_res)4. 灰度复盘审查 CheckList 的落地效果可以把这些检查做成审查清单或持续集成规则检索入口是否携带身份上下文过滤条件是否在服务端生效缓存和异步任务是否复用同一权限边界。效果要用本系统的脱敏测试集和监控数据验证不应预先承诺拦截率、质量提升或资源收益。5. 收尾总结知识检索既要看相关性也要看访问边界。权限过滤应由确定性组件完成模型只处理已经获准进入上下文的材料。评审时逐项检查文档进入索引、召回、重排和回答引用四个阶段的身份信息是否一致。评审时逐项检查文档进入索引、召回、重排和回答引用四个阶段的身份信息是否一致。缓存键和异步任务同样要带上租户与权限版本入口有过滤而缓存没有隔离仍会造成越权。用明确的越权样例验证拒绝行为比阅读提示词更可靠。
返回列表