0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

日本の住所正規化をAIに任せてはいけない理由——abr-geocoderとAPIアプローチの比較

0
Posted at

TL;DR

  • AI SaaSで「ユーザーが入力した日本の住所を整形してDB保存したい」という要件は頻発するが、LLMに直接やらせると 存在しない地名・番地に黙って書き換える 事故が起きやすい
  • 日本の住所は「表記揺れ・旧字体・号レベル・京都通り名」など、単純な文字列正規化では扱いきれない構造を持つ
  • デジタル庁の abr-geocoder(MIT License)は、アドレス・ベース・レジストリ(ABR)を辞書とした本家の正規化エンジンで、この領域の de facto standard
  • ただし自前ホストには SQLite 10〜50GB・Node.js 常駐・辞書更新運用 が必要で、サーバーレスAI SaaSには素直に載らない
  • 解決策: abr-geocoder を裏で動かす APIレイヤ を挟む。AIエージェントからは fetch 3行で呼べる
  • Shirabe住所API(2026年5月リリース予定)がこの位置に入る予定で、OpenAPI 3.1 + MCP対応、出典表記(CC BY 4.0)自動付与の設計

この記事の対象読者

  • 日本の住所を扱うAI SaaSのエンジニア(CRM、不動産、物流、保険、地方自治体向け業務)
  • LLMに「この住所を正規化して」と投げて良さそうな結果が返った経験がある人
  • abr-geocoder を知っていて、自前ホストするかAPIに逃がすか迷っている人

日本の住所はなぜ難しいのか

「東京都千代田区丸の内1-1-1」程度なら正規表現で十分な気がするが、実運用ではすぐ破綻する。日本の住所は以下の構造的特徴を持つ。

特徴1: 表記揺れが多層で発生する

同じ物理的住所が、次のようなバリエーションで書かれる。

入力例 本来の住所
東京都千代田区丸の内1-1-1 丸の内一丁目1番1号
東京都 千代田区 丸の内1丁目1番1号
東京都千代田区丸ノ内一ー一ー一
東京都千代田区丸ノ内1−1−1 〃(ハイフン違い)
〒1000005 東京都千代田区丸の内1-1 〃(郵便番号前置、番地欠落)

「丸の内」「丸ノ内」「マルノウチ」の表記揺れ、全角/半角ハイフン・マイナス・ダッシュ・波ダッシュのゆらぎ、全角/半角数字のゆらぎが 独立の次元で組み合わさる ため、単純テーブルでは爆発する。

特徴2: 旧字体・異体字・ JIS水準外

昔ながらの地名は旧字体を含むことがある(「龍ケ崎市」vs「竜ケ崎市」、「塩竈市」vs「塩釜市」)。JIS第3水準・第4水準や IVS(Ideographic Variation Selector)まで考慮すると、同じ地名が Unicode コードポイント上で複数の正解 を持つ状態になる。

特徴3: 「丁目・番地・号」の区切り方

住所は「大字・丁目・街区符号(番)・住居番号(号)」の階層構造を持つが、カジュアルに書かれる住所はこの階層が:

  • 数字の連続(1-1-1)に潰されている
  • 全角ハイフンで区切られている
  • 「番地の1」「1番地先」のような例外表現で書かれている

さらに、号レベルの住居表示は実施済みかどうかが自治体ごとに違う。同じ自治体の中でも住居表示実施地区と未実施地区(地番区域)が混在することがある。

特徴4: 京都の通り名・仙台の地割・札幌の条丁目

  • 京都市中京区: 「東洞院通三条上る曇華院前町706」のような通り名表記が正式で、これを丁目番地に変換する辞書は自前で持たないといけない
  • 仙台市: 「青葉区上杉一丁目」と「青葉区宮町4丁目」のような地割が混在
  • 札幌市: 「北○条西○丁目」の条丁目表記

これらは地域特化ルールで、汎用の住所パーサでは必ず取りこぼす


LLMに住所正規化を直接やらせる危険性

「じゃあLLMに賢く解釈させればよい」と考えて、ChatGPTやClaudeに丸投げするとどうなるか。典型的な事故パターンを挙げる。

事故1: 存在しない住居番号を補完する

LLMに「東京都千代田区丸の内1-1 を正規化して」と投げると、「丸の内1-1-1」と 号レベルを勝手に補って 返してくることがある。元入力に無い「1号」が生成され、DB側では合法な住所として保存され、請求書の住所誤りや配送事故に繋がる。

事故2: 町名を「近い名前」に寄せる

「大田区洗足池」(実在しない)を投げると、「大田区北千束」とか「大田区南千束」 に勝手に書き換えて返すことがある(洗足池は地名ではなく駅名・池名で、住所表記では「南千束」「北千束」等になる)。LLMは最尤で補完するため、存在しない地名を検出してエラーにすることが苦手

