Files
group_xinghuo_jinrong/app/service/memory_service.py
T
zhanghongyu_0626 04c12152f6 feat(chat): 重构对话接口与服务,增强会话管理与工具节点支持
- 更新 chat.py,整合四个 Agent 的统一入口,增加输入防护与会话校验逻辑。
- 扩展 agent_service.py,加入工具节点与 LLM 交互,支持意图匹配与合规护栏。
- 改进 memory_service.py,优化会话窗口管理,支持 Redis 与 MySQL 的数据同步。

此更新提升了对话系统的安全性与可扩展性,确保了会话数据的可靠性与合规性。
2026-09-08 19:54:46 +08:00

61 lines
2.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""记忆服务(T-06 最小闭环):Redis 会话窗口 + MySQL 权威落盘。
口径(redis-keys §2.1):`sess:{agent}:{session_id}:msgs` List,TTL 2h,
最近 N≤20 条 JSON;Redis 只保窗口、丢失可重建(miss/异常回源 MySQL,
MySQL 为权威)。L1/L2/L3 画像读写归后续任务(画像不得覆盖 L0 正式测评)。
落盘策略:「每条消息同步或 5s 内异步写 MySQL」——最小闭环同步写(api/chat
双条落库),异步化归后续优化。
"""
from __future__ import annotations
import json
import logging
from app.config.settings import settings
from app.repository.session_repository import SessionRepository
from app.service.risk.redis_gateway import get_gateway
logger = logging.getLogger(__name__)
SESSION_TTL_SECONDS = 2 * 3600
WINDOW_SIZE = 20
def window_key(agent_type: str, session_id: str) -> str:
"""redis-keys §2.1:sess:{agent}:{session_id}:msgs。"""
return f"sess:{agent_type}:{session_id}:msgs"
def _session_repo() -> SessionRepository:
"""回源仓储入口(测试 monkeypatch 点,与 api 模式一致)。"""
return SessionRepository()
def get_recent(agent_type: str, session_id: str, limit: int = WINDOW_SIZE) -> list[dict]:
"""最近 N 轮消息([{role, content}]);Redis miss/异常回源 MySQL。"""
try:
raw = get_gateway().lrange(window_key(agent_type, session_id), -limit, -1)
if raw:
return [json.loads(item) for item in raw]
except Exception:
logger.warning("session window read failed, fallback to MySQL: %s", session_id, exc_info=True)
return _session_repo().list_messages(session_id, limit=limit)
def append_window(
agent_type: str,
session_id: str,
messages: list[dict],
) -> None:
"""追加窗口(RPUSH + LTRIM 保留最近 N 条 + TTL 续期);失败降级不阻塞。"""
try:
key = window_key(agent_type, session_id)
client = get_gateway()
client.rpush(key, *[json.dumps(m, ensure_ascii=False) for m in messages])
client.ltrim(key, -WINDOW_SIZE, -1)
client.expire(key, SESSION_TTL_SECONDS)
except Exception:
# 窗口丢失可重建(下次读回源 MySQL),不阻塞对话主链路
logger.warning("session window append failed (degrade): %s", session_id, exc_info=True)