🎧 Listen to this article: हिंदी · English · தமிழ் · తెలుగు · ಕನ್ನಡ · മലയാളം · ଓଡ଼ିଆ · 日本語 · 中文
🌍 Read this in your language: हिंदी · தமிழ் · తెలుగు · ಕನ್ನಡ · മലയാളം · ଓଡ଼ିଆ · 日本語 · 中文
弁護士が日常語で質問を入力するだけで、何千ものキーワード検索結果をかき分けることなく、最も関連性の高い5つの判例と該当する重要段落を即座に取得できることを想像してみてください。それこそがセマンティック検索の約束する世界です。しかし、3,370万件の裁判判決に対してそれを実現するのは、まったく次元の異なる挑戦です。
EDRSR — Unified State Register of Court Decisions(裁判判決統一国家レジストリ) — は、ウクライナの全司法記録を公開しました。現在、チームはその全テキストを実際に検索可能にするための取り組みを進めています。
なぜ今これが重要なのか
2026年現在、ウクライナでは裁判判決は公開データとなっていますが、効果的に検索するのは依然として困難です。特定の問題に関する判例を探す弁護士は、使いづらいキーワード検索を使用せざるを得ず、無関係な検索結果が何千件も返されていました。システムは 意味 — を理解しておらず、入力された単語を含むドキュメントを見つけるだけだったのです。ベクトル埋め込みによるセマンティック検索を活用することで、弁護士は実際に知りたいこと(例:「銀行の繰上返済手数料の回収に関する判例はあるか?」)を質問できるようになります。システムは最も関連性の高い5つの判決を見つけ出し、重要な段落を抽出して、裁判所がどのように判断したかを示します。
しかし、セマンティック検索を行う前に、テキストをベクトル化しなければなりません。そしてウクライナの裁判制度の規模は、決して小さな問題ではありません。
規模
レジストリには2006年までさかのぼる判決が保持されています。内訳は以下の通りです:
- 民事訴訟(CPC):3,370万件のドキュメント — 最大のカテゴリ
- 刑事訴訟(CrPC):1,200万件以上
- 行政訴訟(CAS):1,400万件以上
- 商事訴訟(CC):600万件以上
- 軽罪・行政違反(CUaP):600万件以上
現時点で、Qdrantベクトルデータベースには4,400万件以上のベクトルが保持されています。民事訴訟は42%が完了しています(3,370万件中1,430万件が処理済み)。民事データの処理が完了すれば、コレクションにはおよそ6,300万件以上のベクトルが保持されることになり、これは通常のRAGプロジェクト(10万〜100万ベクトル程度)より2桁大きい規模です。
これほど多くのドキュメントを処理するには、途中でダウンしないパイプラインを構築する必要がありました。
技術スタック
チームは検証済みで実用的な選択肢を採用しました:
埋め込みモデル: 1024次元のベクトルを出力するVoyage AIの voyage-3.5。チームは Voyage 3 Large およびOpenAIの text-embedding-3-large もテストしましたが、法律テキストにおける品質の向上は価格差に見合わないと判断しました。Voyage 3 Large は3倍高価です。
ベクトルデータベース: 専用の Amazon EC2 インスタンス(r6a.xlarge: 4 CPU、32 GB RAM、2 TB gp3 ストレージ)上の Docker でセルフホストされた Qdrant v1.17。HNSWインデックス作成を伴う4,400万件以上のポイントにより本番データベースがメモリ不足になり、チャットサービス全体がブロックされていたため、専用インスタンスが割り当てられました。
信頼できる情報源(Source of truth): 判決日に基づいてテーブルがパーティショニングされた PostgreSQL 15。裁判テキスト全文は1つのテーブルに、メタデータは別のテーブルに配置されています。全パーティションにわたる JOIN は3,000万行以上に触れるため、パイプラインは1年ずつ処理します。
パイプライン実行環境: Python 3.11、asyncio、aiohttp。重厚なフレームワークは使用せず、Voyage および Qdrant への直接的な HTTP 呼び出しのみを行っています。全体で1つのファイル内に440行で収まっています。
タスクの分割方法
裁判判決は 長いのです。平均的な民事判決は8,000〜12,000文字で、中には200,000文字に達するものもあります。Voyage は入力あたり最大32,000トークンを受け入れますが、コンテキストが長いと品質が低下し、1つの長いベクトルは検索に役に立ちません。言語モデルがどの段落が関連しているかをピンポイントで特定できないためです。
そこでチームはチャンク分割(チャンキング)を行っています:
- チャンクあたり最大2,048文字
- 隣接するチャンク間で50語のオーバーラップ(境界でのコンテキストを保持するため)
- 意味的まとまりを維持するため段落境界で分割
平均して、1つの判決から2.7個のチャンクが生成されます。各チャンクには Qdrant 内で複合ID(doc_id × 1000 + chunk_index)が割り当てられ、これにより単一のペイロードフィルタで1つの判決の全チャンクを取得できます。
速度と並行処理
Voyage にはレート制限があり、APIキーごとに毎分2,000リクエストです。チームは2つのキーを使用し、それらの間でラウンドロビンを行うことで、理論上の上限である4,000 RPMに達しています。
並行リクエスト数を50に維持することで、毎秒63件のドキュメント処理という安定した速度を得ています。これはキーあたり毎分約170リクエストであり、制限を大幅に下回っています。並行数を70に増やしてみたところ、Python GIL(グローバルインタプリタロック)の壁に突き当たりました。プロセスはCPU使用率13%で停止し、進行もせずエラーも出力しませんでした。単にハングしたのです。50に戻したところ、スムーズに動作しました。
100ドキュメントごとに、500チャンクをバッチ化して Voyage に送信し、埋め込みを収集して Qdrant ポイントを構築し、upsert を行います。エラー発生時(429レート制限、ネットワークタイムアウトなど)は、ジッター付きの指数バックオフを使用し、最大5回リトライします。
数週間を救ったチェックポイント機能
3,370万件のドキュメントを前にしては、いかなる障害も数時間から数日分の作業の喪失を意味します。チームはチェックポイントシステムを構築しました。1,000件のドキュメントを処理するごとに、パイプラインは最後のドキュメントID、件数、使用トークン数、タイムスタンプを含む JSON スナップショットを書き出します。
再起動時には、そのチェックポイントを読み込み、WHERE doc_id > last_doc_id から再開します。重複作業もゼロからの再スタートも発生しません。
これにより、すでに2回救われました。1回は PostgreSQL がメモリ不足になったとき(詳細は後述)、もう1回は Qdrant が再起動し、環境からAPIキーが失われたときです。
本番環境のインシデント:Postgres のメモリ不足
286万件のドキュメントの時点で、PostgreSQL がリカバリモードに陥りました。根本原因は設定の不一致でした。
データベースは shared_buffers=16GB に設定されていましたが、コンテナのメモリ上限は12GBでした。PostgreSQL が割り当て可能な量を超えて割り当てようとしたため、OSによってプロセスがキルされたのです。
修正(PR #1453)により、コンテナの上限が24GBに、shm_size が16GBに引き上げられました。再起動後、PostgreSQL は4秒で立ち上がり、安定した状態を維持しました。
得られた教訓: PostgreSQL の設定パラメーターはコンテナのメモリ上限と整合させる必要があります。 システムは最初の負荷スパイクが発生するまでは正常に動作しますが、その後予期せぬ形でダウンします。
また、Voyage API の大量トラフィックにより Python プロセス内で多数の一時オブジェクトが生成されるため、開発マシンのスワップ領域も8GBから24GBに引き上げました。
これまでにかかったコスト
民事ドキュメント1件の平均は 2.7チャンク × 850トークン = 2,300トークン です。100万トークンあたり6セントという Voyage の価格設定では、ドキュメント1件あたり0.014セント(約138マイクロドル)となります。
これまでの経過(42%完了):
- 1,430万件のドキュメントを処理済み
- Voyage API への支出:約1,980ドル
- パイプライン実行時間:約63時間
残り(あと58%):
- 1,940万件のドキュメント
- Voyage の推定コスト:約2,680ドル
- 推定時間:85時間(連続実行で約3.5日)
民事データ全体にかかる総コスト: API利用料でおよそ4,660ドル。
専用の EC2 オンデマンドインスタンスの費用は1時間あたり約0.20ドル(月額約145ドル)です。本番環境での OOM インシデントからの復旧費用に比べれば安価です。
比較として、OpenAI の text-embedding-3-large で同じ予算を使用した場合、データ量の4分の1しかベクトル化できません。この規模では、Voyage を選択することがコスト面で理にかなっています。
これによって可能になること
パイプラインが完了すると、コレクションには全民事訴訟にわたる6,300万件以上のベクトルが保持されます。弁護士が自然言語のクエリ(例:「売主の行為能力喪失を理由とする売買契約の無効化に関する判例」)を入力すると、システムは適切な管轄裁判所から最も関連性の高い判決を表示し、主要段落の抜粋と EDRSR へのリンクを提供します。
これにより、ウクライナの民事裁判制度全体におけるセマンティック検索が実現します。
結論
3,370万件の裁判判決をベクトル化することは、決して小さなエンジニアリング課題ではありません。コストと品質のトレードオフに適した埋め込みモデルの選択、本番環境のリソース枯渇を防ぐためのベクトルデータベースの分離、GILデッドロックを回避するための慎重な並行処理管理、そして100時間以上に及ぶパイプラインへの耐障害性の構築が必要とされます。ウクライナの司法記録は今、検索可能なナレッジベースへと変貌を遂げつつあります。
メリット
- 全文に対するセマンティック検索。 弁護士は単なるキーワードの検索結果ではなく、答えを得ることができます。
- 大規模環境での優れたコスト効率。 このデータ量において、Voyage AI は他の代替手段と比較して4倍安価でした。
- 耐障害性に優れた設計。 チェックポイント機能により、パイプラインは再実行することなく障害から復旧できます。
- 実用的なインフラ構成。 別コンテナでの Qdrant の運用、適切なメモリ制限を設定した PostgreSQL — 本番環境を保護するための設計上の決定。
- 記録されたインシデント。 Postgres の OOM 障害は、設定の整合性に関する明確な教訓となりました。
デメリット
- 長いパイプライン実行時間。 残り85時間以上ということは数週間の連続運用を意味し、チェックポイントがあっても実行途中でインフラが障害を起こすリスクがあります。
- 通常より2桁大きい規模。 6,300万件以上のベクトルは未開拓の領域であり、スケーリング上のリスクが残ります。
- 専用ハードウェアのコスト。 r6a.xlarge インスタンスは必要不可欠ですが、継続的な運用費用が発生します。
- 言語モデルへの依存。 品質は埋め込みモデルに依存します。Voyage が価格設定やサービスを変更した場合、損益計算が変化します。
- クエリレイテンシに関する言及がないこと。 記事では、6,300万件のベクトルに対してセマンティック検索が実際にどれだけの速度で実行されるかについては説明されていません。
注意点
本記事は教育的目的で書かれており、ソース資料で報告されている実際のプロジェクトについて記述しています。実装にあたっては、現在の Voyage の価格設定でコスト数値を確認し、ご自身の環境とデータで PostgreSQL の設定パラメーターをテストし、並行設定を検証してください(ここで機能した50の並行リクエストがすべてのシステムに適しているとは限りません)。Postgres の shared_buffers の値は実際のコンテナメモリと一致させる必要があります。特定の数値やアプローチに依存する前に、一次情報源およびご自身のインフラストラクチャを確認してください。
よくある質問
- EDRSRとは何ですか?また、なぜウクライナはすべての裁判判決を一般に公開しているのですか?
- ベクトル埋め込みはどのように機能し、なぜ法律文書においてキーワード検索よりも優れているのですか?
- チームはなぜ Pinecone や Milvus といった他のベクトルデータベースではなく Qdrant を使用したのですか?
- GILデッドロックとは何ですか?また、なぜ並行数70でパイプラインがハングしたのですか?
- チェックポイントベースの再開機能はどのように動作し、再起動のオーバーヘッドはどれくらい発生しますか?
- PostgreSQL の設定とコンテナメモリ上限の整合性を保つことが、なぜそれほど重要なのですか?
- 3,370万件のドキュメントにおいて、Voyage AI と OpenAI の埋め込みのコスト差はどれくらいですか?
- 6,300万件以上のベクトルコレクションに対して、セマンティック検索クエリの実行にはどれくらいの時間がかかりますか?
タグ
#vectorsearch #qdrant #voyageai #legaltech #ukraine #semanticsearch #ragapplications #scalinginfrastructure
Docker Security Checklist
Lock down your containers from build to runtime — 29 practical controls covering images, runtime flags, secrets, and the daemon. Enter your email — you'll get the PDF instantly, plus new posts on Docker, Linux & security.
Free. No spam — unsubscribe in one click.


Responses
Sign in to leave a response.