-
Notifications
You must be signed in to change notification settings - Fork 46
Expand file tree
/
Copy pathunified_retrieval_service.py
More file actions
122 lines (98 loc) · 3.53 KB
/
Copy pathunified_retrieval_service.py
File metadata and controls
122 lines (98 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"""
统一检索服务
提供知识库内容的统一检索接口,支持多种知识库类型(向量、知识图谱等)。
使用策略模式实现不同知识库类型的检索逻辑。
"""
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