mcpField
D
defluff

defluff

ローカル
github.com/ahmedak開発ツール218 週間前に更新

defluff について

defluff は、LLM の文章に含まれる冗長表現、決まり文句、曖昧表現、流行語を検出する決定論的な文章チェッカーです。執筆者やエージェント、CI 向けで、モデルや API キーなしで再現可能なスコアを返し、辞書も調整できます。

主な機能

  1. 01冗長表現や決まり文句を検出
  2. 02密度スコアと該当箇所を出力
  3. 03カスタム辞書とプロジェクト設定に対応
  4. 04分野別パックとカテゴリ指定
  5. 05CLI、Python API、CI で利用
  6. 06文章チェック用 MCP ツールを提供

活用シーン

  1. 01エージェントの回答前に下書きを確認
  2. 02CI で冗長な文書の公開を阻止
  3. 03削除候補の具体的な表現を編集者に提示
  4. 04下書き間の冗長表現の密度を比較

MCP 対応

MCP サーバーは slop_detect、slop_add、slop_ignore ツールを提供し、MCP エージェントによる文章の検査と、ユーザーまたはプロジェクト単位の辞書調整を可能にします。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"ahmedak-defluff": {
"command": "uvx",
"args": [
"defluff"
]
}
}
}
起動コマンドuvx defluff

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypidefluff0.1.2

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

defluff

AI が生成した文章の定型的な冗長表現を、決定論的に検出します。変更履歴、ドキュメント、エージェント自身の出力を指定すると、削除すべき埋め草のフレーズと、CI の終了コード、固定可能なスコアが返されます。実行するたびに同じ結果になります。モデルも API キーも不要です。

CI PyPI Python 3.10+ License: MIT Last commit

冗長な文章を検出:defluff がバズワードや決まり文句だらけの文をチェックし、冗長表現の箇所と閾値超過スコアを返します。

検出された箇所には情報が含まれていないため、削除しても何も失われません。すっきりした文章なら、同じツールに通すだけでそのままパスします。

すっきりした文章はパス:defluff が平易で具体的な文をチェックし、冗長表現スコア 0% を返します。

単発の grep より defluff をインストールする価値があるのは、リストを支えるエンジンです。独自のフレーズやプロジェクトごとのオーバーレイを追加でき、エージェントが設定なしで使える MCP サーバーも備えています。


インストール

pip install defluff

または、macOS/Linux では Homebrew を使用します。

brew install ahmedak/defluff/defluff

これで完了です。モデルのダウンロードも API キーも不要です。Python が動作する環境ならどこでも実行できます。


クイックスタート

# Lint a file — exit 1 on slop, 0 when clean
defluff lint essay.md

# Pipe text
cat draft.md | defluff lint

# Get a bare score for scripts (0.0 – 1.0)
defluff score essay.md

# Machine-readable JSON for downstream tooling
defluff lint essay.md --json

MCP サーバー

3 つのツールを公開するため、MCP 対応エージェントは、特別な設定をせずに文章を自己チェックできます。返す前の自身の下書きも対象です。

uvx を使えばインストール不要で実行できます(推奨)。初回実行時にパッケージと mcp エクストラを取得します。

{
  "mcpServers": {
    "defluff": {
      "command": "uvx",
      "args": ["--from", "defluff[mcp]", "defluff-mcp"]
    }
  }
}

または、インストールしてエントリーポイントを直接実行します。

pip install "defluff[mcp]"
defluff-mcp
{
  "mcpServers": {
    "defluff": { "command": "defluff-mcp" }
  }
}

io.github.ahmedak/defluff として MCP Registry に公開されています(server.json を参照)。

mcp-name: io.github.ahmedak/defluff

ツール引数戻り値
slop_detecttext: strslop_score、spans(テキスト、カテゴリ、重み、オフセット)、categories、lexicon_version
slop_addpattern: str, category: str, scope: "user"|"project"レキシコンのオーバーレイにフレーズを追加します
slop_ignorepattern: str, scope: "user"|"project"フレーズ(例:専門分野の用語)を検出対象から除外します

