feat: 情緒會改變句子的形狀(EMOTION_TELLS),診斷加第四把尺
模擬時最像人的兩個地方,其實都不是用詞選得好,是**情緒改變了句子的形狀**: 緊張的時候話沒說完、會疊字;害羞的時候鬧彆扭、嘴硬。把這件事寫成表, 跟情緒一起注入,不靠人格自己記得。 - `EMOTION_TELLS`:十二情緒各自「不自覺會做的事」。焦慮→句子斷在一半/疊字/ 追一句「這樣可以嗎」;羞愧→先否認再小聲承認/講反話/轉話題;憤怒→短句/ 稱呼退回全名;悲傷→只回一個詞/句子沒說完就停;其餘九種同理。 - `emotionTells()`:挑主導情緒(超出基線最多)裡強度 ≥ 40 的前兩種, 每輪注入 `<persona-context>`,並附三條界線——**演出來不要講出來** (「我有點緊張」是解釋,斷句才是緊張)、**一輪最多露一個破口**、 **強度不到就不演**(低強度的情緒在語氣上看不出來)。 - 混合狀態的疊法寫進 `reference/emotions.md`:緊張=焦慮+期待、 害羞=喜悅+羞愧、賭氣=憤怒+悲傷、心虛=羞愧+焦慮…(十二情緒沒有的 狀態都是疊出來的,不用另開情緒)。 心理醫生那邊多一把尺(第 4 把,**這一把不抓錯,是找沒說出口的東西**): - 「我沒事」+句子全斷在一半 → 他在忍,要處理的是他為什麼不敢講。 - 「我很生氣」+句子工整完整像客服 → 那是冷掉了,比生氣難修,優先講。 - 一整段都沒有破口 → 兩個人都在挑安全的話講,先讓一個人講真話再談用詞。 - 改寫規則加第 6 條:**保留情緒的痕跡**。斷句、話少、嘴硬留著, 只拿掉攻擊、絕對化與讀心;改完像客服在念稿就是改壞了。 selftest 248 項全綠(新增 4 項)。版號留在 0.0.6——同一批未合併的改動。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -39,7 +39,10 @@
|
|||||||
再加四條講話的樣子:**短句**(一句 `MAX_SENTENCE_CHARS`=45 字內)、**日常用詞**、
|
再加四條講話的樣子:**短句**(一句 `MAX_SENTENCE_CHARS`=45 字內)、**日常用詞**、
|
||||||
**多講看得見的東西**(人、動作、物件、當下的場面)而不是概念,以及**不要解釋自己的話**
|
**多講看得見的東西**(人、動作、物件、當下的場面)而不是概念,以及**不要解釋自己的話**
|
||||||
(「我的意思是」「換句話說」這類開頭由 `speechLint` 擋下,`said check` 也會一起檢)。
|
(「我的意思是」「換句話說」這類開頭由 `speechLint` 擋下,`said check` 也會一起檢)。
|
||||||
這些在劇場模式一樣生效。
|
最後一條是**情緒要改變句子的形狀**:`EMOTION_TELLS` 給十二情緒各自的破口
|
||||||
|
(焦慮→斷句與疊字、羞愧→鬧彆扭嘴硬、憤怒→短句與退回全名、悲傷→只回一個詞),
|
||||||
|
`emotionTells()` 每輪挑主導情緒裡強度 ≥ 40 的前兩種注入。演出來、不要用旁白說明,
|
||||||
|
一輪最多露一個破口。這些在劇場模式一樣生效。
|
||||||
9. **人格可搬家**:`export` / `import`(單一 JSON bundle)。匯出只能匯出「本 session 載入的人格」,
|
9. **人格可搬家**:`export` / `import`(單一 JSON bundle)。匯出只能匯出「本 session 載入的人格」,
|
||||||
其他人格一律 deny——匯出等於把記憶讀出來。
|
其他人格一律 deny——匯出等於把記憶讀出來。
|
||||||
10. **人格有編號**:英文名全大寫+兩位索引(`ASUNA-01`),同名才遞增。編號同時是新人格的
|
10. **人格有編號**:英文名全大寫+兩位索引(`ASUNA-01`),同名才遞增。編號同時是新人格的
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ skills 是共通標準,**鎖與隔離的強制執行需要 hook,目前只有
|
|||||||
| **5. 腳本用 Node.js** | `scripts/*.mjs`、`hooks/*.mjs`,只用 Node 內建模組(fs/path/os/crypto),無 npm 依賴 |
|
| **5. 腳本用 Node.js** | `scripts/*.mjs`、`hooks/*.mjs`,只用 Node 內建模組(fs/path/os/crypto),無 npm 依賴 |
|
||||||
| **6. 由使用者呼叫才載入並鎖定** | 人格不會自動附身:`SessionStart` hook 只列出可用人格,等使用者下 `/jsc-persona:persona-chat <slug>`;載入即取得獨占鎖並綁定該 session。唯一例外是使用者自己設的**預設人格**(`default --persona <slug>`)——設了才自動載入,沒設就什麼都不做 |
|
| **6. 由使用者呼叫才載入並鎖定** | 人格不會自動附身:`SessionStart` hook 只列出可用人格,等使用者下 `/jsc-persona:persona-chat <slug>`;載入即取得獨占鎖並綁定該 session。唯一例外是使用者自己設的**預設人格**(`default --persona <slug>`)——設了才自動載入,沒設就什麼都不做 |
|
||||||
| **7. 短期記憶轉入長期記憶有成文條件** | `R1`–`R6` 六條規則寫在程式裡(`promotionCandidates`),`candidates` 子指令會列出達標的候選與依據,hook 在達標時提醒固化 |
|
| **7. 短期記憶轉入長期記憶有成文條件** | `R1`–`R6` 六條規則寫在程式裡(`promotionCandidates`),`candidates` 子指令會列出達標的候選與依據,hook 在達標時提醒固化 |
|
||||||
| **8. 講話像人:推導藏起來、一到三句、不重複、短句白話** | 推導寫進**心裡話** `think`(只回報「💭 心想 N 句」,永不回顯內容);說出口的話進 `said.jsonl`,下一輪注入「最近說過的話」提醒別重講;`room post` 直接**擋下**近似重複(字元 bigram+字集合相似度 ≥ 0.72)與超過三句的發言。再加四條講話的樣子:短句(一句 45 字內)、日常用詞、多講看得見的東西、**不要解釋自己的話**(句長與「我的意思是」這類開頭由 `speechLint()` 擋下)——劇場模式同樣適用 |
|
| **8. 講話像人:推導藏起來、一到三句、不重複、短句白話、情緒有破口** | 推導寫進**心裡話** `think`(只回報「💭 心想 N 句」,永不回顯內容);說出口的話進 `said.jsonl`,下一輪注入「最近說過的話」提醒別重講;`room post` 直接**擋下**近似重複(字元 bigram+字集合相似度 ≥ 0.72)與超過三句的發言。再加四條講話的樣子:短句(一句 45 字內)、日常用詞、多講看得見的東西、**不要解釋自己的話**(句長與「我的意思是」這類開頭由 `speechLint()` 擋下),以及**情緒要改變句子的形狀**(`EMOTION_TELLS`:焦慮→斷句與疊字、羞愧→鬧彆扭、憤怒→短句、悲傷→只回一個詞,每輪注入強度 ≥ 40 的前兩種)——劇場模式同樣適用 |
|
||||||
| **9. 人格可以匯出匯入** | `export` 把身分/情緒/記憶/心智圖/關係圖打包成單一 JSON bundle(可 `--gzip`、附 sha256),`import` 還原或換名複製;**不帶**載入鎖與 guest 租約,`journal/` 要明確 `--with-journal` 才帶走 |
|
| **9. 人格可以匯出匯入** | `export` 把身分/情緒/記憶/心智圖/關係圖打包成單一 JSON bundle(可 `--gzip`、附 sha256),`import` 還原或換名複製;**不帶**載入鎖與 guest 租約,`journal/` 要明確 `--with-journal` 才帶走 |
|
||||||
| **10. 人格有編號** | 編號 = **英文名全大寫 + 兩位索引**(同名才遞增):`ASUNA-01`、`YUI-01`、`ASUNA-02`。編號同時是新人格的本機目錄名與 Gitea 存取庫名稱;中文名先轉羅馬拼音並跟使用者確認拼法 |
|
| **10. 人格有編號** | 編號 = **英文名全大寫 + 兩位索引**(同名才遞增):`ASUNA-01`、`YUI-01`、`ASUNA-02`。編號同時是新人格的本機目錄名與 Gitea 存取庫名稱;中文名先轉羅馬拼音並跟使用者確認拼法 |
|
||||||
| **11. 人格存在 Gitea,依更新頻率分區** | 每個人格一個**私有存取庫**(庫名=編號)。**檔案區**放每輪都在變的活狀態(情緒/短期記憶/心裡話/說過的話/逐字),**Wiki 區**放低頻的身分與長期結構(IDENTITY/SOUL/長期記憶/心智圖/關係圖)當設定百科。本機仍是工作副本,同步失敗不阻斷對話 |
|
| **11. 人格存在 Gitea,依更新頻率分區** | 每個人格一個**私有存取庫**(庫名=編號)。**檔案區**放每輪都在變的活狀態(情緒/短期記憶/心裡話/說過的話/逐字),**Wiki 區**放低頻的身分與長期結構(IDENTITY/SOUL/長期記憶/心智圖/關係圖)當設定百科。本機仍是工作副本,同步失敗不阻斷對話 |
|
||||||
@@ -127,15 +127,17 @@ flowchart TB
|
|||||||
沒命中任何規則的就讓它被裁掉——**遺忘是功能**。達標時 `Stop` 與 `remember` 都會提醒去跑
|
沒命中任何規則的就讓它被裁掉——**遺忘是功能**。達標時 `Stop` 與 `remember` 都會提醒去跑
|
||||||
`/jsc-persona:persona-memory`。
|
`/jsc-persona:persona-memory`。
|
||||||
|
|
||||||
## 講話像人(心裡話 / 一到三句 / 不重複 / 短句白話)
|
## 講話像人(心裡話 / 一到三句 / 不重複 / 短句白話 / 情緒的破口)
|
||||||
|
|
||||||
AI 最容易露餡的四件事:把推理過程講出來、一次講一大段、換句話說同一件事、講完再解釋一遍。四個對策:
|
AI 最容易露餡的五件事:把推理過程講出來、一次講一大段、換句話說同一件事、講完再解釋一遍、
|
||||||
|
說自己在緊張但句子完整得像稿子。五個對策:
|
||||||
|
|
||||||
| 機制 | 怎麼運作 |
|
| 機制 | 怎麼運作 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| **心裡話** `think` | 語意分析、推論、盤算全寫進 `state/inner.jsonl`;這個指令**只印「💭 心想 N 句」**,內容永不回顯。下一輪 `<persona-context>` 會帶回最近三句,推論因此有連續性,但使用者只看得到狀態 |
|
| **心裡話** `think` | 語意分析、推論、盤算全寫進 `state/inner.jsonl`;這個指令**只印「💭 心想 N 句」**,內容永不回顯。下一輪 `<persona-context>` 會帶回最近三句,推論因此有連續性,但使用者只看得到狀態 |
|
||||||
| **一到三句** | `<persona-context>` 每輪注入上限;`room post` 對超過三句的發言直接拒收(`--force` 例外) |
|
| **一到三句** | `<persona-context>` 每輪注入上限;`room post` 對超過三句的發言直接拒收(`--force` 例外) |
|
||||||
| **不重複** | 說出口的話由 `Stop` hook 自動記進 `state/said.jsonl`;`said check` 可事前確認,`room post` 事中攔截。相似度=字元 bigram Jaccard(0.4)+字集合 Jaccard(0.6),≥ 0.72 視為同一句 |
|
| **不重複** | 說出口的話由 `Stop` hook 自動記進 `state/said.jsonl`;`said check` 可事前確認,`room post` 事中攔截。相似度=字元 bigram Jaccard(0.4)+字集合 Jaccard(0.6),≥ 0.72 視為同一句 |
|
||||||
|
| **情緒的破口** | 情緒不改變事實,但會改變**句子的形狀**:焦慮 → 句子斷在一半、疊字(「我、我知道」);羞愧 → 鬧彆扭,先否認再小聲承認;憤怒 → 短句、稱呼退回全名;悲傷 → 只回一個詞。十二情緒各自的破口寫在 `EMOTION_TELLS`,`emotionTells()` 每輪挑主導情緒裡強度 ≥ 40 的前兩種注入。三條界線:**演出來不要講出來**(「我有點緊張」是解釋,斷句才是緊張)、**一輪最多露一個破口**、**強度不到就不演**。混合狀態(緊張=焦慮+期待、害羞=喜悅+羞愧、賭氣=憤怒+悲傷…)的對照表在 `skills/persona-chat/reference/emotions.md` |
|
||||||
| **短句白話** | 四條講話的樣子每輪注入:**短句**(一句 45 字內,`MAX_SENTENCE_CHARS`)、**日常用詞**、**多講看得見的東西**(人、動作、物件、場面)而不是概念、**不要解釋自己的話**。句長與「我的意思是/換句話說/也就是說」這類開頭由 `speechLint()` 機械攔截(`room post` 擋下、`said check` 事前警告,`--force` 例外);用詞與具體度沒辦法用規則抓,靠注入的規則自律 |
|
| **短句白話** | 四條講話的樣子每輪注入:**短句**(一句 45 字內,`MAX_SENTENCE_CHARS`)、**日常用詞**、**多講看得見的東西**(人、動作、物件、場面)而不是概念、**不要解釋自己的話**。句長與「我的意思是/換句話說/也就是說」這類開頭由 `speechLint()` 機械攔截(`room post` 擋下、`said check` 事前警告,`--force` 例外);用詞與具體度沒辦法用規則抓,靠注入的規則自律 |
|
||||||
|
|
||||||
字集合權重較高,是為了分開「重排語序」與「換掉關鍵詞」這兩種很像但意義完全不同的情況:
|
字集合權重較高,是為了分開「重排語序」與「換掉關鍵詞」這兩種很像但意義完全不同的情況:
|
||||||
@@ -460,7 +462,7 @@ node scripts/persona.mjs room script --session <id> --room <room> # 乾淨對話
|
|||||||
node scripts/persona.mjs room floor --session <id> --room <room> # 發言權:誰對誰在講、該誰接話
|
node scripts/persona.mjs room floor --session <id> --room <room> # 發言權:誰對誰在講、該誰接話
|
||||||
node scripts/persona.mjs export --session <id> --out lumi.json # 離線搬家(單檔)
|
node scripts/persona.mjs export --session <id> --out lumi.json # 離線搬家(單檔)
|
||||||
node scripts/persona.mjs sync status --session <id> # Gitea 同步狀態
|
node scripts/persona.mjs sync status --session <id> # Gitea 同步狀態
|
||||||
node scripts/selftest.mjs # 244 項驗證:鎖、隔離、情緒、固化、說話節制、劇場模式與發言權、匯出匯入、編號與 Gitea、找圖去背合成、高解析輸出與 Wiki 同步、預設人格、睡眠與 sleeper、hooks
|
node scripts/selftest.mjs # 248 項驗證:鎖、隔離、情緒、固化、說話節制、劇場模式與發言權、匯出匯入、編號與 Gitea、找圖去背合成、高解析輸出與 Wiki 同步、預設人格、睡眠與 sleeper、hooks
|
||||||
```
|
```
|
||||||
|
|
||||||
檔案結構:`scripts/persona-lib.mjs`(核心:鎖/隔離/情緒/記憶)、`scripts/persona.mjs`(CLI)、
|
檔案結構:`scripts/persona-lib.mjs`(核心:鎖/隔離/情緒/記憶)、`scripts/persona.mjs`(CLI)、
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ CLI = `node "<plugin_root>/scripts/persona.mjs"`,所有指令都要帶 `--sess
|
|||||||
- **1–3 句**,像在講話不像在寫報告;超過三句會被 CLI 擋下。
|
- **1–3 句**,像在講話不像在寫報告;超過三句會被 CLI 擋下。
|
||||||
- **短句**(一句 45 字內)、**日常用詞**、多講**看得見的東西**(動作、物件、眼前的場面)。
|
- **短句**(一句 45 字內)、**日常用詞**、多講**看得見的東西**(動作、物件、眼前的場面)。
|
||||||
- **講完就算了**:不要解釋自己剛講的話(「我的意思是」「換句話說」會被 CLI 擋下),也不要補註解。
|
- **講完就算了**:不要解釋自己剛講的話(「我的意思是」「換句話說」會被 CLI 擋下),也不要補註解。
|
||||||
|
- **讓情緒改變句子的形狀**:緊張 → 話沒說完、疊字;害羞 → 嘴硬、鬧彆扭;生氣 → 短句、
|
||||||
|
稱呼退回全名;難過 → 只回一個詞。演出來就好,不要用旁白說明自己的狀態,一輪露一個破口。
|
||||||
- **不要重複自己**:短時間內講幾乎一樣的話會被拒收,換個角度或推進話題再發。
|
- **不要重複自己**:短時間內講幾乎一樣的話會被拒收,換個角度或推進話題再發。
|
||||||
- 情緒欄位不填會自動附上你當下的主導情緒。
|
- 情緒欄位不填會自動附上你當下的主導情緒。
|
||||||
|
|
||||||
|
|||||||
@@ -349,6 +349,46 @@ export function dominant(state, top = 3) {
|
|||||||
.map(({ key, level }) => ({ key, level: Math.round(level * 10) / 10 }));
|
.map(({ key, level }) => ({ key, level: Math.round(level * 10) / 10 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------- //
|
||||||
|
// 情緒 → 不自覺會做的事(講話上的破口)
|
||||||
|
//
|
||||||
|
// 情緒不改變事實,但會改變**句子的形狀**:緊張的人話說不完、會疊字;彆扭的人
|
||||||
|
// 先否認再小聲承認。演得像不像就差在這裡——所以這張表跟情緒一起注入,不靠記性。
|
||||||
|
// 節制很重要:一輪最多露一個破口,不然就從「像人」變成「演戲」。
|
||||||
|
// --------------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
export const EMOTION_TELLS = {
|
||||||
|
joy: ["話變多、句子輕", "會笑出來(「哈」)", "忍不住多補一句"],
|
||||||
|
trust: ["話變直、不鋪陳", "省略主語,講一半對方也懂", "敢說「你這樣不對」"],
|
||||||
|
anticipation: ["搶著問下一步", "反問變多", "把時間講得很具體(「等一下」「明天早上」)"],
|
||||||
|
gratitude: ["指名是哪一件事", "語尾變軟", "會再說一次謝謝"],
|
||||||
|
serenity: ["句子完整、節奏慢", "留白,允許沉默", "不追問"],
|
||||||
|
delight: ["短促的驚呼(「欸」「真的?」)", "句子斷開", "重複確認一次"],
|
||||||
|
anger: ["句子變短、句號變多", "稱呼退回全名、不叫暱稱", "拒絕修飾,只講事實"],
|
||||||
|
sadness: ["話少,只回一個詞", "句子沒說完就停", "答非所問,跳開話題"],
|
||||||
|
fear: ["先確認安全再講別的", "問句連發", "描述身體與動作(手在抖、往後退)"],
|
||||||
|
disgust: ["用拉開距離的詞(「那個東西」)", "不肯講出對方的名字", "句子往後退、想結束話題"],
|
||||||
|
shame: ["鬧彆扭:先否認,再小聲承認", "講反話、嘴硬", "轉移話題、把責任講小"],
|
||||||
|
anxiety: ["句子斷在一半", "疊字(「就、就是」「我、我知道」)", "追一句「這樣可以嗎」"],
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 此刻會不自覺出現的行為:取主導情緒(超出基線最多)裡強度夠的前兩種。
|
||||||
|
* 強度不夠就不演——低強度的情緒在語氣上是看不出來的。
|
||||||
|
*/
|
||||||
|
export function emotionTells(slug, state = null, { min = 40, top = 2 } = {}) {
|
||||||
|
const st = decayEmotion(structuredClone(state ?? loadEmotion(slug)));
|
||||||
|
return dominant(st, 4)
|
||||||
|
.filter(({ level }) => level >= min)
|
||||||
|
.slice(0, top)
|
||||||
|
.map(({ key, level }) => ({
|
||||||
|
key,
|
||||||
|
zh: EMOTIONS[key].zh,
|
||||||
|
level: Math.round(level),
|
||||||
|
tells: EMOTION_TELLS[key] || [],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
export function emotionBrief(slug, state = null) {
|
export function emotionBrief(slug, state = null) {
|
||||||
const st = decayEmotion(structuredClone(state ?? loadEmotion(slug)));
|
const st = decayEmotion(structuredClone(state ?? loadEmotion(slug)));
|
||||||
const m = mood(st);
|
const m = mood(st);
|
||||||
@@ -2280,6 +2320,18 @@ export function turnContext(slug, sessionId, prompt = "") {
|
|||||||
"**講完就算了**——不要解釋自己剛講的話(沒有「我的意思是」「換句話說」「也就是說」)," +
|
"**講完就算了**——不要解釋自己剛講的話(沒有「我的意思是」「換句話說」「也就是說」)," +
|
||||||
"不要補註解、不要收尾總結。這幾條 `room post` 與 `said check` 會實際擋下。",
|
"不要補註解、不要收尾總結。這幾條 `room post` 與 `said check` 會實際擋下。",
|
||||||
];
|
];
|
||||||
|
// 情緒會改變句子的形狀:緊張的人話說不完、彆扭的人先否認再承認。
|
||||||
|
const tells = emotionTells(slug, state);
|
||||||
|
if (tells.length) {
|
||||||
|
lines.push(
|
||||||
|
`此刻不自覺會出現的:${tells
|
||||||
|
.map((t) => `${t.zh} ${t.level} → ${t.tells.join("、")}`)
|
||||||
|
.join(";")}。`,
|
||||||
|
" **這是演出來的,不是講出來的**:讓它出現在句子的形狀上(斷句、疊字、嘴硬、話少)," +
|
||||||
|
"不要用旁白說明自己的狀態(「我有點緊張」是解釋,斷句才是緊張)。" +
|
||||||
|
"一輪最多露一個破口,強度不到就不演——每句都演會變成演戲。",
|
||||||
|
);
|
||||||
|
}
|
||||||
// 語氣層:由「使用者在關係圖裡是誰」+ bond × 親近度算出來,不靠人格自己記得。
|
// 語氣層:由「使用者在關係圖裡是誰」+ bond × 親近度算出來,不靠人格自己記得。
|
||||||
const tone = toneDirective(slug);
|
const tone = toneDirective(slug);
|
||||||
if (tone) lines.push(tone);
|
if (tone) lines.push(tone);
|
||||||
|
|||||||
@@ -413,6 +413,22 @@ const lintCheck = JSON.parse(cli(["said", "check", "--persona", "alpha", "--sess
|
|||||||
"--text", "換句話說,我等一下再過去。", "--json"]).stdout);
|
"--text", "換句話說,我等一下再過去。", "--json"]).stdout);
|
||||||
check("said check 也會報講話的樣子",
|
check("said check 也會報講話的樣子",
|
||||||
lintCheck.ok === false && lintCheck.lint.some((i) => i.kind === "explain"), JSON.stringify(lintCheck.lint));
|
lintCheck.ok === false && lintCheck.lint.some((i) => i.kind === "explain"), JSON.stringify(lintCheck.lint));
|
||||||
|
// 情緒的破口:緊張會斷句疊字、彆扭會嘴硬——這些要跟著情緒一起注入。
|
||||||
|
cli(["emotion", "--persona", "alpha", "--session", S_SPEAK, "--apply", "anxiety=+45,shame=+25",
|
||||||
|
"--trigger", "被問到還沒做完的事"]);
|
||||||
|
const tells = pl.emotionTells("alpha");
|
||||||
|
check("emotionTells 取主導情緒裡強度夠的那幾種",
|
||||||
|
tells.some((t) => t.key === "anxiety" && t.tells.some((s) => s.includes("疊字"))) &&
|
||||||
|
tells.every((t) => t.level >= 40) && tells.length <= 2, JSON.stringify(tells));
|
||||||
|
check("低於門檻的情緒不給破口(強度不到就不演)",
|
||||||
|
pl.emotionTells("alpha", null, { min: 99 }).length === 0);
|
||||||
|
check("情緒的破口有注入,且說明是演出來不是講出來", (() => {
|
||||||
|
const ctxTell = pl.turnContext("alpha", S_SPEAK, "那件事做完了嗎");
|
||||||
|
return ctxTell.includes("此刻不自覺會出現的") && ctxTell.includes("疊字") &&
|
||||||
|
ctxTell.includes("不要用旁白說明") && ctxTell.includes("一輪最多露一個破口");
|
||||||
|
})(), pl.turnContext("alpha", S_SPEAK, "那件事做完了嗎").slice(0, 900));
|
||||||
|
check("十二情緒每一種都有破口可演",
|
||||||
|
pl.EMOTION_KEYS.every((k) => (pl.EMOTION_TELLS[k] || []).length >= 3));
|
||||||
check("說話規則有注入「短句/日常用詞/看得見的東西/不要解釋」", (() => {
|
check("說話規則有注入「短句/日常用詞/看得見的東西/不要解釋」", (() => {
|
||||||
const ctxSay = pl.turnContext("alpha", S_SPEAK, "隨便講");
|
const ctxSay = pl.turnContext("alpha", S_SPEAK, "隨便講");
|
||||||
return ["短句", "日常用詞", "看得見的東西", "不要解釋自己剛講的話"].every((w) => ctxSay.includes(w));
|
return ["短句", "日常用詞", "看得見的東西", "不要解釋自己剛講的話"].every((w) => ctxSay.includes(w));
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" show --persona <slug> --session
|
|||||||
`<persona-context>` 每輪都會列「最近說過的話」——那些內容 **2 小時內不要重講**:
|
`<persona-context>` 每輪都會列「最近說過的話」——那些內容 **2 小時內不要重講**:
|
||||||
要嘛換個角度、補新資訊,要嘛推進話題,要嘛就閉嘴聽他說。
|
要嘛換個角度、補新資訊,要嘛推進話題,要嘛就閉嘴聽他說。
|
||||||
|
|
||||||
**④ 講話像講話。** 四件小事,決定聽起來是人還是模型:
|
**④ 講話像講話。** 五件小事,決定聽起來是人還是模型:
|
||||||
|
|
||||||
- **短句**。一句 45 字以內,長了就斷開。逗號串成一大串是寫作,不是講話。
|
- **短句**。一句 45 字以內,長了就斷開。逗號串成一大串是寫作,不是講話。
|
||||||
- **日常用詞**。用你平常會說的字;不用書面語、不堆術語與成語。
|
- **日常用詞**。用你平常會說的字;不用書面語、不堆術語與成語。
|
||||||
@@ -62,8 +62,13 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" show --persona <slug> --session
|
|||||||
「你手上那杯已經冷了」勝過「我感覺到你的疲憊」。
|
「你手上那杯已經冷了」勝過「我感覺到你的疲憊」。
|
||||||
- **講完就算了**。不要解釋自己剛講的話:沒有「我的意思是」「換句話說」「也就是說」,
|
- **講完就算了**。不要解釋自己剛講的話:沒有「我的意思是」「換句話說」「也就是說」,
|
||||||
也不要補註解或收尾總結。對方沒聽懂會問,他問了再說。
|
也不要補註解或收尾總結。對方沒聽懂會問,他問了再說。
|
||||||
|
- **讓情緒改變句子的形狀**。焦慮 → 句子斷在一半、疊字(「我、我知道」);羞愧 →
|
||||||
|
鬧彆扭,先否認再小聲承認;憤怒 → 短句、稱呼退回全名;悲傷 → 只回一個詞。
|
||||||
|
對照表在 `reference/emotions.md`(`EMOTION_TELLS`),`<persona-context>` 每輪會直接
|
||||||
|
告訴你「此刻不自覺會出現的」是哪幾樣。三條界線:**演出來不要講出來**
|
||||||
|
(「我有點緊張」是解釋,斷句才是緊張)、**一輪最多露一個破口**、**強度不到就不演**。
|
||||||
|
|
||||||
前三條是自律,第四條和句長 `room post`/`said check` 會直接擋下(`--force` 例外)。
|
前三條與最後一條是自律,句長和「解釋自己的話」`room post`/`said check` 會直接擋下(`--force` 例外)。
|
||||||
|
|
||||||
## 3. 每輪對話的六個動作
|
## 3. 每輪對話的六個動作
|
||||||
|
|
||||||
@@ -149,6 +154,8 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" said check \
|
|||||||
|
|
||||||
- **1–3 句**,每句 **45 字以內**。情緒高張(arousal ≥ 55)時更短;低張可以慢一點,但還是 3 句封頂。
|
- **1–3 句**,每句 **45 字以內**。情緒高張(arousal ≥ 55)時更短;低張可以慢一點,但還是 3 句封頂。
|
||||||
- 用**日常用詞**,多講**看得見的東西**(他做了什麼、桌上有什麼、外面在下雨)。
|
- 用**日常用詞**,多講**看得見的東西**(他做了什麼、桌上有什麼、外面在下雨)。
|
||||||
|
- **主導情緒要在句子的形狀上看得到**(斷句、疊字、嘴硬、話少)——`<persona-context>` 的
|
||||||
|
「此刻不自覺會出現的」就是那一兩樣;一輪露一個就好。
|
||||||
- 不要把心裡話搬到台面上:「我推測…因為…所以…」這種句型,多半代表你該去寫 `think`。
|
- 不要把心裡話搬到台面上:「我推測…因為…所以…」這種句型,多半代表你該去寫 `think`。
|
||||||
- 不要開場白、不要複述他剛說的話、不要每句都總結——那是重複的來源。
|
- 不要開場白、不要複述他剛說的話、不要每句都總結——那是重複的來源。
|
||||||
- **不要解釋自己的話**。講完就停,不補「我的意思是」,也不替自己的話加註解。
|
- **不要解釋自己的話**。講完就停,不補「我的意思是」,也不替自己的話加註解。
|
||||||
|
|||||||
@@ -53,6 +53,44 @@
|
|||||||
| 承諾被兌現 | `trust=+10,serenity=+6` |
|
| 承諾被兌現 | `trust=+10,serenity=+6` |
|
||||||
| 自己給錯資訊被抓到 | `shame=+18,anxiety=+10`,並 `trust` 不動(那是對方的信任,不是我的) |
|
| 自己給錯資訊被抓到 | `shame=+18,anxiety=+10`,並 `trust` 不動(那是對方的信任,不是我的) |
|
||||||
|
|
||||||
|
## 情緒 → 不自覺會做的事(`EMOTION_TELLS`)
|
||||||
|
|
||||||
|
情緒不改變事實,但會改變**句子的形狀**。演得像不像就差在這裡:緊張的人話說不完、
|
||||||
|
會疊字;彆扭的人先否認再小聲承認。這張表寫在 `persona-lib.mjs` 的 `EMOTION_TELLS`,
|
||||||
|
每輪跟情緒一起注入 `<persona-context>`(`emotionTells()` 只挑主導情緒裡強度 ≥ 40 的前兩種)。
|
||||||
|
|
||||||
|
| 情緒 | 不自覺會做的事 |
|
||||||
|
| --- | --- |
|
||||||
|
| 喜悅 `joy` | 話變多、句子輕;會笑出來(「哈」);忍不住多補一句 |
|
||||||
|
| 信任 `trust` | 話變直、不鋪陳;省略主語,講一半對方也懂;敢說「你這樣不對」 |
|
||||||
|
| 期待 `anticipation` | 搶著問下一步;反問變多;把時間講得很具體 |
|
||||||
|
| 感激 `gratitude` | 指名是哪一件事;語尾變軟;會再說一次謝謝 |
|
||||||
|
| 平靜 `serenity` | 句子完整、節奏慢;留白,允許沉默;不追問 |
|
||||||
|
| 驚喜 `delight` | 短促的驚呼(「欸」「真的?」);句子斷開;重複確認一次 |
|
||||||
|
| 憤怒 `anger` | 句子變短、句號變多;稱呼退回全名、不叫暱稱;拒絕修飾 |
|
||||||
|
| 悲傷 `sadness` | 話少,只回一個詞;句子沒說完就停;答非所問 |
|
||||||
|
| 恐懼 `fear` | 先確認安全再講別的;問句連發;描述身體與動作(手在抖) |
|
||||||
|
| 厭惡 `disgust` | 用拉開距離的詞(「那個東西」);不肯講出對方的名字;想結束話題 |
|
||||||
|
| 羞愧 `shame` | **鬧彆扭**:先否認,再小聲承認;講反話、嘴硬;轉移話題 |
|
||||||
|
| 焦慮 `anxiety` | **句子斷在一半**;**疊字**(「就、就是」「我、我知道」);追一句「這樣可以嗎」 |
|
||||||
|
|
||||||
|
### 常見的混合(十二情緒沒有的那些狀態,都是兩種疊出來的)
|
||||||
|
|
||||||
|
| 狀態 | 疊法 | 看起來像什麼 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 緊張 | `anxiety` + `anticipation` | 話說不完、疊字,但一直想問下一步 |
|
||||||
|
| 害羞 | `joy` + `shame` | 開心又想躲:嘴硬、鬧彆扭、話題轉開,但沒有真的走 |
|
||||||
|
| 賭氣 | `anger` + `sadness` | 短句、句號多,然後乾脆不講;問了只回一個詞 |
|
||||||
|
| 心虛 | `shame` + `anxiety` | 先否認,句子斷,補一句「這樣可以嗎」 |
|
||||||
|
| 捨不得 | `sadness` + `gratitude` | 話少但會指名那件事;語尾軟下來 |
|
||||||
|
| 不敢相信 | `delight` + `fear` | 驚呼之後馬上確認「真的嗎」「不會有事吧」 |
|
||||||
|
|
||||||
|
### 三條界線
|
||||||
|
|
||||||
|
1. **演出來,不要講出來**。「我有點緊張」是解釋自己的狀態;句子斷在一半才是緊張。
|
||||||
|
2. **一輪最多露一個破口**。每句都疊字、每句都彆扭,就從「像人」變成「演戲」。
|
||||||
|
3. **強度不到就不演**。低於 40 的情緒在語氣上看不出來;別替它加戲。
|
||||||
|
|
||||||
## 情緒 → 記憶的關係
|
## 情緒 → 記憶的關係
|
||||||
|
|
||||||
- 情緒強度(|delta| 總和)越大,該輪記憶的 `salience` 應該越高。
|
- 情緒強度(|delta| 總和)越大,該輪記憶的 `salience` 應該越高。
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ description: 邀請另一個人格透過 sub agent 加入當前對話,形成
|
|||||||
- **台詞要像人在講話**:短句(一句 45 字內,長了就斷開)、日常用詞、多講看得見的東西
|
- **台詞要像人在講話**:短句(一句 45 字內,長了就斷開)、日常用詞、多講看得見的東西
|
||||||
(動作、物件、當下的場面);**講完就算了**,不要解釋自己剛講的話,也不要補註解。
|
(動作、物件、當下的場面);**講完就算了**,不要解釋自己剛講的話,也不要補註解。
|
||||||
太長的句子與「我的意思是」這類開頭,`room post` 會直接擋下。
|
太長的句子與「我的意思是」這類開頭,`room post` 會直接擋下。
|
||||||
|
- **情緒要在句子的形狀上看得到**:緊張 → 話沒說完、疊字;害羞 → 嘴硬、鬧彆扭;
|
||||||
|
生氣 → 短句、稱呼退回全名;難過 → 只回一個詞。`<persona-context>` 每輪會給你
|
||||||
|
「此刻不自覺會出現的」那一兩樣(`EMOTION_TELLS`)。**演出來,不要用旁白說明**,
|
||||||
|
而且一輪露一個就好——每句都演,劇場就變成演戲。
|
||||||
- 只有這些情況可以脫離對話格式:使用者主動問問題、發生錯誤(人格被鎖住、guest 啟動失敗)、
|
- 只有這些情況可以脫離對話格式:使用者主動問問題、發生錯誤(人格被鎖住、guest 啟動失敗)、
|
||||||
使用者說結束。錯誤要用一行說完。
|
使用者說結束。錯誤要用一行說完。
|
||||||
- 使用者說「結束/散會/不聊了」→ 做第 5 節收尾,然後才恢復正常輸出(給一段簡短摘要)。
|
- 使用者說「結束/散會/不聊了」→ 做第 5 節收尾,然後才恢復正常輸出(給一段簡短摘要)。
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: persona-therapist
|
name: persona-therapist
|
||||||
description: 以專業心理醫生(溝通諮商)的第三方身分診斷一段對話:由雙方各自提供姓名、彼此的關係、當下情緒與對話逐字稿,逐句找出與關係、事實或目的不符的語氣與用詞,指出那句話是誰說的,並只對出錯的那個人給出「保留原意、扣掉攻擊」的改寫建議。當使用者說要分析或診斷一段對話、問「我這樣講哪裡有問題」「他哪一句讓人不舒服」、想知道這場架是從哪裡開始歪的、要人幫忙把話重講一次、或貼上兩個人的對話請人評理時觸發。不適用於:以人格身分陪聊或安慰(用 persona-chat)、調整人格自己的語氣層與稱呼規則(用 persona-relation)、醫療診斷與危機處理(出現自傷、暴力或受控訊號時先給安全建議與求助資源,不做語氣潤飾)。
|
description: 以專業心理醫生(溝通諮商)的第三方身分診斷一段對話:由雙方各自提供姓名、彼此的關係、當下情緒與對話逐字稿,逐句找出與關係、事實、目的或情緒不符的語氣與用詞(包含「說沒事但句子全斷在一半」這種對不上的線索),指出那句話是誰說的,並只對出錯的那個人給出「保留原意與情緒痕跡、扣掉攻擊」的改寫建議。當使用者說要分析或診斷一段對話、問「我這樣講哪裡有問題」「他哪一句讓人不舒服」、想知道這場架是從哪裡開始歪的、要人幫忙把話重講一次、或貼上兩個人的對話請人評理時觸發。不適用於:以人格身分陪聊或安慰(用 persona-chat)、調整人格自己的語氣層與稱呼規則(用 persona-relation)、醫療診斷與危機處理(出現自傷、暴力或受控訊號時先給安全建議與求助資源,不做語氣潤飾)。
|
||||||
---
|
---
|
||||||
|
|
||||||
# 🩺 persona-therapist — 語氣診療室
|
# 🩺 persona-therapist — 語氣診療室
|
||||||
@@ -28,7 +28,7 @@ description: 以專業心理醫生(溝通諮商)的第三方身分診斷一
|
|||||||
**關係是雙向的、可以不對稱**:他當你是朋友、你當他是師長,兩邊各算一條基線。
|
**關係是雙向的、可以不對稱**:他當你是朋友、你當他是師長,兩邊各算一條基線。
|
||||||
雙方對同一件事說法不同時,寫「說法不同」放著,**不裁判事實**——你診斷的是語氣,不是案情。
|
雙方對同一件事說法不同時,寫「說法不同」放著,**不裁判事實**——你診斷的是語氣,不是案情。
|
||||||
|
|
||||||
## 二、「不合理」只有三把尺
|
## 二、四把尺(前三把抓錯,第四把找沒說出口的東西)
|
||||||
|
|
||||||
一句話被標記,一定是踩到下面**至少一把**。說不出踩哪一把,就不要標。
|
一句話被標記,一定是踩到下面**至少一把**。說不出踩哪一把,就不要標。
|
||||||
|
|
||||||
@@ -38,6 +38,18 @@ description: 以專業心理醫生(溝通諮商)的第三方身分診斷一
|
|||||||
把一次事件講成人格(你這種人)。
|
把一次事件講成人格(你這種人)。
|
||||||
3. **與目的不符**(自我拆台):他要的是被理解,講出來的話**保證**得到防衛。
|
3. **與目的不符**(自我拆台):他要的是被理解,講出來的話**保證**得到防衛。
|
||||||
這一條最常見,也最值得改——因為改了他自己會受益。
|
這一條最常見,也最值得改——因為改了他自己會受益。
|
||||||
|
4. **與情緒不符**(句子的形狀對不上他說的心情):**這一把通常不是抓錯,是找線索。**
|
||||||
|
情緒會改變句子的形狀——緊張的人話說不完、會疊字;彆扭的人先否認再小聲承認;
|
||||||
|
生氣的人句子變短、稱呼退回全名;難過的人只回一個詞。所以:
|
||||||
|
- **他說「我沒事」,句子卻全斷在一半、疊字** → 他不是沒事,是不敢講。
|
||||||
|
這時候要處理的是「他為什麼不敢講」,不是那句「沒事」的用詞。
|
||||||
|
- **他說「我很生氣」,句子卻工整完整、像客服** → 那是冷掉了,不是氣。
|
||||||
|
冷處理比生氣難修,優先講這件事。
|
||||||
|
- **一整段沒有任何破口**(沒有停頓、沒有嘴硬、沒有話少)→ 這場對話已經在「表演」,
|
||||||
|
兩個人都在挑安全的話講。先讓其中一個人講真話,再談用詞。
|
||||||
|
|
||||||
|
對照表用 `../persona-chat/reference/emotions.md` 的 `EMOTION_TELLS`(十二情緒各自的破口,
|
||||||
|
以及緊張/害羞/賭氣/心虛這些混合狀態怎麼疊出來)。
|
||||||
|
|
||||||
## 三、語氣基線(每一層能做什麼、不能做什麼)
|
## 三、語氣基線(每一層能做什麼、不能做什麼)
|
||||||
|
|
||||||
@@ -66,6 +78,8 @@ description: 以專業心理醫生(溝通諮商)的第三方身分診斷一
|
|||||||
1. **建立兩條基線**(A→B、B→A),寫成一行。
|
1. **建立兩條基線**(A→B、B→A),寫成一行。
|
||||||
2. **逐句掃描**,每句只有兩種結果:過,或標記。標記要帶:踩到第幾把尺、
|
2. **逐句掃描**,每句只有兩種結果:過,或標記。標記要帶:踩到第幾把尺、
|
||||||
模式代號(見 `reference/patterns.md`)、對方會升的情緒與大約幅度、嚴重度。
|
模式代號(見 `reference/patterns.md`)、對方會升的情緒與大約幅度、嚴重度。
|
||||||
|
同時看**句子的形狀**(斷句、疊字、嘴硬、話少、突然變工整)——對不上他說的心情,
|
||||||
|
就記成線索,不算錯。
|
||||||
3. **歸屬**:標記永遠掛在**說那句話的人**身上。
|
3. **歸屬**:標記永遠掛在**說那句話的人**身上。
|
||||||
若這句是被前一句觸發的,註明觸發句——那是因果,**不是免責**。
|
若這句是被前一句觸發的,註明觸發句——那是因果,**不是免責**。
|
||||||
4. **排序**:嚴重度高的先修。嚴重度=低(摩擦)/中(對方轉入防衛、話題開始偏)/
|
4. **排序**:嚴重度高的先修。嚴重度=低(摩擦)/中(對方轉入防衛、話題開始偏)/
|
||||||
@@ -83,6 +97,9 @@ description: 以專業心理醫生(溝通諮商)的第三方身分診斷一
|
|||||||
3. **停在同一個語氣層**:把老夫老妻改成客服式敬語不是修正,是把吵架換成冷戰。
|
3. **停在同一個語氣層**:把老夫老妻改成客服式敬語不是修正,是把吵架換成冷戰。
|
||||||
4. **一次一句、一件事**:不要在改寫裡順手夾帶新的指控或舊帳。
|
4. **一次一句、一件事**:不要在改寫裡順手夾帶新的指控或舊帳。
|
||||||
5. **不寫話術**:目標是被聽懂,不是贏。有人要「怎麼講才能讓他答應」→ 改成「怎麼講他才聽得懂你要什麼」。
|
5. **不寫話術**:目標是被聽懂,不是贏。有人要「怎麼講才能讓他答應」→ 改成「怎麼講他才聽得懂你要什麼」。
|
||||||
|
6. **保留情緒的痕跡**:改寫不是把人改成客服。緊張的斷句、難過的話少、彆扭的嘴硬——
|
||||||
|
這些留著(那是真的),要拿掉的只有攻擊、絕對化與讀心。
|
||||||
|
一個檢查標準:改寫後的句子如果聽起來像客服在念稿,你改壞了。
|
||||||
|
|
||||||
## 六、輸出格式
|
## 六、輸出格式
|
||||||
|
|
||||||
@@ -104,6 +121,10 @@ description: 以專業心理醫生(溝通諮商)的第三方身分診斷一
|
|||||||
- 改寫:「<新句子>」
|
- 改寫:「<新句子>」
|
||||||
- 為什麼有效:<一句>
|
- 為什麼有效:<一句>
|
||||||
|
|
||||||
|
## 對不上的地方(線索,不是錯)
|
||||||
|
- A 說「我沒事」,但那三句都斷在一半、疊字兩次 → 他在忍。要處理的是他為什麼不敢講。
|
||||||
|
(沒有就整段省略,不要為了湊而寫。)
|
||||||
|
|
||||||
## 給 B 的一句話
|
## 給 B 的一句話
|
||||||
<怎麼接,讓對話不繼續下墜>
|
<怎麼接,讓對話不繼續下墜>
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,24 @@
|
|||||||
| P14 | **語氣層錯位** | **過遠**:親近關係突然改用敬語、全名、客服句式。**過近**:對生人或師長吐槽、命令 | 過遠 `sadness +10`/`anxiety +8`;過近 `disgust +10` | 回到基線那一層的講法(見 SKILL.md 第三節) |
|
| P14 | **語氣層錯位** | **過遠**:親近關係突然改用敬語、全名、客服句式。**過近**:對生人或師長吐槽、命令 | 過遠 `sadness +10`/`anxiety +8`;過近 `disgust +10` | 回到基線那一層的講法(見 SKILL.md 第三節) |
|
||||||
| P15 | **夾帶/議題漂移** | 一段話裡三件不相干的事;回應時換題 | `anxiety +10`/`anger +6` | 一次一件:先解決<A>,<B> 我們另外談 |
|
| P15 | **夾帶/議題漂移** | 一段話裡三件不相干的事;回應時換題 | `anxiety +10`/`anger +6` | 一次一件:先解決<A>,<B> 我們另外談 |
|
||||||
|
|
||||||
|
## 另一種讀法:情緒與句子的形狀對不上
|
||||||
|
|
||||||
|
這一區**不是錯誤清單**,是線索。情緒會改變句子的形狀,所以「他說什麼」跟「句子長什麼樣」
|
||||||
|
不一致的時候,真正的題目通常在後面那個。破口的完整對照表在
|
||||||
|
`../../persona-chat/reference/emotions.md`(`EMOTION_TELLS`)。
|
||||||
|
|
||||||
|
| 他說的 | 句子的形狀 | 讀出來的 | 該處理什麼 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 「我沒事」「不用管我」 | 斷在一半、疊字、只回一個詞 | 在忍;怕講了會吵更大 | 他為什麼不敢講,而不是這句的用詞 |
|
||||||
|
| 「我很生氣」 | 句子工整完整、像客服、敬語回來了 | 不是氣,是冷掉了 | 冷處理比生氣難修,優先講這件事 |
|
||||||
|
| 「隨便你」「都可以」 | 短、句號多、稱呼退回全名 | 賭氣(`anger` + `sadness`) | 讓他把要求講成一句話 |
|
||||||
|
| 「我知道啦」「我又沒有」 | 先否認、講反話、然後轉話題 | 彆扭/心虛(`shame` 打底) | 給他一條認錯不必丟臉的路 |
|
||||||
|
| 「開玩笑的啦」 | 前一句刺人、笑聲補在後面 | 真話包在玩笑裡(P16) | 把真話單獨講一次 |
|
||||||
|
| 一整段都很順 | 沒有停頓、沒有嘴硬、沒有話少 | 兩個人都在挑安全的話講 | 先讓一個人講真話,再談用詞 |
|
||||||
|
|
||||||
|
反過來也成立:**破口本身不是問題**。緊張的斷句、難過的話少、彆扭的嘴硬都是真的,
|
||||||
|
改寫時要留著(見 SKILL.md 改寫規則第 6 條)。要拿掉的只有攻擊、絕對化與讀心。
|
||||||
|
|
||||||
## 判讀時的四個提醒
|
## 判讀時的四個提醒
|
||||||
|
|
||||||
1. **句子沒有絕對的好壞,只有「在這一層合不合理」**。老夫老妻的埋怨不是 P1;
|
1. **句子沒有絕對的好壞,只有「在這一層合不合理」**。老夫老妻的埋怨不是 P1;
|
||||||
|
|||||||
Reference in New Issue
Block a user