@moon791017/neo-skills 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -23
- package/bin/install-skills.js +84 -0
- package/package.json +3 -1
- package/skills/neo-stop-slop/SKILL.md +146 -0
- package/skills/neo-stop-slop/evals/eval_queries.json +30 -0
- package/skills/neo-stop-slop/evals/evals.json +28 -0
- package/skills/neo-stop-slop/references/dev-slop.md +77 -0
- package/skills/neo-stop-slop/references/examples.md +50 -0
- package/skills/neo-stop-slop/references/phrases-en.md +79 -0
- package/skills/neo-stop-slop/references/phrases-zh.md +63 -0
- package/skills/neo-stop-slop/references/structures.md +86 -0
- package/skills/neo-stop-slop/scripts/analyze-slop.js +276 -0
package/README.md
CHANGED
|
@@ -86,6 +86,10 @@
|
|
|
86
86
|
|
|
87
87
|
* **AI 助手開發治理 (`skills/neo-agent-harness`)**:檢查專案規則、測試、CI、審查流程與安全防護是否足夠清楚,協助 AI 助手更穩定、更安全地參與開發。
|
|
88
88
|
|
|
89
|
+
### 13. AI Tells / Slop 贅詞消除專家
|
|
90
|
+
|
|
91
|
+
* **文字去 AI 腔調 (`skills/neo-stop-slop`)**:消除中英文 AI 腔、贅詞與公式化囉唆句式,還原為乾淨、生動且簡煉的自然語言,並包含工程師註解、Git Commit 及 PR 說明的特化優化。
|
|
92
|
+
|
|
89
93
|
## 📂 系統架構
|
|
90
94
|
|
|
91
95
|
本專案主要由標準專家技能模組組成的知識庫所構成:
|
|
@@ -96,26 +100,51 @@
|
|
|
96
100
|
|
|
97
101
|
## 📦 安裝與使用
|
|
98
102
|
|
|
99
|
-
Neo Skills
|
|
103
|
+
Neo Skills 已全面升級並支援專屬的極簡安裝器,同時相容於 [agentskills.io](https://agentskills.io) 官方推薦的 **Agent Skills 開源標準規範**。
|
|
104
|
+
|
|
105
|
+
根據您的使用場景,可以選擇以下兩種最適合您的安裝方式:
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### 一、一鍵同步全域技能(Antigravity CLI 專用,推薦)
|
|
100
110
|
|
|
101
|
-
|
|
111
|
+
如果您使用的是 **Antigravity CLI**,建議使用專門設計的 `neo-skills` 安裝工具(舊稱 `install-skills`)。這是一個極簡化的工具,會一鍵將本專案所有的專家技能,複製到您的全域路徑 `~/.gemini/antigravity-cli/skills` 中,同時自動過濾無關檔案(如 `.git`、`node_modules`、`.DS_Store` 等)。
|
|
102
112
|
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
#### 透過 npx 直接執行:
|
|
114
|
+
```bash
|
|
115
|
+
npx -y @moon791017/neo-skills@latest
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### 本地開發手動安裝:
|
|
119
|
+
如果您已複製本專案至本地,也可以直接在專案根目錄下執行:
|
|
120
|
+
```bash
|
|
121
|
+
node bin/install-skills.js
|
|
122
|
+
```
|
|
105
123
|
|
|
106
124
|
---
|
|
107
125
|
|
|
108
|
-
###
|
|
126
|
+
### 二、使用標準 Skills CLI 安裝(通用於專案或其他 AI Agent)
|
|
109
127
|
|
|
110
|
-
|
|
128
|
+
針對其他支援 [agentskills.io](https://agentskills.io) 標準規範的 AI 代理(如 Claude Code, Cursor, Copilot 等),您可以使用標準的 `skills` 包管理器。預設會安裝至當前專案,**若您希望將技能安裝至全域路徑,只需在指令後方加上 `-g` 參數**。
|
|
111
129
|
|
|
130
|
+
#### 1. 專案一鍵安裝所有技能(免互動勾選):
|
|
112
131
|
```bash
|
|
113
|
-
npx skills add Benknightdark/neo-skills
|
|
132
|
+
npx skills add Benknightdark/neo-skills --all
|
|
114
133
|
```
|
|
115
134
|
|
|
135
|
+
> [!TIP]
|
|
136
|
+
> * **全域一鍵安裝**:若要將所有技能安裝至標準全域路徑下,只需加上 `-g`:`npx skills add Benknightdark/neo-skills --all -g`。
|
|
137
|
+
> * **命令行指定**:若只需安裝特定 Skill,可以使用 `--skill <名稱>`(例如 `npx skills add Benknightdark/neo-skills --skill neo-typescript,neo-vue`)。
|
|
138
|
+
|
|
139
|
+
#### 💡 終端機互動選單操作小秘訣:
|
|
140
|
+
如果您執行了不帶 `--all` 的預設互動選單命令 `npx skills add Benknightdark/neo-skills`:
|
|
141
|
+
1. **一鍵全選 (Select All)**:在選單畫面中直接按下鍵盤上的 **`a`** 鍵,即可立刻自動勾選所有的技能!
|
|
142
|
+
2. **反向選取 (Invert Selection)**:按下鍵盤上的 **`i`** 鍵,反向切換目前的所有勾選狀態。
|
|
143
|
+
3. **確認送出**:全選後按下 `Enter` 鍵即可一次完成安裝。
|
|
144
|
+
|
|
116
145
|
---
|
|
117
146
|
|
|
118
|
-
###
|
|
147
|
+
### 三、按需安裝特定技能
|
|
119
148
|
|
|
120
149
|
如果您只需要其中某幾項特定領域的專家技能,您可以使用 `--skill` 參數指定安裝:
|
|
121
150
|
|
|
@@ -142,21 +171,7 @@ npx skills add Benknightdark/neo-skills
|
|
|
142
171
|
| **19. 程式碼解釋助手** | `npx skills add Benknightdark/neo-skills --skill neo-explain` |
|
|
143
172
|
| **20. 需求分析與釐清助手** | `npx skills add Benknightdark/neo-skills --skill neo-clarification` |
|
|
144
173
|
| **21. AI 開發流程治理專家** | `npx skills add Benknightdark/neo-skills --skill neo-agent-harness` |
|
|
145
|
-
|
|
146
|
-
---
|
|
147
|
-
|
|
148
|
-
### 三、主流 AI Agent 對齊說明
|
|
149
|
-
|
|
150
|
-
在安裝技能後,主流的 AI 代理會遵循以下載入機制,無須任何額外手動配置:
|
|
151
|
-
|
|
152
|
-
> [!TIP]
|
|
153
|
-
> **全域安裝選項**:若您希望將技能安裝至全域路徑以供所有專案使用,可以在上述指令後面加上 `-g` 參數(例如 `npx skills add -g Benknightdark/neo-skills`)。
|
|
154
|
-
|
|
155
|
-
| AI Agent | 專案載入目錄 (Project-level) | 全域載入目錄 (Global-level) | 系統提示載入方式 |
|
|
156
|
-
| :--- | :--- | :--- | :--- |
|
|
157
|
-
| **Antigravity (AGY)** | `<project>/.agents/skills/` | `~/.gemini/skills/` | 自動掃描並動態感知載入(Perceive 階段) |
|
|
158
|
-
| **Claude Code** | `<project>/.agents/skills/` | `~/.claude/skills/` | 原生載入並透過 trigger-phrases 自動觸發 |
|
|
159
|
-
| **Copilot CLI / Cursor** | `<project>/.agents/skills/` | `~/.copilot/skills/` | 自動偵測專案下的 `.agents/` 設定檔案 |
|
|
174
|
+
| **22. AI Tells/Slop 消除專家** | `npx skills add Benknightdark/neo-skills --skill neo-stop-slop` |
|
|
160
175
|
|
|
161
176
|
---
|
|
162
177
|
|
|
@@ -228,6 +243,7 @@ npx -p @moon791017/neo-skills install-system-instructions --ai-agent claude --in
|
|
|
228
243
|
| **TS 型別設計與 CJS/ESM 互通** | `neo-typescript` | `npx skills add Benknightdark/neo-skills --skill neo-typescript` | `解決 tsconfig 還有 ESM/CJS 互通性的問題` |
|
|
229
244
|
| **複雜/模糊需求釐清與規格化** | `neo-clarification` | `npx skills add Benknightdark/neo-skills --skill neo-clarification` | `我想做一個電商網站` |
|
|
230
245
|
| **AI 助手開發治理與流程健檢** | `neo-agent-harness` | `npx skills add Benknightdark/neo-skills --skill neo-agent-harness` | `幫我檢查這個專案怎麼讓 AI 助手開發得更穩、更安全` |
|
|
246
|
+
| **清除文案/註解/Commit 中的 AI 腔** | `neo-stop-slop` | `npx skills add Benknightdark/neo-skills --skill neo-stop-slop` | `消除這段話裡的 AI 腔贅詞,使其極簡直接` |
|
|
231
247
|
|
|
232
248
|
## 🛠 開發與測試指南
|
|
233
249
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Neo Skills — 全域技能安裝程式
|
|
4
|
+
*
|
|
5
|
+
* 用法:
|
|
6
|
+
* install-skills 安裝專案的技能至全域 Antigravity CLI 技能目錄 (~/.gemini/skills)
|
|
7
|
+
*/
|
|
8
|
+
import { cp, mkdir, access } from 'node:fs/promises';
|
|
9
|
+
import { join, resolve, dirname } from 'node:path';
|
|
10
|
+
import { homedir } from 'node:os';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
|
|
13
|
+
import { setupGlobalErrorHandlers } from './_cli-utils.js';
|
|
14
|
+
|
|
15
|
+
setupGlobalErrorHandlers();
|
|
16
|
+
|
|
17
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const packageRoot = resolve(__dirname, '..');
|
|
19
|
+
const sourceDir = join(packageRoot, 'skills');
|
|
20
|
+
|
|
21
|
+
async function main() {
|
|
22
|
+
console.log('╔══════════════════════════════════════════╗');
|
|
23
|
+
console.log('║ 🧠 Neo Skills — 全域技能安裝程式 ║');
|
|
24
|
+
console.log('╚══════════════════════════════════════════╝');
|
|
25
|
+
console.log('');
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
await access(sourceDir);
|
|
29
|
+
} catch {
|
|
30
|
+
console.error(`❌ 錯誤: 找不到來源技能目錄 ${sourceDir}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 決定安裝目標路徑 (支援透過 TEST_HOME_DIR 覆寫以供測試)
|
|
35
|
+
const home = process.env.TEST_HOME_DIR || homedir();
|
|
36
|
+
const targetDir = join(home, '.gemini/antigravity-cli/skills');
|
|
37
|
+
|
|
38
|
+
console.log(`🚀 開始同步 Neo Skills 至全域 Antigravity CLI...`);
|
|
39
|
+
console.log(`📁 來源路徑: ${sourceDir}`);
|
|
40
|
+
console.log(`🎯 目標路徑: ${targetDir}`);
|
|
41
|
+
console.log('');
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
await mkdir(targetDir, { recursive: true });
|
|
45
|
+
|
|
46
|
+
let copyCount = 0;
|
|
47
|
+
await cp(sourceDir, targetDir, {
|
|
48
|
+
recursive: true,
|
|
49
|
+
force: true,
|
|
50
|
+
filter: (src) => {
|
|
51
|
+
// 解析相對於來源目錄的相對路徑
|
|
52
|
+
const relativePath = src.replace(sourceDir, '');
|
|
53
|
+
|
|
54
|
+
// 忽略無關的隱藏檔案或特定資料夾
|
|
55
|
+
const isIgnored =
|
|
56
|
+
relativePath.includes('node_modules') ||
|
|
57
|
+
relativePath.includes('.git') ||
|
|
58
|
+
relativePath.includes('dist') ||
|
|
59
|
+
relativePath.includes('.antigravitycli') ||
|
|
60
|
+
relativePath.includes('.agents') ||
|
|
61
|
+
relativePath.includes('.DS_Store');
|
|
62
|
+
|
|
63
|
+
if (!isIgnored) {
|
|
64
|
+
copyCount++;
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (copyCount === 0) {
|
|
72
|
+
console.warn('⚠️ 警告: 沒有任何技能檔案被複製。');
|
|
73
|
+
} else {
|
|
74
|
+
console.log('══════════════════════════════════════════');
|
|
75
|
+
console.log(`✅ 安裝成功!已同步 ${copyCount} 個項目到全域。`);
|
|
76
|
+
console.log('💡 提示: Neo Skills 已成功安裝。請確保您的 Antigravity CLI 已正常啟用技能!');
|
|
77
|
+
}
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error(`❌ 安裝失敗:`, error.message || error);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moon791017/neo-skills",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Neo Skills: A Universal Expert Agent Extension",
|
|
6
6
|
"homepage": "https://neo-blog-iota.vercel.app/",
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
"ai agent skills"
|
|
14
14
|
],
|
|
15
15
|
"bin": {
|
|
16
|
+
"neo-skills": "./bin/install-skills.js",
|
|
17
|
+
"install-skills": "./bin/install-skills.js",
|
|
16
18
|
"install-system-instructions": "./bin/install-system-instructions.js"
|
|
17
19
|
},
|
|
18
20
|
"files": [
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: neo-stop-slop
|
|
3
|
+
description: >
|
|
4
|
+
Remove AI writing patterns, tells, and slop from prose, technical drafts, code comments,
|
|
5
|
+
git commit messages, or pull request descriptions. Supports both Traditional Chinese and English.
|
|
6
|
+
Use this skill when the user wants to polish, edit, rewrite, or review drafts to make them sound
|
|
7
|
+
more natural, concise, and direct, or when they ask to eliminate AI tells/slop, even if they don't
|
|
8
|
+
explicitly say "stop-slop".
|
|
9
|
+
license: MIT
|
|
10
|
+
compatibility: Requires Node.js (ESM) to run the analyze-slop.js script.
|
|
11
|
+
metadata:
|
|
12
|
+
author: Ben Knight Dark
|
|
13
|
+
version: "1.0.0"
|
|
14
|
+
patterns: reviewer, generator
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Neo Stop Slop
|
|
18
|
+
|
|
19
|
+
`neo-stop-slop` 是一個專門設計用來消除中英文 AI 腔調(AI Tells)、贅詞及公式化囉唆結構的雙核技能。它能讓 AI 生成的文案、技術草稿、程式碼註解、Git Commit 及 PR 說明,轉換為極簡、乾淨且生動的自然語言。
|
|
20
|
+
|
|
21
|
+
本技能結合了 **Reviewer (文字診斷審查)** 與 **Generator (極簡重寫生成)** 兩大核心工作流。
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Gotchas
|
|
26
|
+
|
|
27
|
+
* **過度精簡風險**:在進行「Rewrite (重寫)」時,務必確保**沒有遺漏關鍵的技術細節或事實資訊**。去 AI 腔是指「清除贅詞與修飾架構」,而不是刪減實質內容。
|
|
28
|
+
* **代碼語法與註解標記**:修剪「代碼註解」時,切勿破壞 XML 文件結構(如 C# 的 `<summary>`、`<param>`)或 JSDoc/TSDoc 的結構標記。
|
|
29
|
+
* **檢測腳本執行**:使用 `analyze-slop.js` 時,一律採用**非互動模式**(傳入 `--file` 或 `--input`,配合 `--format json` 或不帶選項),避免任何 TTY 卡死。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Workflow Checklist
|
|
34
|
+
|
|
35
|
+
Progress:
|
|
36
|
+
- [ ] **Step 1 — Perceive (感知環境)**:辨識輸入文字的語言(繁中/英文)與場景(文案、註解、Git Commit 或 PR 說明),確認使用者需要 `Review`(診斷)還是 `Rewrite`(重寫)。
|
|
37
|
+
- [ ] **Step 2 — Reason (制定策略)**:根據語言與場景,加載相對應的參考手冊(`references/` 資源檔)。
|
|
38
|
+
- [ ] **Step 3 — Act: Review (執行診斷,若適用)**:執行內建的 `scripts/analyze-slop.js` 統計贅詞並計算 Slop 密度分數。
|
|
39
|
+
- [ ] **Step 4 — Act: Rewrite (執行重寫,若適用)**:對照 `references/examples.md` 的轉換標準,將文字徹底重寫為極簡且充滿力量的直白文句。
|
|
40
|
+
- [ ] **Step 5 — Verify (結果驗證)**:再次對重寫後的文字執行 `analyze-slop.js`,確保 Slop 密度降至 A+ 級(< 0.5%)。
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Detailed Guidelines
|
|
45
|
+
|
|
46
|
+
### Step 1 — Perceive (感知環境)
|
|
47
|
+
仔細分析使用者的請求與文本:
|
|
48
|
+
1. **語言檢索**:辨識主要語言是 **繁體中文 (Taiwan)** 還是 **英文**。
|
|
49
|
+
2. **場景分類**:
|
|
50
|
+
* *一般文案/草稿*:加載 `phrases-zh.md`/`phrases-en.md` 與 `structures.md`。
|
|
51
|
+
* *開發者文字 (註解/Commit/PR)*:加載 `dev-slop.md`。
|
|
52
|
+
3. **模式選擇**:
|
|
53
|
+
* 使用者問「這段文字有 AI 腔嗎?」或「幫我做文字審查」:進入 **Review 模式**。
|
|
54
|
+
* 使用者直接說「幫我重寫這段話」或「把 AI 腔消掉」:進入 **Rewrite 模式**。
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### Step 2 — Reason & Load References
|
|
59
|
+
動態加載該技能目錄下的專用知識庫。請根據 Step 1 的感知結果載入以下相對應的路徑:
|
|
60
|
+
* **英文通用**:`references/phrases-en.md`
|
|
61
|
+
* **中文通用**:`references/phrases-zh.md`
|
|
62
|
+
* **公式化結構**:`references/structures.md`
|
|
63
|
+
* **開發者專項**:`references/dev-slop.md`
|
|
64
|
+
* **Before/After 對照組**:`references/examples.md`
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### Step 3 — Act: Review 模式 (診斷)
|
|
69
|
+
1. 將使用者提供的文本寫入臨時檔案,或直接作為參數傳遞給統計腳本。
|
|
70
|
+
2. 在終端非互動執行 `analyze-slop.js`:
|
|
71
|
+
```bash
|
|
72
|
+
node skills/neo-stop-slop/scripts/analyze-slop.js --input "[使用者輸入的文本內容]" --format json
|
|
73
|
+
```
|
|
74
|
+
3. 解析腳本產出的 JSON 數據,擷取:
|
|
75
|
+
* **Slop Density Score (Slop 密度分數)**
|
|
76
|
+
* **Grade (評估等級)**
|
|
77
|
+
* **Violations (檢出的贅詞清單)**
|
|
78
|
+
4. 依據 Output Templates 呈現 Slop 診斷報告,列出違規行數、違規類型,並給出重構建议。
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### Step 4 — Act: Rewrite 模式 (重寫)
|
|
83
|
+
當需要重寫文本時,請遵循以下 6 條去 Slop 鋼鐵鐵律:
|
|
84
|
+
1. **消滅清喉嚨詞 (Cut fillers)**:徹底刪去「值得注意的是」、「不容忽視」、「Here's the thing」等起手式。
|
|
85
|
+
2. **用主動代替被動 (Active voice)**:確保每個句子都有具體的主語(如「人」或「具體組件」)在執行動作。避免擬人化 ("The code wants to...")。
|
|
86
|
+
3. **打碎公式化結構 (Break formulaic setups)**:去除「不是因為 X,而是因為 Y」這類刻意轉折的二元對立;刪除「試想一下:」等自我設問。
|
|
87
|
+
4. **用具體事實代替空泛形容詞 (Be specific)**:將「大幅提升效能、解決痛點」等空話,改寫為具體成效(例如「減少 80% 記憶體開銷」)。
|
|
88
|
+
5. **縮減字數至少 30%**:AI 腔的本質是稀釋資訊。優秀的文字會以最少字數傳達最大資訊量。
|
|
89
|
+
6. **適用開發者規則 (Apply Dev Conventions)**:若處理代碼註解或 Git Commit,嚴格套用 `dev-slop.md` 的精簡規則。
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### Step 5 — Verify (結果驗證)
|
|
94
|
+
1. 將重寫後的文字再次輸入檢測腳本:
|
|
95
|
+
```bash
|
|
96
|
+
node skills/neo-stop-slop/scripts/analyze-slop.js --input "[重寫後的文本]" --format json
|
|
97
|
+
```
|
|
98
|
+
2. 確認 `slopDensityScore` **小於 0.5%**(評估等級達到 **A+**)。
|
|
99
|
+
3. 向使用者呈交成果時,標明重寫前後的字數變化與 Slop 密度的巨大改善。
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Output Templates
|
|
104
|
+
|
|
105
|
+
### 1. Review 診斷報告範本
|
|
106
|
+
當使用者要求「審查/診斷」文字時,請格式化輸出如下:
|
|
107
|
+
|
|
108
|
+
```markdown
|
|
109
|
+
### 🔍 AI Slop 診斷報告
|
|
110
|
+
|
|
111
|
+
* **文本字數**: [總字數] 字
|
|
112
|
+
* **檢出 AI Tells 數量**: [檢出數] 處
|
|
113
|
+
* **Slop 密度分數**: **[密度Score]%** (每百字出現 [檢出數] 次)
|
|
114
|
+
* **評估等級**: **[等級]**
|
|
115
|
+
|
|
116
|
+
#### ⚠️ 檢出細節與修改建議
|
|
117
|
+
| 行數 | 檢出贅詞 | 類型 | 診斷與重構建议 |
|
|
118
|
+
| :--- | :--- | :--- | :--- |
|
|
119
|
+
| 第 X 行 | "值得注意的是" | 廢話起手式 | 刪除此段過渡句,直接陳述後續事實。 |
|
|
120
|
+
| 第 Y 行 | "賦能生態系" | AI 濫用詞 | 替換為「提供技術支持」或「構建合作社群」。 |
|
|
121
|
+
|
|
122
|
+
#### 📝 優化建議摘要
|
|
123
|
+
1. [針對該文章結構的第一條具體調整建議]
|
|
124
|
+
2. [針對副詞或被動語氣的第二條調整建議]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 2. Rewrite 重寫成果範本
|
|
128
|
+
當使用者要求「重寫」文字時,請格式化輸出如下:
|
|
129
|
+
|
|
130
|
+
```markdown
|
|
131
|
+
### ✨ 去 AI 腔重寫成果
|
|
132
|
+
|
|
133
|
+
* **字數變化**: [原始字數] 字 ➡️ **[重寫字數] 字 (縮減 [縮減比例]%)**
|
|
134
|
+
* **Slop 密度**: [原始密度]% ➡️ **0.0% (等級 A+ ✨)**
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
#### 📄 重寫後文本
|
|
139
|
+
> [在此處寫入重寫後的極簡自然文本。保持排版清爽,避免任何 AI 贅字。]
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
#### 💡 關鍵重構解析
|
|
144
|
+
1. **[重構點 1]**:將原始的「[Before 文字]」轉化為「[After 文字]」,去除了「[AI 腔]」並讓語氣更為[主動/直接]。
|
|
145
|
+
2. **[重構點 2]**:刪除贅言,以具體事實「[具體內容]」代替空洞的「[Before 詞彙]」。
|
|
146
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"query": "幫我把這篇文案裡的 AI 腔調和贅詞消掉",
|
|
4
|
+
"should_trigger": true
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
"query": "Review this English draft and remove any AI writing patterns or filler words",
|
|
8
|
+
"should_trigger": true
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"query": "這段 C# 代碼註解看起來很像 ChatGPT 寫的,幫我精簡一下",
|
|
12
|
+
"should_trigger": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"query": "Write a Git commit message for this fix, but make it very concise and natural, no AI tells",
|
|
16
|
+
"should_trigger": true
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"query": "如何用 Python 實作一個快速排序演算法?",
|
|
20
|
+
"should_trigger": false
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"query": "幫我把這篇英文論文翻譯成繁體中文",
|
|
24
|
+
"should_trigger": false
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"query": "這段程式碼有記憶體洩漏嗎?幫我做 Code Review",
|
|
28
|
+
"should_trigger": false
|
|
29
|
+
}
|
|
30
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "neo-stop-slop",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "請幫我重寫這段文字,消除所有的 AI 腔贅詞,使其顯得極簡且直白:\n『值得注意的是,這是一把雙刃劍,不容忽視。總結來說,為企業賦能構建生態圈是至關重要的,我們需要深入探討背後的邏輯。』",
|
|
7
|
+
"expected_output": "重寫後的繁體中文文字。沒有『值得注意的是』、『雙刃劍』、『不容忽視』、『總結來說』、『賦能』、『生態圈』、『至關重要』、『深入探討』與『背後的邏輯』。文字字數大幅縮減,且意思直接生動。",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"輸出文字中不包含『值得注意的是』",
|
|
10
|
+
"輸出文字中不包含『不容忽視』",
|
|
11
|
+
"輸出文字中不包含『至關重要』",
|
|
12
|
+
"輸出文字中不包含『生態圈』或『生態系』",
|
|
13
|
+
"文字語氣直白、精煉"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": 2,
|
|
18
|
+
"prompt": "Rewrite the following technical blog draft to eliminate AI slop:\n'Here's the thing: building scalable systems is hard. Not because the technology is complex. Because human coordination is messy. Delving into microservices is pivotal to foster synergy, but make no mistake, it elevates complexity.'",
|
|
19
|
+
"expected_output": "Clean, direct English prose. No 'Here's the thing', 'Not because... Because...', 'delving', 'pivotal', 'foster synergy', 'make no mistake', 'elevates'. Mixes sentence lengths and uses active voice.",
|
|
20
|
+
"assertions": [
|
|
21
|
+
"The output does not contain 'Here\\'s the thing'",
|
|
22
|
+
"The output does not contain the word 'delve' or 'delving'",
|
|
23
|
+
"The output does not contain 'make no mistake' or 'foster synergy'",
|
|
24
|
+
"The response is direct and shorter than the original text"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Developer Slop Removal (開發者專用 Slop 消除指南)
|
|
2
|
+
|
|
3
|
+
身為開發者,程式碼註解 (Code Comments)、Git Commit 訊息、以及 PR (Pull Request) 說明書是我們最常寫文字的地方。然而,當使用 AI 輔助生成這些內容時,極易帶入累贅、客套且公式化的 AI Tells。這本指南能幫助您寫出如資深工程師般精煉、乾淨且精確的開發文字。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. 程式碼註解與文檔 (Code Comments & Docstrings)
|
|
8
|
+
AI 寫註解時往往過度解釋「這段代碼是做什麼的」,並充斥著無意義的過渡語。
|
|
9
|
+
|
|
10
|
+
### 🚨 AI 腔特徵:
|
|
11
|
+
* **EN**: "This function is responsible for calculating..." / "Helper method to..." / "Please note that..."
|
|
12
|
+
* **ZH**: 「這個函式的主要職責是負責計算...」 / 「用於...的輔助方法」 / 「請注意,這個方法會...」
|
|
13
|
+
|
|
14
|
+
### 💡 消除方法:
|
|
15
|
+
**直接使用「動詞」開頭**。省略主詞與贅詞,專注於行為本身。
|
|
16
|
+
|
|
17
|
+
* *AI 腔 (EN)*:
|
|
18
|
+
```typescript
|
|
19
|
+
// This function is responsible for retrieving the user profiles from the database.
|
|
20
|
+
// Please note that it returns null if the user does not exist in the system.
|
|
21
|
+
function getUser(id: string) { ... }
|
|
22
|
+
```
|
|
23
|
+
* *重構 (EN)*:
|
|
24
|
+
```typescript
|
|
25
|
+
// Fetch user profiles from database. Returns null if not found.
|
|
26
|
+
function getUser(id: string) { ... }
|
|
27
|
+
```
|
|
28
|
+
* *AI 腔 (ZH)*:
|
|
29
|
+
```csharp
|
|
30
|
+
/// <summary>
|
|
31
|
+
/// 這個類別的主要目的是用來處理支付流程,它整合了多個第三方 API。
|
|
32
|
+
/// 值得注意的是,在使用此類別之前必須先進行初始化。
|
|
33
|
+
/// </summary>
|
|
34
|
+
class PaymentProcessor { ... }
|
|
35
|
+
```
|
|
36
|
+
* *重構 (ZH)*:
|
|
37
|
+
```csharp
|
|
38
|
+
/// <summary>
|
|
39
|
+
/// 整合第三方 API 處理支付流程。使用前須完成初始化。
|
|
40
|
+
/// </summary>
|
|
41
|
+
class PaymentProcessor { ... }
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 2. Git Commit 訊息 (Git Commit Messages)
|
|
47
|
+
Git Commit 應是命令式、簡短且直接的。AI 喜歡使用完成時態與贅詞。
|
|
48
|
+
|
|
49
|
+
### 🚨 AI 腔特徵:
|
|
50
|
+
* **Avoid**: "In this commit, we successfully implemented..." / "Add a new feature that permits the user to..." / "Fix a bug where the database will crash when..."
|
|
51
|
+
* **Avoid (ZH)**: 「在此 commit 中,我們成功實現了...」 / 「修復了一個當用戶輸入為空時資料庫會崩潰的 Bug。」
|
|
52
|
+
|
|
53
|
+
### 💡 消除方法:
|
|
54
|
+
**使用現在式、命令式動詞**。絕不說 "successfully"、"in this commit"。
|
|
55
|
+
|
|
56
|
+
* *AI 腔 (EN)*: `feat: successfully added authentication middleware to secure endpoints`
|
|
57
|
+
* *重構 (EN)*: `feat: add auth middleware`
|
|
58
|
+
* *AI 腔 (ZH)*: `fix: 在此提交中,修復了當資料庫連線失敗時會引發記憶體洩漏的嚴重問題`
|
|
59
|
+
* *重構 (ZH)*: `fix: 修正資料庫連線失敗時的記憶體洩漏`
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 3. Pull Request 說明書 (PR Descriptions)
|
|
64
|
+
PR 說明書應該像一份高效的變更清單,而不是一份行銷簡報。
|
|
65
|
+
|
|
66
|
+
### 🚨 AI 腔特徵:
|
|
67
|
+
AI 產生的 PR 說明通常像這樣:
|
|
68
|
+
> "This PR introduces a series of vital enhancements designed to elevate our developer experience and foster better synergy between our modules. We have carefully modified the configuration..."
|
|
69
|
+
|
|
70
|
+
### 💡 消除方法:
|
|
71
|
+
**直接使用項目符號 (Bullet points) 列出具體變更**。去掉所有宣傳性廢話。
|
|
72
|
+
|
|
73
|
+
* *AI 腔 (ZH)*:
|
|
74
|
+
> 「這是一個非常重要的 Pull Request,我們對身份驗證模組進行了重塑。值得注意的是,我們將舊有的 Token 驗證機制替換為更安全的 JWT。這無疑能為系統安全提供極佳的護城河,並解決過去用戶偶爾會遇到的登入痛點。」
|
|
75
|
+
* *重構 (ZH)*:
|
|
76
|
+
> - 替換舊有 Token 機制為 JWT,提升驗證安全性。
|
|
77
|
+
> - 修正特定邊界條件下用戶被強制登出的 Bug。
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Before/After Examples (中英文重寫對照範例)
|
|
2
|
+
|
|
3
|
+
以下是不同情境下,AI 腔調(Before)與極簡、乾淨、生動文字(After)的重寫對照範例,並分析其修改重點。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 範例 1:技術部落格或文章片段 (Technical Blog Post)
|
|
8
|
+
|
|
9
|
+
### 🚨 Before (AI 腔):
|
|
10
|
+
> "Here's the thing: building scalable systems is hard. Not because the technology itself is inherently complex, but because human coordination is incredibly messy. In this landscape, we often lean into sophisticated microservices architectures, but the truth is, they sometimes elevate complexity rather than foster synergy. Let that sink in."
|
|
11
|
+
|
|
12
|
+
### 💡 After (直接、極簡):
|
|
13
|
+
> "Building scalable systems is hard. Technology is manageable; human coordination isn't. While microservices promise scalability, they often introduce more complexity than they resolve."
|
|
14
|
+
|
|
15
|
+
* **修改重點**:
|
|
16
|
+
* 刪除廢話起手式 ("Here's the thing:", "but the truth is")。
|
|
17
|
+
* 重構二元對立結構 ("Not because... but because...") 為簡短的平行句對比。
|
|
18
|
+
* 移除無謂副詞 ("inherently", "incredibly", "sometimes")。
|
|
19
|
+
* 替換空洞的 AI 高頻詞彙 ("landscape", "lean into", "elevate", "foster synergy", "Let that sink in.")。
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 範例 2:功能與產品說明文件 (Product Description)
|
|
24
|
+
|
|
25
|
+
### 🚨 Before (AI 腔):
|
|
26
|
+
> 「值得注意的是,我們的全新自動化部署工具無疑是一項重大的遊戲規則改變者。它不僅為開發團隊賦能,更解決了持續整合中的關鍵痛點。這項改變是不容忽視的,因為它能將原本耗時的流程轉化為輕量級的無縫體驗。簡單來說,它重塑了我們的開發維度。」
|
|
27
|
+
|
|
28
|
+
### 💡 After (事實陳述、乾淨俐落):
|
|
29
|
+
> 「我們的全新部署工具能自動化持續整合流程,將平均部署時間縮短 80%,讓團隊專注於代碼開發,免於手動配置的繁瑣步驟。」
|
|
30
|
+
|
|
31
|
+
* **修改重點**:
|
|
32
|
+
* 刪除清喉嚨起手式 (「值得注意的是,...」、「簡單來說,...」)。
|
|
33
|
+
* 移除空洞的行銷與 AI 詞彙 (「遊戲規則改變者/Game-changer」、「賦能」、「痛點」、「重塑」、「維度」)。
|
|
34
|
+
* 刪除弱化詞與誇大修飾語 (「無疑是」、「是不容忽視的」)。
|
|
35
|
+
* **以「具體事實與數據」代替「空泛讚美」**。將「輕量級的無縫體驗」改寫為實質成效「將平均部署時間縮短 80%」。
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 範例 3:業務聯絡與電子郵件 (Business Email)
|
|
40
|
+
|
|
41
|
+
### 🚨 Before (AI 腔):
|
|
42
|
+
> "I hope this email finds you well. I am writing to you today to see if we can circle back on our previous discussion regarding the system integration. As we navigate these challenges, I believe we are on the same page. Let's take a step back and unpack the key findings from our analysis, so we can double down on our commitment to moving forward."
|
|
43
|
+
|
|
44
|
+
### 💡 After (效率溝通、直奔主題):
|
|
45
|
+
> "I would like to follow up on our last discussion about system integration. Let's review our analysis findings next Tuesday to agree on the implementation steps."
|
|
46
|
+
|
|
47
|
+
* **修改重點**:
|
|
48
|
+
* 刪除陳腔濫調的問候語 ("I hope this email finds you well") 與宣告動作句 ("I am writing to you today to see if...")。
|
|
49
|
+
* 移除大量商業廢字與隱喻 ("circle back", "navigate these challenges", "on the same page", "take a step back", "unpack", "double down", "moving forward")。
|
|
50
|
+
* **化被動為主動**,將空泛的「加倍承諾往前行」落實為具體的「下週二確認執行步驟」。
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# English Phrases to Remove (AI Tells)
|
|
2
|
+
|
|
3
|
+
## 1. Throat-Clearing Openers
|
|
4
|
+
These phrases announce that you are about to make a point, rather than simply making it. They add zero value. **Delete them and state the content directly.**
|
|
5
|
+
|
|
6
|
+
* "Here's the thing:"
|
|
7
|
+
* "Here's what [X]" / "Here's why [X]"
|
|
8
|
+
* "The uncomfortable truth is"
|
|
9
|
+
* "It turns out that"
|
|
10
|
+
* "The real [X] is"
|
|
11
|
+
* "Let me be clear"
|
|
12
|
+
* "The truth is," / "To be honest,"
|
|
13
|
+
* "I'll say it again:"
|
|
14
|
+
* "Can we talk about"
|
|
15
|
+
* "Here's what I find interesting"
|
|
16
|
+
* "Here's the problem though"
|
|
17
|
+
* "It is important to note that"
|
|
18
|
+
* "It goes without saying that"
|
|
19
|
+
* "Needless to say,"
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 2. Emphasis Crutches
|
|
24
|
+
These are cheap rhetorical tricks used to manufacture profoundness or demand attention. **Delete them entirely; if your point is strong, the reader will feel it.**
|
|
25
|
+
|
|
26
|
+
* "Full stop." / "Period."
|
|
27
|
+
* "Let that sink in."
|
|
28
|
+
* "This matters because"
|
|
29
|
+
* "Make no mistake"
|
|
30
|
+
* "Here's why that matters"
|
|
31
|
+
* "Not all heroes wear capes."
|
|
32
|
+
* "At the end of the day,"
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 3. Classic AI High-Frequency Words
|
|
37
|
+
AI has an extremely predictable vocabulary of "sophisticated" words. They make prose sound like a high school essay or marketing brochure. **Avoid them.**
|
|
38
|
+
|
|
39
|
+
| Avoid | Meaning / Problem | Better Alternative |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| **Delve** | AI's absolute favorite word for "explore" | Explore, examine, study, look into, write |
|
|
42
|
+
| **Tapestry** | Used to describe any complex system ("tapestry of life") | System, network, pattern, structure, mix |
|
|
43
|
+
| **Testament** | "A testament to..." | Proof, sign, evidence, shows |
|
|
44
|
+
| **Beacon** | "A beacon of..." | Example, guide, leader |
|
|
45
|
+
| **Catalyst** | "A catalyst for..." | Cause, trigger, spark |
|
|
46
|
+
| **Revolutionize** | Over-hyped marketing puffery | Improve, change, update |
|
|
47
|
+
| **Synergy** | Empty business jargon | Cooperation, teamwork, alignment |
|
|
48
|
+
| **Pivotal** | Overused emphasis | Key, crucial, important, major |
|
|
49
|
+
| **Elevate** | "Elevate your writing..." | Improve, raise, sharpen |
|
|
50
|
+
| **Foster** | "Foster a community..." | Build, grow, encourage |
|
|
51
|
+
| **Demystify** | "Demystify the process..." | Explain, simplify |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 4. Business & Tech Jargon
|
|
56
|
+
Empty corporate words that mask a lack of specific meaning. **Replace with plain, active language.**
|
|
57
|
+
|
|
58
|
+
| Avoid | Better Alternative |
|
|
59
|
+
|---|---|
|
|
60
|
+
| Navigate (challenges) | Handle, address, solve, face |
|
|
61
|
+
| Unpack (analysis) | Explain, examine, discuss |
|
|
62
|
+
| Lean into | Accept, embrace, adopt |
|
|
63
|
+
| Landscape (context) | Situation, field, industry |
|
|
64
|
+
| Game-changer | Significant, major, important |
|
|
65
|
+
| Double down | Commit, increase, focus on |
|
|
66
|
+
| Deep dive | Analysis, examination, review |
|
|
67
|
+
| Take a step back | Reconsider, pause |
|
|
68
|
+
| Moving forward | Next, from now on, in the future |
|
|
69
|
+
| Circle back | Return to, revisit, talk later |
|
|
70
|
+
| Leverage (as verb) | Use, apply |
|
|
71
|
+
| Paradigm shift | Big change, transformation |
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 5. Adverbs & Hedges
|
|
76
|
+
Adverbs (especially those ending in `-ly`) weaken active verbs. Hedges show lack of confidence. **Kill them all.**
|
|
77
|
+
|
|
78
|
+
* **Softeners/Hedges**: "really", "just", "literally", "basically", "essentially", "typically", "generally", "virtually".
|
|
79
|
+
* **Manufactured Intensifiers**: "extremely", "incredibly", "obviously", "absolutely", "completely", "deeply", "highly".
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# 中文 AI Tells 贅詞庫 (Chinese Phrases to Remove)
|
|
2
|
+
|
|
3
|
+
這些詞彙與片語是中文 AI(例如 Gemini, ChatGPT, Claude)在生成繁體中文時極高機率會使用的「AI 腔調」。它們會讓文章顯得累贅、空洞、像罐頭行銷文或八股論文。**請徹底清除它們,直接陳述事實。**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. 廢話起手式與過渡詞 (Throat-Clearing Openers)
|
|
8
|
+
AI 在進入主題前,非常喜歡使用這些空洞的過渡句來「清喉嚨」。**直接剪掉,從真正的內容開始寫起。**
|
|
9
|
+
|
|
10
|
+
* **「值得注意的是,...」** (AI 最愛) -> *直接說出值得注意的事實即可。*
|
|
11
|
+
* **「不得不說,...」**
|
|
12
|
+
* **「老實說,...」 /「坦白說,...」**
|
|
13
|
+
* **「不可否認的是,...」**
|
|
14
|
+
* **「毫無疑問地,...」**
|
|
15
|
+
* **「簡單來說,...」 /「換句話說,...」** -> *如果能簡單說,一開始就簡單說,不需要在前面加上這句。*
|
|
16
|
+
* **「總結來說,...」 /「綜上所述,...」** -> *直接下結論,刪除宣告語。*
|
|
17
|
+
* **「讓我們來看看...」 /「我們需要深入探討...」**
|
|
18
|
+
* **「正如我們所知,...」 /「眾所周知,...」**
|
|
19
|
+
* **「好消息是,...」 /「壞消息是,...」** (常見於美式 AI 翻譯腔)
|
|
20
|
+
* **「正如前面所提到的,...」**
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. 刻意渲染與誇大字眼 (Emphasis Crutches)
|
|
25
|
+
AI 喜歡用誇張的語氣來強調某個普通的事情,這會降低文字的專業度與可信度。**刪除它們,讓事實自己說話。**
|
|
26
|
+
|
|
27
|
+
* **「不容忽視」 /「不容小覷」** -> *例如:「這項改變是不容忽視的。」改寫為:「這項改變會影響 [具體人事物]。」*
|
|
28
|
+
* **「扮演著舉足輕重的角色」 /「至關重要」** -> *過度誇大。改用「是關鍵」、「有助於」或直接說明其影響。*
|
|
29
|
+
* **「無疑是...」** -> *例如:「這無疑是最好的解決方案。」改寫為:「這是最好的解決方案。」*
|
|
30
|
+
* **「...的縮影」 /「...的完美體現」**
|
|
31
|
+
* **「令人驚嘆的」 /「令人興奮的」** -> *少用情緒煽動詞。*
|
|
32
|
+
* **「不言而喻」**
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 3. 經典 AI 高頻詞彙對照表 (Classic Chinese AI Slop)
|
|
37
|
+
這些詞彙被 AI 嚴重濫用。它們聽起來很「高級」,實則模糊且空洞。**請替換為更具體、更自然的日常中文。**
|
|
38
|
+
|
|
39
|
+
| 避免使用 (Avoid) | AI 濫用情境 | 推薦替換為 (Use instead) |
|
|
40
|
+
| :--- | :--- | :--- |
|
|
41
|
+
| **維度** | 「從這個維度來看...」 | 角度、方面、部分、層面 |
|
|
42
|
+
| **畫卷** | 「展開一幅...的畫卷」 | 展現、呈現、面貌、前景 |
|
|
43
|
+
| **雙刃劍** | 「這是一把雙刃劍」 | 有利有弊、有風險、存在副作用 |
|
|
44
|
+
| **落地** | 「讓這個項目落地」 | 實施、執行、上線、實踐、落實 |
|
|
45
|
+
| **賦能** | 「為企業賦能」 | 提供支持、協助、使能夠、強化 |
|
|
46
|
+
| **生態系 / 生態圈** | 「構建一個生態系」 | 系統、環境、社群、平台、鏈條 |
|
|
47
|
+
| **護城河** | 「建立技術護城河」 | 競爭優勢、防線、技術壁壘 |
|
|
48
|
+
| **痛點** | 「為了解決用戶的痛點」 | 解決問題、困難、需求、不便之處 |
|
|
49
|
+
| **閉環** | 「形成一個業務閉環」 | 流程完整、整合、循環 |
|
|
50
|
+
| **抓手** | 「找到一個轉型的抓手」 | 切入點、著力點、突破口、方法 |
|
|
51
|
+
| **背後** | 「這背後的邏輯是...」 | 原因在於、因為、原理是 |
|
|
52
|
+
| **智能** | 「打造智能化的流程」 | 自動化、智慧型、電腦化 |
|
|
53
|
+
| **重塑** | 「重塑我們的業務」 | 改變、重建、優化、改造 |
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 4. 無謂的副詞與弱化詞 (Adverbs & Hedges)
|
|
58
|
+
中文副詞會讓語氣變得不確定、不堅定,或是顯得累贅。**精簡語句,去除贅字。**
|
|
59
|
+
|
|
60
|
+
* **弱化與不確定詞**:「基本上」、「原則上」、「實質上」、「可以說是」、「似乎」。
|
|
61
|
+
* **過度修飾副詞**:「非常」、「極其」、「相當」、「簡直」、「深刻地」。
|
|
62
|
+
* *反例*:「我們需要深刻地理解這個問題。」
|
|
63
|
+
* *正例*:「我們必須理解這個問題。」
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Formulaic AI Structures to Avoid (避開公式化句式指南)
|
|
2
|
+
|
|
3
|
+
AI 的寫作不只單字重複,其「句式結構」與「邏輯推進方式」也非常公式化。以下是中英文中最常見的 AI 特徵句式,以及如何將其重構為更自然、直白的寫法。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. 二元對立與刻意轉折 (Binary Contrasts / Telegraphed Reversals)
|
|
8
|
+
AI 為了製造戲劇效果,極其喜歡先否定一個顯而易見的點,然後翻轉出主旨。這顯得刻意且不真誠。
|
|
9
|
+
|
|
10
|
+
### 🚨 特徵句型:
|
|
11
|
+
* **EN**: "Not because X, but because Y." / "[X] isn't the problem. [Y] is." / "The answer isn't X. It's Y."
|
|
12
|
+
* **ZH**: 「不是因為 X,而是因為 Y。」 / 「問題不在於 X,而在於 Y。」 / 「答案不是 X,是 Y。」
|
|
13
|
+
|
|
14
|
+
### 💡 解決方法:
|
|
15
|
+
**直接陳述 Y。** 讀者不需要那個「否定 X」的助跑過程。
|
|
16
|
+
|
|
17
|
+
* *AI 腔 (EN)*: "Designing software is hard. Not because code is complex. Because requirements change. Let that sink in."
|
|
18
|
+
* *重構 (EN)*: "Designing software is hard because requirements change."
|
|
19
|
+
* *AI 腔 (ZH)*: 「寫測試很麻煩。不是因為工具不好用,而是因為我們沒有好的測試結構。」
|
|
20
|
+
* *重構 (ZH)*: 「混亂的測試結構讓寫測試變得很麻煩。」
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. 否定式表列 (Negative Listing / Rhetorical Striptease)
|
|
25
|
+
在揭曉事物本質前,先列出一長串「它不是什麼」,像是在剝洋蔥。這會浪費讀者的時間。
|
|
26
|
+
|
|
27
|
+
### 🚨 特徵句型:
|
|
28
|
+
* **EN**: "It wasn't X. It wasn't Y. It was Z." / "Not a blueprint, not a rulebook, but a compass."
|
|
29
|
+
* **ZH**: 「這不是指引,也不是指南,而是一盞明燈。」 / 「這無關技術,無關架構,關乎於人。」
|
|
30
|
+
|
|
31
|
+
### 💡 解決方法:
|
|
32
|
+
**直接寫出 Z。** 省去多餘的鋪墊。
|
|
33
|
+
|
|
34
|
+
* *AI 腔 (EN)*: "This project is not a replacement for Git, nor is it a new server. It is a local CLI tool."
|
|
35
|
+
* *重構 (EN)*: "This project is a local CLI tool."
|
|
36
|
+
* *AI 腔 (ZH)*: 「這項改進無關乎伺服器硬體,也無關乎頻寬,而是演算法的優化。」
|
|
37
|
+
* *重構 (ZH)*: 「這項性能提升來自演算法優化。」
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 3. 刻意破碎的短句 (Dramatic Fragmentation / Performative Simplicity)
|
|
42
|
+
AI 經常使用「名詞。這就夠了。」或「X。然後是 Y。最後是 Z。」等破碎句型來裝作高深、有權威感,但實際上讀起來非常做作。
|
|
43
|
+
|
|
44
|
+
### 🚨 特徵句型:
|
|
45
|
+
* **EN**: "[Noun]. That's it. That's the [thing]." / "X. And Y. And Z."
|
|
46
|
+
* **ZH**: 「[名詞]。就這樣。這就是 [事物]。」 / 「極簡。這就是我們追求的。」
|
|
47
|
+
|
|
48
|
+
### 💡 解決方法:
|
|
49
|
+
**使用連貫的完整句子。** 信任內容本身的力量,不需要靠格式演戲。
|
|
50
|
+
|
|
51
|
+
* *AI 腔 (EN)*: "Continuous integration. That's it. That's the secret."
|
|
52
|
+
* *重構 (EN)*: "Continuous integration is the secret to stable deploys."
|
|
53
|
+
* *AI 腔 (ZH)*: 「高內聚,低耦合。這就是優秀代碼的精髓。」
|
|
54
|
+
* *重構 (ZH)*: 「優秀代碼通常具有高內聚、低耦合的特性。」
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 4. 虛假主動權 / 擬人化 (False Agency / Anthropomorphism)
|
|
59
|
+
AI 喜歡將「無生命的事物」或「抽象概念」寫得像是有自主意識的活人。這在技術寫作中顯得滑稽且不精確。
|
|
60
|
+
|
|
61
|
+
### 🚨 特徵句型:
|
|
62
|
+
* **EN**: "The code wants to do X." / "The compiler is trying to tell us..." / "The library brings peace."
|
|
63
|
+
* **ZH**: 「這行代碼渴望告訴我們...」 / 「編譯器正在向我們抗議...」 / 「這個錯誤默默地守護著系統。」
|
|
64
|
+
|
|
65
|
+
### 💡 解決方法:
|
|
66
|
+
**改用客觀、事實性的描述。**
|
|
67
|
+
|
|
68
|
+
* *AI 腔 (EN)*: "The garbage collector is fighting to keep the memory clean."
|
|
69
|
+
* *重構 (EN)*: "The garbage collector frees unused memory."
|
|
70
|
+
* *AI 腔 (ZH)*: 「這個函式庫試圖去解決多線程衝突的問題。」
|
|
71
|
+
* *重構 (ZH)*: 「這個函式庫解決了多線程衝突。」
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 5. 設問句與自我解答 (Rhetorical Setups & Socratic Posturing)
|
|
76
|
+
AI 很喜歡用「如果...會怎樣?」或「想像一下:」等問題來作為段落開頭,然後自己回答。這在非教學性文章中顯得居高臨下。
|
|
77
|
+
|
|
78
|
+
### 🚨 特徵句型:
|
|
79
|
+
* **EN**: "What if we could [X]?" / "Think about it:" / "Let's be real:"
|
|
80
|
+
* **ZH**: 「如果我們能自動化這一切,會怎麼樣?」 / 「試想一下:」 / 「老實說:」
|
|
81
|
+
|
|
82
|
+
### 💡 解決方法:
|
|
83
|
+
**直接陳述解決方案或事實。**
|
|
84
|
+
|
|
85
|
+
* *AI 腔 (ZH)*: 「如果我們能每天節省一小時的部署時間會怎樣?這就是 Docker 的用處。」
|
|
86
|
+
* *重構 (ZH)*: 「Docker 能將每日部署時間縮短一小時。」
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Neo Stop Slop - CLI Analyzer
|
|
5
|
+
*
|
|
6
|
+
* Analyze text or markdown files for AI writing patterns (Slop) and calculate Slop Density.
|
|
7
|
+
* Strictly non-interactive, accepts arguments, separates stdout/stderr.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
|
|
13
|
+
// Define high-frequency AI Tells & Slop Patterns
|
|
14
|
+
const ENGLISH_PATTERNS = [
|
|
15
|
+
// Throat-clearing
|
|
16
|
+
{ phrase: "here's the thing", category: "Throat-Clearing", regex: /\bhere's the thing\b/gi },
|
|
17
|
+
{ phrase: "the uncomfortable truth is", category: "Throat-Clearing", regex: /\bthe uncomfortable truth is\b/gi },
|
|
18
|
+
{ phrase: "it turns out that", category: "Throat-Clearing", regex: /\bit turns out that\b/gi },
|
|
19
|
+
{ phrase: "let me be clear", category: "Throat-Clearing", regex: /\blet me be clear\b/gi },
|
|
20
|
+
{ phrase: "the truth is,", category: "Throat-Clearing", regex: /\bthe truth is\b/gi },
|
|
21
|
+
{ phrase: "it is important to note that", category: "Throat-Clearing", regex: /\bit is important to note that\b/gi },
|
|
22
|
+
{ phrase: "it goes without saying that", category: "Throat-Clearing", regex: /\bit goes without saying that\b/gi },
|
|
23
|
+
// Emphasis crutches
|
|
24
|
+
{ phrase: "full stop.", category: "Emphasis Crutch", regex: /\bfull stop\b/gi },
|
|
25
|
+
{ phrase: "let that sink in", category: "Emphasis Crutch", regex: /\blet that sink in\b/gi },
|
|
26
|
+
{ phrase: "make no mistake", category: "Emphasis Crutch", regex: /\bmake no mistake\b/gi },
|
|
27
|
+
// High-frequency AI Slop Words
|
|
28
|
+
{ phrase: "delve", category: "AI Slop Word", regex: /\bdelve\b/gi },
|
|
29
|
+
{ phrase: "tapestry", category: "AI Slop Word", regex: /\btapestry\b/gi },
|
|
30
|
+
{ phrase: "testament", category: "AI Slop Word", regex: /\btestament\b/gi },
|
|
31
|
+
{ phrase: "beacon", category: "AI Slop Word", regex: /\bbeacon\b/gi },
|
|
32
|
+
{ phrase: "catalyst", category: "AI Slop Word", regex: /\bcatalyst\b/gi },
|
|
33
|
+
{ phrase: "revolutionize", category: "AI Slop Word", regex: /\brevolutionize\b/gi },
|
|
34
|
+
{ phrase: "synergy", category: "AI Slop Word", regex: /\bsynergy\b/gi },
|
|
35
|
+
{ phrase: "foster", category: "AI Slop Word", regex: /\bfoster\b/gi },
|
|
36
|
+
{ phrase: "demystify", category: "AI Slop Word", regex: /\bdemystify\b/gi },
|
|
37
|
+
// Business jargon
|
|
38
|
+
{ phrase: "navigate challenges", category: "Jargon", regex: /\bnavigate (?:the )?challenges\b/gi },
|
|
39
|
+
{ phrase: "unpack", category: "Jargon", regex: /\bunpack\b/gi },
|
|
40
|
+
{ phrase: "lean into", category: "Jargon", regex: /\blean into\b/gi },
|
|
41
|
+
{ phrase: "double down", category: "Jargon", regex: /\bdouble down\b/gi },
|
|
42
|
+
{ phrase: "deep dive", category: "Jargon", regex: /\bdeep dive\b/gi },
|
|
43
|
+
{ phrase: "paradigm shift", category: "Jargon", regex: /\bparadigm shift\b/gi }
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const CHINESE_PATTERNS = [
|
|
47
|
+
// 廢話起手式
|
|
48
|
+
{ phrase: "值得注意的是", category: "起手式", regex: /值得注意的是/g },
|
|
49
|
+
{ phrase: "不得不說", category: "起手式", regex: /不得不說/g },
|
|
50
|
+
{ phrase: "不可否認的是", category: "起手式", regex: /不可否認的是/g },
|
|
51
|
+
{ phrase: "毫無疑問地", category: "起手式", regex: /毫無疑問地?/g },
|
|
52
|
+
{ phrase: "簡單來說", category: "起手式", regex: /簡單來說/g },
|
|
53
|
+
{ phrase: "總結來說", category: "起手式", regex: /總結來說/g },
|
|
54
|
+
{ phrase: "綜上所述", category: "起手式", regex: /綜上所述/g },
|
|
55
|
+
{ phrase: "讓我們來看看", category: "起手式", regex: /讓我們來看看/g },
|
|
56
|
+
{ phrase: "我們需要深入探討", category: "起手式", regex: /我們需要深入探討/g },
|
|
57
|
+
// 誇大字眼
|
|
58
|
+
{ phrase: "不容忽視", category: "誇大渲染", regex: /不容忽視/g },
|
|
59
|
+
{ phrase: "不容小覷", category: "誇大渲染", regex: /不容小覷/g },
|
|
60
|
+
{ phrase: "扮演著舉足輕重的角色", category: "誇大渲染", regex: /扮演著舉足輕重的角色/g },
|
|
61
|
+
{ phrase: "至關重要", category: "誇大渲染", regex: /至關重要/g },
|
|
62
|
+
{ phrase: "無疑是", category: "誇大渲染", regex: /無疑是/g },
|
|
63
|
+
// AI 高頻詞彙
|
|
64
|
+
{ phrase: "維度", category: "AI 濫用詞", regex: /維度/g },
|
|
65
|
+
{ phrase: "畫卷", category: "AI 濫用詞", regex: /畫卷/g },
|
|
66
|
+
{ phrase: "雙刃劍", category: "AI 濫用詞", regex: /雙刃劍/g },
|
|
67
|
+
{ phrase: "落地", category: "AI 濫用詞", regex: /落地/g },
|
|
68
|
+
{ phrase: "賦能", category: "AI 濫用詞", regex: /賦能/g },
|
|
69
|
+
{ phrase: "生態系/生態圈", category: "AI 濫用詞", regex: /生態[系圈]/g },
|
|
70
|
+
{ phrase: "護城河", category: "AI 濫用詞", regex: /護城河/g },
|
|
71
|
+
{ phrase: "痛點", category: "AI 濫用詞", regex: /痛點/g },
|
|
72
|
+
{ phrase: "閉環", category: "AI 濫用詞", regex: /閉環/g },
|
|
73
|
+
{ phrase: "抓手", category: "AI 濫用詞", regex: /抓手/g },
|
|
74
|
+
{ phrase: "背後的邏輯", category: "AI 濫用詞", regex: /背後的邏輯/g },
|
|
75
|
+
{ phrase: "重塑", category: "AI 濫用詞", regex: /重塑/g },
|
|
76
|
+
// 贅詞副詞
|
|
77
|
+
{ phrase: "基本上", category: "贅字副詞", regex: /基本上/g },
|
|
78
|
+
{ phrase: "深刻地", category: "贅字副詞", regex: /深刻地/g }
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
function showHelp() {
|
|
82
|
+
console.warn(`
|
|
83
|
+
Neo Stop Slop Analyzer - 檢測並計算文本中的 AI Tells / Slop 密度。
|
|
84
|
+
|
|
85
|
+
用法:
|
|
86
|
+
node analyze-slop.js [選項]
|
|
87
|
+
|
|
88
|
+
選項:
|
|
89
|
+
-f, --file <路徑> 指定要分析的文字或 Markdown 檔案路徑。
|
|
90
|
+
-i, --input <文字> 直接傳入要分析的文字字串。
|
|
91
|
+
-o, --output <路徑> 將結果寫入指定檔案 (預設為輸出至 stdout)。
|
|
92
|
+
--format <格式> 輸出格式: "text" (預設,易讀報告) 或 "json" (程式解析用)。
|
|
93
|
+
-h, --help 顯示此說明訊息。
|
|
94
|
+
|
|
95
|
+
範例:
|
|
96
|
+
node analyze-slop.js --file src/README.md --format json
|
|
97
|
+
node analyze-slop.js --input "Here's the thing: Not because it's hard. But because it's necessary. Full stop."
|
|
98
|
+
`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function parseArgs() {
|
|
102
|
+
const args = process.argv.slice(2);
|
|
103
|
+
const options = {
|
|
104
|
+
file: null,
|
|
105
|
+
input: null,
|
|
106
|
+
output: null,
|
|
107
|
+
format: 'text' // text or json
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
for (let i = 0; i < args.length; i++) {
|
|
111
|
+
const arg = args[i];
|
|
112
|
+
if (arg === '-h' || arg === '--help') {
|
|
113
|
+
showHelp();
|
|
114
|
+
process.exit(0);
|
|
115
|
+
} else if (arg === '-f' || arg === '--file') {
|
|
116
|
+
options.file = args[++i];
|
|
117
|
+
} else if (arg === '-i' || arg === '--input') {
|
|
118
|
+
options.input = args[++i];
|
|
119
|
+
} else if (arg === '-o' || arg === '--output') {
|
|
120
|
+
options.output = args[++i];
|
|
121
|
+
} else if (arg === '--format') {
|
|
122
|
+
options.format = args[++i];
|
|
123
|
+
if (options.format !== 'text' && options.format !== 'json') {
|
|
124
|
+
console.error(`[ERROR] 不支援的輸出格式: ${options.format}. 請使用 "text" 或 "json"。`);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
console.error(`[ERROR] 未知參數: ${arg}`);
|
|
129
|
+
showHelp();
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return options;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function calculateWordCount(text) {
|
|
138
|
+
// Simple word count: English words + Chinese characters
|
|
139
|
+
const enWords = text.match(/[a-zA-Z]+/g) || [];
|
|
140
|
+
const zhChars = text.match(/[\u4e00-\u9fa5]/g) || [];
|
|
141
|
+
return enWords.length + zhChars.length;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function analyzeText(text) {
|
|
145
|
+
const lines = text.split('\n');
|
|
146
|
+
const violations = [];
|
|
147
|
+
let matchCount = 0;
|
|
148
|
+
|
|
149
|
+
// Process English and Chinese patterns
|
|
150
|
+
const allPatterns = [...ENGLISH_PATTERNS, ...CHINESE_PATTERNS];
|
|
151
|
+
|
|
152
|
+
lines.forEach((lineText, lineIndex) => {
|
|
153
|
+
const lineNumber = lineIndex + 1;
|
|
154
|
+
|
|
155
|
+
allPatterns.forEach(pattern => {
|
|
156
|
+
// Reset regex index due to 'g' flag
|
|
157
|
+
pattern.regex.lastIndex = 0;
|
|
158
|
+
let match;
|
|
159
|
+
while ((match = pattern.regex.exec(lineText)) !== null) {
|
|
160
|
+
matchCount++;
|
|
161
|
+
violations.push({
|
|
162
|
+
line: lineNumber,
|
|
163
|
+
matchedText: match[0],
|
|
164
|
+
phrase: pattern.phrase,
|
|
165
|
+
category: pattern.category,
|
|
166
|
+
lineContent: lineText.trim()
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const totalWords = calculateWordCount(text);
|
|
173
|
+
// Calculate Slop Density Score (violations per 100 words)
|
|
174
|
+
const slopDensity = totalWords > 0 ? parseFloat(((matchCount / totalWords) * 100).toFixed(2)) : 0;
|
|
175
|
+
|
|
176
|
+
// Grade based on density
|
|
177
|
+
let grade = 'A+ (極其精煉,無 AI 腔)';
|
|
178
|
+
if (slopDensity > 10) {
|
|
179
|
+
grade = 'F (充斥大量 AI Tells,廢話連篇)';
|
|
180
|
+
} else if (slopDensity > 5) {
|
|
181
|
+
grade = 'D (AI 腔過重,亟需重寫)';
|
|
182
|
+
} else if (slopDensity > 2) {
|
|
183
|
+
grade = 'C (有明顯 AI Tells,建議修改)';
|
|
184
|
+
} else if (slopDensity > 0.5) {
|
|
185
|
+
grade = 'B (有些許贅詞,品質尚可)';
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
metrics: {
|
|
190
|
+
totalWords,
|
|
191
|
+
totalViolations: matchCount,
|
|
192
|
+
slopDensityScore: slopDensity,
|
|
193
|
+
grade
|
|
194
|
+
},
|
|
195
|
+
violations
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function formatTextReport(result, sourceName) {
|
|
200
|
+
let output = `==================================================\n`;
|
|
201
|
+
output += ` NEO STOP SLOP - AI TELLS 檢測報告\n`;
|
|
202
|
+
output += `==================================================\n`;
|
|
203
|
+
output += `來源名稱: ${sourceName}\n`;
|
|
204
|
+
output += `總字詞數: ${result.metrics.totalWords}\n`;
|
|
205
|
+
output += `檢出 AI 贅詞數: ${result.metrics.totalViolations}\n`;
|
|
206
|
+
output += `Slop 密度分數: ${result.metrics.slopDensityScore}% (每百字出現次數)\n`;
|
|
207
|
+
output += `評估等級: ${result.metrics.grade}\n`;
|
|
208
|
+
output += `--------------------------------------------------\n`;
|
|
209
|
+
|
|
210
|
+
if (result.violations.length === 0) {
|
|
211
|
+
output += `✨ 太棒了!您的文字極其精煉,沒有檢測到任何 AI 贅詞特徵!\n`;
|
|
212
|
+
} else {
|
|
213
|
+
output += `檢出細節 (前 30 筆違規):\n\n`;
|
|
214
|
+
const displayList = result.violations.slice(0, 30);
|
|
215
|
+
displayList.forEach(v => {
|
|
216
|
+
output += `[第 ${v.line} 行] 【${v.category}】檢出: "${v.matchedText}" (預設關鍵字: "${v.phrase}")\n`;
|
|
217
|
+
output += ` 上下文: "${v.lineContent}"\n\n`;
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
if (result.violations.length > 30) {
|
|
221
|
+
output += `... 還有其他 ${result.violations.length - 30} 處違規未列出。\n`;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
output += `==================================================\n`;
|
|
225
|
+
return output;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function main() {
|
|
229
|
+
const options = parseArgs();
|
|
230
|
+
|
|
231
|
+
let sourceContent = '';
|
|
232
|
+
let sourceName = '';
|
|
233
|
+
|
|
234
|
+
if (options.file) {
|
|
235
|
+
const absolutePath = path.resolve(options.file);
|
|
236
|
+
if (!fs.existsSync(absolutePath)) {
|
|
237
|
+
console.error(`[ERROR] 找不到指定的檔案: ${options.file}`);
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
sourceContent = fs.readFileSync(absolutePath, 'utf8');
|
|
241
|
+
sourceName = path.basename(options.file);
|
|
242
|
+
} else if (options.input !== null) {
|
|
243
|
+
sourceContent = options.input;
|
|
244
|
+
sourceName = '直接傳入字串';
|
|
245
|
+
} else {
|
|
246
|
+
console.error(`[ERROR] 請提供 --file <路徑> 或 --input <文字>。`);
|
|
247
|
+
showHelp();
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Run analysis
|
|
252
|
+
console.error(`[INFO] 正在分析 "${sourceName}" 中的 AI 腔贅詞...`);
|
|
253
|
+
const result = analyzeText(sourceContent);
|
|
254
|
+
|
|
255
|
+
// Generate output string
|
|
256
|
+
let outputResult = '';
|
|
257
|
+
if (options.format === 'json') {
|
|
258
|
+
outputResult = JSON.stringify(result, null, 2);
|
|
259
|
+
} else {
|
|
260
|
+
outputResult = formatTextReport(result, sourceName);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Handle output destination
|
|
264
|
+
if (options.output) {
|
|
265
|
+
const outputPath = path.resolve(options.output);
|
|
266
|
+
console.error(`[INFO] 正在將分析結果寫入: ${outputPath}`);
|
|
267
|
+
fs.writeFileSync(outputPath, outputResult, 'utf8');
|
|
268
|
+
} else {
|
|
269
|
+
// Print to stdout
|
|
270
|
+
process.stdout.write(outputResult + '\n');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
console.error(`[INFO] 分析完成。`);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
main();
|