よくある使用例

  • エージェントによる自己修正 — 下書きに対して slop_detect を呼び出し、返す前に検出されたフレーズを修正します。設定不要で、1 つのセッション内で完結し、処理に別のモデルを加える必要もありません。
  • 生成コンテンツに対する CI ゲート — AI が作成した変更履歴やドキュメントに「さらに」や「堅牢」といった表現が満載の場合、ビルドを失敗させます。決定論的な動作、終了コード、固定可能なレキシコンがそろっている点は、LLM による判定ゲートでは実現できません。
  • ライティングアシスタントによるフィードバック — 「AI っぽい」という曖昧な指摘の代わりに、編集者が削除するであろうフレーズを正確に強調表示します。
  • ファインチューニングの報酬 コンポーネント — 注意点については報酬ループを参照してください。単独では不正に利用される可能性があります。

なぜ defluff なのか?

あらゆる「AI 検出ツール」は、文章が AI によって生成されたかどうかを判定しようとします。これは難しく、信頼性に欠ける問題です。defluff は別の問いを投げかけます。この文章には取り除ける冗長表現が含まれているか? これは決定的に判定でき、「結局のところ」のような表現を人間が書いたか LLM が書いたかに関係なく当てはまります。

最も近い既存ツールは proselint です。モデルを使わず、決定的に判定しますが、調整可能な密度スコアではなく、はい/いいえの警告を出力します。また、入れ替えたり、重ねたり、固定したりできるリストを中心に設計されていません。

単語リストに対して grep を使えば、単純な一致結果が得られます。defluff は、そのリストを使って別途構築する必要がある機能を提供します。

  • MCP サーバー — エージェントは設定作業なしで自己チェックできます。
  • Markdown とコードを認識 — まずコードフェンス、インラインコード、URL を除外します。
  • 単語全体で照合 — "foster" は "fostering" 内では検出されません。
  • 検出件数ではなく正規化スコア — 冗長表現の 密度 なので、ツイートにも 5,000 語の文書にも同じしきい値を使えます。
  • 重複の処理 — "at the end of the day" と重複する "end of the day" は、各単語を一度だけ数えます(最長一致を優先)。
  • 終了コード、JSON、文字オフセットの範囲 — CI、pre-commit、エディターツールに組み込めます。
  • 固定可能なレキシコンハッシュ — 実行間で判定基準が変わっていないことを証明できます。
独自の冗長表現を追加
defluff lint draft.md --lexicon team-slop.md
# team-slop.md
- circle back
- low-hanging fruit
- boil the ocean
paradigm shift

