アプリ開発者のための生成AI(LLM)ユースケース集

本記事は日本オラクルが運営する下記Meetupで発表予定の内容になります。発表までに今後、内容は予告なく変更される可能性があることをあらかじめご了承ください。



https://oracle-code-tokyo-dev.connpass.com/event/325752/

※ミートアップ実施時の動画は↓こちら。

<iframe width="560" height="315" src="https://www.youtube.com/embed/XQCKTrnxO88?si=o7FeZB6h_no65YbO" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>



# 本記事で紹介するユースケース
本記事では、知っておくと便利なLLM関連の実装サンプルやtipsをまとめてご紹介してゆきます。各技術の概要や仕組み、実装コードの概説などです。実装コードの説明は長くなりますので別記事へのリンクをはっています。詳細を知りたい方は是非そちらの記事もご参照ください。既に有名なものから比較的新しい技術まで今後も更新してゆきますのでよろしくお願いいたします。


| ユースケース                          | 説明                                                                                      |
|-------------------------------|-------------------------------------------------------------------------------------------|
| [**Function Calling (Tool Calling)**](#function-calling-tool-calling)             | LLMからユーザー定義関数をCallするOpenAI社の機能。アプリケーションの処理を大幅に拡張する仕組みです。                                      |
| [**MCP (Model Context Protocol)**](https://qiita.com/ksonoda/items/1c681a563a95a93975ff)             | Function Calling同様、LLMアプリケーションの処理を大幅に拡張する仕組みですが、こちらは業界標準のプロトコルとして策定されています。                                      |
| [**SQLデータベースの分析**](#自然言語によるsqlデータベースの分析) | SQLではなく、自然言語によりSQLデータベースを分析する手法です。|
| [**社内データ活用のためのRAG**](https://qiita.com/ksonoda/items/ba6d7b913fc744db3d79)   | ベクトルデータベースとの組み合わせによりLLMの知識を大幅に拡張する手法です。 |
| [**マルチモーダルRAG**](https://qiita.com/ksonoda/items/28586434904c26ec465b)   | テキストデータだけでなく画像データも扱えるRAGを構築する手法です。 |
| [**GraphRAG**](#graphrag)   | RAGの精度をグラフデータベースのグラフ検索により向上させる手法です。 |
| [**マルチエージェントRAG**](#マルチエージェントrag)         | 複数のエージェントに個別の役割を割り当て、協業させながら応答を生成する手法です。より精度が高く、複雑なRAGを構成できます。|
| [**AIエージェント**](https://qiita.com/ksonoda/items/08bdfadfb760043f2183)         | 複数のエージェントに個別の役割を割り当て、協業させながら複雑なタスクを高精度で実行できるようにします。|
| [**ファインチューニング**](https://qiita.com/ksonoda/items/b9fd3e709aeae79629ff)         | LLMプロバイダーが提供する学習済モデルに対して、ユーザーデータを使って追加の学習を行うことによりLLMに新たな知識を追加する処理です。|
| [**プライベートLLM(ローカルLLM)**](#プライベートllmローカルllm) | クラウドサービスのLLMではなく、ローカルにモデルをダウロードして利用する手法です。          |
| [**LLMの量子化**](#llmの量子化)                   | LLMをコンパクトに圧縮し、GPUメモリなどのリソースを節約する手法です。                      |




# Function Calling (Tool Calling)

質問内容からLLMが事前定義済みの「関数(function(tool)」を呼び出して、必要な情報を取得し、その結果を応答テキストに盛り込むことができるようにする機能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/808201d0-23e3-3661-0192-011006d705b0.png)

例えば、プロンプトの内容から必要に応じて下記のような処理を実行し、その結果を応答テキストに反映することが可能になります。

- googlesearchを実行し応答テキスト生成に必要な情報を検索
- ニュースサイトサイトの最新情報を検索
- twitterで今現在話題になっている情報を検索
- データベースやCRMなど業務システムからの情報取得

LLMを使ったアプリケーションを大幅に拡張できる非常に有用な機能なのでアップデートも頻繁にあり現在はTool Calling(Function Callingの上位互換)という名前になっていますが、現在のところ基本的にできることはFunction Callingと変わりません。

Function Callingを使うことで、必要に応じて世の中にある様々なサービスにアクセスして情報を取得することにより、最新で具体的かつ正確な応答テキストを生成できるようになります。


#### Function Callingの仕組み

天気情報を提供しているサイト[OpenWeather](https://openweathermap.org/)に現在の天気情報を確認するfunction(tool)を定義しておけば、ユーザーから「今日の東京は？」というプロンプトが入力された際に、このfunction(tool)で今現在の天気情報を確認し、その結果からテキスト生成を行うことができるようになります。

その際のFunction Callingの処理シーケンス概要は下図のようなものになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/9c966209-9b6e-2165-6749-741357990c90.png)

ユーザーアプリ側にtoolを定義しますが、これは一つでも複数でも構いません。上図は複数のtool(get_news_info、get_weather_infoなど複数のtoolが既に定義されている状態です。(上図左上の「Function(Tool)の定義」というところです。この状態からプロンプトを入力した場合の処理シーケンスは下記のようなものになります。


1. プロンプトを入力すると、プロンプトだけでなく定義しているtoolの内容がLLMに渡されます。

2. プロンプトの内容から、toolが必要なのか、不要なのか、必要な場合はどのtoolを使うのか、複数のツールを使う場合はどの順序で使うのかなどが決められます(推論されます)。

3. 使うtoolが決まったのち、そのtool、つまり関数の引数の値を決め、実行する関数を完成させます。

4. 完成した関数(ここではget_weather_info(tokyo))を実行します。これはLLMの仕事ではなくユーザーアプリ側で実行されます。

5. この例の想定ではget_weather_info(tokyo)により、天気情報を提供するサイトOpenWeather.orgが公開するAPIをCallし東京の天気情報を取得します。

6. 取得した天気情報と、元のプロンプトをLLMに入力します。

7. 最終的な応答テキストが生成されます。

特に、function(tool)の処理を実行しているのはあくまでもユーザーアプリ側であり、なんでもLLMで処理しているのではないという点に注意したいですね。

あくまでも、ユーザーアプリとLLMとの連携で処理をこなしていくというイメージです。

#### ユースケース
Function Callingは応用範囲が広く、これにより様々な処理を加えた業務アプリケーションを開発することができるようになります。例示を絞ることはできませんが一例として下記のようなものが挙げられます。特にLLM外部の業務アプリやサービスとの連携が必要になるユースケースは全てが適用対象だと言っていいと思います。


| ユースケース              | 説明                                                                                 |
|-----------------------------|-------------------------------------------------------------------------------------------|
| カスタマーサポートの自動化 | カスタマーサポートチャットボットが、ユーザーの問い合わせに応じてデータベースから情報を取得。顧客満足度の向上と迅速な対応が可能。|
| 営業支援ツール            | 営業担当者が顧客情報を即座に取得するためにCRMシステムに関数呼び出しを行う。効果的な顧客対応と営業プロセスの効率化を実現。|
| 顧客フィードバックの分析  | 顧客からのフィードバックを自動的に処理し、トレンドや感情分析を実施。サービスや製品の改善点を迅速に特定できる。|
| 動的なレポート生成        | 売上データやパフォーマンス指標をリアルタイムで取得し、レポートを生成。即時レポート生成により迅速な意思決定をサポート。|
| 動的な在庫管理            | 在庫状況をリアルタイムで監視し、自動的に再発注を行う。 在庫切れの防止と在庫管理の効率化、販売機会の損失の最小化に貢献。|

#### サンプルコードの概説

サンプルコードの概説はこちらの記事をご参照ください。

https://qiita.com/ksonoda/items/1ba3916c9ee9f4d9c10c







# 自然言語によるSQLデータベースの分析

一般的に、データベースの分析はSQLで分析処理を実行したり、BIツールでその処理を行ったりします。が、それらに関する深い技術的知識がなくても、LLMを利用し、自然言語で質問を入力するだけでデータ分析が可能になるユースケースです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/9f7a37f4-e816-8675-d1fc-4e8635ca89eb.png)



#### 仕組み
基本的な仕組みとしては下記のようになりいたってシンプルです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/f60918d4-33a3-4d57-bdba-a3f59a2ae75b.png)



①ユーザーからの質問をLLMに入力
②LLMが質問をSQLに変換
③変換されたSQLでデータベースにクエリを実行
④クエリ結果と質問文をLLMに入力し回答を生成

という流れで処理が進むようなコードを実装します。予想通りという感じではないでしょうか。とは言えこれをスクラッチで実装すると実は意外と面倒なことになります。そこでLangChain(のSQL Database Agent)の登場です。LangChainがバックエンドで自動的に処理してくれる内容も含めてサンプルコードを概説します。


#### ユースケース
DBの分析に関連するアプリケーションは全てユースケースの対象となります。例えば以下のようなアプリケーションです。

| ユースケース                        | 説明                                                                                   |
|-------------------------------------|----------------------------------------------------------------------------------------|
| 営業レポートの自動生成              | 営業部門の方々が自然言語で質問し、リアルタイムで営業レポートを生成。迅速な意思決定が可能に。       |
| マーケティングキャンペーンの効果測定| キャンペーンの効果を自然言語で分析し、ROI評価や次の戦略調整に役立てる。                     |
| 人事分析                            | 自然言語で退職率などを分析し、社員満足度やエンゲージメント向上のインサイトを得る。          |
| 財務分析と予算管理                  | 自然言語で経費データを集計し、予算管理や支出計画の迅速な把握をサポート。                      |
| 在庫管理の最適化                    | 自然言語で在庫データを分析し、適時の補充や在庫管理の最適化を実現。                            |


#### サンプルコードの概説

サンプルコードの概説はこちらの記事をご参照ください。

https://qiita.com/ksonoda/items/9a40c1017613d3ccf1e0






# GraphRAG
[以前の記事：【ChatGPT】とベクトルデータベースによる企業内データの活用(いわゆるRAG構成)](https://qiita.com/ksonoda/items/ba6d7b913fc744db3d79)ではベクトルデータベースを利用したRAGの実装をご紹介しました。ただ、ベクトルデータベースの類似検索だけでは目的のチャンクテキストをうまく抽出することができず、結果として効果的な応答テキストが生成できないことが多々発生します。

現在、RAGを実データで構築する際に誰しもが必ずぶつかると言っていいほど最もメジャーな壁だと言えます。LLM周辺では最も研究が盛んな技術分野であり、毎月のように新しい論文が提出されていますが、その中でも比較的新しいソリューションがGraphRAGです。

RAGの精度を向上させるアプローチとして、「非構造化データ(テキストデータ)の類似検索だけでなく、構造化データ(テキストデータ内のメタデータやその他の外部データなどの検索)を併用する方法が効果的なはず」という仮説はLLMが流行りだした当初から一般に認知されていました。

ベクトルデータベースでは主にベクトル検索と全文検索という二種類の検索手法、つまり非構造化データのみの検索となります。GraphRAGではここにさらにグラフ検索(これが上述の構造化データの検索に相当)を追加することにより、より精度の高いコンテキストからLLMがテキスト生成を実行できるようになります。

要は今現在、RAGといえば、ベクトルデータベースを使う手法が一般的ですが、そのデータベースをグラフデータベースに置き換えたRAGがGraphRAGということになります。

#### グラフとは？
グラフとは主にノードとエッジから構成されるデータモデルです。ノードは具体的なもの（例えば、人、場所、製品、イベントなど）や抽象的な概念（例えば、アイデア、カテゴリ、トピックなど）を定義し、エッジはノード間の関係性を表します。例えばノードにSNSのアカウントユーザーを定義した場合、エッジは人とユーザー同士の関係性、ということでフォローしている、されているという情報を定義することになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/e2e5ed5a-7a51-8424-d937-21e8e5e19137.png)

このグラフ技術は、RDBでは表現できない複雑なデータのスキーマ構造を定義しなければいけない技術領域で古くからグラフデータベースとして利用されてきました。MetaやLinkedInなどのソーシャルメディアプラットフォームでは、ユーザー間の友人関係やフォロワー関係のモデル化に利用されていますし、AmazonやNetflixのような企業では、ユーザーの購入履歴や視聴履歴に基づいて、関連商品やコンテンツを推薦するシステムで利用されているそうです。

グラフデータベースでの検索の例としては下図のようなものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/f4d38361-389b-7182-1061-d59a6159bb25.png)

上図左がSNSユーザーのグラフ構成です。登録されているユーザーがノードで、ユーザー間の関係性(友達、家族、同僚など)がエッジ(relationship)です。このグラフから友達関係のユーザーのみを検索するようなクエリを実行した場合、上図右のように友達関係にあるユーザーの関連性のみを検索することができます。


#### GraphRAGの仕組み
GraphRAGはその名が示す通り、ベクトルデータベースの代わりにグラフデータベースを利用します。ベクトルデータベースではベクトル検索(もしくはベクトル検索とキーワード検索を併用したハイブリッド検索)を実行し取り出したコンテキストを質問文章のヒントとしてLLMに入力しますが、グラフデータベースでは、ここに、更に「グラフ検索」の結果をヒントとしてLLMに入力し最終的な応答テキストを生成します。つまり、「グラフ検索」を追加することにより、更に精度の高いコンテキストを抽出することで応答テキストの精度向上を狙った実装となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/c8bfd1d6-0755-f69b-fe5e-7639bee467d4.png)


これまで同様、LangChainを使った場合、複雑な処理の殆どがLangChainの有用な関数によりバックグラウンドで実行されるため処理フローは下記のように極めてシンプルになります。

①入力文章からハイブリッド検索(ベクトル検索、キーワード検索、グラフ検索の3種類の検索)を実行
②検索結果と質問文章をLLMに入力
③応答テキストを生成


#### ユースケース

GraphRAGは通常のRAG同様、適用範囲は極めて広いですが、対象のテキストデータの内容がグラフデータベースと相性がいい場合(ノードやエッジなどの構造にしやすい内容の場合)は効果が高くなります。下記のユースケースで扱われるようなデータの内容は一般的には非常に複雑で、通常のデータベースのスキーマでは表現しきれないデータモデルになる傾向があります。そのような複雑な内容のデータモデルを定義するためにグラフデータベースが存在しますので、このようなデータを扱う業務ドメインでGraphRAGを利用しない手はありません。また単純に、ベクトルデータベースのRAGで精度がでない場合もGraphRAGを試してみる価値は大いにあると思います。

| ユースケース                         | 説明                                                                                 |
|--------------------------------------|--------------------------------------------------------------------------------------|
| ペルソナベースのレコメンデーション     | ユーザープロファイルを詳細に保存した知識グラフと統合することで、GraphRAGは個別化されたコンテンツ、商品、またはサービスの推薦を生成することができます。                   |
| ソーシャルネットワーク分析       | 人物間の関係や影響力の分析、友人の推薦、コミュニティの発見などに利用されます。                   |
| 医療診断と治療提案              | ヘルスケア分野では、GraphRAGは症状、疾病、治療法の関係を含む医療知識グラフを統合することで、診断のサポートや治療提案を提供するのに役立ちます。                                 |
| 法律文書の分析                    | 法律専門家にとって、GraphRAGは大量の法律文書を分析する際に、関連する判例、法令、および法的先例を知識グラフからリトリーブ（検索）して提示するのに役立ちます。               |
| 科学研究分野のデータ分析        |  気象データの解析、気候モデルのシミュレーション、異常気象のパターン検出、生物内の代謝ネットワーク、タンパク質相互作用ネットワーク、食物連鎖の解析など、生命体内外の関係をモデル化など、複雑な関係性を持つデータ扱う科学分野のデータ分析など。 |


#### サンプルコードの概説

サンプルコードの概説はこちらの記事をご参照ください。

https://qiita.com/ksonoda/items/98a6607f31d0bbb237ef






# マルチエージェントRAG

今年に入ってからLLMを利用するアプリにグラフ技術を応用する論文が多数発表されています。それを受けてかLangChain, Inc.からもLangGraphという名のライブラリが登場しました。このライブラリではこれまでのように一つではなく複数のエージェントを定義し、各エージェントに異なる役割を与え、それらを協業させることにより、プロンプトに対する応答テキストを生成します。ここで重要になるのは、複数のエージェントをどのように協業させるかというロジックの実装です。その協業ロジック定義、いわば、複数エージェントの協業ワークフローの定義にグラフの技術を応用し、マルチエージェントシステムを実装しようという試みです。これを簡単に実装できるようLangGraphがリリースされました。

#### マルチエージェントとは？
シングルエージェントのコードを抽象的な図で表すと下図のようになります。LangChain Agentを使う場合、テキスト生成に必要な主要パーツ(ここではLLM、プロンプト、Tools)をエージェントで纏め、このエージェントがどのパーツをどの順序で使うかというプランをたてて実行してゆく構造になります。その際、このエージェントにはLLMによって明確な役割が割り当てられます。例えば現在の天気情報を求められた場合、「天気情報を検索し、ユーザーのプロンプトに応答する」という役割です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/c5661fb1-982b-3bf8-49b6-5436f33dba6d.png)

これに対して、マルチエージェントでは文字通り複数のエージェントを定義し、各エージェントにそれぞれ異なる役割を与え、協業することで最終的な応答を生成します。例えば、「過去5年間の日本のGDPをチャートにしてください。」というプロンプトの場合、エージェント1には「ウェブ検索をして過去5年間の日本のGDPの情報を収集する」という役割を与え、エージェント2には「収集された情報からチャートを作成するコードを生成する」という役割を与えます。これらが協業することにより最終的な応答を生成するという実装がマルチエージェントRAGの実装です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/ecf87fb2-7ecd-7fc4-2a8a-f74467f473d9.png)


シングルエージェントに対するマルチエージェントのメリットには以下のようなものが挙げられます。


| **特性**                   | **シングルエージェントRAG**                                   | **マルチエージェントRAG**                                  |
|----------------------------|-------------------------------------------------------------|-------------------------------------------------------------|
| **専門性の向上**           | 幅広いタスクに対応するが専門性が低い可能性がある              | 各エージェントが特定のドメインに特化し、高い専門性を発揮   |
| **タスクの分割と効率化**    | すべてのタスクを1つのエージェントが処理するため、処理が遅くなる可能性がある | タスクを分割し並行処理することで、全体の処理速度が向上     |
| **柔軟性とスケーラビリティ**| 1つのエージェントに依存するため、スケーラビリティに限界がある  | エージェントを追加・削除することで、システムが柔軟に拡張できる|
| **エラー耐性と信頼性の向上**| エージェントの失敗がシステム全体に影響を与える可能性がある  | 異なるエージェントがタスクをカバーすることで、信頼性が向上 |
| **応答の多様性と品質の向上**| 応答が1つのエージェントに依存するため、多様性が制限される可能性がある | 複数のエージェントが異なる視点で応答を生成し、質と多様性が向上 |


####  グラフとは？
グラフとは主にノードとエッジから構成されるデータモデルです。ノードは具体的なもの（例えば、人、場所、製品、イベントなど）や抽象的な概念（例えば、アイデア、カテゴリ、トピックなど）を定義し、エッジはノード間の関係性を表します。例えばノードにSNSのアカウントユーザーを定義した場合、エッジは人とユーザー同士の関係性、ということでフォローしている、されているという情報を定義することになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/e2e5ed5a-7a51-8424-d937-21e8e5e19137.png)

このグラフ技術は、RDBでは表現できない複雑なデータのスキーマ構造を定義しなければいけない技術領域で古くからグラフデータベースとして利用されてきました。MetaやLinkedInなどのソーシャルメディアプラットフォームでは、ユーザー間の友人関係やフォロワー関係のモデル化に利用されていますし、AmazonやNetflixのような企業では、ユーザーの購入履歴や視聴履歴に基づいて、関連商品やコンテンツを推薦するシステムで利用されているそうです。


そして、このグラフをマルチエージェントに適用する場合はちょうど下図のような実装になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/4bae1aa6-8a0e-52b6-8a1b-5b9c445be9ab.png)

グラフのノードには「エージェント」が定義され、エッジには「エージェント間の実行順序」の関係性が定義されます。この定義により、複数のエージェントの協業モデル(ワークフロー)を定義しているということになります。たとえば「Agent1の処理が実行されたあとは Agent3の処理を実行する」というような感じです。

ただし、LangGraphの場合は、単純なエッジではなく、「条件付きエッジ」と呼ばれるタイプになります。その名の通り、条件によってエッジの向き、つまり次に実行されるエージェントが動的に変わるというものです。この「条件」はエージェントの実行結果から取り出される「ステイタス」により決まります。この条件付きエッジによってエージェントの実行順序のロジックを柔軟に定義することができるという非常に重要かつ、マルチエージェントの中核となる概念です。(サンプルコードのパートで詳解します。)


####  ユースケース
LLMを利用する全てのアプリケーションで利用可能です。特にシングルエージェント構成での下記のようなデメリットが発生してしまう場合に適用を検討するとよいかと思います。

- シングルエージェント構成ではテキスト生成の精度が上がらない場合
- シングルエージェント構成で多数のfunction(tool)を定義していることが理由でエージェントが理想的なtoolの使い方をプランできない状況に陥る場合
- シングルエージェント構成では実装しきれないような複雑なワークフローが必要になるRAG



#### サンプルコードの概説

サンプルコードの概説はこちらの記事をご参照ください。

https://qiita.com/ksonoda/items/92a224e3f56255182140






# プライベートLLM(ローカルLLM)
ChatGPTのリリース以降、大規模言語モデルの有用性に注目があつまり、LLMのクラウドサービスを利用することが当たり前になっている現在ですが、それと同時に、クラウドサービスではなくローカルでLLMを運用するアーキテクチャも現実的になってきています。(※呼称としてはローカルLLMやプライベートLLMと言ったりします。)

その背景には以下のような理由が挙げられると思います。

- 様々な団体から実用に耐える高性能なOSSのLLMが多数リリースされている
- それを動作させるハードウェア(特にGPU)性能の著しい技術発展
- セキュリティやプライバシーに関するシステム要件のプライオリティがますます高くなっている

言語モデルのクラウドサービスが存在しなかった時代はみんな苦労しながらローカルでモデルを動作させていましたので特段新しい考え方ではありませんが、昨今では様々なツールがリリースされており、動作させるだけであれば以前のような高度な知識は全く不要になっているというのが実情です。

#### ローカルLLMの仕組みとPros/Cons
LLMをローカルで動作させるアーキテクチャではほとんどの処理をOSSのツールに頼ることになります。これには様々な手法がありますが本記事ではその中の代表的な方法としてOllamaと呼んでいるOSSを使うパターンとHugging Faceを利用する2パターンをご紹介します。

下図がOllamaを使ったローカルLLMの実装です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/b8727430-244c-4030-bd19-1419b0d21ba1.png)

- 一般的なLLMのクラウドサービスの場合(上図左)
例えばOpenAIを使う場合は、クラウド、もしくはオンプレミスにLLMを利用するアプリケーションを実装し、そのアプリからインターネット(もしくは専用線やVPN)経由でOpenAI社のデータセンターに実装されているモデルを利用(APIでCall)します。OpenAIのモデルをダウンロードしてローカルで動作させることは当然できません。

- ローカルLLMの実装(上図右 Ollamaを使った場合)
モデルそのものをローカル環境にダウンロードし、ローカル環境にデプロイします。アプリケーションからのAPI Callもローカル環境内で全て完結するということになります。(Ollamaがサポートしているモデルの一覧は[こちら](https://ollama.com/library))


そして下図がHugging Faceを利用したローカルLLMの実装です。今やAIテクノロジー界隈では説明の必要がないほど重要なプラットフォームになった[Hugging Face](https://huggingface.co/)を利用するパターンです。現在市場でリリースされているほぼすべてのOSSモデルが登録されおり、githubのLLM版と称されるほど知名度の高いサイトです。(Hugginf Faceで利用できるモデルの一覧は[こちら](https://huggingface.co/models)。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/e16c7a8b-4563-d02c-f793-e58645f36b3a.png)

ローカルLLMですのでモデルをリポジトリからローカルにダウンロードするという考え方はOllamaと変わりません。Huggin Faceのモデルを利用する場合、そのモデルを開発した企業や団体がモデル利用のAPIを提供していますのでそれを使って実装することになります。LangChainでは各社のAPIをラップしたHuggingFacePipelineというクラスがあり、このクラスでどのモデルも同じようなコードで実装することができるようになります。

ローカルLLMを使うアーキテクチャのpros/consとしては下記の通りです。


| メリット                          | 説明                                                                                     |
|-----------------------------------|------------------------------------------------------------------------------------------|
| プライバシーとセキュリティ         | データがローカルに保持されるため、機密情報を外部サーバーに送信する必要がなくなり、プライバシーとセキュリティが向上します。 |
| 様々なモデルが利用可能         | 様々な団体・企業が公開しているモデルを利用可能です。特定のタスクに特化したモデルなども簡単に利用することができます。 |
| カスタマイズの自由度              | モデルの調整や微調整を容易に行えるため、特定のユースケースに最適化されたモデルを作成できます。               |
| インターネット接続が不要           | オフライン環境でもLLMを使用できるため、ネットワークに依存しない運用が可能です。                                     |
| コスト削減                        | クラウドベースのサービスと比べ、長期的に見てコストを削減できる場合があります（ただし、初期投資は必要）。                  |
| レイテンシの低減                  | ローカル環境での処理により、クラウド経由の通信による遅延がなくなり、リアルタイム処理が向上します。                    |

| デメリット                        | 説明                                                                                     |
|-----------------------------------|------------------------------------------------------------------------------------------|
| ハードウェア要件               | LLMをローカルで動作させるには、非常に高性能なハードウェアが必要であり、特にGPUや大量のメモリが必要になります。 |
| 運用と管理の負担                  | モデルのインストール、更新、メンテナンス、トラブルシューティングなどを自分で行う必要があり、運用コストや時間がかかります。 |
| 拡張性の制限                      | ローカル環境では、スケーリングが難しく、クラウドのように簡単にリソースを追加できません。                              |
| 初期コストの高さ                  | 必要なハードウェアを購入するための初期投資が大きく、これが特に小規模なプロジェクトにとっては負担になることがあります。       |
| 更新とサポートの遅延              | クラウドサービスは最新のモデルや機能が即座に利用可能ですが、ローカル環境ではこれらを手動で更新する必要があります。         |


最低でもこの程度のpros/consは念頭にアーキテクチャを採用を決める感じです。


#### ユースケース
全てのLLMアプリケーションが対象となります。特に上述したメリットが重要な要件になるシステムで検討するべき構成となります。中でもやはりセキュリティの観点からローカルLLMを検討するユーザーが多いといえます。特に官庁系や金融系のシステムではセキュリティ要件のプライオリティが最も高くなる傾向にありますからローカルLLMを検討することは必然といえるでしょう。また、ローカルLLMだからといって、実装パターンが限られるということはありません。APIさえあれば、他の記事で紹介している様々な実装パターンも可能です。

#### サンプルコードの概説

上述したOllamaとHuggingFacePipelineのサンプルコード概説はこちらの記事をご参照ください。

https://qiita.com/ksonoda/items/febf91746bfc6494fea6




# LLMの量子化

「量子化」という技術は、深層学習に使われるニューラルネットワークの計算負荷やコンピューティングリソースを軽減する目的で開発されました。ですのでLLMが流行りだす以前からあった技術になりますが、LLMのように、その他のモデルと比較して超大規模なニューラルネットワークとなると量子化の効果は絶大です。

#### 量子化の仕組みとpros/cons
かなりざっくりした説明になりますが、量子化とはニューラルネットワークの中で繰り返し行われる浮動小数点演算の小数点の桁数を丸めて少なくすることにより演算負荷を下げるという処理です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109260/a2f75366-d710-59ff-d9cf-cf72674a4869.png)

具体的には、32bitのモデルであれば少数第7位まで計算するところを、16bitに量子化することで少数第3位までの計算ですませるというイメージです。その程度のことでそんなに大きな効果が得られるのかと思われるかもしれませんが、画像系AIなどで構成するような規模のニューラルネットワークとは異なり、LLMとなるとその効果はケタ違いです。

例えばGPT3.5はパラメータの数が1750億だといわれています。これを考慮すると、GPT3.5で推論を行うときはニューラルネットワークの中で、少なくとも数千億回の浮動小数点演算が実行されることになります。GPT4はパラメータの数が1兆を超えているといわれているので数兆回ということになります。

しかもこれはたった一つのトークン(≒単語)を推論する際に行われる浮動小数点演算の回数です。LLMのテキスト生成処理ではたいていの場合、多数のトークンを繰り返し推論して長文を生成することになりますからその際の演算回数は更に何倍にも跳ね上がります。このような天文学的な回数の浮動小数点演算が繰り返し実行されるため、その中で扱う値の桁数が少し変わるだけでも非常に大きな影響になります。その影響によるメリットは下記のようなものです。


| メリット                  | 説明                                                                                      |
|---------------------------|-------------------------------------------------------------------------------------------|
| モデルサイズの削減       | 量子化により、モデルのパラメータが少ないビット数で表現され、モデルのサイズが小さくなる。         |
| 計算速度の向上           | 低精度の計算を使用するため、推論処理が高速化し、リアルタイム応答性が改善される。                 |
| 省電力                   | 低精度の演算はエネルギー消費が少なく、大量のGPUを使った構成においてその電力量を下げることが期待できます。                     |
| コスト削減               | モデルサイズの縮小と計算の高速化により、インフラストラクチャのコスト削減が可能になる。          |
| エッジデバイスでの実行   | リソースが限られたエッジデバイスでもモデルを実行でき、IoTデバイスや組み込みシステムでの利用が現実的になる。|


この中でも特にモデルサイズの削減の効果は大きく、これによりGPUメモリ使用量の削減が期待できます。今日、恐らくほとんどのユーザーはこれを目的に量子化を行います。今やGPUメモリはコンピューティングリソースの中で最も貴重なものになりましたので、それを節約したいというのは当然の流れです。Nvidia A100やH100のような非常に高価なGPUにしかのらなかったモデルが量子化することにより、数基のA10にのせられるようになるわけですからこのコスト効果は絶大です。

しかし量子化には当然デメリットもあります。ニューラルネットワークの浮動小数点演算の桁数を少なくするということは本来の値とは異なる値を使う(四捨五入するようなイメージ)ということですから、最終的なモデルの精度に少なからず影響があります。LLMのニューラルネットワークの中では、入力された文章に関係性の高い複数のトークン(≒単語)を選出し、それらを「確率分布」に変換して、最終的に最も可能性の高い一つのトークンを選出するという処理を繰り返します。量子化により数値の桁数を丸めることで、その「確率分布」が変わり、もし量子化していなければ選ばれていたであろうトークンが選ばれなくなるということが発生し得ます。

つまり、量子化によりモデルのサイズを小さくすするほど(ビット数を小さくするほど)GPUメモリの消費量は少なくなりますが、それと同時に精度は落ちるということになります。このような技術的背景もあり、以前はLLMの量子化といえば「8bitまでが精度妥協の限界ライン」というのが暗黙の了解だったように感じますが、最近は4bitでテストされる方もちらほら見かけます。また、同じ8bit量子化でも採用するモデルによっても精度は変わってきますので注意が必要です。

量子化のビット数と精度の反比例についてはネットにベンチマーク結果や記事が沢山ありますのでそれらを参考にしつつ、自身のデータで精度検証を実施しながら利用したいところです。今後も優秀なモデルが沢山開発されるでしょうから目が離せない非常に重要な技術分野だと思います。

#### サンプルコードの概説

サンプルコードの概説はこちらの記事をご参照ください。

https://qiita.com/ksonoda/items/036b224b72ef029b4677


以上、7つのユースケースをご紹介しました。