大規模なモデルが問題にならない場合、LLM のエンジニアリング実装の課題にどのように対処すればよいでしょうか?

数か月前、Thoughtworks の社内 AIGC ワークショップで、私たちは次のような一連の合意点に達しました。LLM の企業アプリケーションのコストを削減する「オープンソース モデル」がなければ、LLM は間もなく消滅するでしょう。したがって、オープンソースの LLM + LoRA 微調整が企業にとって主流の手法になると考えています。現在、LLaMA 2、Code LLaMA 2 などのモデルが常にこの可能性を更新しているのを見ることができます。

67de0d73cff971d2066eb56142681f02.png

モデルに問題がなくなったら、アーキテクトや開発者として、エンジニアリング的な方法で LLM を実装することに取り組む必要があります。そのため、過去数か月間、私たちはさまざまな分野で一連の LLM アプリケーション PoC を開発し、さまざまな視点から LLM アプリケーションを構築する方法を考えてみました。のような:

  • 言語と生態学の観点から、言語間の相互作用を探索し、最適化しますか?

  • 技術的なアーキテクチャはどのように設計されるべきでしょうか?

  • 迅速なモデリングと最適化?

  • より良いモデルコンテキストを構築するためのパターンにはどのようなものがありますか?

  • 言語 API には何を含める必要がありますか?

その他の質問には、小規模モデルと従来の LLM を通じて大規模モデルのコストを削減するにはどうすればよいかなどがあります。それぞれの質問はより興味深い質問であり、着地する際に考慮しなければならないことでもあります。

言語とエコロジーの観点から: API としての LLM サービスと FFI の比較

多くの企業が、Python + LangChain を使用して知識強化ツールの PoC を構築しようとしています。エンジニアリングの観点から見ると、次のことを考慮する必要があることを意味します。

  1. すべてのスマート サービスに Python を使用し、API を外部に提供していますか?

  2. 既存の言語とインフラストラクチャで可能なコード ソリューションをお探しですか?

また、Python は動的な性質を持っているため、IDE のインテリジェントな分析に影響を及ぼし、Pydantic のようなタイプ ライブラリを使用する場合でも、開発効率に影響を及ぼします。したがって、この言語について私が最初に考慮するのは、企業の既存のインフラストラクチャと組み合わせるということです。特に、私の既存のライブラリとフレームワークはすべて JVM 言語で書かれています。

言語AIインフラ

0a59ea58f77014cf57d15890a9326b84.png

そこで、Java/Kotlin、TypeScript、Rust 言語を使用してさまざまなタイプとシナリオのアプリケーションを開発し、さまざまな言語で LLM アプリケーションを構築できるかどうかを確認しました。

既存のシステムから判断すると、主流のプログラミング言語はすべて深層学習に関連するコードベースを持っています。Python エコシステムを参考例として使用できます。のような:

  • Java 言語システムの Deep Java ライブラリは、多数の深層学習関連ライブラリを提供しており、LLM ベースのアプリケーションを迅速に構築できます。

  • Kotlin 言語システムの KInference は、主にサーバー側およびローカル (クライアント側) で ONNX モデル推論を実行するために推論用に特別に最適化されています。

  • 錆びた言語。CoUnit の構築では、開発言語として Rust 言語を使用し、ndarray などの多次元配列ライブラリが必要です。

しかし、ほとんどのシナリオでは、AI インフラストラクチャは必要ありません。基本的な AI アプリケーションとしては、不必要な LLM コストを回避するために、トークンの長さを計算する機能のみが必要になる場合があります。

インターフェース方式としての FFI

0689219a2dfec5e21b03640fcee0294a.png

現時点では、Tiktoken/Tokenizer  * * は、トークン長を計算するために FFI (Foreign Function Interface、外部関数インターフェイス) 関数を必要とする最初のライブラリです。FFI を使用すると、異なるプログラミング言語のコードを呼び出して相互作用することができます。たとえば、Python を使用して Rust によって実装された基礎となるライブラリを呼び出し、より高速な計算速度を実現します。

