长期记忆技术方案
修行问答:长期记忆技术方案
目标:为修行问答系统引入长期记忆能力,在控制 Token 消耗的前提下,保持上下文一致性,准确维护用户偏好、历史状态等实心实体,并在出现信息冲突时优先采纳最新内容,同时向用户标记矛盾点。
适用范围:修行(Cultivation)问答模块,基于 RAG + LLM 的对话系统。
目录
- 一、背景与问题
- 二、设计目标
- 三、核心原则
- 四、总体架构
- 五、记忆分层模型
- 六、Token 优化策略
- 七、选择性召回
- 八、实体状态维护
- 九、一致性检查与冲突处理
- 十、完整实现流程
- 十一、与现有系统集成
- 十二、评估与监控
- 十三、示例
一、背景与问题
当前修行问答系统基于 RAG:用户提问 → 检索修行文档 → 组装 Prompt → LLM 生成回答。但该流程存在以下局限:
- 无状态对话:每次提问独立,模型无法记住用户上次的偏好、修行进度、习惯。
- Token 浪费:随着对话轮次增加,完整历史容易超出上下文窗口,导致成本上升或回答质量下降。
- 信息冲突:用户可能在不同时间表达矛盾偏好(如先喜欢冥想音乐,后改为静音),模型缺乏一致性校验机制。
- 关键信息丢失:用户明确提到的偏好、目标、上次问题等"实心实体"没有持久化维护。
本方案通过引入分层长期记忆解决上述问题。
二、设计目标
| 目标 | 说明 |
|---|---|
| Token 可控 | 无论历史多长,输入 LLM 的上下文 Token 保持在预算范围内。 |
| 上下文一致 | 每次回复前校验历史状态,确保模型基于最新、最可靠的信息作答。 |
| 实时压缩 | 对话过程中即时压缩冗余内容,不依赖离线批处理。 |
| 摘要压缩 | 长历史自动提炼为结构化摘要,替代原始对话。 |
| 语义压缩 | 合并语义相近的多条记忆,减少重复表达。 |
| 选择性召回 | 根据当前问题,仅召回最相关的记忆片段。 |
| 实体状态维护 | 持久化用户偏好、上次询问内容、修行目标等关键实体。 |
| 冲突可见 | 发现矛盾时优先用最新信息,并向用户明确标记矛盾点,请求确认。 |
三、核心原则
-
最新优先原则(Recency Wins)
当同一实体存在多个版本时,以时间戳最新的记录为准。 -
显式标记原则(Explicit Conflict Flag)
模型不能静默覆盖旧信息。发现冲突时,必须在回复中提示用户:"你之前提到喜欢冥想音乐,这次说希望静音,我以最新偏好(静音)为准,是否需要调整?"
-
最小上下文原则(Minimal Context)
只把与当前问题最相关的记忆放入 Prompt,避免历史堆砌。 -
可解释召回原则(Explainable Recall)
每条被召回的记忆都应能说明召回原因(相关度分数、实体匹配、时间衰减等)。 -
分层存储原则(Tiered Memory)
原始对话、摘要、实体状态分别存储,各自有独立的更新和压缩策略。
四、总体架构
用户提问
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 长期记忆管理器 (Memory Manager) │
│ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐ │
│ │ 工作记忆 WM │ │ 短期记忆 STM │ │ 长期记忆 LTM │ │
│ │ 当前对话轮次 │ │ 近期摘要 │ │ 实体状态 + 历史 │ │
│ │ 原始消息 │ │ 主题片段 │ │ 语义向量索引 │ │
│ └───────┬───────┘ └───────┬───────┘ └────────┬────────┘ │
│ │ │ │ │
│ └──────────────────┴───────────────────┘ │
│ │ │
│ ┌─────────┴─────────┐ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ 一致性检查器 │ │ 选择性召回引擎 │ │
│ │ 冲突检测 │ │ 语义 + 实体召回 │ │
│ └──────┬──────┘ └────────┬────────┘ │
│ │ │ │
│ └────────┬───────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ 压缩与组装模块 │ │
│ │ 实时/摘要/语义 │ │
│ └────────┬────────┘ │
└───────────────────────────┼─────────────────────────────────┘
│
▼
┌─────────────────┐
│ Prompt 组装 │
│ 系统指令 + 记忆 │
│ + 知识库 + 问题 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ LLM 生成 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 更新记忆存储 │
│ 实体 / 摘要 / 向量│
└─────────────────┘
五、记忆分层模型
5.1 工作记忆(Working Memory, WM)
- 内容:当前会话最近 N 轮(如 3-5 轮)原始对话。
- 作用:保证对话连贯性,处理指代、追问等。
- 压缩策略:当轮次超过阈值,触发实时压缩,移入短期记忆。
5.2 短期记忆(Short-Term Memory, STM)
- 内容:近期会话的摘要、主题片段、关键事件。
- 作用:补充工作记忆,覆盖最近几次会话的核心信息。
- 压缩策略:按主题聚类,定期摘要;语义相近的片段合并。
5.3 长期记忆(Long-Term Memory, LTM)
- 内容:
- 实体状态(Solid Entities):用户偏好、修行目标、习惯、上次询问内容等。
- 历史摘要:按时间线的压缩摘要。
- 语义向量索引:所有记忆的向量化表示,支持语义召回。
- 作用:跨会话持久化,支持长期个性化。
- 压缩策略:摘要压缩 + 语义压缩 + 实体冲突消解。
5.4 存储示例
{
"working_memory": {
"session_id": "sess_20250826_001",
"turns": [
{"role": "user", "content": "我昨天冥想时总走神", "timestamp": "2026-08-25T21:00:00Z"},
{"role": "assistant", "content": "走神是正常的...", "timestamp": "2026-08-25T21:01:00Z"}
]
},
"short_term_memory": {
"summaries": [
{
"topic": "冥想走神处理",
"summary": "用户反馈冥想走神,建议从 5 分钟短时冥想开始,使用计数呼吸法。",
"start_time": "2026-08-25T21:00:00Z",
"end_time": "2026-08-25T21:05:00Z"
}
]
},
"long_term_memory": {
"entities": {
"user_preferences": {
"meditation_sound": {
"value": "静音",
"updated_at": "2026-08-26T00:03:00Z",
"source_turn_id": "turn_123",
"confidence": 0.95
},
"meditation_duration": {
"value": "15分钟",
"updated_at": "2026-08-25T21:00:00Z",
"source_turn_id": "turn_120",
"confidence": 0.9
}
},
"last_queries": {
"topic": "冥想走神",
"content": "我昨天冥想时总走神",
"timestamp": "2026-08-25T21:00:00Z"
},
"goals": {
"daily_meditation": {
"value": "每天早晚各 15 分钟",
"updated_at": "2026-08-20T08:00:00Z"
}
}
},
"vector_index": "chroma_db/memory"
}
}
六、Token 优化策略
6.1 实时压缩
目标:在对话进行过程中,立即压缩刚刚发生的对话内容,避免工作记忆无限增长。
触发条件:
- 工作记忆轮次超过 N(如 5 轮)。
- 单轮消息 Token 数超过阈值。
- 检测到当前轮次主题已结束(用户切换话题)。
压缩方式:
- 去除冗余礼貌语:如"你好"、"谢谢"等不影响语义的内容可简化。
- 提取动作-结果对:把用户行为与助手建议压缩为"问题→结论"结构。
- 合并连续追问:同一主题的多轮追问合并为一条。
示例:
原始对话:
用户:我最近冥想总是走神,怎么办?
助手:走神很正常,可以尝试把注意力放在呼吸上。
用户:我试了,但还是会想工作的事情。
助手:这是常见的,建议你在冥想前先写下待办事项,把念头释放出来。
用户:好的,我今晚试试。
实时压缩后:
主题:冥想走神
用户问题:冥想时走神,会想到工作。
建议方案:使用呼吸专注法,冥想前写下待办事项释放念头。
用户反馈:计划今晚尝试。
6.2 摘要压缩
目标:将较长历史对话提炼为高密度摘要,替代原始消息进入 Prompt。
摘要生成策略:
- 滑动窗口摘要:每 K 轮对话生成一段摘要,保留关键信息。
- 分层摘要:低层摘要继续合并为高层摘要,形成金字塔结构。
- 实体感知摘要:摘要中必须保留与实体状态相关的事实。
摘要模板:
时间段:2026-08-20 ~ 2026-08-25
主题:冥想习惯建立
关键事件:
- 用户设定目标:每天早晚各 15 分钟冥想(8/20)。
- 用户反馈走神问题,建议使用呼吸法和事前释放法(8/25)。
- 用户偏好:冥想时使用静音(8/26)。
6.3 语义压缩
目标:识别并合并语义相近的记忆片段,减少重复存储和重复召回。
实现步骤:
- 对记忆片段编码向量。
- 计算片段间余弦相似度。
- 相似度超过阈值(如 0.85)的片段合并为一条。
- 合并时保留最新时间戳,融合不同角度信息。
示例:
片段 A:"用户喜欢晚上冥想。"
片段 B:"用户通常在睡前冥想。"
语义压缩后:
用户偏好:晚上/睡前进行冥想。
来源:A, B
更新时间:取最新
6.4 Token 预算分配
假设 LLM 上下文窗口为 8K,总 Token 预算分配如下:
| 模块 | Token 上限 | 说明 |
|---|---|---|
| 系统指令 | 500 | 角色定义、输出规则、冲突提示规则。 |
| 实体状态 | 800 | 用户偏好、目标、上次询问等。 |
| 知识库召回 | 1500 | 修行文档相关段落。 |
| 工作记忆 | 1000 | 最近 3-5 轮原始对话。 |
| 短期/长期记忆 | 1500 | 相关摘要与历史片段。 |
| 用户问题 | 500 | 当前问题。 |
| 预留 | 2200 | 给模型输出和安全冗余。 |
当某部分超出预算时,优先压缩长期记忆摘要,其次工作记忆,实体状态一般只保留最高置信度的条目。
七、选择性召回
7.1 召回来源
根据当前问题,从以下三类来源召回记忆:
- 实体状态:与用户偏好、目标、习惯、上次询问相关的记录。
- 短期摘要:与当前主题相关的近期摘要。
- 长期语义索引:与问题语义最相似的历史片段。
7.2 召回策略
7.2.1 实体触发召回
解析当前问题中的实体关键词,直接命中实体状态:
- 问题中提到"冥想" → 召回
user_preferences.meditation_*。 - 问题中提到"上次" → 召回
last_queries。
7.2.2 语义相似度召回
使用向量检索,召回与问题最相关的历史摘要或片段。
def semantic_recall(query: str, top_k: int = 3):
query_vec = embedder.encode(query)
results = vector_index.query(query_vec, n_results=top_k)
# 过滤:相关度分数 > 0.7
return [r for r in results if r.score > 0.7]
7.2.3 时间衰减召回
近期记忆权重更高,但也要保留重要的远期记忆(如用户核心目标)。
def time_decay_score(timestamp, half_life_days=7):
days_ago = (now - timestamp).days
return 0.5 ** (days_ago / half_life_days)
7.2.4 综合排序
最终召回分数:
score = w1 * semantic_score + w2 * entity_match + w3 * time_decay
其中 w1 + w2 + w3 = 1,根据场景可调。
7.3 召回去重
召回结果中可能存在重复或互相包含的内容,需要再次语义去重,避免 Prompt 冗余。
八、实体状态维护
8.1 实心实体定义
实心实体是指需要长期维护、对个性化回答至关重要的信息:
| 实体类别 | 示例 | 更新频率 |
|---|---|---|
| 用户偏好 | 冥想是否开声音、喜欢的修行方式、回答风格偏好 | 每次对话 |
| 修行目标 | 每日冥想时长、戒烟目标、读经计划 | 用户主动设定 |
| 行为习惯 | 通常修行时间、常见困扰、进步节奏 | 持续观察 |
| 上次询问 | 上一个问题的主题与内容 | 每轮更新 |
| 事实状态 | 当前戒烟第几天、连续冥想天数 | 每次确认 |
8.2 实体提取
每轮对话后,使用轻量级模型或规则从对话中提取实体更新:
def extract_entities(dialog_turn) -> list[EntityUpdate]:
"""
从单轮对话中提取实体变化。
返回:(entity_key, value, confidence, source)
"""
prompt = f"""
从以下对话中提取用户偏好、目标、习惯等长期信息。
只输出明确表达的事实,不要推测。
格式:key | value | confidence(0-1)
对话:
用户:{dialog_turn.user}
助手:{dialog_turn.assistant}
"""
return llm_extract(prompt)
8.3 实体更新规则
- 无冲突:直接写入,更新
updated_at。 - 有冲突:保留最新值,但在
conflicts列表中记录旧值,供一致性检查使用。 - 置信度低:放入待确认区,不直接覆盖旧值。
九、一致性检查与冲突处理
9.1 一致性检查时机
每次生成回复前必须执行一致性检查:
- 读取当前实体状态。
- 读取本次召回的所有记忆。
- 检测是否存在时间戳更近、内容矛盾的记录。
- 检查当前用户问题是否与已知实体状态冲突。
9.2 冲突类型
| 类型 | 示例 | 处理方式 |
|---|---|---|
| 实体自我冲突 | 先喜欢冥想音乐,后改为静音 | 用最新值,标记矛盾 |
| 用户问题与历史冲突 | 上次说已戒烟,这次问"怎么减少抽烟" | 用最新表述,温和确认 |
| 摘要与实体冲突 | 摘要写"每日冥想",实体写"已暂停" | 以实体状态为准,更新摘要 |
| 知识库与记忆冲突 | 文档说"双盘 30 分钟",用户说"我只能 5 分钟" | 以用户实际状态为准 |
9.3 冲突处理流程
检测到冲突
│
▼
┌─────────────────┐
│ 1. 取最新时间戳 │
│ 2. 保留旧值为 conflict_record │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 组装 Prompt 时 │
│ 把冲突信息注入 │
│ 系统指令 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ LLM 生成回复 │
│ 优先按最新信息答 │
│ 末尾提示矛盾点 │
└─────────────────┘
9.4 回复中的矛盾标记
当存在冲突时,模型应在回复末尾以固定格式输出:
【记忆提示】
我注意到你之前提到「喜欢冥想时播放音乐」,这次说「希望冥想时保持静音」。
我已按最新偏好(静音)回答。如果这是口误或偏好已改变,请告诉我。
系统指令模板:
你在回答前会检查历史记忆的一致性。
如果发现用户当前表述与历史记录矛盾,请优先采纳时间最新的信息生成回答,
但必须在回复末尾用【记忆提示】段落说明矛盾点,并请求用户确认。
不要默默忽略旧信息,也不要质问用户。
十、完整实现流程
10.1 对话开始
async def on_user_query(session_id: str, query: str):
# 1. 加载实体状态
entities = memory_store.load_entities(session_id)
# 2. 加载工作记忆
working = memory_store.load_working_memory(session_id)
# 3. 选择性召回
recalled = selective_recall(query, entities, working)
# 4. 一致性检查
checked, conflicts = consistency_check(entities, recalled)
# 5. 压缩与 Token 预算控制
compressed = compress_context(working, recalled, checked, budget=BUDGET)
# 6. 组装 Prompt
prompt = build_prompt(
system_instruction=SYSTEM_PROMPT,
entities=checked,
memories=compressed,
knowledge=retrieve_knowledge(query),
conflicts=conflicts,
query=query
)
# 7. 调用 LLM
answer = await llm.generate(prompt)
# 8. 更新记忆
update_memory(session_id, query, answer)
return answer
10.2 记忆更新
def update_memory(session_id, query, answer):
turn = {"user": query, "assistant": answer, "timestamp": now()}
# 加入工作记忆
working_memory.add(session_id, turn)
# 提取实体
updates = extract_entities(turn)
for update in updates:
entity_store.upsert(session_id, update, conflict_policy="latest_wins_flag")
# 工作记忆超限时触发实时压缩
if working_memory.token_count(session_id) > WM_TOKEN_LIMIT:
summary = realtime_compress(working_memory.get(session_id))
short_term_memory.add(session_id, summary)
working_memory.clear_older(session_id, keep_last=2)
# 更新向量索引
vector_index.upsert(session_id, [turn, summary])
10.3 定时维护
def scheduled_maintenance():
"""每天或每周运行一次"""
# 1. 对短期记忆进行摘要压缩
for session in active_sessions:
merge_similar_summaries(session)
generate_high_level_summary(session)
# 2. 语义压缩
deduplicate_memories(session)
# 3. 清理低置信度实体
prune_low_confidence_entities(session, threshold=0.5)
十一、与现有系统集成
11.1 接入点
本方案作为独立模块 src/memory/ 接入现有后端:
src/
├── memory/
│ ├── __init__.py
│ ├── manager.py # MemoryManager 统一入口
│ ├── compression.py # 实时/摘要/语义压缩
│ ├── recall.py # 选择性召回
│ ├── entities.py # 实体状态维护
│ ├── consistency.py # 一致性检查
│ └── store.py # 存储层(JSON/向量库)
├── api/
│ └── chat.py # 问答接口,调用 MemoryManager
11.2 数据存储
- 实体状态:
data/memory_entities.json,按 session 索引。 - 工作记忆:内存 + 可选持久化到
data/working_memory.json。 - 短期/长期摘要:
data/memory_summaries.json。 - 向量索引:复用现有
data/vectorstore/目录,新增memorycollection。
11.3 与 RAG 结合
问答接口的完整 Prompt 结构:
[系统指令]
- 角色定义
- 一致性检查规则
- 矛盾标记规则
- Token 预算意识
[实体状态]
- 用户偏好
- 上次询问
- 修行目标
[相关知识]
- 从修行文档召回的段落
[历史记忆]
- 相关摘要/片段
[工作记忆]
- 最近 3-5 轮对话
[冲突提示]
- 检测到的矛盾点(如有)
[用户问题]
十二、评估与监控
12.1 关键指标
| 指标 | 说明 | 目标 |
|---|---|---|
| Prompt Token 数 | 每次请求的输入 Token | 稳定在预算内 |
| 记忆命中率 | 用户问题涉及历史信息时,正确召回的比例 | > 85% |
| 冲突检出率 | 实际冲突中被检测出的比例 | > 80% |
| 误报冲突率 | 无冲突时错误提示矛盾的比例 | < 10% |
| 用户确认率 | 用户对冲突提示进行确认/修正的比例 | tracked |
| 摘要保留率 | 关键信息经压缩后仍被保留的比例 | > 90% |
12.2 日志记录
每次请求记录:
- 召回来源与分数
- 检测到的冲突
- 使用的 Token 分布
- 最终 Prompt 长度
便于后续调优压缩和召回策略。
十三、示例
13.1 用户偏好冲突
历史记录:
- 8/20:用户说"我喜欢冥想时播放流水声"。
- 8/26:用户说"以后冥想请保持静音"。
当前问题:"推荐一段适合冥想的背景音乐。"
处理:
-
召回偏好实体,发现两条记录时间戳不同且内容矛盾。
-
以 8/26 的"静音"为准。
-
生成回答:
"你最新提到希望冥想时保持静音,所以这里不为你推荐背景音乐。如果你现在想尝试声音辅助,可以从很轻的流水声开始,音量调到几乎听不见。"
【记忆提示】你此前曾表示喜欢冥想时播放流水声,最新偏好为静音。如果需要调整,请告诉我。
13.2 上次询问继承
历史记录:
- 上次:用户问"如何提高冥想专注力"。
当前问题:"那我平时走路的时候也可以练吗?"
处理:
- 代词解析发现"那"指代上次话题。
- 召回
last_queries:主题为"提高冥想专注力"。 - 生成连贯回答,将专注力训练扩展到行禅/踱步场景。
13.3 长历史压缩
场景:用户连续 30 轮讨论戒烟、冥想、踱步。
处理:
- 工作记忆只保留最近 4 轮。
- 早期对话压缩为三个主题摘要:"戒烟计划"、"冥想走神"、"踱步习惯"。
- 当前问题关于"踱步"时,主要召回"踱步习惯"摘要和最近工作记忆。
- Prompt Token 控制在预算内。
附录:关键配置项
# config.py
MEMORY_CONFIG = {
"working_memory_turns": 5,
"working_memory_token_limit": 1000,
"short_term_summary_token_limit": 1500,
"long_term_recall_top_k": 3,
"semantic_similarity_threshold": 0.85,
"entity_confidence_threshold": 0.6,
"time_decay_half_life_days": 7,
"conflict_flag_enabled": True,
"total_context_budget": 8000,
}
附录 A:模块接口设计(API 草案,无实现)
以下为建议的 src/memory/ 模块接口,仅描述职责与调用方式,不展开具体代码。
A.1 MemoryManager(统一入口)
class MemoryManager:
def __init__(self, session_id: str, config: MemoryConfig)
async def prepare_context(self, query: str) -> PreparedContext
# 职责:加载实体、召回记忆、一致性检查、压缩、组装 Prompt
async def update(self, query: str, answer: str) -> None
# 职责:更新工作记忆、提取实体、触发压缩、写入向量索引
def get_entities(self) -> EntityState
def get_conflicts(self) -> list[ConflictRecord]
A.2 EntityStore(实体状态维护)
class EntityStore:
def load(self, session_id: str) -> EntityState
def upsert(self, session_id: str, update: EntityUpdate,
policy: ConflictPolicy = ConflictPolicy.LATEST_WINS_FLAG)
def get_conflicts(self, session_id: str) -> list[ConflictRecord]
def prune_low_confidence(self, session_id: str, threshold: float)
A.3 RecallEngine(选择性召回)
class RecallEngine:
def __init__(self, entity_store: EntityStore,
summary_store: SummaryStore,
vector_index: VectorIndex)
def recall(self, query: str, entities: EntityState,
budget: int) -> RecallResult
# 返回:实体命中、语义召回摘要、时间衰减加权结果
A.4 CompressionEngine(压缩引擎)
class CompressionEngine:
def realtime_compress(self, turns: list[Turn]) -> CompressedSummary
def summary_compress(self, summaries: list[Summary]) -> Summary
def semantic_compress(self, fragments: list[MemoryFragment],
threshold: float) -> list[MemoryFragment]
def fit_budget(self, context: PreparedContext, budget: int) -> PreparedContext
A.5 ConsistencyChecker(一致性检查)
class ConsistencyChecker:
def check(self, entities: EntityState,
recalled: RecallResult,
query: str) -> tuple[EntityState, list[ConflictRecord]]
# 返回:校验后的实体状态、待提示的冲突列表
附录 B:数据 Schema
B.1 实体状态(memory_entities.json)
{
"session_id": "sess_xxx",
"entities": {
"user_preferences": {
"meditation_sound": {
"value": "静音",
"confidence": 0.95,
"updated_at": "2026-08-26T00:03:00Z",
"source_turn_id": "turn_123"
}
},
"goals": {
"daily_meditation": {
"value": "每天早晚各 15 分钟",
"confidence": 0.9,
"updated_at": "2026-08-20T08:00:00Z",
"source_turn_id": "turn_100"
}
},
"last_queries": {
"topic": "冥想走神",
"content": "我昨天冥想时总走神",
"timestamp": "2026-08-25T21:00:00Z"
},
"facts": {
"smoke_free_days": {
"value": 12,
"confidence": 0.85,
"updated_at": "2026-08-24T10:00:00Z",
"source_turn_id": "turn_110"
}
}
},
"conflicts": [
{
"entity_key": "user_preferences.meditation_sound",
"current_value": "静音",
"previous_value": "流水声",
"current_time": "2026-08-26T00:03:00Z",
"previous_time": "2026-08-20T20:00:00Z"
}
]
}
B.2 摘要(memory_summaries.json)
{
"session_id": "sess_xxx",
"summaries": [
{
"id": "sum_001",
"level": 1,
"topic": "冥想走神处理",
"content": "用户反馈冥想走神,建议呼吸专注与事前释放法。",
"start_time": "2026-08-25T21:00:00Z",
"end_time": "2026-08-25T21:05:00Z",
"source_turn_ids": ["turn_120", "turn_121", "turn_122"],
"embedding_id": "emb_sum_001"
}
]
}
B.3 工作记忆(内存 + 可选持久化)
{
"session_id": "sess_xxx",
"turns": [
{
"turn_id": "turn_123",
"role": "user",
"content": "以后冥想请保持静音",
"timestamp": "2026-08-26T00:03:00Z"
},
{
"turn_id": "turn_124",
"role": "assistant",
"content": "好的,后续冥想建议中不再推荐背景音乐。",
"timestamp": "2026-08-26T00:03:05Z"
}
]
}
附录 C:接入现有问答接口步骤
C.1 新增文件(不修改业务逻辑,仅新增模块)
src/
├── memory/
│ ├── __init__.py
│ ├── manager.py # MemoryManager
│ ├── store.py # EntityStore / SummaryStore
│ ├── entities.py # 实体提取与更新规则
│ ├── recall.py # RecallEngine
│ ├── compression.py # CompressionEngine
│ ├── consistency.py # ConsistencyChecker
│ └── config.py # MemoryConfig
C.2 改动点(最小侵入)
-
src/api/chat.py(或现有问答入口)- 在收到用户问题时,根据
session_id初始化MemoryManager。 - 调用
memory_manager.prepare_context(query)获取上下文。 - 将返回的实体、记忆、冲突信息注入原有 Prompt 组装流程。
- LLM 生成回答后,调用
memory_manager.update(query, answer)。
- 在收到用户问题时,根据
-
main.py或启动脚本- 启动时加载向量索引(复用
data/vectorstore/)。 - 可选:注册定时任务,每天执行一次
scheduled_maintenance()。
- 启动时加载向量索引(复用
-
requirements.txt- 若使用向量去重/压缩,可能需要
numpy、scikit-learn等;若复用现有 embedding 则无需新增。
- 若使用向量去重/压缩,可能需要
C.3 调用时序
用户请求到达 /chat
│
▼
[chat.py] 初始化 MemoryManager(session_id)
│
▼
[MemoryManager.prepare_context]
├─ 加载 EntityStore
├─ 加载 Working Memory
├─ RecallEngine.recall(query)
├─ ConsistencyChecker.check(...)
├─ CompressionEngine.fit_budget(...)
└─ 返回 PreparedContext
│
▼
[chat.py] 原 RAG 知识库召回(不变)
│
▼
[chat.py] 组装完整 Prompt(系统指令 + 实体 + 记忆 + 冲突 + 知识 + 问题)
│
▼
[chat.py] 调用 LLM
│
▼
[chat.py] MemoryManager.update(query, answer)
│
▼
返回回答给用户
C.4 风险与回退
- 风险 1:实体提取不准确
- 回退:设置高置信度阈值,低置信度实体不写入实体状态,仅作为临时记忆。
- 风险 2:冲突误报
- 回退:通过配置关闭
conflict_flag_enabled,或仅对高置信度实体启用。
- 回退:通过配置关闭
- 风险 3:Token 仍未控住
- 回退:降低
working_memory_turns和long_term_recall_top_k,优先保证核心实体状态。
- 回退:降低
结语
本方案通过分层记忆 + 多层压缩 + 选择性召回 + 实体维护 + 一致性校验,在不显著增加 Token 开销的前提下,为修行问答系统赋予长期记忆能力。核心目标是:让模型"记得住"、"记得准"、"放得下"、"说得清"——记得住用户关键信息,记得准最新状态,放得下无关历史,说得清矛盾与取舍。
浙公网安备 33010602011771号