2024年のLLMアプリ開発を取り巻くソフトウェアを整理する
はじめに
こんにちは、motacaplaと申します。
OpenAIやAnthropic、Google、AWSなど各社LLMの開発が激化している中で、そのLLMを使ったアプリ開発を取り巻くソフトウェアも非常に沢山生まれていると感じています。
自分はとても全てを把握しているとは言い難いですし、選定する上で整理しておくほうが良いと思い、調べられる範囲で名前とGithubの☆数、分類、機能概要について、まとめることにしました。
内容が不足していたり、リストの漏れもあると思いますが、ご指摘頂けると大変助かります。
不足あれば適宜追記していきます。
言語ライブラリ
LangChain (☆96.9k)
LLMアプリを構築するためのOSSフレームワークとして、巷で非常に人気の高いLangChainです。
AWSの解説に委ねます:
LangChain は、大規模言語モデル (LLM) に基づいてアプリケーションを構築するためのオープンソースフレームワークです。LLM は、大量のデータで事前にトレーニングされた大規模な深層学習モデルで、ユーザーのクエリに対する応答を生成できます。たとえば、質問に答えたり、テキストベースのプロンプトから画像を作成したりします。LangChain は、モデルが生成する情報のカスタマイズ、正確性、関連性を向上させるためのツールと抽象化を提供します。たとえば、開発者は LangChain コンポーネントを使用して新しいプロンプトチェーンを構築したり、既存のテンプレートをカスタマイズしたりできます。LangChain には、LLM が再トレーニングなしで新しいデータセットにアクセスできるようにするコンポーネントも含まれています。
いくつか固有の概念や言語があるので、簡単に解説します。
LangChain コンポーネント
コンポーネントは、アプリ構築において核となる以下のようなブロックを指しています:
- Prompt templates
- Example selectors (正しいfew shotのexampleを選択する)
- Chat models、Messages (Chat modelsのInput/Output)
- LLMs
- ...
Runnable interface
Runnable interfaceは、コンポーネントの標準的なインターフェイスを定義しています。
Invoked: A single input is transformed into an output.
Batched: Multiple inputs are efficiently transformed into outputs.
Streamed: Outputs are streamed as they are produced.
Inspected: Schematic information about Runnable's input, output, and configuration can be accessed.
Composed: Multiple Runnables can be composed to work together using the LangChain Expression Language (LCEL) to create complex pipelines.
こちらの記事が大変分かりやすかったため、詳細は割愛します。
LCEL (LangChain Expression Language)
LCEL (LangChain Expression Language)と呼ばれる独自言語を使って、Runnableを作成できます。
The LangChain Expression Language (LCEL) takes a declarative approach to building new Runnables from existing Runnables.
Runnableを繋げたchainという形式で記述することができ、より簡易な記述、ストリーミングや非同期、バッチがサポートされているといった特徴があります。直でLLMを呼び出すとコンテキストウィンドウを超過してしまうような文章も処理できそうです。
こちらの記事が大変分かりやすかったため、詳細は割愛します。
docsによると、複雑なワークフローを組み立てる場合はLangGraphのエージェントを活用することが推奨されています。後述するLangGraphのノード内でもLECLは利用できるようです。
LLMOps
LangSmith
LancChainと組み合わせずとも利用でき、エンタプライズ向けのプランを利用するとセルフホスティングも可能です。
Dify (☆56.3k)
LangGenius社開発のLLMアプリ開発プラットフォームです。説明文でLangChainが名指しされているのは、対抗意識を感じられます。
DifyはオープンソースのLLMアプリ開発プラットフォームです。RAGエンジンを使用して、エージェントから複雑なAIワークフローまでLLMアプリを編成します。
LangChain よりも本番環境に適しています。
Difyのプラットフォーム上では、GUIから様々なモデルを利用してLLMアプリを構築することができます。
ワークフローという機能では、LLMやコード実行といったノードらを自由に配置することで、フローを構築することができます。 他にもナレッジベースを構築できたり、Webアプリ公開が容易で(セルフホスティングもクラウドも可)、ログやモニタリングの機能もあります。Langflow (☆40.9k)
プロンプトマネジメント、プレイグラウンド、コンポーネントを使ったワークフロー作成、エージェント作成といった多様な機能を備えています。
GUI上のD&Dでフローを描画することができます。
LlamaIndex (☆37.6k)
コンポーネントやワークフローと、LangChainやDifyらと似た概念が多いです。
ユースケースとしては、RAG、チャットボット、構造化されたデータの抽出、エージェント作成、ファインチューニングといった様々なシーンで利用できます。
複雑なアプリの場合、ワークフローを使うことで複雑性を引き下げることが出来るようです。LangChainのchainなどのように、以前は有向非巡回グラフ(DAG)ベースのアプローチでこの複雑性を解決しようとしていましたが、イベントベースのパターンとvanillaのPythonを使うアプローチで解決する方針に転換したそうです。
As generative AI applications become more complex, it becomes harder to manage the flow of data and control the execution of the application. Workflows provide a way to manage this complexity by breaking the application into smaller, more manageable pieces.
Other frameworks and LlamaIndex itself have attempted to solve this problem previously with directed acyclic graphs (DAGs) but these have a number of limitations that workflows do not:
Logic like loops and branches needed to be encoded into the edges of graphs, which made them hard to read and understand.
Passing data between nodes in a DAG created complexity around optional and default values and which parameters should be passed.
DAGs did not feel natural to developers trying to developing complex, looping, branching AI applications.
The event-based pattern and vanilla python approach of Workflows resolves these problems.
Haystack (☆18.3k)
LangChainと似たコンポーネントという概念やドキュメントストアなどがあり、コンポーネント間の処理フローを表現するパイプラインを構築できます。
他にも、トレーシング、ロギング、評価といった機能もあります。
Langfuse (☆7.5k)
プロンプトマネジメント、プレイグラウンド、トレーシングや可視化、評価、データセット作成やメトリクスなど多様な機能が用意されています。
クラウドサービスだけでなくセルフホストできるので、外部に送信出来ないデータを扱ったRAG構築にも向いていそうです。
Arize Phoenix (☆4.3k)
オープンソースで、こちらもLangfuse同様にプロンプトマネジメント、プレイグラウンド、トレーシングや可視化、評価、データセット作成やメトリクスなど多様な機能が存在しています。
特に評価に関して、生成の評価だけでなく、RAGの検索処理の関連度をLLMで評価できるところは興味深いです:
他にも要約やコード生成など、ユースケースごとの評価をする仕組みも用意されています。TruLens (☆2.2k)
RAGなどのアプリを実装している環境で計測することもできますし、TruVirtualという機能ではTruLensの外にあるアプリのログに対しても同様の機能を提供できます。
TruLensは評価にRAG triadというContext Relevance, Groundedness, Answer Relevanceといった3つの指標を使っているところが特徴です。
The RAG triad is composed of three evaluations: context relevance, groundedness and answer relevance. If an LLM app scores high on all of them, we can confidently assert that it is free from hallucination. Let’s review them in order.
Context Relevance: Retrieval is the initial step in any RAG application. In order to check the quality of our retrieval, we want to make sure that each piece of context is relevant to the input query. This is crucial because this context will be used by the LLM to produce an answer and thus any irrelevant information in the context could be weaved into a hallucination.
Groundedness: Once the context is retrieved, the LLM produces an answer. LLMs have a tendency to exaggerate, distort, or make up facts that sound correct but are not. To mitigate this risk, we divide the response into distinct claims and independently search for evidence that supports each within the retrieved context. Groundedness measures the extent to which the claims made by the LLM can be attributed back to source text.
Answer Relevance: Finally, the original question must still be helpfully answered by our response. We can confirm this by evaluating the relevance of the final response to the user input.
DataStax
AstraDBと呼ばれるApache CassandraベースのDBとLangflowを組み合わせて、GUIでワークフローを構築できるプラットフォームです。
エージェント・マルチエージェント
Langflowもエージェント機能を備えていますが、こちらでは特にエージェントにフォーカスしているものを紹介します。
LangGraph
LangGraphは単一エージェント・複雑なエージェントシステムを構築してオーケストレーション可能なOSSフレームワークです。
図のように、エージェントのステートや条件付きの行動を定義して、状態管理することができます。
FAQにLangChainとの差分が明記されていました。
Do I need to use LangChain to use LangGraph? What’s the difference?
LangGraph is an orchestration framework for complex agentic systems and is more low-level and controllable than LangChain agents
セルフホスティング可能なLangGraph PlatformはOSSでは無いです。
LangGraphとLangGraph Platformの違いもFAQにまとめられていますが、主な違いとして、
Streamingでのdedicated modeの提供、PostgreSQLを使った Persistence Layer、Auto-scaling of task queues and servers、Fault-toleranceの自動リトライ、cronのスケジューリング、LangSmithと連携したモニタリングなど実運用していくうえで必要な機能を提供しています。
AutoGen (☆36.4k)
協調してタスクを処理するマルチエージェントを作ることができるOSSのプログラミングフレームワークです。
AutoGen is an open-source programming framework for building AI agents and facilitating cooperation among multiple agents to solve tasks. AutoGen aims to provide an easy-to-use and flexible framework for accelerating development and research on agentic AI, like PyTorch for Deep Learning.
browser_utilsという機能ではPlaywrightを使ったブラウザ操作のクラスを提供していたり、キャッシュやロガーのクラス、様々な関数(例. 入出力変換)が提供されています。
こちらはプログラミングのフレームワークのため、ターゲットとなるユーザーは開発者になります。
CrewAI (☆23k)
Sales/Marketing/Analytics/Finance/Technologyといった、開発以外の様々な業務もターゲットとしており、GUIベースでエージェントの構築から運用まで担えます。
Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling complex tasks.
かのML講義で有名なAndrew NgさんがFounderとして動画に出ていました。
Langdock
開発者向けにはエージェントやAPI、非開発者向けにはRAGやチャット、アシスタントといった機能を提供しています。
API経由で、簡単にRAGを構築したり、会話するボットを作成できます。
Assistants are chatbots you can set up for a specific situation or to work with a specific document. It works similarly to the chat, with the difference that you save documents and instructions to refer to the assistant without setting the chat up again.
コミュニティ
毛色が違いますが、プラットフォームという枠でまとめました。
Hugging Face Hub
Hugging Faceは2016年に設立されたアメリカの企業で、特に自然言語処理(NLP)に焦点を当てたライブラリ(Transformers、Diffusers)などを提供している。
The platform where the machine learning community collaborates on models, datasets, and applications.
プロンプト改善
DSPy
DSPy is the framework for programming—rather than prompting—language models. It allows you to iterate fast on building modular AI systems and offers algorithms for optimizing their prompts and weights, whether you're building simple classifiers, sophisticated RAG pipelines, or Agent loops.
プロンプトを記述する代わりに、入出力の振る舞いを定義することで、プロンプトチューニングなどの手間を省けます。
以下のRAGの例では、.ChainOfThought でコンテキストを与えたうえで、質問に対して回答するように振る舞いを定義しています。
def search_wikipedia(query: str) -> list[str]:
results = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')(query, k=3)
return [x['text'] for x in results]
rag = dspy.ChainOfThought('context, question -> response')
question = "What's the name of the castle that David Gregory inherited?"
rag(context=search_wikipedia(question), question=question)
理由と回答は以下:
Possible Output:
Prediction(
reasoning='The context provides information about David Gregory, a Scottish physician and inventor. It specifically mentions that he inherited Kinnairdy Castle in 1664. This detail directly answers the question about the name of the castle that David Gregory inherited.',
response='Kinnairdy Castle'
)
通常だと「実行してほしいタスク」と「そのタスクをどう伝えるか」を人間が検討する必要があるが、これらが分離されていて、前者のみ記述すれば良いです。
他にも、質問と回答の対を使ってプロンプト/モデルの重みの最適化も出来るようです。
以下はWikipediaの情報を検索して質問に回答するdspy.ReActエージェントを設定する例で、HotPotQA データセットからサンプリングした500個の質問-回答の対を用いて、dspy.MIPRov2を使った最適化をしています。
import dspy
from dspy.datasets import HotPotQA
dspy.configure(lm=dspy.LM('openai/gpt-4o-mini'))
def search_wikipedia(query: str) -> list[str]:
results = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')(query, k=3)
return [x['text'] for x in results]
trainset = [x.with_inputs('question') for x in HotPotQA(train_seed=2024, train_size=500).train]
react = dspy.ReAct("question -> answer", tools=[search_wikipedia])
tp = dspy.MIPROv2(metric=dspy.evaluate.answer_exact_match, auto="light", num_threads=24)
optimized_react = tp.compile(react, trainset=trainset)
ref
- LLMアプリ開発の必須ツール?!Langfuseがすごい!
https://qiita.com/moritalous/items/76ba9f2ad200df335d07 - Langfuse による LLM アプリのログの取得
https://zenn.dev/machinelearning/articles/langfuse_usage - LLM 搭載エージェント向けの 人気のオープンソース フレームワークの紹介
https://qiita.com/Dataiku/items/4dbdec1f5046cc415ffc - 各ドキュメント
Discussion