From c76b7631011ea49f9ffdb1214b884650c8d81fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=83=9C=E5=AE=87?= <17412268+zzzzz11122222@user.noreply.gitee.com> Date: Fri, 11 Sep 2026 10:13:48 +0800 Subject: [PATCH] feat: configure local customer service knowledge runtime --- .env.example | 1 + .gitignore | 1 + app/core/config.py | 6 ++++++ app/infrastructure/milvus_knowledge_adapter.py | 4 ++++ app/service/agent/bootstrap.py | 2 +- app/service/health_service.py | 2 +- app/service/knowledge_config.py | 2 +- app/service/knowledge_tool_service.py | 6 +++--- pyproject.toml | 1 + requirements.txt | 1 + tools/dependency_health_check.py | 2 +- tools/publish_customer_service_knowledge.py | 4 ++-- 12 files changed, 23 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index ba48de3..2225cae 100644 --- a/.env.example +++ b/.env.example @@ -25,6 +25,7 @@ MESSAGE_BROKER_OUTBOX_TOPIC=agent.outbox MESSAGE_BROKER_DLQ_TOPIC=agent.dlq MILVUS_URI=http://127.0.0.1:19530 +MILVUS_LOCAL_URI= MILVUS_TOKEN= MILVUS_COLLECTION=jr_memory diff --git a/.gitignore b/.gitignore index 78f0d48..9b8d394 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,6 @@ coverage.xml build/ dist/ *.log +data/milvus/ .idea/ .vscode/ diff --git a/app/core/config.py b/app/core/config.py index 189015b..d361143 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -46,6 +46,7 @@ class Settings(BaseSettings): message_broker_outbox_topic: str = "agent.outbox" message_broker_dlq_topic: str = "agent.dlq" milvus_uri: str + milvus_local_uri: str = "" milvus_token: str = "" milvus_collection: str = "jr_memory" neo4j_uri: str @@ -101,6 +102,11 @@ class Settings(BaseSettings): offsite_smtp_use_ssl: bool = True offsite_smtp_timeout_seconds: float = Field(default=30, gt=0) + @property + def resolved_milvus_uri(self) -> str: + """本地开发优先使用 Lite 文件;部署环境仅配置标准 Milvus URI。""" + return self.milvus_local_uri or self.milvus_uri + model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore") diff --git a/app/infrastructure/milvus_knowledge_adapter.py b/app/infrastructure/milvus_knowledge_adapter.py index 98a9530..9c05b8b 100644 --- a/app/infrastructure/milvus_knowledge_adapter.py +++ b/app/infrastructure/milvus_knowledge_adapter.py @@ -26,6 +26,10 @@ class MilvusKnowledgeClient: raise RecoverableAgentError("知识检索参数无效") try: client = await self._ensure_client() + # Lite 重启后集合默认未加载;远程 Milvus 对重复加载保持幂等。 + load_collection = getattr(client, "load_collection", None) + if load_collection is not None: + await load_collection(collection_name=collection) batches = await client.search( collection_name=collection, data=[vector], diff --git a/app/service/agent/bootstrap.py b/app/service/agent/bootstrap.py index 639f975..603fc19 100644 --- a/app/service/agent/bootstrap.py +++ b/app/service/agent/bootstrap.py @@ -84,7 +84,7 @@ def get_vector_memory_adapter() -> VectorMemoryAdapter | None: from pymilvus import MilvusClient # type: ignore[import-untyped] settings = get_settings() - client = MilvusClient(uri=settings.milvus_uri, token=settings.milvus_token or None) + client = MilvusClient(uri=settings.resolved_milvus_uri, token=settings.milvus_token or None) return VectorMemoryAdapter(client, settings.milvus_collection) except Exception: logger.warning("vector memory adapter unavailable; semantic recall disabled", diff --git a/app/service/health_service.py b/app/service/health_service.py index 2592e0b..278f3f5 100644 --- a/app/service/health_service.py +++ b/app/service/health_service.py @@ -79,7 +79,7 @@ class HealthService: try: async with asyncio.timeout(self._milvus_timeout_seconds): client = await asyncio.to_thread( - _create_milvus_client, settings.milvus_uri, settings.milvus_token + _create_milvus_client, settings.resolved_milvus_uri, settings.milvus_token ) await client.get_server_version() return True, "ok" diff --git a/app/service/knowledge_config.py b/app/service/knowledge_config.py index ca906ba..beb2453 100644 --- a/app/service/knowledge_config.py +++ b/app/service/knowledge_config.py @@ -5,7 +5,7 @@ class KnowledgeRuntimeConfig: "policy_explain": ("fin_policy_collection", 5), } - def __init__(self, *, vector_dim: int = 1024, similarity_threshold: float = 0.70) -> None: + def __init__(self, *, vector_dim: int = 1024, similarity_threshold: float = 0.60) -> None: self.routes = dict(self.DEFAULT_ROUTES) self.vector_dim = vector_dim self.similarity_threshold = similarity_threshold diff --git a/app/service/knowledge_tool_service.py b/app/service/knowledge_tool_service.py index 20eaa65..2027d10 100644 --- a/app/service/knowledge_tool_service.py +++ b/app/service/knowledge_tool_service.py @@ -43,9 +43,9 @@ async def query_knowledge_tool( settings.knowledge_embedding_timeout_ms, gateway=DatabaseModelGateway(), ) - vector_store = MilvusKnowledgeClient( - settings.milvus_uri, token=settings.milvus_token or None - ) + # 兼容旧测试替身;真实 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) diff --git a/pyproject.toml b/pyproject.toml index 3c9c0af..959f1a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,7 @@ dependencies = [ "redis>=5.2,<6", "neo4j>=5.28,<6", "pymilvus>=2.5,<3", + "milvus-lite>=3.2,<4", "PyJWT>=2.10,<3", "cryptography>=44,<51", "httpx>=0.28,<1", diff --git a/requirements.txt b/requirements.txt index 9980b9e..6ab896f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,7 @@ pymysql>=1.1,<2 redis>=5.2,<6 neo4j>=5.28,<6 pymilvus>=2.5,<3 +milvus-lite>=3.2,<4 PyJWT>=2.10,<3 cryptography>=44,<51 httpx>=0.28,<1 diff --git a/tools/dependency_health_check.py b/tools/dependency_health_check.py index 6225a53..56eb826 100644 --- a/tools/dependency_health_check.py +++ b/tools/dependency_health_check.py @@ -25,7 +25,7 @@ async def main() -> None: finally: await driver.close() try: - connections.connect(alias="default", uri=settings.milvus_uri) + connections.connect(alias="default", uri=settings.resolved_milvus_uri) print("milvus", "ok") except Exception as exc: print("milvus", f"unavailable:{type(exc).__name__}") diff --git a/tools/publish_customer_service_knowledge.py b/tools/publish_customer_service_knowledge.py index 374e6ad..242eecf 100644 --- a/tools/publish_customer_service_knowledge.py +++ b/tools/publish_customer_service_knowledge.py @@ -133,7 +133,7 @@ class SqlAlchemyKnowledgePublicationStore: row = await session.execute( text( "SELECT id FROM sys_user " - "WHERE id = :reviewer_id AND status = 'active' " + "WHERE id = :reviewer_id AND status IN ('正常', 'active') " "AND user_type IN ('employee', 'admin')" ), {"reviewer_id": self._reviewer_id}, @@ -170,7 +170,7 @@ class MilvusKnowledgePublicationStore: def __init__(self) -> None: settings = get_settings() - self._uri = settings.milvus_uri + self._uri = settings.resolved_milvus_uri self._token = settings.milvus_token or None self._client: Any | None = None