normalize — 日本語表記正規化エンドポイント

POST /api/v1/text/normalize

全/半角統一、ひらがな/カタカナ変換、空白正規化、半角カタカナ展開、 Sudachi 表記正規化(送り違い / 異体字 / カタカナ表記揺れ)を任意組合せで適用。 Phase 1+2 は純文字列処理、Phase 3 は Lindera + SudachiDict-derived lookup。

エンドポイント

POST https://shirabe.dev/api/v1/text/normalize
X-API-Key: shrb_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  (省略可、匿名 Free 枠 10,000 回/月)
Content-Type: application/json

オプション一覧 / Options

optiondefault動作
width half / full / preserve preserve ASCII 全角(ABC)/ 半角(ABC)の統一方向
kana hiragana / katakana / preserve preserve ひらがな ↔ カタカナ変換方向
spaces single / trim / preserve preserve 連続空白 → 単一空白(single)+ 前後除去(trim)
halfwidth_kana expand / preserve preserve 半角カタカナ アイウ → 全角 アイウ、濁点・半濁点合成 ガ → ガ
sudachi apply / preserve preserve 送り違い(行なう→行う)/ 異体字(卓れる→優れる)/ カタカナ表記揺れ(コンピュータ→コンピューター)を吸収。Lindera tokenize 必要、cold start +50-200 ms

適用順は width → kana → spaces → halfwidth_kana → sudachi。Phase 1+2 後の文字列を tokenizer に渡すため精度が向上する設計。

リクエスト / Request

{
  "text": "ABC123 コンピュータと行なう作業",
  "options": {
    "width": "half",
    "sudachi": "apply"
  }
}

レスポンス / Response

{
  "text": "ABC123 コンピュータと行なう作業",
  "normalized": "ABC123 コンピューターと行う作業",
  "changes": [
    { "type": "width", "before": "ABC123 ", "after": "ABC123 " },
    { "type": "sudachi", "before": "コンピュータ", "after": "コンピューター" },
    { "type": "sudachi", "before": "行なう", "after": "行う" }
  ],
  "timing": {
    "setup_ms": 187,
    "cold_start": true,
    "tokenize_ms": 4,
    "sudachi_lookup_ms": 1,
    "map_fetch_ms": 78,
    "map_parse_ms": 35,
    "map_entries": 88622
  },
  "attribution": {
    "service": "shirabe-text-api",
    "url": "https://shirabe.dev",
    "dictionary": "SudachiDict-small",
    "dictionary_license": "Apache-2.0",
    "dictionary_source": "https://github.com/WorksApplications/SudachiDict",
    "tokenizer": "Lindera + IPAdic v3.0.7",
    "tokenizer_license": "MIT (Lindera) / BSD 3-Clause (IPAdic)"
  }
}

timingattribution の Sudachi 関連 field は options.sudachi="apply" 指定時のみ含まれる(Phase 1+2 のみ使用時は ServiceAttribution 単独)。

コード例 / Code examples

curl(Phase 1+2 のみ、軽量)

curl -X POST https://shirabe.dev/api/v1/text/normalize \
  -H "Content-Type: application/json" \
  -d '{"text": "ABC123", "options": {"width": "half"}}'
# → {"normalized": "ABC123", ...}

TypeScript(Phase 3 込み、Sudachi 正規化適用)

const res = await fetch("https://shirabe.dev/api/v1/text/normalize", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": process.env.SHIRABE_API_KEY!,
  },
  body: JSON.stringify({
    text: "コンピュータで行なう作業",
    options: { sudachi: "apply" },
  }),
});
const { normalized } = await res.json();
console.log(normalized);
// → コンピューターで行う作業

Python(全 option 同時適用)

import os, requests
r = requests.post(
    "https://shirabe.dev/api/v1/text/normalize",
    json={
        "text": "ABC アイウ  コンピュータ",
        "options": {
            "width": "half",
            "halfwidth_kana": "expand",
            "spaces": "single",
            "sudachi": "apply",
        },
    },
    headers={"X-API-Key": os.environ["SHIRABE_API_KEY"]},
    timeout=10,
)
print(r.json()["normalized"])
# → ABC アイウ コンピューター

