2026-09-10 18:42:44 +08:00
|
|
|
from typing import Protocol
|
|
|
|
|
|
|
|
|
|
from app.core.config import get_settings
|
|
|
|
|
from app.core.contracts import RequestContext
|
|
|
|
|
from app.core.knowledge_contracts import KnowledgeQuery, KnowledgeSearchResult
|
|
|
|
|
from app.infrastructure.db import SessionFactory
|
|
|
|
|
from app.infrastructure.milvus_knowledge_adapter import MilvusKnowledgeClient
|
|
|
|
|
from app.service.knowledge_authority import KnowledgeMysqlAuthority
|
|
|
|
|
from app.service.knowledge_config import KnowledgeRuntimeConfig
|
|
|
|
|
from app.service.knowledge_retrieval_service import KnowledgeRetrievalService
|
|
|
|
|
from app.service.model_gateway import DatabaseModelGateway
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class EmbeddingGateway(Protocol):
|
|
|
|
|
async def embed(self, *, endpoint_code: str, text: str, timeout_ms: int) -> list[float]: ...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DatabaseEmbeddingAdapter:
|
|
|
|
|
def __init__(
|
|
|
|
|
self, endpoint_code: str, timeout_ms: int, *, gateway: EmbeddingGateway
|
|
|
|
|
) -> None:
|
|
|
|
|
self._endpoint_code = endpoint_code
|
|
|
|
|
self._timeout_ms = timeout_ms
|
|
|
|
|
self._gateway = gateway
|
|
|
|
|
|
|
|
|
|
async def embed(self, text: str) -> list[float]:
|
|
|
|
|
return await self._gateway.embed(
|
|
|
|
|
endpoint_code=self._endpoint_code, text=text, timeout_ms=self._timeout_ms
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def query_knowledge_tool(
|
|
|
|
|
arguments: KnowledgeQuery, context: RequestContext
|
|
|
|
|
) -> KnowledgeSearchResult:
|
|
|
|
|
settings = get_settings()
|
|
|
|
|
if not settings.knowledge_embedding_endpoint_code:
|
|
|
|
|
return KnowledgeSearchResult(
|
|
|
|
|
degraded=True, degradation_reason="embedding_endpoint_unconfigured"
|
|
|
|
|
)
|
|
|
|
|
# 知识向量端点与默认聊天端点隔离,避免回答模型被误用于检索。
|
|
|
|
|
embedder = DatabaseEmbeddingAdapter(
|
|
|
|
|
settings.knowledge_embedding_endpoint_code,
|
|
|
|
|
settings.knowledge_embedding_timeout_ms,
|
|
|
|
|
gateway=DatabaseModelGateway(),
|
|
|
|
|
)
|
2026-09-11 10:13:48 +08:00
|
|
|
# 兼容旧测试替身;真实 Settings 会优先提供本地/远程统一解析后的地址。
|
|
|
|
|
milvus_uri = getattr(settings, "resolved_milvus_uri", settings.milvus_uri)
|
|
|
|
|
vector_store = MilvusKnowledgeClient(milvus_uri, token=settings.milvus_token or None)
|
2026-09-10 18:42:44 +08:00
|
|
|
# 权威元数据只读回查,确保对客答案始终来自已发布、有效的知识条目。
|
|
|
|
|
async with SessionFactory() as session:
|
|
|
|
|
authority = KnowledgeMysqlAuthority(session)
|
|
|
|
|
service = KnowledgeRetrievalService(
|
|
|
|
|
embedder, vector_store, KnowledgeRuntimeConfig(), authority
|
|
|
|
|
)
|
|
|
|
|
return await service.search(arguments, context)
|