- 作息與疲勞、想念累積與時間感,主動發話沿用 care.ts 的冷卻、日限、靜音 - 想家與適應度(9.13) - 獨立腳本 fetch-materials.mjs 由系統排程寫入快取,hook 只讀、不連網 - 新增 /jsc-mod-companion:materials 與 setup location=、feeds= - 天氣微調心情基準,新聞依適應度每天最多 2 則並寫入情節記憶 - 版本 0.0.5 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
148 lines
5.2 KiB
TypeScript
148 lines
5.2 KiB
TypeScript
// 規則表:標籤 → 數值增減。所有數值集中在這裡;模型只給標籤,不給數值。
|
||
import type { Pad } from './types'
|
||
import { isTag, type Tag } from './tags'
|
||
|
||
export const RULES = {
|
||
thanks: { p: 0.15, a: 0.05, d: 0.05 },
|
||
scold: { p: -0.2, a: 0.15, d: -0.1 },
|
||
success: { p: 0.08, a: 0.03, d: 0.05 },
|
||
toolFail: { p: -0.08, a: 0.1, d: -0.08 },
|
||
return: { p: 0.1, a: 0.08, d: 0 },
|
||
lateNight: { p: -0.05, a: -0.1, d: 0 },
|
||
favorite: { p: 0.12, a: 0.08, d: 0.03 },
|
||
ignored: { p: -0.05, a: -0.03, d: -0.03 },
|
||
praiseSkill: { p: 0.1, a: 0.04, d: 0.06 },
|
||
amused: { p: 0.1, a: 0.06, d: 0.02 },
|
||
cared: { p: 0.08, a: -0.02, d: -0.02 },
|
||
apology: { p: 0.06, a: -0.06, d: 0.03 },
|
||
soothe: { p: 0.05, a: -0.08, d: 0.02 },
|
||
brushOff: { p: -0.06, a: 0.02, d: -0.04 },
|
||
overstep: { p: -0.15, a: 0.12, d: 0.02 },
|
||
remembered: { p: 0.08, a: 0.02, d: 0.02 },
|
||
selfDisclosure: { p: 0.04, a: 0.03, d: -0.02 },
|
||
gladForYou: { p: 0.08, a: 0.05, d: 0 },
|
||
liedCaught: { p: -0.18, a: 0.1, d: -0.05 },
|
||
brokenPromise: { p: -0.12, a: 0.04, d: -0.08 },
|
||
} as const satisfies Record<Tag, Pad>
|
||
|
||
// 記憶權重 W = I_eff × F × A 與生命週期的數值(第 9.5 章)
|
||
export const MEMORY = {
|
||
/** I_eff 下限與上限 */
|
||
weightMin: 1,
|
||
weightMax: 5,
|
||
/** 編碼時情緒峰值(0–100)除以此值加進 I_eff */
|
||
peakDiv: 40,
|
||
/** 新鮮度半衰的回合數:F = 0.5^(Δseq / 200) */
|
||
halfSeq: 200,
|
||
/** 被檢索到時 F 至少回到此值 */
|
||
floor: 0.8,
|
||
/** 存取加成:A = 1 + step × min(命中次數, cap) */
|
||
accessStep: 0.1,
|
||
accessCap: 5,
|
||
/** 未解負向事件:每日 +20%,上限 3 倍 */
|
||
ruminatePerDay: 0.2,
|
||
ruminateCap: 3,
|
||
/** 類別加成的角色參數門檻(0–1) */
|
||
bonusThreshold: 0.65,
|
||
/** 暫時記憶 7 天衰減 */
|
||
tempDays: 7,
|
||
/** 可升級記憶:30 天未升級就降權、90 天未檢索就封存 */
|
||
demoteDays: 30,
|
||
demoteFactor: 0.5,
|
||
archiveDays: 90,
|
||
/** 被檢索到這麼多次就升級為長期記憶 */
|
||
upgradeHits: 3,
|
||
/** 開放迴路:她的提問經過這麼多個使用者回合沒有回應就逾時 */
|
||
loopTurns: 2,
|
||
/** RRF:fused = Σ 1 / (k + rank) */
|
||
rrfK: 60,
|
||
/** 心情一致加權 w_m = base + slope × (1 − 釋懷速度) */
|
||
moodBase: 0.1,
|
||
moodSlope: 0.05,
|
||
} as const
|
||
|
||
// 正則先判明確的情況;順序即優先序
|
||
const PATTERNS: [Tag, RegExp][] = [
|
||
['scold', /笨|白痴|廢物|爛|你很煩|閉嘴|stupid|useless|idiot/i],
|
||
['thanks', /謝謝|感謝|太棒|好棒|厲害|讚|thanks?|thank you|great job|awesome/i],
|
||
['success', /成功|完成了|通過|搞定|passed|done|fixed/i],
|
||
]
|
||
|
||
/** 以正則判斷使用者文字的標籤;沒有明確情況回 null */
|
||
export function regexTag(text: string): Tag | null {
|
||
for (const [tag, re] of PATTERNS) if (re.test(text)) return tag
|
||
return null
|
||
}
|
||
|
||
/** 正則優先;正則沒判出才用模型補的標籤(須在白名單內),缺失或不合法就是沒有標籤 */
|
||
export function classify(text: string, modelTag?: string | null): Tag | null {
|
||
return regexTag(text) ?? (isTag(modelTag) ? modelTag : null)
|
||
}
|
||
|
||
// 作息與疲勞(第 9.12 章的簡化):只動精力基準,隨讀取計算、不寫回
|
||
export const SCHEDULE = {
|
||
/** 醒著超過這麼多小時後,每小時精力基準 −perHour,最多 −awakeMax */
|
||
awakeFreeH: 12,
|
||
perHour: 0.02,
|
||
awakeMax: 0.15,
|
||
/** 連續工作超過這麼多小時後,每小時 −workPerHour,最多 −workMax */
|
||
workFreeH: 1,
|
||
workPerHour: 0.03,
|
||
workMax: 0.15,
|
||
/** 使用者的睡眠時段內仍在線上(熬夜):精力基準再 −lateShift */
|
||
lateShift: 0.1,
|
||
/** 起床後這麼多小時內的「剛起床」微幅回復 */
|
||
wakeBoostH: 2,
|
||
wakeBoost: 0.03,
|
||
} as const
|
||
|
||
// 想念累積與時間感:想念 = 速度 × max(0, 離開小時 − graceH),上限 max;速度隨「想念累積速度」參數調整
|
||
export const MISSING = {
|
||
graceH: 2,
|
||
perHour: 0.03,
|
||
max: 0.8,
|
||
/** 想念達此值,回來時主動說出口 */
|
||
speakAt: 0.5,
|
||
/** 離開這麼久以上再回來,才算「回來」事件 */
|
||
returnH: 6,
|
||
} as const
|
||
|
||
// 適應度(第 9.13 章):每日 ΔA = k × (1 − A/100),k = 1.5 + 1.5 × (主動度 + 想像力)/2;本地第一次事件 +2
|
||
export const ADAPT = {
|
||
kBase: 1.5,
|
||
kSpan: 1.5,
|
||
first: 2,
|
||
/** 想家基準 = homesickMax × (1 − A/100) */
|
||
homesickMax: 0.25,
|
||
/** 想家達此值,主動說出口 */
|
||
homesickSpeakAt: 0.4,
|
||
/** 適應度達此值才聊本地新聞;達 newsTwo 時每天最多 2 則,否則 1 則 */
|
||
newsMin: 40,
|
||
newsTwo: 70,
|
||
} as const
|
||
|
||
// 外部素材:hook 不連網,只讀由排程腳本寫入的快取;過期或缺失當作沒查
|
||
export const MATERIALS = {
|
||
weatherTtlMs: 6 * 3_600_000,
|
||
newsTtlMs: 24 * 3_600_000,
|
||
/** 讀取快取的間隔,避免 band 每次重繪都讀檔 */
|
||
readEveryMs: 60_000,
|
||
newsPerDay: 2,
|
||
/** 記住已經提過的新聞連結上限 */
|
||
seenMax: 50,
|
||
/** 天氣只微調心情基準,上限 */
|
||
weatherCap: 0.06,
|
||
} as const
|
||
|
||
/** 天氣狀況(快取的標題)→ 心情基準微調 */
|
||
export const WEATHER_MOOD: Record<string, number> = {
|
||
晴: 0.04,
|
||
多雲: 0.01,
|
||
陰: -0.01,
|
||
霧: -0.02,
|
||
毛毛雨: -0.02,
|
||
雨: -0.04,
|
||
雪: 0.01,
|
||
雷雨: -0.06,
|
||
}
|