さらに、アプリケーション側の観点から見ると、クライアントであってもサーバーであっても、いくつかの小さな推論モデルを導入する必要があります。以下は、一般的に使用される 2 つの FFI ベースのライブラリです。

  • トークナイザー/トークナイザーOpenAI の Tiktoken であっても、HuggingFace の Tokenizers であっても、基礎となる言語としての選択は Rust です。さらに、わずかな違いは、JetBrains の AI Assistant は Tokenizer を実装するために Kotlin を使用するか、FFI パフォーマンスを考慮するためであるということです。

  • ONNX ランタイムOnnx は、クロスプラットフォームの機械学習推論アクセラレータです。通常、ローカルで類似性検索を実行するための SentenceTransformers を導入するなど、クライアントとサーバーに小規模なモデル推論を導入するために使用されます。実装に関しては、ONNX は C++ で実装されているため、他の言語でも FFI の形式が使用されます。

私たちにとってより大きな影響を与える唯一の点は、言語によってはサンプルとしての参照コードや参照アーキテクチャがそれほど多くない可能性があり、このタイプのアプリケーションの開発には長い時間がかかることです。

LLM アプリケーションの技術アーキテクチャ

LLM アプリケーションと通常のアプリケーション開発には大きな違いはありません。LLM の影響と、さまざまなシナリオでこれらの構造を管理する方法を考慮する必要があるだけです。

さまざまなビジネス シナリオにおける AI アプリケーションの 3 つのモード

0a5abc6814bc6b31428fa994d8733955.png

一般的に、ビジネスモデルの違いによりAIの組み合わせの度合いも異なりますが、弊社では3つの異なるモデルにまとめています。

  • 基本的な LLM アプリケーション。ヒント エンジニアリングは通常、事前トレーニングされたモデルと対話する場合にのみ必要です。

  • 副操縦士タイプのアプリケーション。ヒント エンジニアリングを使用して、事前トレーニングされたモデルと外部ツール ストアを組み合わせたエージェント (エージェント) と対話します。通常、ワークフローは特定のパターンと組み合わせて記述され、ユーザーの意図に基づいてコンテキストを自動的に構築します。

  • 自律エージェント。高度なエージェント (エージェント) を使用して、事前トレーニングされたモデルや外部ツールを制御するためのヒントを自動的に生成します。一般に、LLM はユーザーの意図に応じてワークフローを自動生成し、外部ツールを自動的に制御します。

そこで、以前に構築したいくつかの PoC に基づいて、アーキテクチャ設計の 4 つの基本原則にまとめます。

LLM ファーストのソフトウェア アーキテクチャの原則

ecf8b0fef2d3c3b8486bc84f71de732d.png

ここで考える 4 つのアーキテクチャ原則は、実際には LLM の機能によって制限されます。

  • ユーザーの意図に基づいた設計人間とコンピューターの新しい対話エクスペリエンスを設計し、ユーザーの意図をよりよく理解するためにドメイン固有の AI キャラクターを構築します。たとえば、DSL に基づいてより多くのコンテキストを出力するようにユーザーを徐々に誘導できます。

  • コンテキストエンジニアリングビジネスコンテキストの取得に適したアプリケーションアーキテクチャを構築して、より正確なプロンプトを生成し、応答速度の高いエンジニアリング手法を検討します。

  • 原子力地図LLM が得意とするアトミック機能を分析し、アプリケーションに欠けている機能と組み合わせて、機能マッピングを実行します。

  • 言語インターフェースLLM のサービス機能の理解、スケジューリング、オーケストレーションを促進するために、適切な新世代 API を探索して見つけます。

実用的な観点から見ると、ユーザーをガイドし、コンテキストを改善することが、エンジニアリング実装における最大の困難です。

