Files
rag/core/agentic_meta.py
lacerate551 100d1a06eb init: RAG 知识库服务初始提交
- 后端 API(Flask + Gunicorn)
- RAG 引擎(混合检索 + 云端 Reranker + 引用溯源)
- 文档解析(MinerU + 多格式支持)
- Docker 生产部署配置
- 排除前端项目、敏感配置、模型文件
2026-06-04 17:35:27 +08:00

134 lines
5.9 KiB
Python

"""
Agentic RAG - 元问题处理 Mixin
包含元问题判断和知识库元数据回答方法
"""
import logging
from .agentic_base import logger
logger = logging.getLogger(__name__)
class MetaQuestionMixin:
"""元问题处理方法"""
def _is_meta_question(self, query: str) -> bool:
"""判断是否为元问题(关于知识库本身的问题)"""
meta_patterns = [
"有哪些文件", "什么文件", "哪些文件", "文件列表", "文件目录",
"可以查看", "能查看", "有权限查看", "权限查看",
"能访问", "可以访问", "有权限访问",
"我的权限", "用户权限", "查看权限", "访问权限",
"权限能", "权限可以", "有什么权限", "有哪些权限",
"我能看", "我可以看", "我能查", "我可以查",
"能看到什么", "能查到什么", "可以看什么", "可以查什么",
"知识库有哪些", "库里有", "文档有哪些", "有哪些文档",
"有什么文档", "有什么文件", "包含什么", "包含哪些",
"你知道什么", "你都知道", "你能回答什么",
"系统里有什么", "库里有什么",
"public_kb", "dept_tech", "dept_hr", "dept_finance", "dept_operation",
"kb里", "向量库", "有哪些库", "库列表", "kb有哪些"
]
query_lower = query.lower()
return any(kw in query_lower for kw in meta_patterns)
def _answer_meta_question(self, query: str, allowed_levels: list = None,
role: str = None, department: str = None) -> str:
"""回答元问题(关于知识库本身的问题)"""
try:
source_map = {}
try:
from knowledge.manager import get_kb_manager
from auth.gateway import get_accessible_collections as _get_accessible
kb_mgr = get_kb_manager()
accessible = _get_accessible(role or 'user', department or '', 'read')
for kb_name in accessible:
coll = kb_mgr.get_collection(kb_name)
if not coll:
continue
try:
result = coll.get(include=['metadatas'])
except Exception as e:
logger.debug(f"获取{kb_name}元数据失败: {e}")
continue
for meta in result.get('metadatas', []):
source = meta.get('source', '未知')
level = meta.get('security_level', 'public')
page = meta.get('page')
if source not in source_map:
source_map[source] = {
'count': 0, 'levels': set(),
'pages': set(), 'collections': set()
}
source_map[source]['count'] += 1
source_map[source]['levels'].add(level)
source_map[source]['collections'].add(kb_name)
if page:
source_map[source]['pages'].add(page)
except ImportError:
from core.engine import get_engine
all_docs = get_engine().collection.get(include=['metadatas'])
for meta in all_docs.get('metadatas', []):
source = meta.get('source', '未知')
level = meta.get('security_level', 'public')
page = meta.get('page')
if source not in source_map:
source_map[source] = {
'count': 0, 'levels': set(),
'pages': set(), 'collections': set()
}
source_map[source]['count'] += 1
source_map[source]['levels'].add(level)
if page:
source_map[source]['pages'].add(page)
# 根据安全级别过滤
if allowed_levels:
allowed_set = set(allowed_levels)
filtered_sources = {}
for source, info in source_map.items():
if info['levels'] & allowed_set:
filtered_sources[source] = info
source_map = filtered_sources
if not source_map:
return "抱歉,您当前没有权限查看任何文档,或者知识库为空。"
sorted_sources = sorted(source_map.items(), key=lambda x: x[1]['count'], reverse=True)
answer_parts = [f"📚 **知识库文档列表**(共 {len(sorted_sources)} 个文档)\n"]
for i, (source, info) in enumerate(sorted_sources, 1):
colls = info.get('collections', set())
coll_str = f",所属: {', '.join(sorted(colls))}" if colls else ""
pages_str = ''
if info['pages']:
pages_list = sorted(info['pages'])
if len(pages_list) <= 5:
pages_str = f",页码: {', '.join(map(str, pages_list))}"
else:
pages_str = f",共 {len(info['pages'])}"
answer_parts.append(f"{i}. **{source}** ({info['count']} 条片段{coll_str}{pages_str})")
answer_parts.append(f"\n**总计**: {sum(s[1]['count'] for s in sorted_sources)} 条知识片段")
answer_parts.append(f"\n**您的权限级别**: {', '.join(allowed_levels) if allowed_levels else '全部'}")
answer_parts.append("\n\n💡 **提示**: 您可以直接提问关于这些文档内容的问题。")
return '\n'.join(answer_parts)
except Exception as e:
return f"获取文档列表时出错: {str(e)}\n\n您可以直接提问,我会尝试从知识库中检索相关信息。"