Commit Graph
5 Commits
Author SHA1 Message Date
Jeffery 6ce7b2e800 feat(記憶與情緒快取): 記憶與情緒狀態加入 Redis 快取層,連不到時自動退回原行為 2026-08-14 12:44:41 +08:00
JefferyandClaude Sonnet 5 0e9401b891 feat: 完成 P 群組 — 語音子系統
新增 apps/api/src/voice/:Voice Sheet(基礎音色/預設語速/音域幅度/口頭
聲響庫/禁則,依性格原型推導預設值,1:1 掛在 Character,同 EmotionState
的關聯模式);情緒→韻律對照(六狀態語速/音高/音量/句尾走向),音高變化
依角色音域幅度縮放(三無角色近乎單音),設計原則同 O-4 表情外顯度縮放;
非語言發聲與節奏(依情緒插入聲響、重大情緒延長停頓、禁則過濾候選、
低親密度不打斷、talkative 特徵+親密度門檻才可插話);TTSProvider 抽象
完全比照 F-1 LLMProvider(MockTTSProvider 輸出韻律標記+佔位音檔,
RealTTSProvider 待人工確認供應商後再接,TTS_PROVIDER=mock|real 切換);
語音輸入副語言分析(EmotionService 新增 paralinguisticSignal,優先序
排在作息基線之前,讓「文字說沒事但聲音在抖」判為負向)。

修正一個真實 bug:非語言發聲的停頓時長原本直接拿目前主導情緒的數值
當強度訊號,但平靜狀態下 calm 預設就是 100,導致「什麼事都沒發生」被
誤判成「強度最強的重大情緒事件」而觸發不該有的長停頓——修正為 CALM
一律視為強度 0(平靜是情緒事件的缺席,不是訊號)。

刻意簡化:副語言特徵(語速/音量/顫抖/停頓)採結構化輸入,不做真實音訊
分析,比照 M/N 群組「先用結構化輸入代替真實訊號處理」的一貫取捨。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 18:19:51 +08:00
Jeffery d82b834e47 feat: 完成 I 群組 — 生活作息與離線生活
- ScheduleService:I-1 平日/週末/假期時段表(可為角色寫入高中生預設作息)、
  I-3 時間感知(Asia/Taipei 當地時間,不受伺服器時區影響)、剛醒/睡前偵測
- constants.ts:I-2 時段狀態 → 回應可用度對照(FREE/SEMI_BUSY/BUSY/SLEEP →
  NORMAL/BRIEF/DELAYED/NO_REPLY),沒有作息表的角色一律視為 NORMAL(相容既有角色)
- ScheduleExceptionService:I-4 三種破例(深夜還陪你聊/上課偷回訊息/為你調整行程),
  各自獨立冷卻期,觸發時記入關係帳本
- ScheduleEmotionBaselineService:I-5 作息驅動情緒基線(社團剛結束的疲憊、假日偏高心情),
  只在本輪沒有明確情緒訊號時介入,串接進 EmotionService.processInput 的新增選項
- OfflineEventService:I-6 離線事件生成,依「今天已發生的固定行程」挑選對應模板,
  一天只生成一次,寫入低權重情節記憶
- DialogueService 整合以上機制:離線事件生成 → 情緒基線標記 → 累積親密度 →
  作息可用度判定 → 不符合則嘗試破例 → 依可用度決定回覆內容
- 修正真實 bug:G-5 角色建立流程誤用 source=OFFLINE_GENERATED 標記背景故事,
  與 I-6「今天是否已生成離線事件」的判斷共用同一標記,已改為 SOURCE_EXTRACTION
- ChatView.tsx 補上 NO_REPLY/context 為 null 的防呆(作息可用度整合後的必要調整)
- scripts/smoke/I.mjs:以獨立測試角色(避免污染種子角色的排程狀態)驗證全部六項

npm run restart && npm run smoke -- I 皆通過(I-V),A~H 群組冒煙測試無回歸。
2026-08-13 14:08:24 +08:00
Jeffery 503024c92f feat: 完成 G 群組 — 角色人格層
- archetype-params.ts:六原型(傲嬌/冷淡/天然呆/元氣/大小姐/三無)參數表,
  串接進 D 群組 EmotionService(情緒觸發閾值)與 E 群組 SentimentLedgerService(信任成長速度)
- 修正一個真實落差:觸發閾值原本只縮放強度、不影響是否觸發,加入 MIN_TRIGGER_INTENSITY
  門檻後「難觸發」原型才會對弱刺激真的沒反應
- expressiveness.ts:G-3 外顯函數,傲嬌反向表達(傲嬌值=內外差值,隨內部親密度先升後降)
- language-style.ts:G-2 稱呼系統(陌生→您、認識→名字、摯友→暱稱,含跨階事件)與角色禁則清單,
  已串接進 F-3 輸出過濾層與口癖後處理
- contrast-behavior.service.ts:G-4 反差萌,親密度+情緒+機率門檻皆滿足才觸發,
  新增 ContrastTriggerLog 資料表記錄冷卻期
- character-creation.service.ts:G-5 由角色設定表一次產生語意記憶/情節記憶/情緒參數/關係初始值
- cuteness-behavior.ts:G-6 撒嬌/鬧彆扭節奏控制/吃醋/笨拙的努力/專屬揭露觸發條件;
  記住小事擴充了 C-4 睡眠固化,使用者瑣事即使情緒強度低也會寫入語意記憶
- scripts/smoke/G.mjs:涵蓋六原型差異化反應、稱呼進化、傲嬌外顯曲線、反差冷卻、
  可愛行為觸發條件、瑣事固化

npm run restart && npm run smoke -- G 皆通過(G-V),A/B/C/D/E/F 群組冒煙測試無回歸。
2026-08-13 11:26:54 +08:00
Jeffery 611c9b400c feat: 完成 D 群組 — 情緒子系統
- RuleBasedEmotionTagger:關鍵字比對輸出情緒類型與強度(衝突/稱讚/輕度負向/一般負向/正向五級優先序)
- EmotionService:以資料庫 EmotionState 為單一事實來源,dominantState 取非平靜維度最高者,
  半衰期時間衰減(預設 2 小時,可覆寫),狀態轉移時清零其餘維度只設定目標維度
- emotion-state-machine:只實作 wiki 狀態圖與可愛度設計明訂的邊(平靜/愉悅/低落/警戒/害羞/彆扭)
- response-style:情緒 → 語氣/句長/主動性,供 F 群組上下文組裝器使用
- apps/api 新增 /emotion/* 端點作為引擎驗證介面
- scripts/smoke/D.mjs:涵蓋 D-1~D-4 全部轉移邊、回應風格對應、時間衰減與跨 session 殘留驗證

npm run restart && npm run smoke -- D 皆通過(D-V),A/B/C 群組冒煙測試無回歸。
2026-08-13 10:18:58 +08:00