迅速なモデリングと最適化

プロンプトのモデルはプロンプト戦略自体と密接に関連しており、一般的に言えば、複雑な問題を解析する方法に関連しています。

コンテキスト依存のプロンプトモデリング

開発時にプロンプ​​トを書くのは面倒です。さまざまな思考連鎖テンプレートを構築した後、より良い例を提供する必要があります。この目的を達成するために、プロンプトをモデル化して、プロンプトの管理とテストを改善します。LangChain ソース コードのプロンプトを例として挙げます。

Human: What is 2+2?
AI: 4
Human: What is 2+3?
AI: 5
Human: What is 4+4?

対応する Python コードは次のとおりです。

examples = [
    {"input": "2+2", "output": "4"},
    {"input": "2+3", "output": "5"},
]

このため、プロンプト モードに応じて異なる PromptTemplate モードが必要となり、たとえば、 、 FewShotPromptWithTemplatesなど FunctionExplainerPromptTemplate の一連の複雑なプロンプト戦略モードが LangChain に構築されます。

プロンプトテンプレートの継続的な最適化

そして、私たちの PoC プロジェクトには、複数のタイプの例があります。そこで考慮すべき点があります。それらを一貫してモデル化するにはどうすればよいでしょうか? Kotlin で構築したプロジェクトの QA テンプレートの例を次に示します。

@Serializable
data class QAUpdateExample(
    override val question: String,
    override val answer: String,
    val nextAction: String = "",
    val finalOutput: String = "",
) : PromptExample {
}

また、反復することで継続的に最適化されます。また、プロンプトは変数を介してコンテキスト情報を組み合わせる必要があるため、プロンプト内の変数を実際のデータに置き換える Apache Velocity などのテンプレート エンジンも必要です。

コンテキスト構築のパターン: RAG およびドメイン固有のパターン

既存の LLM (Large Language Model) アプリケーションの中で、インテリジェントな顧客サービスと知識の質問応答に関連するシナリオが最も多いことは間違いありません。これらのシナリオの下で、開発者は LLM がより正確に応答できるようにするために、より優れた RAG (検索拡張生成) モードを模索してきました。

ただし、実際には、ほとんどのシナリオでは独自のパターンを構築でき、その品質は多くの場合優れています。ただし、専門家に頼って構築するなど汎用性があまりなく、コストパフォーマンスが不十分な印象です。

ドメイン固有の言語の抽象化

コード生成に関連するツールが 2 番目に人気のある LLM ツールであることは間違いありません。ナレッジ シーンとは異なり、コンテキストの構築を完了するために RAG が必ずしも必要というわけではありません。このシナリオでは、各質問は非常に「具体的」であり、IDE とエディターで十分なコンテキストを取得できます。

GitHub Copilot、JetBrains AI Assistant、またはオープンソース AutoDev のいずれであっても、ユーザーの行動と結果に基づいて対応するプロンプトを生成するだけです。たとえば、Copilot は最新の 20 個のファイルに基づいて現在のコードとは異なるコード チャンクを計算し、プロンプトを生成します。AutoDev では、標準化されたコードを生成するには、コード生成プロンプトに仕様を記述する必要があると考えています。

したがって、特定の分野においては、その分野のコンテキストに応じてDSLを設計し、迅速な戦略を設計し、それをRAGと組み合わせることが最も合理的な方法であると考えています。

検索強化の生成と即時戦略

41a3f0ed560ef8c1a53c7dcbe7e72818.png

社内研修資料では、RAG を一種の即時戦略として捉えています。基本的な RAG モードはベクトル データベースと組み合わせて、知識インデックスを構築する必要があります。基本的な RAG モードでは、構築されたプロンプトは満足のいく結果を達成しません。

