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(), ) # 兼容旧测试替身;真实 Settings 会优先提供本地/远程统一解析后的地址。 milvus_uri = getattr(settings, "resolved_milvus_uri", settings.milvus_uri) vector_store = MilvusKnowledgeClient(milvus_uri, token=settings.milvus_token or None) # 权威元数据只读回查,确保对客答案始终来自已发布、有效的知识条目。 async with SessionFactory() as session: authority = KnowledgeMysqlAuthority(session) service = KnowledgeRetrievalService( embedder, vector_store, KnowledgeRuntimeConfig(), authority ) return await service.search(arguments, context)