事故3: 郵便番号と住所の不一致を見逃す

「〒1000005 東京都千代田区大手町1-1-1」のような、郵便番号が実際の住所と不整合な入力に対して、LLMは どちらかに寄せて辻褄を合わせる。どちらが正しいかは LLM には判定できない。

なぜLLMは苦手なのか

住所正規化は 「入力に対応する正解が辞書に存在するか」のルックアップ問題 であり、生成問題ではない。LLMは生成器なので、辞書にない入力を「生成的に補完してそれっぽく整える」方向に倒れる。これはハルシネーションの典型で、ドメインが住所の場合は実害に直結する。

正しいアプローチは、公式辞書(アドレス・ベース・レジストリ)と照合して、見つからなければ見つからないと返す エンジンを使うこと。これが abr-geocoder の役割になる。


abr-geocoder(デジタル庁、MIT License)

abr-geocoder は、デジタル庁が提供するアドレス・ベース・レジストリ(ABR)対応の住所正規化エンジン。

  • リポジトリ: https://github.com/digital-go-jp/abr-geocoder
  • License: MIT License(商用利用制限なし、Copyright 2024 デジタル庁)
  • 辞書データ: アドレス・ベース・レジストリ(CC BY 4.0、出典表記必須)
  • 実装: Node.js(TypeScript) + SQLite
  • 配布: npmパッケージ @digital-go-jp/abr-geocoder

何が嬉しいのか

  • 日本政府が整備している公式辞書(ABR)を使うため、町名・番地レベルまで網羅性が高い
  • 表記揺れの正規化(全角/半角、新旧字体、通り名表記、地割)が本家仕様に準拠
  • 郵便番号 ↔ 住所のクロスチェックができる
  • MITライセンスで商用利用可能(ただしABRデータは CC BY 4.0 で出典表記が必須)

データの出典表記(CC BY 4.0 の義務)

ABRデータを使うサービスは、利用規約上 出典を明示する義務 がある。Shirabeの住所APIでは後述のとおり、全APIレスポンスに attribution フィールドを必須化して、LLM経由で情報が流通する際も出典が伝搬する設計にしている。

「アドレス・ベース・レジストリ(○○データ)」(デジタル庁)

この表記を、ドキュメント・OpenAPI仕様・APIレスポンスの3箇所に配置しておくと、どのAI統合経路で使われても出典が落ちない。


自前ホスティングの運用課題

abr-geocoder を自前で立てると、実運用では次の課題に全部向き合うことになる。

課題1: 辞書SQLiteが大きい

全国の住所データを展開したSQLiteは 10〜50GB クラスになる。主要6都道府県に絞っても 2〜5GB。Cloudflare Workers や Lambda のようなサーバーレス環境には 素直に載らない(Workers のスクリプト上限は有料で25MB)。

課題2: Node.js 常駐が必要

abr-geocoder 本体は better-sqlite3 等の ネイティブモジュール に依存する。これは V8 の拡張機能を使うため、Cloudflare Workers(V8 isolate、Node.js互換性は限定的)ではそのまま動かない。Node.js を常駐させられる実行環境(Fly.io / Cloud Run / ECS / EC2 など)が必要になる。

課題3: 辞書更新の運用

ABRデータは定期的に更新される(町名変更・住居表示実施・新設住所など)。abr-geocoder の download コマンドで最新辞書に更新する運用を定期ジョブとして回す必要があり、更新中のダウンタイム回避(ブルーグリーンデプロイ等)も自前で組む必要がある。

課題4: スケーリング

住所正規化はCPU寄りの処理で、同時リクエストが増えるとボトルネックになる。SQLiteのIOパターン最適化、コネクションプーリング、リクエストバッチング等を自前で作り込む必要がある。

これらを全部ちゃんと組むのは、住所APIを 本業 にしないと割に合わない工数になる。


APIアプローチの優位性

abr-geocoder を裏で動かしている API サービスを挟めば、AI SaaS 側は fetch 3行で終わる。

観点 自前ホスト abr-geocoder API(Shirabe住所API等)
インフラ Fly.io / Cloud Run / EC2 等が必要 不要(呼ぶだけ)
ディスク 10〜50GB の SQLite 不要
辞書更新 自前で定期ジョブ API側で常に最新
コールドスタート 数秒〜十数秒 なし(エッジ経由)
AI統合 自前で Tool定義を書く OpenAPI 1URLで完了
出典表記 自前で実装 レスポンスの attribution に自動付与

「無料でOSSを使う」が見かけだけ無料で、運用込みで考えると API契約のほうが総コストで安い というパターンの典型だと思う。


Shirabe住所API(2026年5月リリース予定)

公式リリース前の情報として現時点で公開できる範囲で概要を書いておく。

