顧客満足度100%のツールができた
英文の資料を、原文で読んで理解できる気分を味わいたかった。
そこで、フォルダに入っている複数の英文PDFファイルを翻訳し、日本語のテキストファイルを生成してくれるツールを作った。
たとえば、「A.pdf」「B.pdf」「C.pdf」という3つのファイルが「英文資料」というフォルダに入っているとする。このツールで「英文資料」というフォルダ名を指定する。すると、3つのPDFそれぞれから本文を抽出し、日本語に翻訳する。「英文資料」フォルダの中には、jp-translationsというフォルダができる。その中に、Markdown形式のテキストファイルとして「A.md」「B.md」「C.md」が保存される。
これは自分自身の専用ツールだ。
他の人に使ってもらおうという気はない。おそらく、足りない機能は多い。けれども、自分自身が必要とする機能は満たしているので、私は満足している。
ソフトウェアを使う人の事情は、人それぞれである。すべての顧客を満足させるのは、なかなか難しい。でも、このツールの場合、唯一の利用者である私が満足している。したがって、顧客満足度は100%ということになる。
生成AIを使うことで、ソフトウェアの開発はかなり簡単になった。だから、自分専用ツールを開発するという芸当が成り立つ。
開発動機: 英文を原文で読んで、いい気になりたい
外国の映画を見るとき、字幕派と吹替派がいる。
世界的には後者が大半と聞く。でも、私は字幕派である。
大して英語を聞き取れるわけでもないのに、字幕版のほうが、ホンモノ感、オリジナル感、産地直送感のようなものがある気がする。
もしかすると、母国語で完全に意味を理解できてしまうのが嫌なのかもしれない。それとも、文字を読むという一手間を加えることに、何らかの価値を感じているのかもしれない。
左側通行の日本で、運転しやすいのは右ハンドルのクルマだ。そして、手動でギアを切り替えるマニュアル・トランスミッションよりも、オートマチックのほうが便利に決まっている。同じように、外国映画だって、母国語の吹き替えのほうが理解しやすいはずだというのは分かっている。
私は、右ハンドルのオートマチック車を運転する。そのほうが合理的で安全で経済的だからだ。けれど、外国映画となると合理的な判断ができず、字幕派になってしまう。
英文の資料を原文で読みたいのも、同じような動機だ。
原文で読んだほうが、著者の意思や息づかい、行間の意味を感じやすい「気がする」のだ。
もちろん、そこまでの英語読解力があるわけではない。知らない単語が出てきて、辞書を引くことで、読解を中断されることのほうが、とても多い。
それなのに、英文を英語として原文で「読みたい」のだから仕方ない。
知らない単語で流れが切れる
なにしろ英語がそれほど得意ではない。だから、原文を読み続けるのは簡単ではない。ときどき、いや、しょっちゅう、知らない単語が出てくるからだ。
分からない単語がある。
そのうち文脈で理解できるだろうと読み飛ばす。やっぱり、その単語の意味が分からないと、全体像が分からない。だから辞書を引く。
一方で、この単語は調べておいたほうがいいだろうと先に調べた単語に限って、文脈とは無関係で、分からないままにしておいても大した問題がなかったりする。
辞書を調べることで、思考が停止する。
そもそも、その文が何を説明しようとしていたのかを忘れてしまう。仕方がないので、ひとつ前の文へ戻る。それでも話の流れがつかめず、さらに前へ戻る。もっと前の文から読み直して、ようやく元の場所へ戻ってくる。
そして数ページ後、さっき調べたはずの単語がまた現れる。
見覚えはある。しかし、意味を正確には覚えていない。
また検索する。
自分の記憶力の悪さに落胆する。
英文を読むこと自体よりも、こうした小さな中断の積み重ねの方が疲れることがある。
日本語訳だけを読めば速い。
けれども、見落としも多い。
英文だけを読めば、原文の細部まで見える。
けれども、途中で流れを失いやすい。
そこで、日本語訳と英文のどちらか一方を選ぶのではなく、両方を順番に使うことにした。
日本語訳を先に眺める
そこで、すごい方法を思いついた。
英文を読む前に、日本語訳を軽く眺めるようにしたのだ。
少々ずるいが、どうせ英文を原文で読みたいのは自己満足だ。使えるものは使う。
翻訳文を細部まで丁寧に読むわけではない。どのような話が書かれているのか、中心となる主張は何か、どのような順番で説明が進むのかを短時間で確認する。
すると、かなり読みやすくなる。
知らない単語が出てきても、その文が何を説明しているのかを見失いにくい。日本語で内容の方向をすでに知っているため、単語の意味も前後から推測しやすくなる。
日本語訳を読んで、英文を読んだことにするのではない。
日本語訳を、英文へ入っていくための地図として使う。
初めて訪れる町でも、先に地図を見ておけば、途中で道を一本間違えても、自分がどこにいるのか分かる。私にとって日本語訳は、そのような役割を果たしている。
AI翻訳なら使い捨てできる
この方法が現実的になった理由のひとつは、AIによる翻訳が読みやすくなったことだ。しかも安価である。
だから、贅沢な使い方ができる。
翻訳をじっくり読むことはない。斜め読みでよい。目立つ単語を拾うだけでもよい。気分によっては、ほとんど読まなくてもよい。
いわば使い捨てだ。
翻訳本を買ってきたり、誰かに頼んで翻訳してもらったりしたのなら、こんなもったいないことはできない。AIのおかげで、高品質な翻訳を手軽に手に入れられるようになった。
もちろん、AI翻訳が常に正確だと言いたいわけではない。
重要な部分は必ず原文へ戻る。違和感があれば英文を確認する。日本語訳は最終成果物ではない。
原文へ入る前に、方向を確認するための仮の地図である。
「続きをお願いします」は面倒だった
AIに翻訳してもらうには、PDFをChatGPTやClaudeへアップロードし、「日本語に翻訳してください」と頼めばよい。
一度だけなら、それで問題ない。
しかし、何度も使うと、小さな面倒が積み重なる。
いちいちPDFファイルを掴んでドロップするのも面倒だし、そもそも翻訳を待っている時間がまどろっこしい。
数ページにもわたる長い資料では、一度に最後まで出力されないことがある。
途中で出力が止まれば、「続きをお願いします」と入力する。
続きがまた止まれば、もう一度同じことを頼む。
翻訳が終わったら、複数に分かれた出力をコピーして、ひとつのファイルへまとめる。PDFが複数あるなら、最初から同じ作業を繰り返す。
対話型AIには大きな利点がある。翻訳の途中で疑問を尋ねたり、特定の段落を詳しく説明してもらったりできる。
しかし、私が求めていたのは、毎回相談しながら進める作業ではなかった。
決まったルールで、フォルダ内のPDFを順番に最後まで処理してほしい。
必要なのは、新しい翻訳能力ではない。
すでにある翻訳能力を、繰り返し実行できるワークフローへ変えることだった。
AIへ最初に伝えたこと
そこで、Pythonで動く小さなツールを作ることにした。ツールだってソフトウェアの1つではある。
私はソフトウェアエンジニアなので、AIを使わずに、自分でゼロから書くこともできる。PDFを扱うライブラリを探し、APIの呼び出しを書き、長文を分割し、結果を保存する。
技術的に特別難しいプログラムではない。
しかし、ライブラリの選定からコマンドラインの設計、エラー処理、READMEの作成まで行えば、それなりに時間がかかる。
自分用に、そんな手間はかけられない。開発予算はゼロなのだから。そこで、今回は、設計と判断は自分で行い、実装の多くをAIへ任せることにした。
最初のプロンプトでは、おおむね次のことを伝えた。
- 英文のPDFを投入すると、日本語訳を作ってくれるPythonツールが欲しい
- 意訳ではなく、原文に比較的忠実な訳にする
- 広告、ナビゲーション、ヘッダ、フッタ、脚注、参考文献などは訳さず、本文だけを対象にする
- 単に抽出したテキストを順番に訳すのではなく、すでに訳した部分との流れを考慮する
- 指定したフォルダ内のPDFを順次処理し、翻訳結果はMarkdownファイルとして保存する
ここで、実装方法をすべて指定したわけではない。
どのPDFライブラリを使うのか。ファイルをどのように列挙するのか。APIの再試行をどう実装するのか。そうした部分はAIに選ばせた。
一方、自分にとって重要な動作は明確にした。
入力はPDFである。
ひとつずつではなく、フォルダ単位で処理する。
本文だけを訳す。
原文の代わりに読む要約ではなく、原文と比較できる下訳を作る。
以前に訳した部分を文脈として使う。
結果は後で読みやすく、保存や編集もしやすいMarkdownにする。
AIへコードを頼むときに重要なのは、専門用語をたくさん並べることではない。
何を入力し、何を出力し、何をしてほしくないのかを明確にすることだった。
「本文だけ」は簡単ではない
PDFからテキストを取り出すと、必ずしも本文だけが得られるわけではない。
ウェブ上の教材をPDFにしたものには、サイト名、検索欄、前後の章へのリンク、共有ボタン、広告などが含まれる。
学術論文では、雑誌名やページ番号が各ページに繰り返し表示される。
文書の最後には、脚注、参考文献、画像のクレジット、ライセンス情報が並ぶ。
すべて翻訳すると、読みたい文章の途中に、「次の章」「この本を共有」「Creative Commons」といった文が混ざる。
そこで、ツールでは二段階で不要な要素を減らすことにした。
最初に、複数ページで繰り返される短い行、ページ番号だけの行、ダウンロード元を示す行などを、Pythonで機械的に除外する。
その後、翻訳を担当するAIにも、ナビゲーション、広告、脚注、参考文献、画像クレジットなどは出力しないよう指示する。
ルールだけですべてのPDF形式に対応しようとすれば、複雑な例外処理が増える。
すべてをAIへ送れば、明らかなノイズに対してもAPI料金と処理時間を使う。
機械が確実に判断できる部分はコードで除き、曖昧な部分はAIに判断させる。
AIに全部任せるのではなく、従来のプログラムとAIの役割を分けた。
長文を分けても、流れは切りたくない
長いPDFの全文を、一度のAPIリクエストへ入れるのは現実的ではない。
生成AIには受け入れられる文書の長さ制限がある。制限範囲内だとしても、長すぎる文章だと、前半の翻訳は正確だけれども、後半になるにつれて品質が低下してしまうこともある。
そこで文章を複数のチャンク、つまり処理しやすい大きさの塊へ分ける。
ただし、一定の文字数ごとに機械的に切ると、センテンスや段落の途中で分断される。そこで、できるだけ段落の境界で切り、ひとつの段落が長すぎる場合だけセンテンス単位で分割するようにした。
チャンクに分けると、別の問題が生まれる。
AIから見ると、それぞれのチャンクは別の翻訳依頼である。前のチャンクで「アメリカ」と訳した言葉が、次では「米国」になるかもしれない。代名詞が誰を指しているのか分からなくなることもある。
そこで、前までの日本語訳の末尾を、次の翻訳リクエストにも渡すことにした。
全文を毎回渡すと入力が大きくなるため、直前の一定範囲だけを文脈として渡す。そしてAIには、その部分を再出力せず、新しい原文だけを続きとして訳すよう指示する。
文脈を渡せば、長文翻訳の問題がすべて解決するわけではない。
それでも、何も渡さず、すべてのチャンクを独立に翻訳するよりは合理的である。
この段階で、AIへ伝えたプロンプトは、たとえば次のようなものだった。
英文のPDFを投入すると、日本語訳を作ってくれるツールが欲しい。
投入するPDFの例は添付のようなもの。
意訳はしないで逐語訳。
Claudeにお願いした時と同様に、本文だけを訳してほしい。
余計な広告とか注釈の翻訳は不要。
単にテキストを順次訳していくのではなく、
すでに訳した部分との流れを考慮して訳すようにしてほしい。
venv pythonで指定フォルダを順次処理。
出力は当該指定フォルダ内に jp-translations を作成して、その中に格納。
出力はテキストファイル(.md)がいい。最初のコードで完成ではなかった
AIが最初に作ったコードで、基本的な処理は動いた。
指定したフォルダからPDFを探す。テキストを抽出する。段落を考慮してチャンクに分ける。Claude APIへ送り、翻訳をMarkdownとして保存する。
しかし、コードが動いたことで、次の問題が見えるようになった。
できあがったツールは、ターミナルでAPIキーを設定する必要があった。毎回、ツールを使うたびに、そんな面倒なことはやっていられない。
そこで、環境設定ファイル.envにAPIキーを記録できるように指示した。
python-dotenv に対応してる?
ANTHROPIC_API_KEY=... を .env に書く予定。
.env に書いたAPIキーを自動で読み込めるようにしてほしい。いきなりフォルダ全体を処理するのは不安だった。
そこで、ひとつのPDFと出力先を指定して試せる単一ファイルモードを追加した。
テスト用に、1つのPDFを指定して翻訳できるモードも欲しい。
たとえば sample.pdf を指定して、
翻訳結果を result.md のような指定したファイルに出力できるようにしてほしい。
フォルダ一括モードとは別に、単一PDFの動作確認に使えるようにしたい。長いPDFを翻訳中にCtrl+Cで止めると、それまでの結果が失われる可能性があった。
そこで、チャンクがひとつ完成するたびにMarkdownを保存するようにした。
途中で終了したとき、つまり翻訳中にキーボードで Ctrl+C をした場合に、
その時点までの md を取得できるようにしたい。
1つめのチャンクの翻訳ができたら直ちに md を生成して、
それを順次上書きしていくようにするのはどうですか。この会話では、AIが賢さを発揮した。
単純にファイルへ上書きしている途中で処理が止まれば、出力ファイル自体が壊れる可能性があることをAIが指摘した。その対策として、いったん一時ファイルへ完全な内容を書き、書き込みが終わった後で正式なファイルと入れ替えるアトミック書き込みにした。
フォルダ一括処理を再実行したとき、すでに翻訳済みのPDFをもう一度処理する必要はない。
そこで、出力ファイルが存在する場合はスキップするようにした。
フォルダ一括モードを再実行した場合に、
あるPDFの出力ファイルが存在しない場合には、そのファイルのみを翻訳する。
出力ファイルが存在する場合には翻訳を行わない。
中断した後にフォルダ一括モードを再実行しても、
途中までの md ファイルが残っているので、そのままでは再実行されない。
中断した後に当該ファイルを削除して、再度フォルダ一括モードを実行すると、
そのPDFだけを翻訳するようにしたい。巨大なPDFが混ざっていると、予想以上のAPI料金が発生する。
そこで、初期設定では1ファイルにつき10チャンクまでしか処理しない安全弁も追加した。
制限が適用された場合は、ファイル名を次のようにする。
long-document.upto10chunk.mdさらに、翻訳文の末尾にも、全文ではないことと、制限を解除する方法を記録する。
このときのプロンプトは、次のようなものだった。
max_chunk を指定できるようにしたい。初期値は10。
チャンクが10以上になる巨大なファイルの場合は、
デフォルトでは10チャンクまで翻訳する。
max_chunk が適用になったファイルは、
ファイル名末尾を .upto10chunk.md のようにする。
また、翻訳文の末尾にも、
max_chunk が適用されたことと、max_chunk を解除する方法を書いてほしい。
解除方法は、当該ファイルを削除して、
大きな max_chunk を指定するか、
no_max_chunk を指定して再度実行する、という形にしたい。どれも、最初のプロンプトには書いていなかった。
実際に使う状況を想像するたびに、新しい問題が見つかった。その問題を、次のプロンプトでひとつずつ仕様へ変えた。
こうして、自分自身にとって使い勝手の良いツールができあがった。
完璧なプロンプトを書いたわけではない
生成AIの利用法は、「良いプロンプトを書く技術」として語られることが多い。
もちろん、指示を明確にすることは重要である。
しかし今回の経験では、最初から長く完璧なプロンプトを書くことより、動くものを見た後で、次の問題を正確に説明することの方が重要だった。
たとえば、
途中で止めても困らないようにして
だけでは、何を残し、次回どう扱うのかが曖昧である。
そこで、次のように具体化した。
Ctrl+Cで中断した場合でも、直前までの翻訳を取得したい。
ひとつのチャンクが完成するたびにMarkdownを保存する。
書き込み中の中断によってファイルが壊れないようにする。「API料金が心配」も、そのままでは実装できない。
そこで、次のように変えた。
1ファイルあたりの最大チャンク数を指定できるようにする。
初期値は10とする。
制限が適用されたことをファイル名と本文末尾の両方で分かるようにする。曖昧な不満を、外から確認できる動作へ変える。
これは、プロンプトの技巧というより、要件定義である。
これはバイブコーディングなのか
2025年2月、Andrej Karpathyは「vibe coding」と呼ぶ「新しい種類のコーディング」について投稿した。
大まかに言えば、vibe codingとは、人間が自然言語でAIに指示を出し、AIがコードを生成する開発スタイルを指す。しかし、Karpathyが最初に表現したものは、単に「AIを使ってコードを書くこと」ではなかった。彼の説明では、AIに多くを任せることで、開発者がコードそのものから少しずつ距離を取り、しまいには「コードの存在を忘れる」ほどになる、というかなり軽い開発態度が含まれていた。AP Newsもこの投稿を紹介し、AIコーディングツールがソフトウェア開発の仕事を変えつつある一方で、最終的な責任は依然としてエンジニア側に残ると説明している(Karpathy, 2025; O’Brien, 2025)。
その後の研究では、vibe codingはAIとの会話を通じた新しいプログラミングの形として扱われている。Sarkar and Drososは、vibe codingを、AIへの指示、生成されたコードの確認、実行、修正、必要に応じた手動介入を繰り返すプロセスとして整理している。また、Pimenovaらは、AIとの共同制作、会話、フロー、実験性、信頼といった側面を強調している(Sarkar & Drosos, 2025; Pimenova et al., 2025)。
私はこの翻訳ツールの開発に生成AIを使っている。
では、私もバイブコーディングをして、遅ればせながら流行に乗ったのだろうか。
少し違うと思う。
バイブコーディングという言葉には、次のようなニュアンスがある。
- 自然言語でAIにコード生成を依頼する
- 生成されたコードを十分に読まずに受け入れることがある
- エラーや不具合をAIに貼り付けて、追加修正を頼む
- 実装の詳細より、動いているかどうかを中心に判断する
- 試作品や使い捨てのプロジェクトでは、その軽さを楽しむ
今回、AIがコードの多くを書いたことは事実だ。
しかし、生成されたコードを理解しないまま受け入れたわけではない。
私は、AIに「PDF翻訳ツールを作って」と丸投げしたのではない。
日本語訳は英文の代替ではなく、英文を読むための地図であること。
本文だけを訳すこと。
意訳を避けること。
前の訳文を文脈として使うこと。
複数PDFをまとめて処理すること。
途中で止めても結果を失わないこと。
書き込み途中でファイルを壊さないこと。
完了済みファイルを再処理しないこと。
巨大なPDFによるAPI料金を制限すること。
複雑な途中再開機能をあえて実装しないこと。
こうした目的と制約を、自分で定義していった。
生成AIは、私の「バイブ」を感じ取って、いい感じに作ってくれたわけではない。
私が日常の不満を観察し、それを仕様へ変換し、AIが実装できる形で伝えた。
AIに任せたのは、主にコードを書く作業である。
何を作るか。
何を作らないか。
どの動作を安全とみなすか。
どの複雑さを許容するか。
どの結果を正しいと判断するか。
それらは人間側に残した。
だから、今回の開発は、流行語としてのバイブコーディングというより、AIを使って通常のソフトウェアエンジニアリングを加速したものに近い。
より正確に言えば、「仕様駆動のAI支援開発」だったと思う。
翻訳を作ったのではなく、翻訳を回せるようにした
完成したツールを簡単に示すと、次のようになる。
フォルダ内のPDFを探す
↓
PDFからテキストを抽出する
↓
繰り返されるヘッダやフッタを除く
↓
段落を考慮してチャンクに分ける
↓
直前までの訳文を文脈としてAIへ渡す
↓
本文だけを日本語へ訳す
↓
チャンクごとにMarkdownへ保存する
↓
次のPDFを処理する私が作りたかったのは、新しい翻訳モデルではない。
ClaudeやChatGPTには、もともと翻訳能力がある。
作ったのは、その能力を、自分の読み方に合った形で繰り返し使うための仕組みだった。
対話の中で毎回行っていた作業を、再実行可能な処理へ変えた。
そして、そのツールの価値は、翻訳部分だけにあるわけではない。
途中で止めても結果が残る。
翻訳済みのファイルは再処理しない。
巨大なPDFを誤って無制限に処理しない。
本文ではない部分をできるだけ減らす。
こうした地味な動作がそろって、初めて日常的に使える道具になった。
小さな不便を、自分専用の道具へ変える
完成したツールは、世界中の人が必要とする大きなサービスではない。
英語のPDFを頻繁に読み、先に日本語訳を眺めてから原文を読みたい私のための道具である。
以前なら、「自分で作るほどではない」と考えて、毎回PDFをアップロードし、「続きをお願いします」と入力し、翻訳をコピーしていたかもしれない。
今は、小さな不便を言葉にできれば、短時間で最初の試作品を作れる。
ただし、それは「何でもAIに一度頼めば完成する」という意味ではない。
不便を観察する。
具体的な動作へ分解する。
動くものを確認する。
不足を見つける。
次のプロンプトを書く。
その積み重ねによって、一般的なAIの能力が、自分の目的に合った道具へ変わる。
生成AIを使った開発で重要なのは、コードを書かせること自体ではない。
日常の不便を仕様へ変え、動くものを検証しながら、安心して使える道具へ育てることである。
AI翻訳もまた、英語を置き換えるためだけに使う必要はない。
英文を読む流れを支え、最終的に原文へ戻るための足場として設計できる。
私の場合、その出発点は単純だった。
知らない単語を調べるたびに、数センテンス前へ戻りたくなかった。
そして、AIに何度も「続きをお願いします」と入力したくなかった。
その二つの小さな不満から、毎日使えるツールができた。
References
Karpathy, A. [@karpathy]. (2025, February 2). There’s a new kind of coding I call “vibe coding”... [Post]. X. https://x.com/karpathy/status/1886192184808149383
O’Brien, M. (2025, September 29). AI is transforming how software engineers do their jobs. Just don’t call it ‘vibe-coding’. AP News. https://apnews.com/article/ai-vibe-coding-anthropic-assistants-09f35ccc7545ac92447a19565322f13d
Sarkar, A., & Drosos, I. (2025). Vibe coding: Programming through conversation with artificial intelligence. arXiv:2506.23253. https://arxiv.org/abs/2506.23253