検索システムで読めない文書は、存在しないのと同じだ
1990年代から今日に至るまで、日本の官公庁、地方自治体、教育現場、法曹界、そして学術機関では、膨大な思考、政策、知見が一太郎(.jtd / .jtt / .jttc)のフォーマットに託されてきました。そこには、過去30年間にわたり日本社会を支え続けてきた無数の人々の言葉が刻まれています。
しかし、現代のデジタル情報環境において、私たちは極めて冷徹な現実に直面しています。
「検索システムで読めない文書は、存在しないのと同じだ」
ファイルサーバの奥深くに眠る数十万の一太郎ファイルは、OSの刷新、閉域網の制約、クラウドへの移行、そして現代の LLM / RAG(検索拡張生成) による知識活用の波の中で、不可視のデータと化しつつあります。読めない文書は参照されず、参照されない記録はやがて捨てられてしまう。
この切実な課題を解決すべく開発したのが、Apache Tika 向けオープンソース拡張パーサー Tika JTD+ です。
……という壮大な話はさておき、一太郎ヘビーユーザーである筆者が、「手元に大量にある一太郎文書をどうしても OpenWebUI で読みたい(RAG させたい)!」という切実な要求から本プロジェクトを進めています。
30秒でわかる「Tika JTD+」
-
公式 Docker コンテナに JAR 1 本置くだけ:
apache/tika:latest-fullにカスタムビルド不要でボリュームマウントするだけで即座に.jtdを認識。 - 純粋な JVM (Kotlin) 実装: 外部プロセスやネイティブバイナリ(Rust等)に依存しない完全なマネージド実装。
- オブジェクト枠の再帰抽出: 表計算(BIFF8/Excel)や図形(WMF)等の埋め込みオブジェクトを、Tika の既存パーサーチェーンへ透過的に委ねて抽出。
- 実文書 510 ファイルによる耐性検証: 官公庁・自治体・学校などの実流通コーパスで平均一致度 94.8% を実証。
- OpenWebUI 等の RAG パイプラインに直結: 一太郎ファイルをドラッグ&ドロップするだけでナレッジ化完了。
まずは動かしてみる(クイックスタート)
1. 公式 Tika コンテナにマウントして起動
Tika JTD+ の最大の特徴は、コンテナをビルドし直す必要が一切ない 点です。GitHub Releases から tika-parser-jtd-*-server.jar をダウンロードし、以下のように起動します。
docker run -d --name tika \
-p 9998:9998 \
-v "$PWD/jars/tika-parser-jtd-0.2.2-server.jar:/tika-extras/tika-parser-jtd.jar:ro" \
apache/tika:latest-full
たったこれだけで、公式 Tika サーバーが一太郎パーサーを自動認識します。
コンテナイメージごとビルドしたい場合:
ポン置きではなく、最初からパーサーを組み込んだ独自の Docker イメージをビルド・運用したい方向けのリポジトリも用意しています。
🔗 KHiyowa/tika-jtd-docker
2. テキスト抽出の確認
# プレーンテキスト抽出
curl -T sample.jtd http://localhost:9998/tika
# Tika 4 系の JSON テキストエンドポイント(OpenWebUI 等が内部で使用)
curl -T sample.jtd http://localhost:9998/tika/json/text
3. OpenWebUI と繋いで一太郎 RAG 環境を作る
docker-compose.yml に記載する場合も、公式イメージをそのまま指定してマウントするだけです。
services:
tika:
image: apache/tika:latest-full # 公式イメージのまま。ビルド不要!
ports:
- "9998:9998"
volumes:
- ./jars/tika-parser-jtd.jar:/tika-extras/tika-parser-jtd.jar:ro
restart: always
open-webui:
image: ghcr.io/open-webui/open-webui:main
ports:
- "3000:8080"
environment:
- CONTENT_EXTRACTION_ENGINE=tika
- TIKA_SERVER_URL=http://tika:9998
volumes:
- open-webui:/app/backend/data
restart: always
volumes:
open-webui:
OpenWebUI のドキュメントナレッジに .jtd を直接放り込み、ローカル LLM や ChatGPT に一太郎文書の内容を回答させることができるようになります。
4. CLI で単体抽出したい場合(ローカル即席実行)
サーバーや Docker を立てずに、手元のターミナルでサクッとテキストを抜きたい方向けに、スタンドアロン CLI も用意されています。GitHub Releases から Fat JAR(tika-parser-jtd-cli-*-standalone.jar)をダウンロードするだけで使えます。
# プレーンテキスト抽出(標準出力)
java -jar tika-parser-jtd-cli-0.2.2-standalone.jar -t sample.jtd
# メタデータ抽出
java -jar tika-parser-jtd-cli-0.2.2-standalone.jar -m sample.jtd
# 埋め込みオブジェクトを含めた構造化 JSON 出力
java -jar tika-parser-jtd-cli-0.2.2-standalone.jar -J sample.jtd
なぜ JAR 1 本で公式 Docker が動くのか?
「本当に Dockerfile を書かずに JAR 1 個マウントするだけで動くのか?」と疑問に思うかもしれません。これには Apache Tika 4 の公式設計をフル活用した仕掛けがあります。
公式の apache/tika:latest-full(4.0.0)のコンテナ起動スクリプト(ENTRYPOINT)には、標準で /tika-extras/* がクラスパスに含まれています。
java -cp "/opt/tika-server/*:/opt/tika-server/lib/*:/tika-extras/*" \
org.apache.tika.server.core.TikaServerCli -h 0.0.0.0
Tika JTD+ の JAR(-server.jar)はこんな仕組みです。
-
META-INF/services/org.apache.tika.parser.Parser:
Java のServiceLoader機構により、Tika 起動時にcom.hiyowa.tika.jtd.JtdParserが自動検出され、パーサーチェーンに透過的に登録されます。 -
JAR ルートの
custom-mimetypes.xml:
application/vnd.justsystem.ichitaro(拡張子.jtd,.jtt,.jttc)の MIME タイプ定義が Tika 起動時に自動マージされます。 -
純粋 JVM 実装 & ランタイム内包:
C/Rust のネイティブバイナリを含まず、公式 Tika に同梱されていないkotlin-stdlibのみを最小限内包しているため、JAR 1本置くだけで追加ライブラリなしに即座に稼働します(OS アーキテクチャも意識不要)。
510 ファイルの実世界コーパス耐性検証
机上の空論ではなく、実際の現場で流通している文書に耐えうるかを証明するため、日本の官公庁、自治体、学校、法曹などの実文書(計 510 ファイル)を収集し、耐性検証ハーネス(CorpusToleranceVerifier)を構築しました。
一太郎から出力した正解 DOC 形式との間で「文字マルチセット(Bag of Characters)によるカバレッジ(再現率)」を計測した結果が以下です。
| コーパス種別 | ファイル数 | 合格率(Coverage 95%以上) | 平均一致度 |
|---|---|---|---|
| 裁判所 | 16 files | 93.8% | 0.990 |
| 教育委員会・学校 | 114 files | 78.1% | 0.962 |
| 中央省庁・国 | 236 files | 76.7% | 0.971 |
| 地方自治体 | 69 files | 62.3% | 0.916 |
| 都道府県警察 | 73 files | 23.3% | 0.874 |
| オーナー実文書 | 2 files | 50.0% | 0.931 |
| 合計 | 510 files | 67.8% | 0.948 |
全体での 平均一致度は 94.8% に達しています。
- 警察文書の合格率(95%閾値)が低めに出ているのは、人名・地名に多用される「ルビ(ふりがな)」の抽出が未実装であるためです。文字出現頻度を厳密に比較するためルビ欠落でカバレッジが 90% 前後にとどまりますが、平均一致度は 0.874 と非常に高く、本文テキストの回収は極めて高い精度で行われている ことが裏付けられています。
- オーナー実文書とは、大学の修士論文(複数シート・画像・表・数式を含む)と、パブリックコメントで提出した意見書です。v0.2.2現在、数式は抽出することができません。
実文書バグを安全に報告するための「銀河鉄道の夜」ポリシー
パーサーを運用していると、「特定のファイルだけパースに失敗する・文字化けする」というケースに必ず直面します。しかし、実業務のファイルには個人情報や機密情報、著作物が含まれており、そのまま GitHub の Issue に添付することはできません。
そこで Tika JTD+ では、「銀河鉄道の夜」置換ポリシー を採用しています。
バグ報告・テストケース提供のお願い:
パースに失敗するファイルに遭遇した場合、一太郎上でその構造(複雑な表組み、入れ子の枠線、ルビなど)を維持したまま、中の文字列だけを宮沢賢治の『銀河鉄道の夜』(青空文庫のパブリックドメインテキスト)に置き換えて保存したファイル を作成し、テストケースとしてお寄せください。
ジョバンニは、学校の門を出るとき、同じ組の七八人といっしょになりました。
家へは寄らず、活版所へ入って行きました。
「おや、ジョバンニさん、よく来てくれたね。」
バイナリのトポロジー(入れ子構造やテーブルの配置情報)はそのままに、文言のみをパブリックドメインテキストに差し替えることで、機密漏洩リスクを低減しながら、凶悪な実バイナリのバグを再現する CI テストを作成・共有 することができます。
プロジェクトの背景: 先駆者「OpenJTD」の挑戦と、止まってしまったコミット
一太郎バイナリ(JTD)は公開仕様書が存在しないプロプライエタリな形式です。歴史的には OpenOffice.org の一太郎インポートフィルタ開発など、熱心なリバースエンジニアリングの試みがありました。
そして、ほんの2ヶ月前、Qiita に彗星の如く現れたプロジェクトがこちらです。
韓国の HWP 互換実装の知見を手がかりに Rust で挑まれた OpenJTD (rjtd) は、暗闇に閉ざされていた JTD のストリーム構造を解読し、多大な観測資産をオープンソースの世界にもたらしてくれた偉大な先駆者です。
しかし、一太郎は1985年の誕生から40年にわたり、ミリ単位の組版や縦書き、独自外字、入り組んだレイアウト枠、複数シート、さらには埋め込み表計算など、仕様の継ぎ接ぎを繰り返しながら日本の文書表現を突き詰めてきたソフトウェアです。内部的に Windows の GDI+ と不可分に結びついており、互換実装には多くの壁があります。
(開発元のジャストシステムですら、バイナリしか残っていない機能があるとかないとか...)
「画面の見た目をピクセル単位で完全再現するビューア・エディタを自前でゼロから作る」というあまりにも高い巨塔の前に、OpenJTD のコミットはわずか22日で止まってしまいました。
方針転換:「画面再現を捨て、テキストと構造の救出に特化する」
座礁しかけた船のバトンを受け取った Tika JTD+ では、設計方針を根本から転換しました。
-
画面再現を捨て、テキストと論理構造の抽出に全振りする
ピクセル単位の描画再現を諦め、本文の流れ、表(テーブル)、箇条書き、見出し構造の救出に特化しました。構造化テキストさえ抽出できれば、要約や Markdown への整形は現代の大規模言語モデル(LLM)が極めて高精度に肩代わりしてくれます。 -
Apache Tika エコシステムとの協調(埋め込みオブジェクトの再帰解析)
OLE2/CFB コンテナの解体は枯れ切った Apache POI に任せます。また、一太郎文書内のオブジェクト枠に潜む Excel 表や図形などのバイナリは、スライスして Tika のEmbeddedDocumentExtractorに委ねます。Excel なら POI、PDF なら PDFBox といった Tika が誇る膨大な既存パーサーチェーンへ再帰的に流し込むことで、自前で形式パーサーを抱え込まずに安全かつ網羅的な解析を実現しました。 -
純粋 JVM (Kotlin) への再構築
外部プロセス実行やネイティブ共有ライブラリ(Rust の.so/.dylib)を完全に排除しました。これにより、公式 Tika Server への「JAR 1 本ドロップイン」が可能になり、本番環境への導入障壁がゼロになりました。
プロジェクトの舞台裏:バイナリ解析はトークンが溶ける & スポンサーのお願い
開発裏話ですが、「バイナリ解析×生成AI」はトークン消費が桁違いです。
かつ、4日で入力2.5億に対して出力200万と落差が非常に大きいのが特徴です。散々考えたあげく、出力されるコードは2行、ということもザラです。
未知のプロプライエタリバイナリの解析では、何十KB〜何MBもの Hex ダンプやバイト列、構造体を AI に食わせて推論させる作業を繰り返します。これを商用 API(ClaudeやCodex) に投げ続けていると、あっという間にクレジットが蒸発します。
(OpenJTDの作者も、「If API credits become available, maintainers plan to use them for focused, auditable assistance with:」という祈りの言葉をREADMEに記しています。)
そこで本プロジェクトの開発では、クラウド従量課金ではなく 自前のローカル LLM 環境 をフル稼働させ、オーナーが仕事をしている間や寝ている間に泥臭いバイナリ解析・仕様特定を進めています。
しかし…… GPU (Radeon AI Pro R9700 x2本) だけで 50 万円ほど投資 しており、財布へのダメージが深刻です。
日本の過去30年のデジタル資産を救い出し、一太郎文書の未来を切り拓く挑戦を継続するため、もし「役に立った!」「応援したい!」と感じていただけましたら、ぜひ GitHub Sponsors での温かいご支援をよろしくお願いいたします。もしくは、筆者京橋 ひよわはボカロPでもありますので、BOOTHでCDを買ってください!!🙇♂️
👉 GitHub Sponsors で KHiyowa を支援する
👉 京橋 ひよわのCDを購入する
おわりに:一太郎を葬り去るためではなく、愛機として未来へ繋ぐために
このプロジェクトの目的、一太郎を「過去の遺物」として淘汰・排除するためではありません。むしろその逆です。
日本語ワープロソフト「一太郎」が、これからも表現のための愛機として将来へ生き残り、使われ続けていくための防壁にしたい という想いがあります。
日本語の機微に寄り添い、美しい組版と語彙を支え続けてきた一太郎は、いまなお替えの利かない道具です。しかし、「組織の検索システムに入らないから」「AI に食わせられないから」「他部署と共有できないから」というシステムの都合によって、現場は一太郎を手放すことを余儀なくされてきました。
もし、一太郎で書かれた文書が、Tika を通じて透過的に全文検索され、Elasticsearch や OpenSearch でインデックスされ、ローカル LLM が難なく参照できる世界を作ることができればどうでしょうか。
「互換性の壁」さえ取り払われれば、人々はシステムの都合に脅かされることなく、安心して一太郎を選び続けることができます。
バイナリを開くのは、一太郎という文化を終わらせるためではありません。一太郎が紡ぎ出した言葉たち、そして一太郎というソフトウェアそのものを未来へ繋ぐためです。
- GitHub リポジトリ: https://github.com/KHiyowa/tika-jtd
- Docker リポジトリ: https://github.com/KHiyowa/tika-jtd-docker
- GitHub Sponsors: https://github.com/sponsors/KHiyowa
- ライセンス: Apache-2.0