アーキテクチャ: Workers + Fly.io NRT 2層構成

  • Cloudflare Workers レイヤ: 認証・課金・計測・OpenAPI配信・MCP・KVキャッシュ
  • Fly.io(東京リージョン nrt)レイヤ: abr-geocoder 実体(Node.js 20 + SQLite on Fly Volumes)

Workers に乗らないネイティブモジュールだけを Fly.io に逃がし、AIエージェントから見える面(OpenAPI・MCP・認証)はすべてエッジで完結させる構成。

Phase 戦略

  • Phase 1(5月上旬): 主要6都道府県(東京・大阪・愛知・福岡・神奈川・埼玉)限定でMVPリリース。SQLiteは2〜5GB想定
  • Phase 2(5月下旬): 全国展開(10〜50GB)に拡張

Phase 2 前提のスキーマで Phase 1 を設計するため、Phase 1 → 2 でクライアント側の破壊的変更は無い 予定。

出典表記の自動付与(CC BY 4.0 義務履行)

全レスポンスに attribution フィールドを必須で付与する:

{
  "normalized": "東京都千代田区丸の内一丁目1番1号",
  "parts": {
    "prefecture": "東京都",
    "city": "千代田区",
    "town": "丸の内一丁目",
    "block": "1",
    "house_number": "1"
  },
  "match_level": "residential",
  "attribution": {
    "source": "アドレス・ベース・レジストリ",
    "provider": "デジタル庁",
    "license": "CC BY 4.0",
    "notice": "「アドレス・ベース・レジストリ(住所データ)」(デジタル庁)"
  }
}

この設計の狙いは、LLM経由で住所情報が流通した先でも出典が自動的に伝搬 することにある。AIエージェントがこの attribution を会話応答に引用すれば、CC BY 4.0 の帰属義務が技術的に充足される。

OpenAPI 3.1 / MCP 対応

  • OpenAPI 3.1 仕様: https://shirabe.dev/openapi.yaml(住所API追加予定)
  • MCP サーバー: https://shirabe.dev/mcp(住所正規化ツールを追加予定)

ChatGPT GPTs / Claude Tool Use / Gemini Function Calling / LangChain / Dify から OpenAPI URL 1つで統合できる運用は、暦APIと同じ設計を踏襲する。


AI統合経路での住所正規化ユースケース

ユースケース1: CRM の住所クレンジング bot

Slack の AI bot に「顧客リストの住所カラムを正規化して」と投げるだけで、裏で住所APIを一括呼び出しして、表記揺れを潰した列を返す。LLMに直接やらせると事故2(存在しない地名への寄せ)が起きるため、LLM は入出力の整形だけ担当し、正規化本体はAPIに投げる 分業が安全。

ユースケース2: 音声入力からの配送先補正

音声認識の出力(「とうきょうとちよだくまるのうちいちのいちのいち」)をLLMで分かち書きし、APIで正規化、match_levelresidential(住居表示レベル)に到達したかで入力完了を判定する。未達なら足りない階層をユーザーに聞き返す。

ユースケース3: 不動産契約書のチェック

契約書PDFから住所を OCR + LLM で抽出し、APIで正規化した結果と文字列一致するかをチェック。一致しないケースは担当者に人手レビューを促す。LLM単独だと事故1(号レベル勝手補完)で通してしまう案件を止められる。

ユースケース4: GPTs Actions

Import URL: https://shirabe.dev/openapi.yaml
Authentication: API Key (header: X-API-Key)

これだけで「この住所を正規化して」「この郵便番号の地域を教えて」系の質問にカスタムGPTが自動で答えられるようになる。API側の出典表記も GPTs の回答に含まれる設計。

ユースケース5: Claude MCP

{
  "mcpServers": {
    "shirabe-address": { "url": "https://shirabe.dev/mcp" }
  }
}

Claude Desktop から「顧客CSVの住所列を正規化して」のような依頼で MCP ツールが自動的に呼ばれる。


まとめ

  • 日本の住所は 辞書照合問題 で、生成問題ではない。LLMの最尤補完とは相性が悪い
  • デジタル庁の abr-geocoder(MIT)がこの領域の本命だが、自前ホストには 10〜50GB SQLite・Node.js 常駐・辞書更新運用が必要
  • AIエージェントから使うなら、abr-geocoder を APIレイヤで包む 形が素直
  • Shirabe住所API(2026年5月リリース予定)は Workers + Fly.io NRT の2層で、出典表記を自動付与する設計
  • AI SaaS側は fetch 3行で住所正規化を手に入れられる

住所を扱うAI SaaSで、事業リスクを下げたい開発者の選択肢の一つとして使えればと思う。リリース後のOpenAPI URLは https://shirabe.dev/openapi.yaml に追加される予定なので、そのままGPTs / LangChain / Dify にインポートできる。

データ出典:「アドレス・ベース・レジストリ(住所データ)」(デジタル庁)/ CC BY 4.0


関連リンク


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?