feat: configure local customer service knowledge runtime
This commit is contained in:
@@ -25,6 +25,7 @@ MESSAGE_BROKER_OUTBOX_TOPIC=agent.outbox
|
|||||||
MESSAGE_BROKER_DLQ_TOPIC=agent.dlq
|
MESSAGE_BROKER_DLQ_TOPIC=agent.dlq
|
||||||
|
|
||||||
MILVUS_URI=http://127.0.0.1:19530
|
MILVUS_URI=http://127.0.0.1:19530
|
||||||
|
MILVUS_LOCAL_URI=
|
||||||
MILVUS_TOKEN=
|
MILVUS_TOKEN=
|
||||||
MILVUS_COLLECTION=jr_memory
|
MILVUS_COLLECTION=jr_memory
|
||||||
|
|
||||||
|
|||||||
@@ -14,5 +14,6 @@ coverage.xml
|
|||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
*.log
|
*.log
|
||||||
|
data/milvus/
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ class Settings(BaseSettings):
|
|||||||
message_broker_outbox_topic: str = "agent.outbox"
|
message_broker_outbox_topic: str = "agent.outbox"
|
||||||
message_broker_dlq_topic: str = "agent.dlq"
|
message_broker_dlq_topic: str = "agent.dlq"
|
||||||
milvus_uri: str
|
milvus_uri: str
|
||||||
|
milvus_local_uri: str = ""
|
||||||
milvus_token: str = ""
|
milvus_token: str = ""
|
||||||
milvus_collection: str = "jr_memory"
|
milvus_collection: str = "jr_memory"
|
||||||
neo4j_uri: str
|
neo4j_uri: str
|
||||||
@@ -101,6 +102,11 @@ class Settings(BaseSettings):
|
|||||||
offsite_smtp_use_ssl: bool = True
|
offsite_smtp_use_ssl: bool = True
|
||||||
offsite_smtp_timeout_seconds: float = Field(default=30, gt=0)
|
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")
|
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ class MilvusKnowledgeClient:
|
|||||||
raise RecoverableAgentError("知识检索参数无效")
|
raise RecoverableAgentError("知识检索参数无效")
|
||||||
try:
|
try:
|
||||||
client = await self._ensure_client()
|
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(
|
batches = await client.search(
|
||||||
collection_name=collection,
|
collection_name=collection,
|
||||||
data=[vector],
|
data=[vector],
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ def get_vector_memory_adapter() -> VectorMemoryAdapter | None:
|
|||||||
from pymilvus import MilvusClient # type: ignore[import-untyped]
|
from pymilvus import MilvusClient # type: ignore[import-untyped]
|
||||||
|
|
||||||
settings = get_settings()
|
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)
|
return VectorMemoryAdapter(client, settings.milvus_collection)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.warning("vector memory adapter unavailable; semantic recall disabled",
|
logger.warning("vector memory adapter unavailable; semantic recall disabled",
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class HealthService:
|
|||||||
try:
|
try:
|
||||||
async with asyncio.timeout(self._milvus_timeout_seconds):
|
async with asyncio.timeout(self._milvus_timeout_seconds):
|
||||||
client = await asyncio.to_thread(
|
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()
|
await client.get_server_version()
|
||||||
return True, "ok"
|
return True, "ok"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class KnowledgeRuntimeConfig:
|
|||||||
"policy_explain": ("fin_policy_collection", 5),
|
"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.routes = dict(self.DEFAULT_ROUTES)
|
||||||
self.vector_dim = vector_dim
|
self.vector_dim = vector_dim
|
||||||
self.similarity_threshold = similarity_threshold
|
self.similarity_threshold = similarity_threshold
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ async def query_knowledge_tool(
|
|||||||
settings.knowledge_embedding_timeout_ms,
|
settings.knowledge_embedding_timeout_ms,
|
||||||
gateway=DatabaseModelGateway(),
|
gateway=DatabaseModelGateway(),
|
||||||
)
|
)
|
||||||
vector_store = MilvusKnowledgeClient(
|
# 兼容旧测试替身;真实 Settings 会优先提供本地/远程统一解析后的地址。
|
||||||
settings.milvus_uri, token=settings.milvus_token or None
|
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:
|
async with SessionFactory() as session:
|
||||||
authority = KnowledgeMysqlAuthority(session)
|
authority = KnowledgeMysqlAuthority(session)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ dependencies = [
|
|||||||
"redis>=5.2,<6",
|
"redis>=5.2,<6",
|
||||||
"neo4j>=5.28,<6",
|
"neo4j>=5.28,<6",
|
||||||
"pymilvus>=2.5,<3",
|
"pymilvus>=2.5,<3",
|
||||||
|
"milvus-lite>=3.2,<4",
|
||||||
"PyJWT>=2.10,<3",
|
"PyJWT>=2.10,<3",
|
||||||
"cryptography>=44,<51",
|
"cryptography>=44,<51",
|
||||||
"httpx>=0.28,<1",
|
"httpx>=0.28,<1",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pymysql>=1.1,<2
|
|||||||
redis>=5.2,<6
|
redis>=5.2,<6
|
||||||
neo4j>=5.28,<6
|
neo4j>=5.28,<6
|
||||||
pymilvus>=2.5,<3
|
pymilvus>=2.5,<3
|
||||||
|
milvus-lite>=3.2,<4
|
||||||
PyJWT>=2.10,<3
|
PyJWT>=2.10,<3
|
||||||
cryptography>=44,<51
|
cryptography>=44,<51
|
||||||
httpx>=0.28,<1
|
httpx>=0.28,<1
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ async def main() -> None:
|
|||||||
finally:
|
finally:
|
||||||
await driver.close()
|
await driver.close()
|
||||||
try:
|
try:
|
||||||
connections.connect(alias="default", uri=settings.milvus_uri)
|
connections.connect(alias="default", uri=settings.resolved_milvus_uri)
|
||||||
print("milvus", "ok")
|
print("milvus", "ok")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print("milvus", f"unavailable:{type(exc).__name__}")
|
print("milvus", f"unavailable:{type(exc).__name__}")
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ class SqlAlchemyKnowledgePublicationStore:
|
|||||||
row = await session.execute(
|
row = await session.execute(
|
||||||
text(
|
text(
|
||||||
"SELECT id FROM sys_user "
|
"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')"
|
"AND user_type IN ('employee', 'admin')"
|
||||||
),
|
),
|
||||||
{"reviewer_id": self._reviewer_id},
|
{"reviewer_id": self._reviewer_id},
|
||||||
@@ -170,7 +170,7 @@ class MilvusKnowledgePublicationStore:
|
|||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
settings = get_settings()
|
settings = get_settings()
|
||||||
self._uri = settings.milvus_uri
|
self._uri = settings.resolved_milvus_uri
|
||||||
self._token = settings.milvus_token or None
|
self._token = settings.milvus_token or None
|
||||||
self._client: Any | None = None
|
self._client: Any | None = None
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user