LLMにコンテキストを効率よく渡すには?【前編】 〜大量のファイル群から欲しい部分だけ〜

はじめに

こんにちは、ARCHチームの野呂です。

本当は近所の美味しいラーメン屋についてのテック(?)ブログを書こうと思っていたのですが、社内で行われている「LTL会*1」というイベントで共有するために作ったスライドがあったので、先にそれをブログにしたためました。

近所の美味しいラーメン屋は永久に不滅*2ですが、LLMの話題は賞味期限が短いからです。
コーディングエージェントなどのLLMに効率よく追加の情報を渡すためのTipsと、そのための基礎知識について書いておりますので、興味あれば是非ご一読ください。

でも、近所の美味しいラーメン屋についても後で絶対に書きますからね。
たとえ上司や同僚の反対にあったとしても、この情熱は止められないので。


LLMについて

最近LLMがすごいですね。AIAIって、それはもう持て囃されています。

LLMなんて聞いたことないぜ!という方はあんまりいらっしゃらないかと思うのですが、LLMの仕組みを完全に理解している、という方もあまりいらっしゃらないかと思うので(僕もですが)、この記事を読むために必要な前提の部分だけ先に軽く解説したいと思います。
LLM完全に理解した各位につきましては、このセクションは*3読み飛ばしていただいてOKです。

LLMとは何か

まず、LLMは「ナチュラルボーン*4・連想ゲーム超上手い君」です。
基本的には、与えられたコンテキストから連想ゲームをして、続きを思いつくままに出力していく、という性質のやつです。

そのため、「AI」と聞いて思い浮かべるような、「思考」やら「意識」やらという高尚なものは持ち合わせていません。
人間も実は連想ゲームをやっているだけでは?という話もありますが、人間は「立ち止まって考える」「省みる」「問題の焦点っぽい部分を繰り返し思考する」ということができますが、LLMにはできません*5。ただ、反応として連想されたものを出力するだけです。

それを、各社の秘伝の技術によって「教育」し、「連想の中に嘘をできるだけ含めない」だとか「入力された文章の返事っぽいものを生成する」だとか「プログラミング言語で書かれたコードを出力する」だとかみたいな性質を後付けしています。
特に、人間からのフィードバックを使っていい感じに教育していく工程をRLHFと呼び、結構な時間とコストがかかっているようです。

LLMの追加学習

これまで機械学習では、ベースとなるモデルに後から特定の分野に特化したトレーニングを施すことで「モデルの特化」や「ユースケースの後付け」がよく行われていました。ファインチューニングとか呼ばれるやつです。

しかし、LLMは同じ機械学習でありながらRLHFの工程を必要としているため*6、ファインチューニングはあまり行われません*7

できなくもないのですが、少量のデータでもファインチューニングを行うとRLHFの効果が薄れ、再度RLHFを施す必要があります。
すると、コスト的に折り合わないことが多いため、大規模かつ固定された知識でしか用いられません*8

では、一般的にLLMにどうやって知識を追加しているかといえば、まずはご存知の通り「必要な情報をすべて入力として渡す」という力技が採用されがち*9です。
そのために「コンテキスト長(LLMに渡すことのできる文章の長さ)」はどんどん拡張され続けていて、今では本一冊丸々渡せるほどに大きくなっています。

「じゃあ、とりあえず手元にある知識を丸々渡しちゃえばOKじゃん!これで解決!」と思われがちですが、実はそうでもなく「情報の渡し方は工夫する必要がありますよ」というのがこの記事の趣旨です!

前置きが長いですね。

LLMに何でもかんでも情報を渡してしまうと何が問題なのか

再掲ですが、LLMは「連想ゲーム超上手い君」です。
そんな連想ゲーム狂四郎に「やってほしいこととは関係ない情報」を渡してしまうと、その関係ない情報に関しても連想ゲームを始めてしまいます。
連想ゲーム暴走機関車が一度違う方向に走り出すと悲惨で、大量に情報やらソースコードやらを気が済むまで吐き出します。

細かく人間がチェックできる状態であれば途中で気づいて止められますが、GitHub Actionsで実行しているであるとか、Devin的な何かに作業させて放置して開発しているとかになると、何も関係ない謎PRが上がってくることになります。
しかも「言われた通り作業しましたよ!」のていで出してくるので「あれ、なんか変な気がするけど、できたって言ってるし、なんかテストも通ってるっぽいしいいか」とかっつってマージすると大変なことになります*10

そのため、何となく世間で言われているよりも、LLMにタスク内で渡す情報はかなり気をつけて選別する必要があります。
プロンプトをいい感じに書けば良い、という話ではないのです。

LLMに効率よく必要な情報だけ渡すには

いきなりプラクティカルな話になって恐縮ですが、いつものやつ、自分いかせていただきます。

☆簡単4ステップ☆

  1. 情報の分割
  2. 情報の分類
  3. 情報の階層化
  4. indexの作成

1. 情報の分割

1ファイルに1万行の情報が書いてあると、特定の部分だけ読み取るのが難しいので、セクションごとだったり、情報の種類だったりで分割します。

2. 情報の分類

分割してN個になったファイルを、種類ごとにフォルダに分類します

3. 情報の階層化

フォルダに分類されたファイルを、さらに詳細度や依存関係によって分類します。

4. indexの作成