1 行につき 1 つのフレーズを指定します(# コメントと -/* マーカーは無視されます)。これらは組み込みのデフォルト設定に重ねて適用され、中立的な custom カテゴリーとして報告されます。実際のカテゴリーやフレーズごとの重みを指定するには、.json リストを使用してください(レキシコンのオーバーレイを参照)。

すぐに使えるドメインパック
defluff lint post.md --pack marketing-growth
defluff lint post.md --pack marketing-growth,ai-llm   # stack several
パック検出対象パック検出対象
corporate-linkedinオフィス用語crypto-web3暗号資産の誇大表現
startup-vcピッチ資料の言い回しpr-press-releaseプレスリリースの定型文
marketing-growth誇大な宣伝文句academic研究上の婉曲表現
ai-llmLLM 特有の表現wellness-selfhelpインフルエンサー風の言い回し
social-mediaX/Twitter のエンゲージメント狙い

defluff packs で一覧表示できます。誤検出率の高い用語(例:pivot、detox)はコメントアウトされた状態で含まれており、明示的に有効にするまで動作しません。パックの READMEを参照してください。

すぐに使えるデフォルト設定

5 つの重み付きカテゴリーにわたる、約 130 個の厳選パターンを収録しています。大文字と小文字を区別せず、単語全体で照合します。

カテゴリー検出対象例
ai-vocabLLM が不釣り合いに多用する単語delve, tapestry, nuanced, pivotal, robust, showcase
cliche情報を加えない空虚な慣用句at the end of the day, move the needle, circle back, game changer
hedge空疎な限定表現it should be noted that, needless to say, basically, essentially
corporateバズワードの多用leverage, synergy, actionable insights, cutting-edge, scalable
transitionLLM が既定で使いがちな冗長なつなぎ表現furthermore, moreover, in conclusion, first and foremost
レトリックのパターン(リスト以外)

AI 特有の兆候には、決まったフレーズではなく、文の形で現れるものもあります。たとえば、対句の it's not X, it's Y や not just a list but a runtime です。正規表現パターンのレイヤーでは、これらを rhetoric カテゴリで検出します。

モード検出対象デフォルト理由
複合 (確実)完全な形:it's not X, it's Y・not just X but Yオン2つ目の節がレトリック上の動きを裏付けるため、誤検出はほとんどありません
断片 (推測)単独の X, not Y — 例:a signal, not a verdictオフ、--pack rhetoric単純な訂正(shipped Tuesday, not Wednesday)にも反応します

各マッチは、長さにかかわらずスコアに1単位として加算されます。断片モードを有効にすると、レキシコンのハッシュが変わります。

defluff lint draft.md                  # compound antithesis caught by default
defluff lint draft.md --pack rhetoric  # also catch the punchy "X, not Y" fragment
defluff lint draft.md --category rhetoric   # gate CI on antithesis alone
同じ文を2回実行します。デフォルトでは複合的な対句を検出し、--pack rhetoric を指定すると短く印象的な断片形式も検出します。

Python API

import defluff

report = defluff.detect("It is worth noting that we should leverage synergies.")
print(report.slop_score)   # 0.0 – 1.0
print(report.spans)        # flagged phrase locations + categories

score = defluff.score(text)       # bare float
clean = defluff.is_slop(text)     # bool at default threshold

lex = defluff.load_lexicon()                # pin for reproducible runs
score = defluff.score(text, lexicon=lex)

SlopReport のフィールド:

フィールド型備考
slop_scorefloat[0, 1] に制限されます — しきい値に使用します
slop_densityfloat制限前の生の値 — 報酬ループでは、より滑らかな勾配が得られます
spanslist[Span]検出ごとに、text、カテゴリ、重み、クリーニング済みテキスト内の文字オフセットを格納します(制限事項を参照)
categoriesdict[str, float]カテゴリ別の密度
n_wordsintトークン数
low_confidencebooln_words < 20 の場合に True
lexicon_versionstr解決済みエントリーセットの SHA プレフィックス

レキシコンのオーバーレイとバージョン管理

同梱のレキシコンがベースラインです。パッケージを編集せずに、その上にレイヤーを追加できます。

# "synergy" is slop on this machine
defluff lexicon add "synergy" --category corporate --scope user

# "leverage" is fine in this repo (finance context) — commit this with the repo
defluff lexicon rm "leverage" --scope project
git add .defluff/ignore.json && git commit -m "allow 'leverage' in finance context"
  • ユーザーオーバーレイ(~/.config/defluff/)— マシン全体に適用され、コミットされません
  • プロジェクトオーバーレイ(Git ルートの .defluff/)— リポジトリ単位で適用され、チーム全体で使う場合はコミットします

書き込みはアトミックで、プロセス間ロックがかかります。オーバーレイが破損している場合は警告してスキップされ、detect() がクラッシュすることはありません。

解決済みの各レキシコン(同梱分 + オーバーレイ + パック)には短いコンテンツハッシュが付き、実行のたびに表示されます(lexicon: 2cc05ba84457)。また、SlopReport.lexicon_version から取得できます。lexicon=defluff.load_lexicon() を一度渡せば、すべての呼び出しで同じ基準に照らしてスコアを計算できます。CI のベースラインや RL 報酬のために固定でき、ハッシュは解決済みのエントリーセットが変わった場合にのみ変わるため、監査も可能です。各リリースには、日付付きのレキシコンと変更履歴(CHANGELOG.md)が含まれます。ai-vocab はリリースごとに入れ替わることが想定されていますが、cliche/hedge/corporate/transition はほぼ安定しています。


出力の読み方としきい値の設定

  1. スパン — カテゴリ付きで表示される、具体的な埋め草フレーズです。決定論的で信頼性があります。これを基に対処してください。
  2. スコア — slop_score = フラグが付いた単語 ÷ 総単語数。カテゴリごとに重み付けされます(ai-vocab はやや大きく、transition はやや小さくカウントされます)。0.20 は「このテキストの5分の1が、リストに載った埋め草」という目安です。通常は 0.0–1.0 ですが、ほぼすべてが埋め草のテキストでは、わずかに1を超えることがあります。これは品質を定量化するものではなく、CI の終了コードを制御するトリップワイヤーです。

テキストにどの程度の埋め草が許容されるかに応じて、しきい値を選んでください。

--threshold意味適した用途
0.05埋め草約5% — 厳格マーケティングコピー、ランディングページ、顧客向けテキスト
0.08 (デフォルト)埋め草約8% — トリアージ用のトリップワイヤー一般的な文章、ブログの下書き
0.12–0.20大量の水増しのみを検出robust、scalable、in order to を正当に使う技術文書

デフォルトの 0.08 は暫定値です。手動で選んだものであり、ラベル付きコーパスでの調整はまだ済んでいません(そのため [threshold provisional] タグが付いています)。CI で厳格なゲートとして使う場合は、独自のしきい値を設定し、まずドメイン固有の語彙を抑制してください(以下を参照)。


CI での使用

技術文書(API ドキュメント、ADR、RFC)では、robust、scalable、in order to のような語が正当に使われます。まず、プロジェクト固有の用語を抑制します。

defluff lexicon rm "scalable" --scope project
defluff lexicon rm "in order to" --scope project
git add .defluff/ignore.json && git commit -m "defluff: allow domain vocabulary"

5 つすべてではなく、信頼できるカテゴリだけを対象にチェックします。

- name: Check AI-generated content for slop
  # --category ai-vocab,hedge gates only on the highest-precision categories
  run: cat generated_output.md | defluff lint --category ai-vocab,hedge --threshold 0.1

終了コード 1 はステップを失敗させ、0 は成功させます。


pre-commit での使用

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: defluff
        name: defluff slop check
        entry: defluff lint
        language: system
        types: [markdown]

報酬ループでの使用(実験的)

フィラーの密度を示す決定論的で微分不可能なスカラー値は、報酬の組み合わせの小さな 構成要素 になり得ます。ただし、単独では攻略される可能性があります。固定されたフレーズリストだけを基準に最適化されたモデルは、フィラーを取り除くのではなく、言い換えることを学習します。実際の品質シグナル(人間または LLM による判定)と組み合わせてください。有効性を示す公開済みのトレーニング実行結果は、まだありません。

lex = defluff.load_lexicon()  # pin once
reward = lambda text: -defluff.detect(text, lexicon=lex).slop_density  # unclamped, better gradient

delta = defluff.compare(draft_v1, draft_v2, lexicon=lex)
# {"score_a": 0.31, "score_b": 0.18, "delta": -0.13,
#  "improved": [...], "regressed": [...]}  # set diff of flagged phrases, not a semantic diff

CLI リファレンス

defluff lint [FILE] [--json] [--threshold FLOAT] [--category CATS] [--lexicon PATH] [--pack NAMES] [--no-project-overlay]
defluff score [FILE] [--pack NAMES] [--no-project-overlay]
defluff packs          # list bundled domain packs

defluff lexicon list   [--category CATEGORY] [--scope SCOPE] [--json]
defluff lexicon add    PATTERN --category CATEGORY [--scope SCOPE] [--weight FLOAT]
defluff lexicon rm     PATTERN [--scope SCOPE]
  • --category — カンマ区切りで指定します。終了コードの判定にカウントされるのは、指定したカテゴリの範囲だけです(すべてのヒットは引き続き報告されます)。有効な値:ai-vocab、cliche、hedge、corporate、transition、custom、rhetoric。
  • --lexicon PATH — デフォルトに独自のフレーズを追加します。.txt/.md では 1 行につき 1 フレーズを指定し、custom に登録されます。.json ではカテゴリと重みを明示的に指定できます。
  • --pack NAMES — カンマ区切りで既製のドメインパックを指定します。rhetoric はパターンパック用に予約されており、オプトインで X, not Y の対句パターンを有効にできます。

defluff lint の終了コード:0 = 問題なし · 1 = 冗長な表現あり · 2 = 入力不正。


精度

defluff は学習済み分類器ではなく決定論的な照合ツールであるため、重要な指標は適合率です。フラグが付いた表現は、本当に削除可能なフィラーでしょうか。明らかな冗長表現、簡潔な文章、そして 専門用語が内容として使われているケース(例:「the robust standard errors」、「pivotal trials」)を含む、手作業でラベル付けした 50 件のサンプル(eval/validation.jsonl)で、デフォルトのしきい値を使った場合:

指標スコア見方
適合率1.00偽陽性は 0 件 — 簡潔な文章や正当な専門用語にはフラグが付かなかった
再現率0.65辞書の網羅率による制限

再現方法:python eval/score.py eval/validation.jsonl

見逃されるのは、辞書がまだ把握していない新しい流行語(例:「operationalize the ideation funnel」)です。これはリストベースの照合ツールに固有の既知の限界であり、ノイズではありません。リストにあるフィラーに対する再現率は 1.00 で、辞書の拡充に伴って向上します。ただし、意味解析レイヤーがなければ、未知の専門用語を含む開かれた語彙に対して 1.00 には到達しません。

注意点:サンプル数は少なく、作者がラベル付けしたものです。これは適合率の妥当性を確認するものであり、独立した評価者によるベンチマークではありません。


制限事項

  • 既知のリストとの照合を目的としており、テキストを 理解 するわけではありません。 新しい流行語は見逃されます。これは決定論的で、ローカルに実行でき、再現可能であること(モデル不要、API キー不要、ハッシュを固定可能)と引き換えです。新しいフィラーを意味的に検出する必要がある場合は、LLM による判定と組み合わせてください。
  • 専門用語の適切さは文脈によって異なります。 金融文書における "leverage" は、実質的な内容です。フラグが付いた範囲を確認し、defluff lexicon rm で偽陽性を抑制してください(バンドルされた辞書から削除するのではなく、無視リストに追加します)。
  • 範囲のオフセットは、クリーニング後のテキストに対するものです。 defluff は照合前にコードフェンス、インラインコード、URL、Markdown のマークアップを取り除くため、オフセットは元の文書と一致しません。マークアップ付きのソースと照合する場合は、生のオフセットではなく span.text を使ってください。
  • custom はファイル経由でのみ読み取り可能です。 --lexicon ファイルのフレーズは custom に登録されますが、defluff lexicon add --category custom は拒否されます。add が受け付けるのは、厳選された 5 つのカテゴリだけです。
  • v0 では英語のみです。
  • 短いテキスト(20 語未満)には low_confidence: true が設定されます。分母は最低でも 20 となるため、2 文の入力に含まれる 1 つのフレーズだけで、冗長度が 100% と判定されることはありません。

貢献

最も簡単な貢献は、見落とされているフィラー表現を追加することです。

  1. 適切なカテゴリを指定して src/defluff/data/lexicon-v1.json に追加します
  2. pytest — スモークテストで境界の誤りを検出します
  3. 実際に使われている例を1つか2つ添えて、PRを送ります

コードのセットアップとガイドラインについては、CONTRIBUTING.md をご覧ください。


ライセンス

MIT

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。