Files
deepdata/runtime/deepdata-python/app/module/rag/service/unified_retrieval_service.py
T

123 lines
3.6 KiB
Python

"""
统一检索服务
提供知识库内容的统一检索接口,支持多种知识库类型(向量、知识图谱等)。
使用策略模式实现不同知识库类型的检索逻辑。
"""
import logging
from typing import Any, Dict, List
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.exception import BusinessError, ErrorCodes
from app.db.models.knowledge_gen import KnowledgeBase
from app.module.rag.repository import KnowledgeBaseRepository
from app.module.rag.schema.request import PagingQuery, ChunkFilterQuery, RetrieveReq
from app.module.rag.schema.response import PagedResponse
from .strategy import KnowledgeBaseStrategyFactory
logger = logging.getLogger(__name__)
class UnifiedRetrievalService:
"""统一检索服务
揯供统一的检索接口,根据知识库类型自动选择策略。
"""
def __init__(self, db: AsyncSession):
"""初始化服务
Args:
db: 数据库异步 session
"""
self.db = db
self.kb_repo = KnowledgeBaseRepository(db)
async def query(
self,
knowledge_base_id: str,
**kwargs
) -> Any:
"""直接查询知识库数据(不涉及相似度计算)
Args:
knowledge_base_id: 知识库 ID
**kwargs: 额外参数
- 向量知识库: rag_file_id, paging_query
- 知识图谱: node_label
Returns:
查询结果(格式由具体知识库类型决定)
"""
kb = await self._get_knowledge_base(knowledge_base_id)
strategy = KnowledgeBaseStrategyFactory.create_strategy(kb.type, self.db)
return await strategy.query(knowledge_base_id, **kwargs)
async def search(
self,
request: RetrieveReq
) -> List[Dict[str, Any]]:
"""基于输入文本的相似度检索
Args:
request: 检索请求
Returns:
统一格式的检索结果列表(UnifiedSearchResult)
"""
if not request.knowledge_base_ids:
raise BusinessError(
ErrorCodes.RAG_INVALID_REQUEST,
"至少需要一个知识库 ID"
)
kb = await self._get_knowledge_base(request.knowledge_base_ids[0])
strategy = KnowledgeBaseStrategyFactory.create_strategy(kb.type, self.db)
return await strategy.search(
query_text=request.query,
knowledge_base_ids=request.knowledge_base_ids,
top_k=request.top_k,
threshold=request.threshold,
)
async def get_chunks(
self,
knowledge_base_id: str,
rag_file_id: str,
query: ChunkFilterQuery,
) -> PagedResponse:
"""获取指定 RAG 文件的分块列表(仅向量知识库)
Args:
knowledge_base_id: 知识库 ID
rag_file_id: RAG 文件 ID
query: 分页和过滤参数
Returns:
分块列表(分页)
"""
return await self.query(
knowledge_base_id,
rag_file_id=rag_file_id,
chunk_filter_query=query,
)
async def _get_knowledge_base(self, knowledge_base_id: str) -> KnowledgeBase:
"""获取知识库实体
Args:
knowledge_base_id: 知识库 ID
Returns:
知识库实体
Raises:
BusinessError: 知识库不存在
"""
kb = await self.kb_repo.get_by_id(knowledge_base_id)
if not kb:
raise BusinessError(ErrorCodes.RAG_KNOWLEDGE_BASE_NOT_FOUND)
return kb