ユーザーは初心者であり、私たちが期待したようにシステムを操作しません。彼らの入力は曖昧であり、私たちの課題は、曖昧な問題をどのように視覚化するかということです。

  • CoUnit では、セマンティック検索を実行して可能な結果を​​取得するために、ユーザーの意図を中国語、英語、および HyDE ドキュメント (仮説ドキュメント埋め込み) を含む DSL に変換する必要があります。

  • CoUnit などのシナリオでは、これはクエリ拡張のモデルであり、そのようなシナリオでは、Query2Doc などの一連の異なるモードもあります。また、効果的なチャット履歴を保存することで、関連する結果がますます正確になります。

  • LLM に私たちの知識が含まれていないが、内部に同様の知識がたくさんある場合、途中で失われたことの組み合わせを考慮する必要があります。つまり、プロンプト内でチャンクを効率的に分散する方法は? つまり、LLM が焦点を当てることができるように、先頭と末尾の中で最も関連性の高い結果を割り当てます。

半年前のLLMと同様に、RAG関連のコンテンツは今後数か月で大幅に進化しており、引き続き継続的な学習が必要です。

非決定的な変換を行うための言語 API

LLM と対話する場合、API として自然言語が必要です。一般に、シナリオは次の 2 つのカテゴリに分類できます。

  1. LLM + ワークフロー。LLM はユーザーの意図を分析して、適切なツールと API を選択します。

  2. LLM DSL 世代。LLM はユーザーの意図を分析し、特定のコンテキストを組み合わせて DSL を出力します。DSL はアプリケーションによって解析され、プログラムの入力として使用されます。

言語は素晴らしく、LLM の本質と組み合わせることで、非決定論を決定論的な関数呼び出しパラメーターや DSL などに変換します。

関数呼び出し: ユーザーの意図に基づいて適切な拡張ツールを選択します

a1982894c23467e63f49015f64184ef5.png

簡単に言うと、次のプロンプト メソッドと似ています。

你的任务是回答关于代码库的问题。你应该使用一组工具来收集信息,以帮助你回答问题。以下工具可供使用:

実際には、通常、これら 3 つのモデルに分類できます。

  • ツーリングモード。つまり、上記の方法で、可能なオプションのツールを多数提供します。アプリケーションを開発する場合、LLM が適切なツールを選択できるように、コンテキストを組み合わせて動的なツール リストを生成することが必要になることがよくあります。

  • 関数呼び出しモード。LLM でチャットする場合、関数を呼び出すタイミングを検出し、入力を関数に渡し、関数を呼び出します。

  • 意図認識小型モデル。つまり、特定のシナリオで同様の機能を実現するために、OpenAI と同様の方法で微調整されています。

上記のシナリオに加えて、LLM は JSON などの DSL を生成することもでき、プログラムはこの関数を処理して同様の機能を実現できます。

データ駆動型: DSL パターンとガイド付きユーザー

一般に、ユーザーと LLM の間の中間言語として DSL を使用します。LLM にとって理解しやすいだけでなく、人間にとっても理解しやすく、プログラム分析にも適しています。もちろん、次のような解析する必要のない DSL もあります。

----------------------------------------------
|      Navigation(10x)                       |
----------------------------------------------
| Empty(2x) | ChatHeader(8x) | Empty(2x)     |
----------------------------------------------
| MessageList(10x)                           |
----------------------------------------------
| MessageInput(10x)                          |
----------------------------------------------
| Footer(10x)                                |
----------------------------------------------

これは、LLM によるさらなるコード生成のための中間レンダリング モードとして使用できます。

また、DSLモデルに基づいてユーザーをどのように誘導するかは非常に興味深いものです。

まとめと次のステップ

この記事では、過去数か月間で LLM アプリケーションを構築した経験の一部を要約します。そして、これらの経験から、再利用可能なパターンがどんどん見つかりました。

これらのパターンをより適切に生成して、より迅速な LLM アプリケーション開発をサポートする方法を検討します。

おすすめ

転載: blog.csdn.net/gmszone/article/details/132658359