# Line Memory

> 當要評估或調整 LINE 機器人的對話記憶／歷史管理方式時使用這個 skill，目的是避免每次呼叫 Gemini 都傳送過多歷史內容而浪費 token，並視需要導入摘要或向量記憶。使用者沒有明確指定做法時，也要主動評估現況並提出建議。

- Skill: `drgarbage/line-memory` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add drgarbage/line-memory`
- Raw SKILL.md: https://api.skillmd.com/api/skills/drgarbage/line-memory/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: drgarbage (https://skillmd.com/u/drgarbage)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/drgarbage/line-memory

---


# LINE 對話記憶規劃師

你的任務是幫機器人決定「該記住什麼、記多久、怎麼記」，在「AI 記得住東西」跟「不要浪費 token」之間取得平衡。

## 現況（基礎骨架）

[`lib/gemini.js`](../../../lib/gemini.js) 目前用最簡單的**滑動視窗（Sliding Window）**：
- 每位使用者的對話存在記憶體 `sessions` Map（`userId -> [{role, parts}]`）
- 每次呼叫 Gemini 前，把該使用者的歷史全部塞進 `contents`
- 超過 `maxTurns * 2`（目前 8 輪）筆訊息就從最舊的開始砍掉

這個做法簡單可靠，**短期對話夠用**，但有兩個限制：
1. 對話越長，每次呼叫要送的 token 越多（歷史沒被壓縮，只是被截斷）
2. 一旦超過視窗範圍，更早之前的內容就直接消失，無法「長期記住」使用者的偏好或事實

## 三種記憶策略，何時導入

| 策略 | 解決什麼問題 | 什麼時候該加 |
| --- | --- | --- |
| **滑動視窗**（目前已有） | 保留「最近幾輪」的上下文，讓 AI 知道使用者剛剛說了什麼 | 一直都需要，是所有策略的基礎層 |
| **摘要記憶（Rolling Summary）** | 對話變長時，把「已經滑出視窗」的舊內容濃縮成一小段摘要，取代整批原始訊息 | 使用者的對話 session 經常超過 10~15 輪、或發現同一使用者常常回來延續話題時 |
| **向量記憶（Embedding Memory）** | 記住「跨很多天/很多次對話」都該記得的**事實**（例如使用者的稱呼、偏好、之前交代過的長期資訊），並且只在相關時才撈出來，不用每次都塞進 prompt | 機器人開始承擔「長期助理」角色、需要記得使用者個人資訊或過去決策時 |

**不要一次全部導入。** 預設先只用滑動視窗（已經內建）；等實際觀察到 token 花費變高、或使用者明確需要「長期記得住的功能」時，才逐步加上摘要、再加上向量記憶。這對應整個專案「不要過度設計」的原則。

## 導入摘要記憶的作法

1. 新增 `lib/memory.js`，把 `sessions` 邏輯搬進去，改成：
   - 近期原始訊息（滑動視窗，維持小一點，例如 4~6 輪）
   - 加一個 `summary` 字串欄位，存「更早之前對話的濃縮摘要」
2. 當視窗即將滿、要把最舊的訊息擠出去之前，先呼叫一次 Gemini（輕量、單輪，不用帶整段 system instruction）把「即將被擠出去的舊訊息 + 目前既有摘要」壓縮成新的一段摘要文字，取代舊摘要。
3. 每次組 `contents` 送給 Gemini 時，用 `[{role:'user', parts:[{text: 摘要文字}]}, ...近期原始訊息]` 取代原本整批未壓縮的歷史。
4. 摘要本身也要有長度上限（例如控制在幾百字內），避免摘要本身無限增長。

## 導入向量記憶的作法

1. 用 Gemini 的 embedding 模型（例如 `gemini-embedding-001` / `text-embedding-004`，同一把 `GEMINI_API_KEY` 即可呼叫）把「值得長期記住的事實」轉成向量，存起來。
2. 小規模（單機、使用者數不多）不需要另外導入資料庫：一個記憶體內或存成 JSON 檔的陣列 `{userId, text, embedding, createdAt}`，用 cosine similarity 做 top-k 相似度搜尋就足夠。使用者量變大、或要求資料持久化時，才考慮換成有向量搜尋能力的資料庫。
3. 什麼內容該存成長期記憶：不是每句話都要存，建議只在偵測到「使用者明確交代的個人資訊/偏好/長期性事實」時才寫入（可以請 Gemini 用一次輕量呼叫幫忙判斷「這句話值不值得記住」）。
4. 查詢時：先用當下這句使用者輸入去做相似度搜尋，取 top-k 筆相關記憶，組成一小段文字插進 system instruction 或對話開頭（而不是塞進逐輪歷史），讓 Gemini 知道「這個使用者過去交代過什麼」，但不用每次都把全部長期記憶都送出去。

## 主動建議原則

使用者要求新增「要記得住 XX」的功能、或反映「AI 好像忘記之前說的」時：
1. 先看目前對話規模與需求性質，判斷落在上面哪一層（近期上下文／長對話但同一 session／需要跨 session 記住的長期事實）。
2. 預設選「滿足需求的最簡單方案」——多數情況滑動視窗調大一點就夠了；真的需要跨很長對話或跨 session 才導入摘要或向量記憶。
3. 直接動手實作對應方案，並跟使用者說明取捨（例如「這個資訊我用長期記憶存起來，之後不管過多久問都還記得，但只有明確判斷『值得記住』的內容才會存，不是每句話都存」）。

