LangChain v0.1.0
本日、最初の安定版であるlangchain 0.1.0のリリースを発表できることを嬉しく思います。完全な下位互換性があり、PythonとJavaScriptの両方で提供され、機能とドキュメントの両方を通じて焦点が改善されています。LangChainの安定版は、開発者の信頼を得るのに役立ち、ライブラリを体系的かつ安全に進化させる能力を与えてくれます。
紹介
LangChainは1年ちょっと前から存在しており、LLMアプリケーションを構築するためのデフォルトのフレームワークに成長するにつれて、大きく変化しました。1ヶ月前にプレビューしたように、私たちは最近、プロジェクトをより適切に整理し、基盤を強化するために、LangChainパッケージアーキテクチャを大幅に変更することを決定しました。
具体的には、アーキテクチャに 2 つの大きな変更を加えました。それは、langchain-core をパートナー パッケージ (langchain-communityまたはスタンドアロン パートナー パッケージ) から分離することです。
念のために言っておきますが、langchain-coreには主要な抽象化、インターフェース、およびコア機能が含まれています。このコードは安定しており、ここ 1 か月ちょっとの間、より厳格なバージョン管理ポリシーに従っています。
ただし、langchainそれ自体は0.0.xバージョンに残っていました。すべてのリリースをマイナー バージョン 0 にすると、いくつかの課題が生じました。
ユーザーは、更新によって破壊的変更が行われないことを確信できませんでした。
langchainが肥大化し、不安定になったのは、破壊的変更や非推奨の通知を減らすために「すべてを維持する」アプローチを採用したためです。
ただし、本日の 0.1.0 のリリース以降、今後のすべてのリリースは新しいバージョン標準に従います。具体的には:
パブリック API に破壊的変更を行うと、マイナー バージョン バンプ (2 桁目) が発生します。
バグ修正や新機能があると、パッチバージョンが上がります(3桁目)。
これが、以前のアーキテクチャの変更と組み合わさって、次のようになることを願っています。
破壊的変更が加えられた場合に明確に伝達され、開発者が自信を持って更新できるようにします。
古いコードを公式に非推奨化して削除し、肥大化を防ぎます。
より責任を持って統合に対処します(そのSDKはLangChainと同じくらい急速に変化することが多い)。
バージョン 0.2 をリリースした後も、0.1 のブランチを維持することをお約束しますが、重大なバグ修正のみにパッチを適用します。そのための計画については、この投稿の最後の方をご覧ください。
安定した 0.1 リリースに向けてパッケージを再設計する中で、何百人もの開発者に、なぜ LangChain を使用するのか、そして何が気に入っているのかについて話を聞く機会を得ました。このインプットが私たちに方向性と焦点を導きました。また、以下に概説するコア領域で Python と JavaScript のバージョンを同等にする機会としても利用しました。
私たちは、私たちが聞いたことと、LangChainを継続的に改善する計画を共有したいと思います。これらの学びを共有することで、私たちの思考と意思決定の透明性が高まり、他の人がLangChainをよりよく使用し、理解し、貢献できるようになることを願っています。結局のところ、LangChainの大部分は私たちのコミュニティであり、ユーザーベースと2000+の貢献者の両方であり、私たちはすべての人に旅に参加してもらいたいと考えています。
サードパーティの統合
LangChainについて人々が最も気に入っていることの一つは、どのスタックでも簡単に構築を開始できることです。LLMからベクターストア、エージェントが使用するツールまで、約700の統合があります。
約 1 か月前、統合に関する堅牢性、安定性、スケーラビリティ、および一般的な開発者のエクスペリエンスが向上すると思われるいくつかの変更を加え始めました。すべてのサードパーティ統合を分割する langchain-community。これにより、統合固有の作業を一元化できます。また、個々の統合を独自のパッケージに分割し始めました。これまでに、OpenAI、Google、Mistral を含む約 10 個のパッケージに対してこれを実行しました。この利点の 1 つは、依存関係の管理が向上することです。以前は、すべての依存関係がオプションであったため、特定のバージョンをインストールしようとすると頭痛の種が発生していました。統合が独自のパッケージ内にある場合、その要件をより厳密にバージョン管理できるようになり、インストールが容易になります。もう 1 つの利点はバージョン管理です。多くの場合、サードパーティの統合に変更が加えられ、それには重大な変更が必要になります。これらは、スタンドアロン統合パッケージで適切なバージョン管理を行うことで、個別の統合ベースで反映できるようになりました。
可観測性
LLM アプリケーションを構築するには、システムの中心に非決定的なコンポーネントを配置する必要があります。これらのモデルは予期しない結果を出力することが多いため、システム内で何が起こっているかを正確に把握することが不可欠です。
私たちはこれをいくつかの方法で解決しました。
私たちがこれに取り組んだ主な方法は、LangSmithを構築することです。LangSmith が提供する主な価値の 1 つは、LLM アプリケーションに対するクラス最高のデバッグ エクスペリエンスです。どのようなステップが発生しているか、各ステップの入力は何か、各ステップの出力は何か、各ステップにかかる時間、およびその他のデータを正確に記録します。これはユーザーフレンドリーな方法で表示され、どのステップに最も時間がかかっているかを特定したり、プレイグラウンドに入って予期しない LLM 応答をデバッグしたり、トークンの使用状況を追跡したりできるようになります。プライベート ベータ版であっても、LangSmith に対する需要は圧倒的であり、パブリック ベータ版をリリースし、数か月以内に一般公開できるように、スケーラビリティに多大な投資を行っています。また、厳格なデータ プライバシー ポリシーを持つ企業向けの VPC 内展開を備えたエンタープライズ バージョンもすでにサポートしています。
私たちは他の方法でも可観測性に取り組んできました。私たちは長い間、パイプライン全体でさまざまなレベルのログを記録するためのverbose組み込みdebugモードを用意してきました。私たちは最近、作成したチェーンを視覚化し、使用されるすべてのプロンプトを取得するメソッドを導入しました。
構成可能性
開始する際に事前に構築されたチェーンがあると便利ですが、チームがそれらのアーキテクチャの外に出て、チェーンをカスタマイズしたいと考えているのをよく見かけます。プロンプトをカスタマイズするだけでなく、オーケストレーションのさまざまな部分もカスタマイズします。
また、LLM ワークロードに特有の利点もいくつか提供します。主に LLM 固有の可観測性 (上で説明) と、この投稿で後ほど説明するストリーミングです。
LCEL のコンポーネントは LangChain-coreにあります。LangChain の特定のチェーンに対して、より高いレベルのエントリ ポイントの作成を開始しました。LCEL で構築されたチェーンはストリーミング、カスタマイズの容易さ、可観測性、バッチ処理、再試行をすぐに利用できるため、これらは既存の (現在は「レガシー」) チェーンを徐々に置き換えます。私たちの目標は、この移行をシームレスにすることです。以前に次のことを行った可能性があります。
ConversationalRetrievalChain.from_llm(llm, …)
シンプルに作りたいのは次のとおりです。
create_conversational_retrieval_chain(llm, …)
内部では、特定の LCEL チェーンを作成して返します。ロジックを変更したい場合でも、問題ありません。すべて LCEL で記述されているため、何かをサブクラス化したりメソッドをオーバーライドしたりすることなく、その一部を簡単に変更できます。
LangChain には多数のチェーンがあり、その多くが頻繁に使用されています。代替のコンストラクター関数が存在し、使用され、十分にテストされるまで、チェーンのレガシー バージョンを非推奨にすることはありません。
ストリーミング
LLM は応答するまでに時間がかかる場合があります。エンド ユーザーに、空白の画面を見つめるのではなく、作業が行われていることを示すことが重要です。これは、LLM からのトークンのストリーミング、または中間ステップのストリーミング (チェーンまたはエージェントの実行時間が長い場合) のいずれかの形式になります。
私たちは両方に多額の投資を行ってきました。LCEL で構築されたすべてのチェーンは標準streamとastreamメソッドを公開しており、LLM 呼び出し以外の (たとえば、出力パーサー内) ストリーミングを確実にするために多くの作業を行ってきました。astream_logすべてのチェーンは、 LCEL チェーン内のすべてのステップをストリーミングする標準メソッドも公開します。これらをフィルタリングして、実行された中間ステップやその他の情報を簡単に取得できます。
出力の解析
LangChain の主な使用例の 1 つは、LLM を使用して他のツールを呼び出す「ツールの使用」です。
私たちは、出力パーサーの概念を使用して、これに関する優れた開発者エクスペリエンスに多大な投資を行ってきました。
これを行う主な方法の 1 つは、OpenAI 関数呼び出しを使用することです。出力形式 (Pydantic、JSON スキーマ、または関数を使用) を指定するだけでなく、応答を簡単に操作できるようにしました。また、OpenAI 関数呼び出しをサポートしていないモデルでこれを実行し、プロンプトを使用する場合に備えて、いくつかの異なるエンコード方法 ( JSON、XML、Yaml ) もサポートしています。プロンプトを使用する場合は、LLM に応答方法を指示するための適切な指示も必要です。すべての出力パーサーには、get_format_instructionsこれらの指示を取得するメソッドが装備されています。
また、ユーザー エクスペリエンスを向上させるために、出力パーサーの生成時に部分的な結果をストリーミングできるようにするなど、出力パーサーに関するより高度な機能にも投資してきました。これには、JSON、XML、CSV などの構造化フォーマットからの部分的な結果のストリーミングが含まれます。出力解析では、場合によっては注意が必要です。JSON BLOB を解析するには、ほとんどの JSON パーサーで完全な JSON BLOB が必要です。多くの出力パーサーには、この部分解析を行うための組み込みロジックが含まれています。
検索
開発者が構築しているアプリケーションの主なタイプの 1 つは、プライベート データと対話するアプリケーションです。
これには通常、取り込み (データの準備) と取得 (データの取得) という 2 つの異なるコンポーネントが含まれており、どちらも私たちが構築したものです。
取り込み側では、取り込みの大部分は、作業しているテキストをチャンクに分割することです。これは些細なことのように思えるかもしれませんが、最善の方法は微妙な違いがあり、作業しているドキュメントの種類によって異なります。15 種類のテキスト スプリッターがあり、開発者がこのプロセスを最大限に制御できるように、特定のドキュメント タイプ ( HTMLやMarkdownなど) に最適化されたものもあります。ただし、関連データは頻繁に変更されており、当社の取り込みシステムは、実稼働のスケールされたアプリケーション向けに設計されています。変更されていない部分を無視してコンテンツを再取り込みできるようにするインデックス APIを公開しました。これにより、大容量のワークロードの時間とコストを節約できます。
取得側では、より高度な手法に投資するとともに、取得をより本番環境に対応できるようにしました。私たちは、学界からの高度な検索戦略(FLARE や Hyde など) を実装し、独自の戦略 (親ドキュメントや自己クエリなど) を作成し、他の業界のソリューション (検索で一般的に使用されるクエリ拡張から派生したマルチクエリなど) の一部を採用してきました。)。また、複数のユーザーのドキュメントをまとめて保存するアプリケーションにとって重要な、ユーザーごとの取得などの運用上の懸念事項も確実にサポートするようにしました。
重要なのは、LangChain は高度な検索システムを構築するために必要なコンポーネントをすべて提供していますが、その方法については過度に意見を持っているわけではありません。これにより、 EmbedChainやGPTResearcherのような、より独自の検索アプローチを提供するために、LangChain 上に他の多くのライブラリが構築されるようになりました。
エージェント
LangChain が最初に知られるようになったものの 1 つは、エージェントのワークロードでした。これは次の 2 つのことを意味します。
ツールの使用: LLM に関数またはツールを呼び出す
推論: LLM がツールを複数回呼び出せるようにする最適な方法とその順序 (またはツールをまったく呼び出さなくてもよい!)
ツールの使用面では、重要であると考えられるコンポーネントの大部分を取り上げました。
多数のサードパーティツールとの統合
これらのツールの入力スキーマに適合するように LLM 応答を構造化する方法
これらのツールを呼び出すカスタム方法を指定する柔軟な方法 (LCEL)
推論側では、いくつかの異なる「エージェント」メソッドがあります。これは主に、ループ内で実行される LLM として考えることができ、各反復でどのツール (存在する場合) を呼び出す必要があるかを決定し、そのツールの結果を観察します。 私たちは最初からReAct (そのための早期プロンプト戦略) を組み込み、OpenAI Function Callingを使用するもの、新しいツール呼び出し APIを使用するもの、会話用に最適化されたものなど、他の多くのタイプをすぐに追加しました。
検索と同様に、LangChain はエージェントの構成要素を提供しますが、その上に独自のフレームワークがいくつか構築されているのも見てきました。この好例はCrewAIです。これは LangChain 上に構築され、マルチエージェント ワークロードに簡単なインターフェイスを提供します。
ラングチェーン 0.2
LangChain 0.1 をリリースしたばかりですが、すでに 0.2 について検討しています。私たちが最優先に考えていることは次のとおりです。
LCEL でのレガシー チェーンの書き換え (ストリーミングとデバッグのサポートが向上)
新しいタイプのチェーンの追加
新しいタイプのエージェントの追加
本番環境の取り込み機能の向上
古い未使用の機能を削除する
重要なのは、古いコードの一部を削除して、LangChainスリム化と集中化を図ることに興奮している一方で、まだ古いバージョンを使用しているユーザーへのサポートも維持したいということです。そのため、0.2 のリリース後、少なくとも 3 か月間は 0.1 を安定ブランチ (重大なバグ修正のパッチ適用) として維持する予定です。今後はすべての安定版リリースでこれを行う予定です。
貢献を始めたいと思っているなら、今ほど良い時期はありません。最近、出発点をお探しの場合に最適な入門用の問題をGitHub に追加しました。
もう一つ
LangChain v0.1.0 の大部分は安定性であり、上で概説したコア領域に重点を置いています。LangChain について人々が気に入っている分野を特定したので、そこにさらに高度で完全なツールを追加することに取り組むことができます。
LangChain について人々が気に入っている主な点の 1 つは、エージェントのサポートです。ほとんどのエージェントは、主に、ある種のループで LLM を実行するように定義されています。これまでのところ、これを行う必要がある唯一の方法はAgentExecutorを使用することです。AgentExecutor に多くのパラメーターと機能を追加しましたが、これはループを実行する方法の 1 つにすぎません。
これにより、ユーザーはさらに多くのカスタムの周期的動作を作成できるようになります。明示的な計画ステップや明示的な反映ステップを定義したり、特定のツールが常に最初に呼び出されるように簡単にハードコーディングしたりできます。
これは Pregel と Apache Beamからインスピレーションを得ています。現在公開されているインターフェイスは NetworkXからインスピレーションを得たもので、次のようになります。
from langgraph.graph import END, Graph
workflow = Graph()
workflow.add_node("agent", agent)
workflow.add_node("tools", execute_tools)
workflow.set_entry_point("agent")
workflow.add_conditional_edges(
"agent",
should_continue,
{
"continue": "tools",
"exit": END
}
)
workflow.add_edge('tools', 'agent')
chain = workflow.compile()
私たちは過去 6 か月間これに取り組み、ユーザーと一緒にベータテストを行ってきました。現在、OpenGPT を強化しています。今後数週間でさらに多くの例とドキュメントを追加する予定です。これには本当に興奮しています。
ここで試してみてください。
結論
LangChain はエコシステムとともに大きく進化してきました。私たちを後押しし、一緒に構築してくださったコミュニティとユーザーにとても感謝しています。この 0.1 リリースでは、LLM フレームワークに何が必要で何が必要かを理解するのに時間をかけて、引き続きその構築に取り組んでいきます。コミュニティのニーズが進化するにつれて (または何かが足りない場合は)、それに対処できるよう、皆様からのフィードバックをお待ちしています。「千里の道も一歩から始まる」と言います。– 今回の場合は、バージョン 0.1から始まるですが。