各フォルダのトップレベルに、子フォルダの要約を書きます

やってみる

  1. 分割
    分割のプロンプト
    これが
    分割結果

2.と3. 分類と階層化(もっとファイルが沢山できる時にはさらに階層を増やすのもあり)

こうなって

分類のプロンプト

.
├── 01_導入編
│   └── 01_はじめに.md
├── 02_基礎知識編
│   ├── 02_LLMについて.md
│   ├── 03_LLMとは何か.md
│   └── 04_LLMの追加学習.md
├── 03_実践手法編
│   ├── 05_LLMに何でもかんでも情報を渡すと何が問題なのか.md
│   ├── 06_LLMに効率よく必要な情報だけ渡すには.md
│   └── 07_情報整理の4ステップ詳細.md
└── 04_発展応用編
    ├── 08_より良い方法とニーリーでの運用.md
    ├── 09_後編_はじめにと今北産業.md
    └── 10_内緒.md
  1. index作成 こう
    index作成のプロンプト
.
├── 01_導入編
│   ├── 01_はじめに.md
│   └── index.md
├── 02_基礎知識編
│   ├── 02_LLMについて.md
│   ├── 03_LLMとは何か.md
│   ├── 04_LLMの追加学習.md
│   └── index.md
├── 03_実践手法編
│   ├── 05_LLMに何でもかんでも情報を渡すと何が問題なのか.md
│   ├── 06_LLMに効率よく必要な情報だけ渡すには.md
│   ├── 07_情報整理の4ステップ詳細.md
│   └── index.md
└── 04_発展応用編
    ├── 08_より良い方法とニーリーでの運用.md
    ├── 09_後編_はじめにと今北産業.md
    ├── 10_内緒.md
    └── index.md

そんで最後にこう

indexのindex作成のプロンプト

.
├── 01_導入編
│   ├── 01_はじめに.md
│   └── index.md
├── 02_基礎知識編
│   ├── 02_LLMについて.md
│   ├── 03_LLMとは何か.md
│   ├── 04_LLMの追加学習.md
│   └── index.md
├── 03_実践手法編
│   ├── 05_LLMに何でもかんでも情報を渡すと何が問題なのか.md
│   ├── 06_LLMに効率よく必要な情報だけ渡すには.md
│   ├── 07_情報整理の4ステップ詳細.md
│   └── index.md
├── 04_発展応用編
│   ├── 08_より良い方法とニーリーでの運用.md
│   ├── 09_後編_はじめにと今北産業.md
│   ├── 10_内緒.md
│   └── index.md
└── index.md

こうすることで、LLMはindexファイルを読み、関連がありそうなフォルダの下にあるindexファイルを読み、さらに関連のありそうなフォルダの下の…と、辿ることで、コンテキストに最小限の情報を乗せるのみで欲しい情報に辿り着くことができるようになります。

実際にindexを頼りにファイルを特定してもらいました。

実践編

実際、この方法は階層を増やすことでもっと量の多いナレッジに対応することもできますし、常套句ですが「人間にも優しい」です。
別にLLMのためでなくても、ちょっとナレッジが便利になりますね。

より良い方法とニーリーでの運用

ここまでで紹介した方法は、そのコンテキストが短期間、特定の目的でのみ使われる場合に適しています。
今回の例ではは特に要約の方針は指示していませんが、何のためのindexか?を意識するとより使いやすくなるでしょう。

しかし、大勢が変更するナレッジの場合、indexがすぐに陳腐化してしまう懸念があります。
また、要約は情報を圧縮する行為であるため、とある目的ためには適した要約でも、別の目的のためには必要な情報が欠損した状態になることも考えられます。

逆に、1人で利用するナレッジの場合は上記の方法で十分です。

では、複数人で使用する汎用的なナレッジ…例えば、業務領域のドメイン知識や、ビジネスルールのドキュメントなどはどのように管理するのが良いでしょうか?

以下のような特徴があると良さそうです

  • 大勢で同時に編集できる
  • 文字列ではなく、意味的な検索ができる
  • 検索のためのindexが自動的に作り直される

そんな都合の良いもの、あります? 🤔

…長くなってきたので、後半へ続きます!

前半のまとめ

  • LLMは連想ゲームの結果を出力してくるよ!
  • LLMは追加情報をプロンプトと一緒に渡すことで、学習していないデータを使うことができるよ!
  • 追加情報に余計なものが混ざると連想ゲームの結果も混ざっておかしなことになりがちだよ!
  • だから多段で要約したindexを作って、必要のない情報を最小限に抑えよう!

*1:LTのタイポではなく、Lightning Tips Liveという会です

*2:実際にはそんなことはないので、行けるうちに行っておこう!

*3:というかこの記事自体

*4:LLMは、マルコフ連鎖 -> Sec2Secの流れで、文章の続きを予測する精度を上げる過程で生まれてきたはず

*5:各社の弛まぬ努力により、複数のLLMを協調させることで似たようなことはできつつあるようです

*6:理由はそれだけでもないようです

*7:最近強化学習の手法を使ったファインチューニングが盛り上がりを見せているようではあります

*8:強化学習の手法を使っていてもやはりコストが高いという点は変わりません。今のところ。

*9:追加学習なしでデータを追加できるのは他の機械学習手法にはないLLMの特徴とも言えます。お手軽。

*10:別にLLMに限らずなんでもそうですが…