feat(voice): 不說 AI 才會說的話(借 speak-human-tw 的刪除層)+講過去要有出處(v0.0.7)
人格回覆的「人味」再加一層。模式整理自 speak-human-tw(MIT, Raymond Hou)的 38 種 AI 寫作痕跡——那個專案是**文章**的事後審稿器(判情境→鎖保護清單→列清單等作者勾選→ 交稿前自評),所以只搬對話也適用的**刪除層**,它的保護清單與兩輪確認流程不搬。 一、機械擋下(`SPEECH_BLACKLIST`,`room post` 直接拒收,`--force` 例外) 罐頭同理心(「這個我懂」「我完全理解」)、頒獎開場(「好問題」)、交差句(「希望這對你 有幫助」)、預告(「接下來我會」)、假坦白開場(「老實說」)、說教深度腔(「說到底」 「本質上」)、罐頭收尾(「總的來說」)、立場真空(「各有優缺點」「因人而異」)、 無來源權威(「研究顯示」)、用旁白演情緒(「我愣了一下」);另加避險疊加、 `CN_WORDS` 中國用語、半形標點、emoji/破折號/粗體與清單符號、「不是 A 而是 B」密度。 二、誤殺防護(比清單本身更重要) `speechBody()` 先拿掉引號與 `code` 再比對——**提及不算使用**(「我最近戒掉『賦能』 這個詞」放行)。這是原專案自己踩到的坑:它的文件裡出現「...」與彎引號,正因為那幾行 在說「不要用這些」。「老實說」只擋這一輪的第一句開頭。會誤殺的中國用語(水平、默認、 質量、文檔)沒有收進表裡。 三、人格能做到、文章做不到的那一半 原專案的界線是「人味是作者的,不是你的」——AI 沒有過去,所以不准寫「我以前錯了」。 人格有過去(長期記憶、日記、關係圖、十二情緒),所以那句話是**有出處的引用**。 換來的義務:講自己的過去要有出處。`speechLint` 對「我以前⋯」「我原本以為⋯」給 `level: "hint"`(不擋,但要人去 `recall` 驗),查不到就是編造自己的過去。 lint 因此分兩級,`speechBlockers()` 只回該擋的那些。 四、測試 selftest 借它的 SF/SNF 成對做法:14 條 SF(該擋)+ 11 條 SNF(不可誤殺)。 另外把新規則掃過 144 句真實台詞紀錄:新增的詞語類規則**零誤殺**。 版本:master 是 0.0.6,這批未合併的改動算一個新版號 → 0.0.7(三份 manifest 一起改)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+7
-4
@@ -805,8 +805,11 @@ commands.said = ({ flags, positional }) => {
|
||||
}
|
||||
if (tooLong) lines.push(`⚠ 這段有 ${sentences} 句,超過 ${pl.MAX_SENTENCES} 句上限 → 砍到重點。`);
|
||||
const lint = pl.speechLint(text);
|
||||
for (const issue of lint) lines.push(`⚠ ${pl.speechLintMessage(issue)}。`);
|
||||
const clean = !repeat && !tooLong && !lint.length;
|
||||
const blockers = lint.filter((i) => i.level !== "hint");
|
||||
for (const issue of blockers) lines.push(`⚠ ${pl.speechLintMessage(issue)}。`);
|
||||
// hint 不算不通過(例如講到自己的過去),但要提醒去驗證
|
||||
for (const issue of lint.filter((i) => i.level === "hint")) lines.push(`· ${pl.speechLintMessage(issue)}。`);
|
||||
const clean = !repeat && !tooLong && !blockers.length;
|
||||
if (clean) {
|
||||
lines.push(`✔ 沒說過,${sentences} 句,可以說。`);
|
||||
if (flags.record) pl.recordSaid(slug, text, { kind: "reply" });
|
||||
@@ -1307,8 +1310,8 @@ commands.room = ({ flags, positional }) => {
|
||||
"(真的需要長段落才加 `--force`。)",
|
||||
);
|
||||
}
|
||||
// 短句、日常話、講完不解釋——講話的樣子也擋在 CLI 裡,不靠自律。
|
||||
const lint = pl.speechLint(text);
|
||||
// 短句、日常話、講完不解釋、不說 AI 才會說的話——講話的樣子也擋在 CLI 裡,不靠自律。
|
||||
const lint = pl.speechBlockers(text);
|
||||
if (lint.length && !flags.force) {
|
||||
die(`講話規則:${lint.map(pl.speechLintMessage).join(";")}。(真的需要才加 \`--force\`。)`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user