- Trussはこの6か月、LLM中心の機能を運用しながらOpenAIモデルで5億トークン超を処理し、B2Bのテキスト要約・分析・抽出で実際に直面した限界を整理した
- プロンプトは詳細な指示を多く入れるほど安定するわけではなく、GPTがすでに知っている常識については短くて具体性の低い指示のほうが良い結果になる場合があった
- Langchain、JSON mode、function calling、assistantsなしでも、
chat APIとJSON抽出用の関数ひとつで複数機能を運用でき、中核コードは40行の関数とエラー処理・自動切り詰め程度だった
- GPTは「なければ空の値を返す」といった**帰無仮説(null hypothesis)**の扱いと長い出力に弱く、GPT-4の128k入力ウィンドウとは別に出力は4k程度にとどまる
- RAGとベクトルDBは、Trussの限定的なテキスト抽出業務にはあまり適しておらず、全文脈を入れる分析・要約・抽出は信頼性が高い一方、入力が空だったり関連情報がないときに問題が大きくなる
適用範囲と前提
- Trussはこの6か月でLLM中心の機能をいくつかリリースし、利用量は推定で5億トークンを少し超える
- 使用モデルはOpenAI系で、トークン使用量はGPT-4 85%、GPT-3.5 15%
- 扱うデータはテキストのみで、
gpt-4-vision、Sora、Whisperのような非テキスト機能は含まない
- プロダクトの文脈はB2Bで、主な作業は要約・分析・抽出
- 5億トークンは約75万ページ分のテキストに相当する
プロンプトは具体的すぎないほうが良くなることがある
- GPTがすでに知っている一般知識について、正確なリストや指示を過剰に入れると、かえって結果が悪くなることがあった
- あるパイプラインでは、テキストブロックが米国50州または連邦政府のどこに関連するかを分類する必要があった
- 初期プロンプトでは、
locality_idフィールドに50州とfederalのID一覧をJSON形式で入れ、その中から選ばせていた
- この方法はおおむね98%以上は機能したが、失敗も十分多く、追加調査が必要だった
- 別のフィールドである
nameは明示的に要求していなかったのに、正しい州の正式名称を安定して返していた
- その後、
nameに出てきた文字列を検索して州を見つける方式に変えるとうまく動いた
- より良いアプローチは、「50州を知っているはずなので、その州の正式名称またはFederalを返せ」のように常識に任せるプロンプトだった
- 追加の観察もあった
- 失敗はMaryland、Maine、Massachusetts、MichiganのようなMで始まる州でより頻繁に現れた
- IDを一覧から選ばせる際は、各州を1行ずつ並べた見やすいJSONのほうが、カンマでつながった一覧より混乱が少なかった
APIと抽象化はシンプルなままだった
- Langchainはこのケースでは性急な抽象化に近く、数百万トークンと3〜4種類の本番機能を経た後でも、
openai_serviceファイルには40行の関数が1つ残るだけだった
- 実際に使ったAPIは
chatだけ
- 常にJSONを抽出していた
- JSON mode、function calling、assistantsは不要だった
- system promptも使わなかった
gpt-4-turboがリリースされたときも、コードベース内の文字列を1つ変えるだけだった
- 関数の大半は、OpenAI APIの500エラーやソケット切断のようなエラー処理を担っていた
- こうしたエラーは改善されており、OpenAIの負荷を考えれば驚くことではないとしている
- コンテキスト長の制限は独自の自動切り詰めで対処した
- 文字列長が
model_context_size * 3より大きければ切り詰める
- ピリオドや数字が極端に多いと、トークン比率が「3文字で1トークン」より小さくなって失敗することがある
context_length_exceededが出たら、model_context_size * 3 / 1.3を基準に再度切り詰めてリトライする
ストリーミングUXの価値は過小評価しにくい
- ストリーミングAPIで待ち時間を減らし、ユーザーに可変速度で入力される文字を見せる方式は、最初はおもちゃのようにも見えた
- 実際のユーザーは、この可変速度の「タイピング」表示を非常に好意的に受け取った
- この体験は、AIにおけるマウスやカーソルUXに相当する瞬間のように感じられた
空の結果と長い出力は弱点
- 「見つからなければ空の出力を返す」は、最もエラーが多かったプロンプト文言に近かった
- 実際には何も出力しないという意味ではなく、
{value: ""}のような空値表現を返させていた
- 問題は出力制限の失敗というより、帰無仮説の判定そのものの難しさに近かった
- GPTは空値を返すべき場面で幻覚を選ぶことがあり、逆に自信を失って空値を返しすぎることもあった
- テキストブロックが空になりうるバグがあったときは、幻覚がひどく発生した
- 例として、Sunshine Bakery、Golden Grain Bakery、Bliss Bakeryのような架空のベーカリー名が出てきた
- 解決策は、テキストがなければプロンプト自体を送らないことだった
- GPT-4は入力については128kトークンのウィンドウを持てるが、出力ウィンドウは依然として4k程度にとどまる
- 「context window」という表現は、入力と出力を混同させやすい
- JSONオブジェクトのリストを返させる場合、単純なオブジェクトでも10件を超えるのは難しかった
- 15件を要求すると、成功率はおよそ**15%**程度と推定している
- 10件程度で止まるときでも、出力は700〜800トークンにすぎなかった
- 1回に1件ずつ要求し、前の結果を再投入する形で出力限界を回避することはできるが、GPTと伝言ゲームをするような形になり、Langchainのような道具を扱うことになる
RAGとベクトルDBはこのユースケースに向いていない
- ベクトルDBとRAG/埋め込みは、Trussのケースではほとんど役に立たなかった
- ベクトルDBとRAGは、検索、それもGoogleやBingのような本物の検索により適していると見ている
- 中核の問題は関連性の基準にある
- 関連性に明確なカットオフがない
- Cohereのrerankのような解決策や独自ヒューリスティックはあり得るが、安定しない
- 無関係な結果で検索結果が汚染されたり、保守的すぎて重要な結果を取りこぼすリスクがある
- ベクトルを一般データから切り離された専門的・独自のDBに保存することにも損失がある
- GoogleやBingの規模でない限り、文脈損失というトレードオフを正当化しにくいと見ている
- ビジネスアプリ内の検索では、ユーザーがドメイン専門家であることが多い
- ユーザーが直接入力していない意味まで推測して返す意味検索は好まれないと考えている
- 多くの検索ユースケースでは、LLMを通常のcompletion promptとして使い、ユーザーの検索語をfaceted search、複雑なクエリ、SQLへ変換するほうが良い場合がある
文脈が十分あれば幻覚は大きく減る
- Trussのユースケースの多くは、「テキストブロックを渡して、そこから何かを抽出する」という形だった
- テキストに書かれた会社名を求めると、GPTは通常、適当な会社を返さない
- ただし、テキストに会社が存在しないときは、帰無仮説の問題が再び現れる
- コードでも、渡したコードブロックを書き直す途中で変数をでっち上げたり、途中に任意のタイプミスを混ぜたりする意味での幻覚は起こしにくい
- ただし、何かを作らせると標準ライブラリ関数の存在をでっち上げることはある
- これも結局は「わからない」と言えない問題に近いとしている
- 全文脈を与えて分析・要約・抽出させる作業では非常に信頼できた
- 良いデータを入れれば、良いGPTトークン応答が返ってくる構図に近い
今後の見通しについての判断
- 現在のtransformer、インターネット上のデータ、数十億ドル規模のインフラへのアクセスだけではAGIには到達しないと見ている
- GPT-4はマーケティングではなく100%有用な技術であり、まだインターネット初期に近い段階だと考えている
- すべての人を解雇するような技術ではない
- 以前はGoogleだけがアクセスできたML/AIの参入障壁を下げる効果が大きい
- ClaudeやGeminiなどについては、厳密なA/Bテストはしていない
- 日常的なコーディングで試した限りでは、意図を直感する微妙な部分でGPT-4にまだ近くないと感じている
- LLM/AIの流れをすべて追う必要はないと見ている
- The Bitter Lessonに照らし、汎用モデルの性能向上が特化改善より重要なら、GPT-5が出るかどうかだけ気にすればよいという判断だ
- Soraのような別領域を除けば、OpenAIの中間リリースの多くはほぼノイズだと見ている
- GPT-5はすべてを変えるというより、漸進的改善になる可能性が高い
- GPT-3からGPT-3.5へ進むときは、学習強度を2倍にすれば性能が2.2倍良くなるような超線形の改善を期待していた
- 実際には対数的な改善に見え、漸進的な向上のためにトークン速度とトークン単価が幾何級数的に増えていく状況だと見ている
- GPT-4は現在の作業セットでは最適点かもしれない
- GPT-3.5比でGPT-4に20倍のコストを払う意思はあったが、GPT-4からGPT-5に進むためにトークン単価で20倍払うことはなさそうだとしている
- GPT-5がこれを覆すかもしれないし、iPhone 4からiPhone 5に進む程度かもしれない
1件のコメント
Hacker News のコメント
私のチームは毎月 50億+ トークンを処理していて、さらに増え続けているのですが、いくつか学んだことがあります
第一に、早すぎる抽象化が多すぎます。Langchain のようなツールはいずれ役に立つかもしれませんが、結局プロンプトは API 呼び出しにすぎず、LLM 呼び出しを特別扱いするよりも、不安定な API 呼び出しとして標準的なコードで扱うほうが簡単です
第二に、ハルシネーションは間違いなく大きな問題です。要約はテスト上かなり堅牢ですが、推論は本当に難しく、ユーザー入力を受けて次の行動を LLM に決めさせる行動モデルは、とくに文脈理解と「確信がない」と言わせる部分が難しいです。それでも、これができるという事実自体はゲームチェンジャーです
第三に、筆者よりは少し「ゲームチェンジャーだ」という側に近いですが、世界が終わるとは思いません。一部の職業は大きな影響を受け、ボットがプラットフォーム上で世論操作をする厳しい数年が来るかもしれません。全体としては、インターネットのようなブレークスルーというより、能力増幅器に近いように見えます
個人的には 2000年代の DevOps の変化に似ています。もはやデプロイを支援する巨大な専任チームは必要なく、少数の専門家を雇い、大半は既製のソリューションを購入します。同様に、一部の機械学習タスクは私のような Web 開発者でも簡単に実装できるようになりました
DevOps の進化にもトレードオフはありました。たとえば「AWS RDS を使えばいい」の直接的な結果として、データベース管理のような中核的な能力が失われ、クラウド請求額も急増しました。特にデータ規模や地域的な複雑さが大きくないスタートアップの運用費も増えましたし、こうした流れが GitLab の大規模障害に似た事故にもつながったのだと思います
コインの表裏を当てろと言われて「表」と答える場合、答える前なら Pr[表] = .5 のような不確実性を語れますが、実際の予測とコイン投げの結果ではその不確実性が消えるのと似ています。LLM もトークンの最終予測では計算中の不確実性が消えるため、予測そのものが不確実性の表現でない限り、「理解できなかった」という出力はほとんど出てこないでしょう。ただし、その理由はそもそも理解しておらず予測しているからです
基本的に私たちは GPT を、AI 運用における PaaS/Heroku/Render のような等価物として使っているのだと思います
「私たちは常に JSON を抽出している。JSON モードは必要ない」という部分が気になります。私の場合はかなりうまく動きました
「Lesson 4: GPT は帰無仮説を作るのが本当に苦手だ」という話には本当に共感します。昨日もテキスト修正ルールのプロンプトをテストしていて、最後に「どのルールもテキストに適用されない場合は、原文を変更せず返せ」と書きました
ルールがひとつも適用されないテキストに対して ChatGPT が何と答えたか分かりますか?「The original text without any changes」という文字列そのままでした
以前、タロットカード用に美しい庭でワインを飲む3人の女性の画像を作っていたとき、プロンプトの最後に「lush vegetation」を入れたところ、その中の lush の多義性のせいで、優雅な雰囲気から赤い鼻をしたパーティ好きの女子大生のような感じに変わってしまったことがあります
より良いプロンプトを書けば、より安いモデルを使えます
「何も見つからなければ何も返すな」は、LLM に逃げ道を与えるレベル0のやり方です。もっと穏やかな逃げ道を与えるほうがよいです。たとえば「断定的な記述をするのに十分な情報がない場合は、そのようにしていることを明確に述べ、仮説の根拠と論理的基盤を書く限り、仮説を立ててもよい」のように書き、最後に自分の回答を評価させればよいのです
自動化された方法がないなら、さまざまな入力に対するモデルの反応を繰り返しテストし、リクエストをどのように解釈するのか、どこで失敗するのかを理解して、その穴を埋める必要があります。モデルが nothing の意味を知っているかどうかすら検証すべきです
LLM分野の上位3サービスすべてに加入して、同じプロンプトをよく投げているが、GPT-4側が非常に一方的に有利。GPT-4が出てから1年経っていて、その間に何度かアップデートがあったことを考えても驚き
少なくとも自分の利用パターンでは、幻覚も少ないほう。一方でClaudeはコードを書くとき、存在しないもっともらしいAPIをかなり簡単にでっち上げる。GPT-4は自分が正しいと分かっているとき、より頑固で、あまり迎合しない。こうした違いは指標にはほとんど表れないので、個人的に使ってみないと見えてこない
コーディング作業でも、コードを書かせるというより、トピックやコードの説明を求めるのだが、ずっとニュアンスのある答えを返す傾向がある。長いテキストを渡して会話すると、Claude Opusのほうが内容をより深く理解している感じがあり、GPT-4が与えられたテキストの要約にとどまりがちなのに対し、Claudeはよりうまく拡張して推論する
ただし、よく構成されたプロンプトでは Claude Opus のほうがGPT-4より良い出力を出す傾向がある。Claudeはより柔軟で長い回答を提供する一方、ChatGPT/GPT-4はいつも独特の短く「典型的な」回答に聞こえがち
依頼したコード例で、GPT-4が作ったコードはコンパイルすら通らないことが多かったが、Claudeではほとんどそういうことがなかった
最近使っているリトマス試験は「Austinから200マイル以内にある変わったバーを10軒教えて」だ。これはどれにとっても非常に難しく、GPT-4はそこそこ近かったが、Claudeはただ作り上げ、Geminiは完全に崩壊した
GPTはとても素晴らしいが、記事の2段落の解釈には強く同意しない
「GPTよ、君は50州を明らかに知っているのだから、これが該当する州の正式名称を返すか、米国政府に該当するならFederalと答えよ」というようなやり方のほうが良いアプローチだった、という要約はできる
しかし、より曖昧に言ったときにGPTの品質と汎化が良くなることを、高次の委任/思考の典型的な兆候だと解釈するのは行き過ぎだと思う。自然言語はGPTにとって最も確率の高い出力だ。学習したテキストに似ているからだ。この場合、開発者はGPTが得意な方向により寄せただけで、より多くの仕事をさせたわけではない
GPTを失敗させる単純作業は多い。文字置換や意図的な誤字のような作業はGPTには非常に難しい。IDマッピングのようなものも同様で、特に学習中に見たマッピングと大きく異なる場合はなおさらだ。たとえばISOではない国コードのような、似た3文字コードがそうだ
興味深いのは、GPTがマッピングを「理解」するという事実そのものだ。むしろそれこそが 高次元パターンマッチング の実際の手がかりだと思う
「null」問題へのヒント:LLMはトークンを出力するように作られているのであって、トークンを出力しないように作られているわけではない
だから「何も返すな」ではなく、結果がないときは「XYZのデフォルト値を返せ」として、州名を検索するように結果からそのデフォルト値、たとえばXYZをテキスト検索すればよい
また システムプロンプト は非常に有用な場合がある。基本的にはLLMにXのロールプレイをさせる機会だ。システムプロンプトを直接渡せるようにしてくれるとよいが、それでもないよりはまし
GPTがJSONオブジェクトのリストを10個超えてまともに返せないというのは プロンプトの問題 だ。私は正しい順序で最大200個まで安定して返させたことがある
コツはリストを一切使わず、出力で
"item1": {...}のようなJSONキーを使うこと。ある入力に対して0〜n個の出力がある場合は、値としてリストを使えるGPT-4に定義済みの構造を持つ既存項目のリストを渡し、スキーマ変換のような形でJSONに変換させると、一日中でもうまくやってくれる。だが何らかの推論が必要で、実質的に自分でリストを作らなければならない場合は、非常に限定された部分集合しか返さない
他のLLMでも似た問題がある。どうアプローチしているのか非常に気になる
「テキストブロックから会社名を抽出せよ」のような作業は 2段階 に分ければよい
まず「このテキストブロックに会社は言及されているか?」と尋ね、そうでなければnull結果を得たことになる。そうなら「このテキストブロックにある会社名を列挙せよ」とすればよい
個人用の執筆アプリでOpenAIモデルを使っているが、この記事は本当に的確だ。「プロンプトは少ないほどよい」というLesson 1に関して学んだことがある
ノートに対するインテリジェント検索機能を作りながら、ChatGPTに構造化されたJSONデータを返させようとした。たとえば「過去2年以内にHaskellに言及し、下書きとしてマークされた私のノートをすべて出して」と尋ね、ChatGPTに何を返すべきか判断させようとした。これはたまにしか動かなかった
代わりにデータを SQLite データベースに入れ、ChatGPTにスキーマを送ったうえで、欲しい結果を返すクエリを書かせると、ずっとよく動いた
response_format=json_objectを試したことがあるか気になる構造化された応答を得るには関数呼び出しのほうが合っていたが、単にJSON本文を受け取るより制約は多い
あまり正確に指示すると精度が下がる例は、こうしたシステムが動作する仕組みに対する私の粗い理解では筋が通る
州の一覧全体を入れると、すべての州に関するベクトルをある程度活性化することになる。単に「state」と言い、渡したテキストに明示的な州があれば、探している対象に関係するベクトルの活性化は少なくなる。だから ソフトマックス を行うときに、正しい州が選ばれる可能性が高くなる
同じ文脈で、
/nとカンマの比較も、おそらく トークン化の違い が原因である可能性が高い