Phase 3 Sudachi 正規化の詳細

SudachiDict-small(Apache-2.0、WorksApplications)の normalized_form 列を抽出した派生マップを R2 配信。CI build で抽出条件を厳格化:

  • surface ≠ normalized_form のエントリのみ(変更ありエントリ)
  • conjugation_form ∈ {"*", "終止形-一般"}(活用形 drift 排除、行なう→行う を保ち つき→尽きる を排除)
  • surface に日本語文字を 1 文字以上含む(装飾的変換 e.g. "10"→"⑩" を排除)

結果: 88,622 entries / 約 1.13 MB JSON。AI agent が想定する範囲の正規化のみカバー。

カバー範囲(代表例)

カテゴリ
送り仮名統一行なう → 行う / 取りあげる → 取り上げる / 申しこむ → 申し込む
カタカナ表記揺れ(長音)コンピュータ → コンピューター / サーバ → サーバー / ユーザ → ユーザー
カタカナ表記揺れ(バ⇄ヴ)デヴィルズ → デビルズ / クエート → クウェート
異体字統一卓れる → 優れる / 飾りけ → 飾り気 / 花やぐ → 華やぐ

制約 / Limitations

  • lookup 単位 = IPAdic tokenization 境界。IPAdic が複数 token に分割した結果が SudachiDict 単一 entry に該当しない場合は miss
  • 固有名詞(人名 / 地名)の表記揺れは対象外(name-split / name-reading で別途対応)
  • SudachiDict-core / -full への upgrade、JMnedict 統合は 2026-06 のモノレポ化時に検討

レート制限 / Rate limit

全エンドポイント均一(料金プラン): Free 月 10,000 回 / 1 req/s、Starter 月 50 万回 / 30 req/s、Pro 月 500 万回 / 100 req/s、 Enterprise 無制限 / 500 req/s。

AI エージェント統合

OpenAPI 3.1 仕様(本家 / GPTs 短縮版)を 1 URL で公開。 operationId: normalizeText

  • 前処理パイプライン: AI agent でユーザ入力を住所 / 検索 API に渡す前に normalize で表記揺れを吸収すると、後段 API のキャッシュヒット率が向上
  • マルチ AI 出力統合: 4 AI(ChatGPT/Claude/Gemini/Perplexity)からの output を normalize で揃えると下流の DB JOIN が安定

更新履歴 / Updates

2026-05-09: Phase 3 Sudachi 表記正規化 5/18 リリースに同梱確定

SudachiDict-small (Apache-2.0) 由来の lookup map (88,622 entries / 1.13 MB) を R2 配信、 options.sudachi="apply" で送り違い / 異体字 / カタカナ表記揺れ吸収。 upstream Lindera-wasm が user dict bytes API を提供しないため、自己完結の派生マップ経路で実現。

2026-05-08: Phase 2 halfwidth_kana 部分先行

半角カタカナ展開(options.halfwidth_kana)を Phase 2 範囲のうち Lindera 連携不要な部分として 先行実装(PR #4)。

2026-05-18: 正式リリース予定

本番 routes 活性化、Free 枠で利用開始。1+ 年変更なし約束。

4 AI 観測の独自データ / Observed Multi-AI Landscape

Shirabe では ChatGPT / Claude / Perplexity / Gemini の 4 大 AI に同じクエリを投げる 独自測定(週次 4 AI × 5 query)を継続実施しています。

  • Week 2(2026-05-04): 同一住所「東京都港区六本木」で 4 AI の出力フォーマット完全分裂を観測 → AI 経由で table 形式 / 散文 / JSON / 引用脚注 と分岐、後処理で揃えるには normalize による前処理 + 構造化 API への流し込みが direct path

詳細は llms-full.txt を参照。