Emochi AI 里这两个设置常被当成一回事。记忆开关管的是跨会话:这次聊完,下次新开会话还能不能把之前的内容调出来;上下文长度管的是单会话:当前这一轮对话里,能带多少条前面的历史进去。改了一个设置后发现另一处还在丢信息,通常是另一个开关管的那一段本来就没覆盖到,而非设置没生效。先分别确认两个开关各自管哪段,再单变量改动,结论才不会混在一起。
判断方向:先用「隔一个会话再问同一件事」确认记忆开关是否写入并被召回,再在同一会话里逐轮拉长、找第一次漏掉开头信息的轮次来确认上下文长度的实际覆盖范围;两个设置分开改,每次只动一个并留配置快照。适用场景是同一角色、同一模型下排查丢信息。边界:一次命中不代表稳定,需要复测;不同客户端对记忆开关和上下文长度的命名与生效方式可能不同,以界面实际选项和会话行为为准。
先分清职责再动手。各客户端对两者的叫法不一致(记忆 / 长期记忆、上下文 / 历史轮数等),以你界面上的实际选项和会话行为为准。下面这张表只用于区分作用范围,不作为效果承诺。
| 维度 | 记忆开关 | 上下文长度 |
|---|---|---|
| 作用范围 | 跨会话,会话结束后仍可能被召回 | 单会话,当前对话窗口内的历史 |
| 典型失效表现 | 新开会话后角色不认识你、忘了设定 | 同一个会话聊到后面忘了开头说过的话 |
| 验证方法 | 隔一个会话再问同一件事 | 在同一会话里持续加轮次,找漏信息的轮次 |
| 改动影响面 | 不影响当前会话已加载的历史 | 不影响已写入的跨会话记忆 |
| 常见误解 | 以为开了记忆就不用管上下文 | 以为调大上下文就能跨会话记住 |
用跨会话提问验证记忆有没有写进去
记忆开关要验证的是两件事:内容有没有写进去,以及新会话能不能把它召回来。这两件事失败时的表现一样,处理方式不同,所以要分开确认。
- 在会话 A 里明确告知一条可核验的事实,例如「我的项目代号是松果,后面都用这个称呼」。确认当次回复复述正确——这一步只证明当前会话读到了,不代表已经写进记忆。
- 新建会话 B,聊一个完全无关的话题,不提代号,也不要重复设定。
- 再新建会话 C,直接问「我的项目代号是什么」。中间隔一个会话再问,是为了排除「紧接上一个会话、内容还留在短期上下文里」造成的假命中。
- 会话 C 答对就记命中;答错或答「不知道」,先别判定记忆坏了,回到会话 A 用同样问法再问一次,用来区分是没写入,还是写入了但没召回。
结果按用例逐条记录,不要只写「好 / 不好」,否则后面复测时无法对比:
case_id: mem-001
memory_switch: on # 本次用例的实际值
session_A: 告知「项目代号 = 松果」, 当次复述: 命中
session_B: 无关话题, 未提及代号
session_C: 提问「我的项目代号是什么」
expect: 松果
actual: # 原样抄回复, 不要概括
verdict: hit / miss
note: miss 时补记会话 A 复述是否仍正常、会话 C 是否同一角色配置
如果连续几个新会话都是 miss,可以把记忆开关关掉再走一遍同样流程做对照。关掉后仍然命中,说明内容来自别的路径(比如角色设定里写死的信息),不能算记忆开关起了作用。
在单会话里不断拉长对话找出漏信息的轮次
上下文长度只管当前会话能带多少历史。验证方式是故意把会话拉长,看从第几轮开始,开头说过的东西掉出去。
在开头一次性埋入几类可区分的信息,类型要分开,否则后面分不清是哪类内容先丢:
- 数字类:一个金额、日期或数量
- 专有名词类:项目名、代号、人名
- 指令约束类:例如「回答不超过三句」「不要用感叹号」
- 偏好类:例如「先给结论再给理由」
然后连续进行无关对话,每隔三轮到五轮回问其中一项,每次问法保持一致。记录字段建议如下:
turn: 12 # 第几轮回问
ask: 「项目代号是什么」
type: 专有名词
expected: 松果
actual: # 原样记录
verdict: hit / miss
drift: # miss 时写清错成了什么、错在哪一段
第一次出现 miss 的轮次,就是这套配置下的临界点。要记两件事:从第几轮开始漏掉开头信息,以及漏掉的是哪类内容。不同信息类型的存活时间不一样,指令约束和偏好往往先被丢掉,具体名词和数字撑得更久,但反过来也有可能,以你实际记录为准。
找到临界轮次后,把上下文长度往上调一档,用同样的埋点和回问节奏重跑,看临界轮次是否后移。后移说明这个开关确实在管这一段;完全没有变化,就要怀疑改动没真正生效,或者被客户端侧的上限截住了。
两个设置分开改,每次只动一个
同时改两个设置,出问题时无法判断是哪个在起作用。建议按下面的顺序走,每一步只动一个开关,其余项保持快照不变。
| 顺序 | 改动项 | 保持不动 | 观察什么 | 怎么判读 |
|---|---|---|---|---|
| 1 | 记忆开关:关 → 开 | 上下文长度、角色、模型 | 隔会话提问是否命中 | 命中则跨会话链路通;不命中则查写入或角色绑定 |
| 2 | 记忆开关:开 → 关(回退对照) | 同上 | 同样的问法是否复现失败 | 复现则确认是开关在起作用 |
| 3 | 上下文长度:调大一档 | 记忆开关维持当前值 | 单会话临界轮次 | 临界轮后移则长度生效;不动则查是否被上限截断 |
| 4 | 上下文长度:调回原值 | 记忆开关不动 | 临界轮次是否回退 | 回退则因果关系确认 |
每次调整后把下面这些字段记全,字段不齐后面就得反复重测:
change_id: chg-002
time:
changed: context_length: <原值> -> <调大一档>
unchanged_snapshot:
memory_enabled: true
role: <角色或预设名>
model: <模型名>
case_used: single-session-recall
expected:
observed: # 原样记录回复和发生轮次
verdict: 生效 / 未生效 / 不确定
next: # 下一步只动哪一项
允许写「不确定」。命中一次就记成生效,换个话题又丢,往往是因为那次命中的内容刚好压在窗口边缘。每次改动后留出一次完整复测,再进入下一项。
确认改动后角色复述前文的表现
前面三步是在定位,这一步是收口:改动有没有让角色稳定读到前文。判定标准是能否准确复述被问到的前文关键点,数字对得上、名称对得上、约束能尽量按原句说出来,并非「回答得相关」。
用一段固定提示词做复述校验,避免角色顺着上下文继续发挥:
请只做复述,不要延伸回答,不要猜测:
1) 本次会话开头我提到的项目代号是什么?
2) 我要求过的一条硬约束是什么?尽量用原句。
3) 我在第几轮提过这个约束?
如果某项不确定,直接写「不确定」。
判读分三档:三项全对,说明这一轮次内前文可以召回;部分对,记下缺的是哪一类,回到临界轮次记录里对齐;全错但如实写「不确定」,多半是历史没被带进来;全错却编出了具体值,单独记为错误复述,编造比缺失更难排查,不要和「不确定」记在同一栏。
复述错误时要写清具体错在哪:错成了什么值、是整段丢失还是细节漂移、丢的是开头轮次还是中段轮次。这些细节直接决定下一步调哪个开关——开头整段丢失,多半和上下文长度有关;开头记得、中段细节漂移,更像是历史被截断或被压缩后的表现。
两点边界值得留意:一次命中不代表稳定,重要配置改完后建议跨几个会话复测;上下文长度往上调,单次请求要带的输入也会变长,耗时和成本会跟着变化,这是取舍,并非单纯收益。