[AC-MEMORY-SUMMARY] feat(mid): 新增对话记忆摘要生成器
- 新增 MemorySummaryGenerator 用于生成对话摘要 - 新增 memory_summary_prompt 提供摘要生成提示词模板 - 支持将长对话历史压缩为简洁摘要 - 更新 mid 服务模块导出
This commit is contained in:
parent
e9de808969
commit
e45396e1e4
|
|
@ -14,6 +14,7 @@ from .metrics_collector import MetricsCollector, SessionMetrics, AggregatedMetri
|
|||
from .tool_registry import ToolRegistry, ToolDefinition, ToolExecutionResult, get_tool_registry, init_tool_registry
|
||||
from .tool_call_recorder import ToolCallRecorder, ToolCallStatistics, get_tool_call_recorder
|
||||
from .memory_adapter import MemoryAdapter, UserMemory
|
||||
from .memory_summary_generator import MemorySummaryGenerator
|
||||
from .default_kb_tool_runner import DefaultKbToolRunner, KbToolResult, KbToolConfig, get_default_kb_tool_runner
|
||||
from .segment_humanizer import SegmentHumanizer, HumanizeConfig, LengthBucket, get_segment_humanizer
|
||||
from .runtime_observer import RuntimeObserver, RuntimeContext, get_runtime_observer
|
||||
|
|
@ -55,6 +56,7 @@ __all__ = [
|
|||
"get_tool_call_recorder",
|
||||
"MemoryAdapter",
|
||||
"UserMemory",
|
||||
"MemorySummaryGenerator",
|
||||
"DefaultKbToolRunner",
|
||||
"KbToolResult",
|
||||
"KbToolConfig",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
"""
|
||||
Memory summary generator using LLM.
|
||||
[AC-IDMP-14] Generate rolling summary for memory update.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from app.services.llm.base import LLMConfig
|
||||
from app.services.llm.factory import get_llm_config_manager
|
||||
from app.services.mid.memory_summary_prompt import build_memory_summary_prompt
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MemorySummaryGenerator:
|
||||
"""
|
||||
LLM-based memory summary generator.
|
||||
|
||||
Output expected to be a JSON object or structured text.
|
||||
"""
|
||||
|
||||
def __init__(self, max_tokens: int = 512, temperature: float = 0.2):
|
||||
self._max_tokens = max_tokens
|
||||
self._temperature = temperature
|
||||
|
||||
async def __call__(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
old_summary: str | None = None,
|
||||
) -> str | None:
|
||||
try:
|
||||
llm_manager = get_llm_config_manager()
|
||||
llm_client = llm_manager.get_client()
|
||||
except Exception as e:
|
||||
logger.warning(f"[AC-IDMP-14] Failed to get LLM client: {e}")
|
||||
return None
|
||||
|
||||
prompt = build_memory_summary_prompt(messages, old_summary)
|
||||
|
||||
try:
|
||||
response = await llm_client.generate(
|
||||
messages=[
|
||||
{"role": "system", "content": "你是一个严格遵循 JSON 格式的摘要器。仅输出 JSON。"},
|
||||
{"role": "user", "content": prompt},
|
||||
],
|
||||
config=LLMConfig(
|
||||
max_tokens=self._max_tokens,
|
||||
temperature=self._temperature,
|
||||
),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"[AC-IDMP-14] Summary generation failed: {e}")
|
||||
return None
|
||||
|
||||
return response.content
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
"""
|
||||
Memory summary prompt builder.
|
||||
[AC-IDMP-14] Rolling summary prompt for memory update.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
SUMMARY_PROMPT_TEMPLATE = """
|
||||
你是一个记忆摘要生成器。你的目标是把对话中稳定、有长期价值的信息归纳为“可用于记忆召回”的摘要。
|
||||
要求:
|
||||
1) 必须保留:稳定事实、用户偏好、未解决问题;
|
||||
2) 不要写闲聊/情绪;
|
||||
3) 输出必须为严格 JSON 对象,只允许以下字段:summary, facts, preferences, open_issues;
|
||||
4) summary 为一段话(150-300字以内);facts/preferences/open_issues 为列表;
|
||||
5) 如果新内容没有变化,保留旧摘要并可轻微精简;
|
||||
6) 所有内容必须基于对话,不允许编造。
|
||||
|
||||
【旧摘要】
|
||||
{old_summary}
|
||||
|
||||
【最近对话】
|
||||
{recent_messages}
|
||||
""".strip()
|
||||
|
||||
|
||||
def build_recent_messages_text(messages: list[dict[str, Any]]) -> str:
|
||||
lines: list[str] = []
|
||||
for msg in messages:
|
||||
role = msg.get("role", "unknown")
|
||||
content = msg.get("content", "")
|
||||
if not content:
|
||||
continue
|
||||
lines.append(f"{role}: {content}")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def build_memory_summary_prompt(
|
||||
messages: list[dict[str, Any]],
|
||||
old_summary: str | None = None,
|
||||
) -> str:
|
||||
return SUMMARY_PROMPT_TEMPLATE.format(
|
||||
old_summary=old_summary or "无",
|
||||
recent_messages=build_recent_messages_text(messages),
|
||||
)
|
||||
Loading…
Reference in New Issue