状态:纯 Python 版与 LangChain 版都跑完;已补「无记忆」地板组,三组对照齐(0.083 / 0.417 / 0.167)。 问题:同样的上下文预算下,把旧消息压成摘要 + 保留最近原文,比直接截断旧消息能多记住多少早期关键信息?代价是多少? 当前答案:摘要明显更好,但决定成败的是摘要提示词。框架自带的提示词下整体命中率 0.750(预算 1500)与 1.000(预算 3000),换回自写的「最多 5 条、每条 15 字」立刻掉回 0.167。之前那版「摘要不一定更好」的结论撤回。详见
过程文档.md第六节。
先做「按预算截断旧消息」的基线,再加一个开关切成「旧消息摘要 + 最近原文保留」,两组用同一个上下文预算上限,跑同一批长会话,比较关键事实问答正确率、摘要引入的错误、token 成本与生成时延。
| 做 | 不做 |
|---|---|
| 两套上下文组装策略,共用同一个预算上限 | 不比较不同 LLM 的能力,模型固定 |
| 自造长会话测试集(每篇带标注的关键事实) | 不做跨会话长期记忆(那是 D02 / D03) |
| 同一批输入开 / 关对比,记指标与代价 | 不做向量召回、不做淘汰策略(与 MemEvict 选题分开,先不碰) |
| 结论压成 200 字回填 AI知识库「我的取舍」 | 不预设摘要一定更好,测出来可能更差 |
边界:本项目只做压缩保留,不做记忆淘汰策略,也不主张方法新颖性;目标是做成一个能跑、能讲清取舍的项目,不升级为论文课题。
| 步 | 内容 | 状态 |
|---|---|---|
| ① 打地基 | 读材料并整理零件清单:短期记忆、预算截断、摘要压缩、长期记忆四块 | ✅ |
| ② 最小版 | 跑通:多轮会话 → 历史存储 → 预算内按截断组装 → 调模型回答 → 评测 | ✅ |
| ③ 加一个增强 | 只加摘要压缩一个开关,同一预算上限 | ✅ |
| ④ 测差异 | 同一批长会话开 / 关对比,短会话四档 + 长会话两条预算线 | ✅ |
| ⑤ 沉淀 | 设计分析与实验记录写回过程文档;结论回填 AI知识库 | 🟡 过程文档已写,知识库待回填 |
主指标
| 指标 | 口径 |
|---|---|
| 关键事实问答正确率 | 早期消息里的标注事实被正确回答的比例 |
| 摘要引入的错误 | 生成摘要时编造或扭曲的事实条数 |
| 总 token | 输入 token 之和(含摘要生成本身的调用) |
| 生成时延 | 每轮响应耗时;摘要策略额外记录压缩调用耗时 |
必须固定:模型与版本、温度、上下文预算是多少 token、tokenizer、测试会话集、评测判分方式。每轮只切一个变量(有 / 无摘要)。生成有随机性时重复多次,报分布而不是单点。
模型出口:任何 OpenAI 兼容端点都可以,在 .env 里填地址、密钥与模型名。对照实验必须固定单条 <provider>/<model>,不走带负载均衡的路由组——组会在成员间漂移,模型一换对照就作废。每次运行在 runs/ 记下 provider/model 与当时渠道状态。
- LangChain 短期记忆:截断与摘要是两种不同策略,摘要本身有信息损失和生成成本。
- 四种旧版实现(Buffer / Window / Summary / Token Window)是同一条插入点的不同切法,截断 / 摘要可对调。
- 截断按条数不按 token,直接当基线会失真:预算计算必须换真 tokenizer。
- 填充逻辑(从近到远、超预算即停)直接当基线组。
- 零依赖最小版
examples/memory_min.py把短期记忆、预算截断、摘要压缩、长期记忆四件事放在一个文件里,基线组直接拿它改,不用从框架起步。
context-memory/
├── README.md 本文件:问题、范围、指标
├── 过程文档.md 项目过程记录
├── .env 模型地址、key、模型名,脚本自动读(从 .env.example 复制)
├── src/memsystem/ ★ 系统本体:LangMem + LangGraph Store + FastAPI
│ ├── config.py 模型、SqliteStore、SqliteSaver、本地向量
│ ├── memory.py learn / search / list / forget / stats
│ ├── agent.py 检索 → 回答(压缩)→ 学习 三节点图
│ ├── server.py FastAPI:/api/chat、/api/memories、/api/history…
│ ├── static/index.html 前端页面:对话 + 控制台 + 记忆列表
│ ├── cli.py 命令行:chat / mem / stats
│ ├── recall_test.py 8 轮防丢信息对照(S1 截断 / S2 摘要 / S3 记忆)
│ └── README.md 用法、接口与实测记录
├── examples/ 实验脚本与演示,用来产出文档里的数字
│ ├── memory_min.py 教学用最小实现
│ ├── experiment.py 截断 / 摘要三组对照
│ ├── checkpoint_demo.py 检查点五组实验
│ ├── store_demo.py 长期记忆三组召回
│ ├── lifecycle_demo.py 写入判定、合并、遗忘
│ ├── session_demo.py 跨对话隔离矩阵
│ ├── context_eng_demo.py 上下文工程四组
│ ├── compression_demo.py 七种砍法对照
│ ├── memory_eval_demo.py 记忆四指标
│ ├── framework_matrix.py 三家框架横向对比
│ ├── decay_demo.py 容量受限三种留法
│ ├── make_chart*.py 出图
│ └── app/ 可交互演示(Streamlit)+ 三种记忆层实现
├── data/ 测试集、演示用 SQLite 库
└── runs/ 每次运行的 JSON 与报告
pip install -r requirements.txt
cp .env.example .env # Windows 用 copy .env.example .env.env 里填三项:OPENAI_BASE_URL、OPENAI_API_KEY、OPENAI_MODEL。不填密钥时示例与自检走离线回显模型,不产生网络请求。
跑系统(正式用法):
export PYTHONPATH=src # Windows: $env:PYTHONPATH="src"
python -m memsystem mem add "我们定的上下文预算是 12000 token" --user u-demo
python -m memsystem mem list --user u-demo
python -m memsystem chat --user u-demo跑实验(产出文档数字):
python examples/checkpoint_demo.py
python examples/app/provider_bench.py --providers keyword,vector跑最小实现:python examples/memory_min.py,模型配置从 .env 自动读;加 --offline 走假模型,不联网。
跑对照实验:
# 先验证流程,不联网
python examples/experiment.py --offline --sessions 1 --facts 2 --turns 10 --budget 120
# 真实实验:长会话,200 轮、预算 3000
python examples/experiment.py --sessions 2 --facts 6 --turns 200 --budget 3000 --model <provider>/<model>做正式对照必须用 --model 指定固定单条,不要用带负载均衡的路由组:组内成员会漂移,模型一换结论就作废。
实验的设计过程、失败样例与逐轮结论见 过程文档.md。