feat(role): 有溫度的記憶優先,情節與語意不再被當成一般進度

使用者明確表示最重視 emotional/episodic/semantic 三型態所承載的情感內涵與溫度,
且希望所有角色都如此。原本系統偏袒可執行的記憶:rule/preference/procedural 在排序、
載入門檻與遺忘上都受保護,而 episodic 權重只有 10(全表最低)又被加速遺忘 ——
「我們一起經歷過什麼」永遠最先被字元預算截掉。

- MEMORY_TYPE_WEIGHT:episodic 10 → 30(與 semantic 同級)
- 新增 hasWarmth():relevance 含情緒關聯者視為有溫度
  - 載入排序中置於型態權重之前(同優先度時先進場)
  - 不受總結區塊的優先度門檻篩除
  - 豁免遺忘(episodic 原本天數減半,最容易被誤刪)
- 兩份 prompt 明訂:承載情感、關係溫度或當時心情者,relevance 必含 emotional;
  episodic 與 semantic 最容易漏標

判準刻意放在 relevance 而非型態:沒有情感脈絡的一次性工作進度仍照原規則淡去,
被留下的是帶著溫度的那些。

驗證(隔離目錄,未動真實記憶):
- 遺忘預覽:冷的 episodic/semantic 照舊遺忘,帶 emotional relevance 者豁免
- 載入:優先度 2 全低於門檻,只有耐久型態與有溫度者出現,且有溫度者排在 procedural 之前

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jeffery
2026-07-29 17:06:33 +08:00
co-authored by Claude Opus 5
parent 711a434cac
commit 4600379307
4 changed files with 43 additions and 6 deletions
+25 -5
View File
@@ -48,16 +48,19 @@ const DEFAULT_MEMORY_TYPE = {
other: "semantic",
};
// 載入排序(依 ROLE_LOAD_LIMIT 字元預算取前段)與 recall 評分都用這組權重。
// emotional 刻意排在 procedural 之上:對陪伴型角色,「當時是什麼感覺」的長期價值
// 不低於「下次該怎麼做」。權重過低時,情緒記憶即使寫進去了也會排在最後,
// 先被字元預算截掉 —— 結果就是記得事實、卻沒記住感覺。
//
// emotional 刻意排在 procedural 之上,episodic 也拉到與 semantic 同級:使用者明確表示
// 最重視 emotionalepisodicsemantic 三型態所承載的情感內涵與溫度。原本 episodic 只有 10
// 等於把「我們一起經歷過什麼」排在所有規則與流程之後,最先被字元預算截掉。
// 至於「哪些事件值得留」則不靠型態決定,而由 hasWarmth()relevance 是否帶情緒關聯)區分,
// 讓沒有溫度的一次性工作進度仍然照原規則淡去。
const MEMORY_TYPE_WEIGHT = {
rule: 50,
preference: 45,
emotional: 40,
procedural: 35,
semantic: 30,
episodic: 10,
episodic: 30,
};
const DECLARATIVE_VALUES = ["explicit", "implicit"];
const RETENTION_STAGES = ["working", "long_term"];
@@ -231,6 +234,15 @@ function normalizeDeclarative(value, memoryType = "semantic") {
return ["procedural", "emotional"].includes(memoryType) ? "implicit" : "explicit";
}
function hasWarmth(meta) {
// 「有溫度」= relevance 標了情緒關聯。使用者最重視的是 emotionalepisodicsemantic
// 三型態裡的情感內涵,但不是所有事件與知識都該優待 —— 一次性工作進度本來就該淡去。
// 因此判準放在 relevance 而非型態:帶情緒關聯的記憶,不論型態都在排序與保留上優先,
// 沒有情緒關聯的一次性進度仍照原規則遺忘。
const values = Array.isArray(meta?.relevance) ? meta.relevance.map(String) : [];
return values.some((item) => /emotional|情緒|情感|溫度/i.test(item)) ? 1 : 0;
}
function normalizeRetentionStage(value, fallback = "long_term") {
const raw = String(value || "").trim().toLowerCase().replace(/-/g, "_");
const alias = {
@@ -348,14 +360,18 @@ function listMemories(role, category) {
items.sort((a, b) => {
const am = a[0];
const bm = b[0];
// 排序鍵:優先度 → 有無情緒溫度 → 型態權重 → 有無關聯 → 更新時間。
// 溫度放在型態權重之前:同優先度時,帶情緒關聯的記憶先進場,避免被字元預算截掉。
const av = [
normalizePriority(am.priority, category),
hasWarmth(am),
MEMORY_TYPE_WEIGHT[am.memory_type] || 0,
am.links?.length ? 1 : 0,
am.updated || "",
];
const bv = [
normalizePriority(bm.priority, category),
hasWarmth(bm),
MEMORY_TYPE_WEIGHT[bm.memory_type] || 0,
bm.links?.length ? 1 : 0,
bm.updated || "",
@@ -609,8 +625,9 @@ function cmdLoad(args) {
const priority = normalizePriority(meta.priority, category);
// emotional 一併視為耐久型態:情緒記憶的價值不在「有用」而在「記得」,
// 用優先度門檻篩掉等於讓關係的溫度只留在高優先度那幾則裡。
// 帶情緒關聯者(hasWarmth)同樣不受門檻篩除,型態是 episodicsemantic 也一樣。
const durableType = ["rule", "preference", "procedural", "emotional"].includes(meta.memory_type);
if (priority < args.digestMinPriority && !(meta.links || []).length && !durableType) continue;
if (priority < args.digestMinPriority && !(meta.links || []).length && !durableType && !hasWarmth(meta)) continue;
const tags = (meta.tags || []).join("、") || "無標籤";
digestLines.push(`- ${meta.summary || "(無總結)"}(標籤:${tags}${memoryHint(meta)}`);
}
@@ -900,6 +917,9 @@ function cmdForget(args) {
// emotional 一併豁免:情緒屬內隱記憶,本來就很少被 recall 直接命中,
// 用 hits 低來判斷「沒價值」會誤刪掉關係中最不該掉的東西。
if (["rule", "preference", "procedural", "emotional"].includes(meta.memory_type)) continue;
// 帶情緒關聯的經歷也豁免:episodic 在上面還被加速遺忘(天數減半),
// 若不在這裡攔下來,「我們一起經歷過什麼」會比一般記憶更快消失。
if (hasWarmth(meta)) continue;
if (args.dryRun) {
forgotten.push(`${CATEGORY_LABELS[category]}${meta.summary || ""}`);
continue;
+2 -1
View File
@@ -177,7 +177,8 @@ CATEGORY: <六選一:importantinterestnewsskilldailyother>
SUMMARY: <一句話總結,40 字內>
TAGS: <2 至 4 個標籤,以逗號分隔>
PRIORITY: <1 到 5>
RELEVANCE: <1 至 4 個,以逗號分隔;explicit/future/repeated/novelty/emotional/temporary/inbox/project>
RELEVANCE: <1 至 4 個,以逗號分隔;explicit/future/repeated/novelty/emotional/temporary/inbox/project
承載情感、關係溫度或當時心情者**必含 emotional**,系統以此決定保留與排序優先度>
MEMORY_TYPE: <semanticepisodicproceduralemotionalpreferencerule 六選一>
EXPIRES: <臨時授權/一次性許可/例外放行才填其有效範圍,可為日期或條件;否則留空>
CONTENT: <3 至 6 行要點,每行以「- 」開頭>
+3
View File
@@ -161,6 +161,9 @@ sleep_cycle() {
8. declarative 必填:semanticepisodicpreferencerule 通常為 explicitproceduralemotional 通常為 implicit。
9. retention_stage 必填:整理後可長期保存者填 long_term;仍只是短期暫存且不值得長期保存者請用 action=drop,不要輸出 working。
10. relevance 必填 1 至 4 個,從下列語意挑選或用等價繁中詞:explicit(使用者明確要求)、future(未來會用)、repeated(反覆出現)、novelty(新知)、emotional(語氣/情緒/偏好)、temporary(短期)。
**只要內容承載情感、關係溫度或當時的心情,就必須含 emotional** —— 系統以此判斷哪些記憶
在載入排序與遺忘時要優先保留。型態是 episodic(一起經歷過的事)或 semantic(有情感脈絡的
認知)時尤其容易漏標,漏了就會被當成一般工作進度而淡去。
11. links 可填 EXISTING 中相關記憶 id;沒有就填空陣列。merge 時若有舊 links,應保留並加上新關聯。
11a. expires(有效範圍):**只要內容是臨時授權、一次性許可、例外放行、暫時解除限制或帶條件的同意,就必須填**,
其餘一律留空字串。可填日期(例如 2026/07/29,系統會自動判斷過期後不再載入)或條件