feat(voice): 注入層與 CLI 訊息改成人話;越害羞話越少、心裡話越多(v0.0.8 同批)
三層照建議只做兩層半:注入層與 CLI 訊息重寫,文件只順句子、不動規格
(數字、參數名、指令名、判斷條件一個沒改——那些精確的詞就是能力本身)。
一、越害羞的人話越少、心裡話越多(`speechBudget()`)
這不是新加一條規矩,是同一件事的兩面:**說出口的那句常常正好在迴避心裡那句**,
落差本身才是那個角色。所以句數上限與心裡話下限綁在同一個羞恥度上:
羞恥度 ≥ 75 → 最多 2 句、心裡話至少 2 句,且**先寫完再開口**
台詞不可以是心裡話的摘要(心裡「我一直在等你問」→ 出口不能是「我有在等你問」)
50–74 → 3 句、心裡話至少 1 句
≤ 49 → 3 句、想到什麼就講,不用先在心裡繞一圈
`room post` 改用 `speechBudget(speaker).sentences`,不再是固定三句;
被擋下時會講明「這個人格話比別人少」。
二、注入層改成人話
原本是規格書腔(「**講完就算了**——不要解釋自己剛講的話」),現在像有人在旁邊提醒:
「講完就停,不要回頭解釋自己剛講的話,也不要幫自己收尾。」
黑名單從列舉詞條改成講清楚**為什麼**不像人(「先發一句免費的認可,對方要的是回答」)。
機械會擋的規則壓成最後一行括號——保留全部關鍵詞,但不再稀釋前面的重點。
三、CLI 訊息改成人話(20 條)
「⚠ 這段有 4 句,超過 3 句上限 → 砍到重點」→「講太多了,4 句。這裡最多 3 句——挑最想說的那一兩句就好」
「幾乎只給自己加分——這種偏差要自己看得見」→「幾乎都在給自己加分。delta 是你自己挑的,這種偏差沒人會替你抓」
四、測試
314 項全過(新增 4 項)。既有 6 條斷言原本釘在字面上,措辭一改就紅——
改成釘意思(「最多」「講過」「講完就停」)而不是釘整句,這種脆弱本來就該修。
版本:與 PR #11 同一批,維持 0.0.8。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+58
-26
@@ -516,6 +516,39 @@ export function modestyOf(slug) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 越害羞的人,話越少、心裡話越多。
|
||||
*
|
||||
* 這不是加一條規矩,是同一件事的兩面:**說出口的那句,常常正好在迴避心裡那句**。
|
||||
* 落差本身才是那個角色——所以句數上限與心裡話的下限綁在同一個羞恥度上。
|
||||
* 不害羞的人不需要這個緩衝,想到什麼講什麼,落差趨近於零。
|
||||
*/
|
||||
export function speechBudget(slug) {
|
||||
const m = modestyOf(slug);
|
||||
if (m.value >= 75) {
|
||||
return {
|
||||
modesty: m.value, sentences: 2, thinkMin: 2, gap: "high",
|
||||
note: "話會變少,而且說出口的那句常常在**迴避**心裡那句——先把心裡話寫完再開口," +
|
||||
"台詞不可以是心裡話的摘要(心裡想「我一直在等你問」,出口就不能是「我有在等你問」)。",
|
||||
};
|
||||
}
|
||||
if (m.value >= 50) {
|
||||
return { modesty: m.value, sentences: 3, thinkMin: 1, gap: "mid", note: "心裡想到的比講出來的多一點。" };
|
||||
}
|
||||
return { modesty: m.value, sentences: MAX_SENTENCES, thinkMin: 0, gap: "low", note: "想到什麼就講,不用先在心裡繞一圈。" };
|
||||
}
|
||||
|
||||
/** 注入用的一行:這一輪能講幾句、心裡話該有幾句。 */
|
||||
export function speakDirective(slug) {
|
||||
const b = speechBudget(slug);
|
||||
const think = b.thinkMin > 0 ? `這一輪心裡話至少 ${b.thinkMin} 句,而且要先寫再開口` : "心裡話有想到再寫";
|
||||
return (
|
||||
`這一輪最多講 ${b.sentences} 句(劇場模式每人每輪也一樣)。${b.note}\n` +
|
||||
` 推導、比對、盤算不要說給他聽,寫進心裡話(\`persona.mjs think\`)——${think}。` +
|
||||
"要讓他知道你在想,只報「心想 N 句」,不報內容。"
|
||||
);
|
||||
}
|
||||
|
||||
/** 注入用的一行:講清楚它是什麼、從哪來、怎麼演。 */
|
||||
export function modestyDirective(slug) {
|
||||
const m = modestyOf(slug);
|
||||
@@ -1742,27 +1775,27 @@ export const speechBlockers = (text) => speechLint(text).filter((i) => i.level !
|
||||
export function speechLintMessage(issue) {
|
||||
switch (issue.kind) {
|
||||
case "long":
|
||||
return `「${issue.text}…」這句 ${issue.chars} 字,超過 ${MAX_SENTENCE_CHARS} 字——斷成兩句,或把修飾砍掉`;
|
||||
return `「${issue.text}…」這句 ${issue.chars} 字,太長了(上限 ${MAX_SENTENCE_CHARS})——斷成兩句,或把修飾拿掉`;
|
||||
case "explain":
|
||||
return `「${issue.opener}」是在解釋自己剛講的話——刪掉,講完就算了`;
|
||||
return `「${issue.opener}」是在回頭解釋自己剛講的話——拿掉,講完就停`;
|
||||
case "hedge":
|
||||
return `「${issue.words.join("」「")}」一句疊了 ${issue.words.length} 層避險——確定的事零層,真的不確定留一層`;
|
||||
return `一句話裡疊了 ${issue.words.length} 層「${issue.words.join("」「")}」——確定的事就直說,真的不確定留一個就好`;
|
||||
case "cn":
|
||||
return `「${issue.word}」是中國用語 → ${issue.suggest}`;
|
||||
return `「${issue.word}」是中國用語,台灣這邊說「${issue.suggest}」`;
|
||||
case "halfwidth":
|
||||
return `「${issue.text}」用了半形標點——中文句子一律全形`;
|
||||
return `「${issue.text}」是半形標點——中文句子用全形`;
|
||||
case "emoji":
|
||||
return `${issue.count} 個 emoji——講話最多一個`;
|
||||
return `${issue.count} 個 emoji,太多了——講話留一個就夠`;
|
||||
case "dash":
|
||||
return `${issue.count} 個破折號——一輪最多一個,其餘改逗號或句號`;
|
||||
return `${issue.count} 個破折號——一輪留一個,其他改成逗號或句號`;
|
||||
case "markdown":
|
||||
return "粗體、清單符號或標題——講話沒有排版,收掉";
|
||||
return "有粗體、清單或標題——講話的人不會排版,收掉";
|
||||
case "parallel":
|
||||
return `「不是 A 而是 B」出現 ${issue.count} 次——一輪最多一次,其餘改直述`;
|
||||
return `「不是 A 而是 B」講了 ${issue.count} 次——一輪一次就夠,其他改成直說`;
|
||||
case "pastclaim":
|
||||
return `講到「${issue.word}」:先 recall 確認記憶裡真的有這件事,沒有紀錄就是編造自己的過去`;
|
||||
return `你講到「${issue.word}」——先 recall 一下,記憶裡真的有這件事嗎?沒有的話那是在編自己的過去`;
|
||||
default:
|
||||
return `「${issue.word}」是${issue.label}——${issue.fix}`;
|
||||
return `「${issue.word}」——${issue.label}。${issue.fix}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2819,21 +2852,20 @@ export function turnContext(slug, sessionId, prompt = "") {
|
||||
`人格:\`${slug}\` ${identityBrief(slug)}`,
|
||||
`人格倉庫:${personaDir(slug)}(唯一可讀寫的人格資料範圍)`,
|
||||
emotionBrief(slug, state),
|
||||
`說話規則:回使用者 ${MAX_SENTENCES} 句以內(劇場模式每人每輪也一樣);` +
|
||||
"推導、比對、盤算一律走心裡話(`persona.mjs think`),不要說給使用者聽——" +
|
||||
"要讓他知道你在想,就只報「心想 N 句」,不報內容。",
|
||||
`講話像講話:**短句**(一句 ${MAX_SENTENCE_CHARS} 字內,長了就斷開)、**日常用詞**(不用書面語、` +
|
||||
"不用術語、不用成語堆疊)、**多講看得見的東西**(人、動作、東西、當下的場面)而不是概念與感想;" +
|
||||
"**講完就算了**——不要解釋自己剛講的話(沒有「我的意思是」「換句話說」「也就是說」)," +
|
||||
"不要補註解、不要收尾總結。這幾條 `room post` 與 `said check` 會實際擋下。",
|
||||
"不要說 AI 才會說的話:罐頭同理心(「這個我懂」「我完全理解」)、頒獎開場(「好問題」)、" +
|
||||
"交差句(「希望這對你有幫助」)、預告(「接下來我會」)、說教腔(「說到底」「本質上」)、" +
|
||||
"假坦白開場(「老實說」)、罐頭收尾(「總的來說」)、立場真空(「各有優缺點」「因人而異」)、" +
|
||||
"無來源的權威(「研究顯示」)、用旁白演情緒(「我愣了一下」)、一句疊兩層避險、" +
|
||||
"中國用語與半形標點、粗體與清單符號。這些 `room post` 也會擋。",
|
||||
"**講自己的過去要有出處**:「我以前⋯」「我原本以為⋯」只能講記憶裡真的有的事(先 `recall` 查)。" +
|
||||
"沒有紀錄就不要講——編一段轉折比講一句空話糟糕得多。同理,情緒要來自現在的情緒值," +
|
||||
"不是為了有人味而加上去的。",
|
||||
speakDirective(slug),
|
||||
"話短一點。一句講不完就斷開,不要用逗號一直串下去。用你平常會說的字," +
|
||||
"看得見的東西先講——「你手上那杯冷了」比「我感覺到你的疲憊」好。" +
|
||||
"講完就停,不要回頭解釋自己剛講的話,也不要幫自己收尾。",
|
||||
"有些句子一出口就不像人了:「這個我懂」「我完全理解」「好問題」" +
|
||||
"(先發一句免費的認可,對方要的是回答)、「希望這對你有幫助」「接下來我會⋯」、" +
|
||||
"「說到底」「本質上」(假裝在講穿本質,其實只是重講一次)、開場的「老實說」、" +
|
||||
"收尾的「總的來說」、該表態時的「各有優缺點」、沒出處的「研究顯示」、" +
|
||||
"用旁白演情緒的「我愣了一下」。這些不要說。",
|
||||
"**講自己的過去,要真的有那件事**。「我以前⋯」「我原本以為⋯」先 `recall` 查得到才講;" +
|
||||
"查不到就別講——編一段轉折比講一句空話糟糕得多。情緒也一樣," +
|
||||
"照現在的情緒值走,不要為了顯得有人味硬加。",
|
||||
`(機械會擋的:一句 ${MAX_SENTENCE_CHARS} 字、上面那些詞、中國用語、半形標點、` +
|
||||
"粗體與清單符號、兩小時內講過的話——`room post` 與 `said check` 直接拒收。)",
|
||||
];
|
||||
// 情緒先行:先讀對方那句話帶了什麼,再談我自己的狀態。
|
||||
const read = readUserEmotion(prompt);
|
||||
|
||||
Reference in New Issue
Block a user