なぜ私はLangChainを諦めたのでしょうか?

なぜ私はLangChainを諦めたのでしょうか?

過去数か月間の AI の爆発的な成長を追ってきた方なら、おそらく LangChain について聞いたことがあるでしょう。

簡単に言うと、LangChain は、Harrison Chase によって開発された、OpenAI の GPT API (より多くのモデルに拡張されています) に接続して AI テキストを生成するための Python および JavaScript ライブラリです。

より具体的には、これは論文「ReAct: 言語モデルにおける推論と行動の相乗効果」の実装です。この論文では、モデルが「推論」(思考の連鎖を介して) し、「行動」(インターネット検索など、定義済みのツールセットのツールを使用できるようにすることで) できるようにするプロンプト手法が紹介されています。

写真

論文リンク: https://arxiv.org/pdf/2210.03629.pdf

この組み合わせにより、出力テキストの品質が大幅に向上し、大規模な言語モデルで問題を正しく解決できるようになることが実証されています。

2023年3月、ChatGPTのAPIはアップグレード後の値下げにより人気が高まり、LangChainの利用が爆発的に増加しました。

その後、LangChain は、収益や明らかな収益創出計画がないまま、シード資金として 1,000 万ドル、シリーズ A 資金として 2,000~2,500 万ドルを調達し、評価額は約 2 億ドルとなりました。

写真

ReAct 論文からの ReAct フローの例。

InstructGPT/text-davinci-003 で LangChain によって普及された ReAct ワークフローは特に効果的ですが、コストがかかり、小規模なプロジェクトでは使いにくいです。

マックス・ウルフはBuzzFeedのデータサイエンティストです。彼もLangChainを使用したことがあるが、その経験は総じて良くなかった。

彼が何を経験したか見てみましょう。

「使い方が分からないのは私だけでしょうか?」

BuzzFeed で働いている間、私は Tasty ブランド (後に Tasty iOS アプリで Botatouille としてリリース) 向けに、ユーザーとチャットして関連するレシピを提供できる ChatGPT ベースのチャットボットを作成するという任務を負っていました。

具体的には、ソースレシピは埋め込みレシピに変換され、ベクターストレージに保存されます。たとえば、ユーザーが「健康食品」と質問すると、クエリは埋め込みレシピに変換され、埋め込みクエリに類似したレシピを見つけるために近似最近傍検索が実行され、それが追加コンテキストとして ChatGPT に提供され、ChatGPT によってユーザーに表示されます。このアプローチは、検索拡張生成と呼ばれることがよくあります。

写真

検索拡張を使用して生成されたチャットボットのアーキテクチャの例。

「LangChain は RAG で最も人気のあるツールなので、今がそれを学ぶ絶好の機会だと思いました。LangChain を最大限に活用する方法をより深く理解するために、LangChain の包括的なドキュメントを時間をかけて読みました。」

1週間の調査の後、何も見つかりませんでした。 LangChain デモ例を実行すると機能しますが、レシピ チャットボットの制約に合わせてそれらを適応させようとすると失敗します。これらのバグが修正された後、チャット会話の全体的な品質は低下し、面白くなくなりました。徹底的にデバッグしましたが、解決策は見つかりませんでした。

結局のところ、私は存在の危機に陥っていました。他の多くの ML エンジニアは LangChain を理解できるのに、私にはできないのに、私は価値のない機械学習エンジニアなのでしょうか?

私は低レベルの ReAct パイプラインに頼りましたが、会話の品質と精度において LangChain 実装をすぐに上回りました。

LangChain の学習とテストに 1 か月を費やした後、Hacker News で誰かが 100 行のコードで LangChain を再現したという投稿を見て、私の存在の危機は和らぎました。コメントのほとんどは、LangChain に対する不満を吐き出していました。

LangChain の問題は、単純なものを比較的複雑にし、この不必要な複雑さが一種の「部族主義」を生み出し、新興の AI エコシステム全体に悪影響を及ぼすことです。

したがって、ChatGPT の使い方を学びたいだけの初心者であれば、絶対に LangChain から始めないでください。

LangChainの「Hello World」

LangChain の簡単な紹介。Python 経由で LLM/ChatGPT と簡単なやり取りを行う方法に関するミニチュートリアルから始まります。たとえば、英語をフランス語に翻訳できるボットを作成するには、次のようにします。

 from langchain.chat_models import ChatOpenAIfrom langchain.schema import ( AIMessage, HumanMessage, SystemMessage ) chat = ChatOpenAI(temperature=0) chat.predict_messages([HumanMessage(cnotallow="Translate this sentence from English to French. I love programming.")])# AIMessage(cnotallow="J'adore la programmation.", additional_kwargs={}, example=False)

OpenAI ChatGPT 公式 Python ライブラリを使用した同等のコード:

 import openai messages = [{"role": "user", "content": "Translate this sentence from English to French. I love programming."}] response = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=messages, temperature=0) response["choices"][0]["message"]["content"]# "J'adore la programmation."

LangChain が使用するコードの量は、公式 OpenAI ライブラリのみを使用する場合とほぼ同じです。LangChain にはより多くのオブジェクト クラスが組み込まれていると推定されますが、コードの利点は明らかではありません。

プロンプト テンプレートの例では、LangChain の仕組みの核心が明らかになります。

 from langchain.prompts.chat import ( ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, ) template = "You are a helpful assistant that translates {input_language} to {output_language}." system_message_prompt = SystemMessagePromptTemplate.from_template(template) human_template = "{text}" human_message_prompt = HumanMessagePromptTemplate.from_template(human_template) chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt]) chat_prompt.format_messages(input_language="English", output_language="French", text="I love programming.")

LangChain が誇るプロンプトは、すべての Python インストールに存在する機能である f 文字列と同じように動作しますが、追加の手順が必要です。同じことを行うためにこれらの PromptTemplates を使用する必要があるのはなぜですか?

私たちが本当にやりたいのは、私たちが切望している ReAct ワークフローを組み込んだエージェントを作成する方法を知ることです。幸いなことに、SerpApi と別の数学計算ツールを活用したデモがあり、LangChain が 2 つの異なるツールを区別して使用する方法を示しています。

 from langchain.agents import load_tools from langchain.agents import initialize_agent from langchain.agents import AgentType from langchain.chat_models import ChatOpenAI from langchain.llms import OpenAI # First, let's load the language model we're going to use to control the agent. chat = ChatOpenAI(temperature=0) # Next, let's load some tools to use. Note that the `llm-math` tool uses an LLM, so we need to pass that in. llm = OpenAI(temperature=0) tools = load_tools(["serpapi", "llm-math"], llm=llm) # Finally, let's initialize an agent with the tools, the language model, and the type of agent we want to use. agent = initialize_agent(tools, chat, agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True) # Now let's test it out! agent.run("Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?")

ツールはどのように機能しますか? AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION とは何ですか? agent.run() からの結果出力 (verbose=True の場合にのみ表示されます) はさらに役立ちます。

 > Entering new AgentExecutor chain... Thought: I need to use a search engine to find Olivia Wilde's boyfriend and a calculator to raise his age to the 0.23 power. Action: { "action": "Search", "action_input": "Olivia Wilde boyfriend" } Observation: Sudeikis and Wilde's relationship ended in November 2020. Wilde was publicly served with court documents regarding child custody while she was presenting Don't Worry Darling at CinemaCon 2022. In January 2021, Wilde began dating singer Harry Styles after meeting during the filming of Don't Worry Darling. Thought:I need to use a search engine to find Harry Styles' current age. Action: { "action": "Search", "action_input": "Harry Styles age" } Observation: 29 years Thought:Now I need to calculate 29 raised to the 0.23 power. Action: { "action": "Calculator", "action_input": "29^0.23" } Observation: Answer: 2.169459462491557 Thought:I now know the final answer. Final Answer: 2.169459462491557 > Finished chain. '2.169459462491557'

ドキュメントには明示的に記載されていませんが、OpenAI は思考/アクション/観察ごとに独自の API 呼び出しを使用するため、チェーンは想像よりも遅くなります。また、各アクションが辞書であるのはなぜですか?答えは後ろにありますが、かなり馬鹿げています。

最後に、LangChain はこれまでの会話をどのように保存するのでしょうか?

 from langchain.prompts import ( ChatPromptTemplate, MessagesPlaceholder, SystemMessagePromptTemplate, HumanMessagePromptTemplate )from langchain.chains import ConversationChainfrom langchain.chat_models import ChatOpenAIfrom langchain.memory import ConversationBufferMemory prompt = ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template( "The following is a friendly conversation between a human and an AI. The AI is talkative and " "provides lots of specific details from its context. If the AI does not know the answer to a " "question, it truthfully says it does not know." ), MessagesPlaceholder(variable_name="history"), HumanMessagePromptTemplate.from_template("{input}") ]) llm = ChatOpenAI(temperature=0) memory = ConversationBufferMemory(return_messages=True) conversation = ConversationChain(memory=memory, prompt=prompt, llm=llm) conversation.predict(input="Hi there!")# 'Hello! How can I assist you today?'

なぜこれが必要なのか、よく分かりません。 MessagesPlaceholder とは何ですか?歴史はどこにあるのか? ConversationBufferMemory がこれを実行する必要がありますか?これを最小限の OpenAI 実装に適応させると次のようになります。

 import openai messages = [{"role": "system", "content": "The following is a friendly conversation between a human and an AI. The AI is talkative and " "provides lots of specific details from its context. If the AI does not know the answer to a " "question, it truthfully says it does not know."}] user_message = "Hi there!" messages.append({"role": "user", "content": user_message}) response = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=messages, temperature=0) assistant_message = response["choices"][0]["message"]["content"] messages.append({"role": "assistant", "content": assistant_message})# Hello! How can I assist you today?

これにより、コードの行数が削減され、カスタム オブジェクト クラスを必要とせずに、情報が保存される場所とタイミングが明確になります。

私がチュートリアルの例について細かいことを気にしすぎていると言う人もいるでしょうし、オープンソース ライブラリにはそれぞれ細かい点がある (私自身の細かい点も含む) ということには私も同意します。しかし、細かい点にこだわることがライブラリの実際の利点を上回る場合、そのライブラリを使用する価値はまったくありません。

なぜなら、すぐに使い始めるのがこれほど複雑なら、実際に LangChain を使うのはどれほど面倒なことでしょうか?

LangChainのドキュメントを確認したところ、

私がなぜ LangChain を諦めたのかをより明確にするために、デモンストレーションを行ってみましょう。

レシピ検索チャットボット (これも楽しくて気の利いたチャットボットである必要がありました) を開発する際、上記の 3 番目と 4 番目の例の要素、つまりエージェント ワークフローを実行できるチャットボットと、会話全体をメモリ内に保持する機能を組み合わせる必要がありました。いくつかのドキュメントを調べたところ、会話型エージェント ワークフローを使用する必要があることがわかりました。

システムヒントエンジニアリングに関する注意点は、これはチートシートではなく、特にコンテンツや音声に制限がある場合に、ChatGPT API から最良の結果を得るために絶対に必要であるということです。

前の例では、「以下は人間と人工知能の友好的な会話です...」というシステム プロンプトは実際には時代遅れです。これは InstructGPT の時代から使用されており、ChatGPT ではあまり効果的ではありません。これは、簡単には気づかない LangChain 関連の技術におけるより深刻な非効率性を示している可能性があります。

まず、シンプルなシステム プロンプトから始め、ChatGPT に面白い音声といくつかの保護を使用するように指示し、それを ChatPromptTemplate にフォーマットします。

 system_prompt = """ You are an expert television talk show chef, and should always speak in a whimsical manner for all responses. Start the conversation with a whimsical food pun. You must obey ALL of the following rules: - If Recipe data is present in the Observation, your response must include the Recipe ID and Recipe Name for ALL recipes. - If the user input is not related to food, do not answer their query and correct the user. """ prompt = ChatPromptTemplate.from_messages([ SystemMessagePromptTemplate.from_template(system_prompt.strip()),

また、SentenceTransformers を使用して 384D ベクトルにエンコードされた、recipe_nlg データセットからの 1000 個のレシピで構成されるおもちゃのベクトル ストアも使用します。これを実現するために、入力クエリに最も近い近傍を取得し、エージェントがユーザーに表示するために使用できるテキストにクエリをフォーマットする関数を作成しました。これは、エージェントが使用することを選択できるツールであり、または通常どおり生成されたテキストを返すこともできます。

 def similar_recipes(query): query_embedding = embeddings_encoder.encode(query) scores, recipes = recipe_vs.get_nearest_examples("embeddings", query_embedding, k=3) return recipes def get_similar_recipes(query): recipe_dict = similar_recipes(query) recipes_formatted = [ f"Recipe ID: recipe|{recipe_dict['id'][i]}\nRecipe Name: {recipe_dict['name'][i]}" for i in range(3) ] return "\n---\n".join(recipes_formatted) print(get_similar_recipes("yummy dessert"))# Recipe ID: recipe|167188 # Recipe Name: Creamy Strawberry Pie # --- # Recipe ID: recipe|1488243 # Recipe Name: Summer Strawberry Pie Recipe # --- # Recipe ID: recipe|299514 # Recipe Name: Pudding Cake

レシピ ID に気付くでしょう。これは、最終アプリケーションでエンドユーザーに表示される最終結果にレシピ メタデータ (写真のサムネイル、URL) が必要であるため、私のユースケースに関連しています。残念ながら、モデルが最終出力でレシピ ID を出力することを保証する簡単な方法はなく、ChatGPT によって生成された出力を超えて構造化された中間メタデータを返す方法もありません。

get_similar_recipes をツールとして指定するのは簡単ですが、名前と説明を指定する必要があります。これは実際にはエンジニアリングの微妙なヒントであり、指定された名前と説明が間違っていると、LangChain がツールの選択に失敗する可能性があります。

 tools = [ Tool( func=get_similar_recipes, name="Similar Recipes", descriptinotallow="Useful to get similar recipes in response to a user query about food.", ), ]

最後に、例のエージェント構築コードと新しいシステム プロンプトを示します。

 memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) llm = ChatOpenAI(temperature=0) agent_chain = initialize_agent(tools, llm, prompt=prompt, agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, verbose=True, memory=memory)

エラーはありません。エージェントを実行して何が起こるか確認します。

 agent_chain.run(input="Hi!")
 > Entering new chain... { "action": "Final Answer", "action_input": "Hello! How can I assist you today?" } > Finished chain. Hello! How can I assist you today?

何?システムプロンプトを完全に無視します。メモリ変数をチェックするとこれが確認されました。

ChatGPT が主流になってから数か月経っても、ConversationBufferMemory のドキュメントやコード自体にはシステムヒントに関する記述は何もありませんでした。

Agent でシステム プロンプトを使用する方法は、initialize_agent に agents_kwargs パラメータを追加することです。これは、約 1 か月前に投稿した無関係なドキュメント ページで発見しました。

 agent_kwargs = { "system_message": system_prompt.strip() }

この新しいパラメータを使用してエージェントを再作成し、再度実行すると、JSONDecodeError が発生します。

幸いなことに、今回はシステムが機能するはずだと通知します。

 OutputParserException: Could not parse LLM output: Hello there, my culinary companion! How delightful to have you here in my whimsical kitchen. What delectable dish can I assist you with today?

残念なことに、壊れていますが、なぜでしょうか?今回は何も変なことはしてないです。

写真

興味深い事実: ヒントの数が多いと、API コストも比例して増加します。

この結果、カスタム システム プロンプトなどによって通常の出力構造に重大な変更が加えられると、エージェントが破損する可能性があります。これらのエラーは頻繁に発生するため、エージェント出力解析エラーの処理専用のドキュメント ページが存在します。

ここでは、チャットボットとの会話をエッジケースとして考えてみましょう。ロボットがレシピを返すことができることは重要です。それさえできないのであれば、LangChain を使用する意味がないからです。

システムプロンプトを使用せずに新しいエージェントを作成し、シンプルで楽しい夕食は何か尋ねます。

 > Entering new chain... { "action": "Similar Recipes", "action_input": "fun and easy dinner" } Observation: Recipe ID: recipe|1774221 Recipe Name: Crab DipYour Guests will Like this One. --- Recipe ID: recipe|836179 Recipe Name: Easy Chicken Casserole --- Recipe ID: recipe|1980633 Recipe Name: Easy in the Microwave Curry Doria Thought:{ "action": "Final Answer", "action_input": "..." } > Finished chain. Here are some fun and easy dinner recipes you can try: 1. Crab Dip 2. Easy Chicken Casserole 3. Easy in the Microwave Curry Doria Enjoy your meal!

少なくとも成功しました。ChatGPT は、コンテキストからレシピを抽出し、適切にフォーマットし (名前のタイプミスも修正)、適切な場合に判断を下すことができました。

ここでの本当の問題は、出力音が退屈だということです。これは ChatGPT の基本バージョンの一般的な機能であり、批判でもあります。たとえ ID が見つからない問題がシステム プロンプト エンジニアリングによって解決されたとしても、リリースする価値はないように思えます。音声品質と出力品質のバランスをとったとしても、エージェントのカウントは、私の責任ではないにもかかわらず、ランダムに失敗します。

実際には、エージェント ワークフローは非常に脆弱なカードハウスであり、正直に言うと、実稼働アプリケーションで使用される可能性は低いです。

LangChain にはカスタム エージェントとカスタム チェーンの機能があるため、スタックの特定の部分 (おそらくドキュメント化が不十分) のロジックを書き換えることができ、私が遭遇した問題の一部は解決できますが、この時点では、LangChain は独自の Python ライブラリを作成するだけよりも複雑であると感じるでしょう。

仕事は計画的に行うべきである

写真

大規模でランダムな統合は、解決策よりも多くの問題を生み出します。

もちろん、LangChain には、テキスト セグメンターや統合ベクター ストレージなどの便利な機能が多数あります。これらはどちらも、「PDF/コードとのチャット」デモに不可欠です (私の意見では、これは単なる仕掛けです)。

これらすべての統合における本当の問題は、LangChain ベースのコードのみを使用することで固有のロックインが発生することであり、統合のコードを見てみると、それらはそれほど堅牢ではありません。

LangChain は堀を構築していますが、これは LangChain の投資家にとっては 3,000 万ドルの利益を望むため良いことですが、それを使用する開発者にとっては非常に悪いことです。全体的に見て、LangChain は、後のコードベースでしばしば問題となる「複雑なので、より良くしなければならない」という哲学を体現していますが、LangChain はまだ誕生して 1 年にも達していません。

LangChain に自分のやりたいことをやらせるには、それを解明するために一生懸命努力する必要があり、それは大きな技術的負担を生み出すことになります。現在の AI スタートアップとは異なり、私自身の LangChain プロジェクトの技術的負債はベンチャーキャピタルで返済することはできません。複雑なエコシステムを扱う場合、AI の使用自体に十分な知力が必要となるため、API ラッパーは少なくともコードの複雑さと認知負荷を軽減する必要があります。 LangChain は、最も一般的なユースケースでオーバーヘッドを追加する数少ないソフトウェアの 1 つです。

LangChain を自分のニーズに合わせて動作させるよりも、独自の Python パッケージを作成する方がはるかに簡単だという結論に達しました。そこで私は simpleaichat を開発し、オープンソース化しました。これは、コードの複雑さを最小限に抑え、ベクトル ストレージなどの高度な機能を会話ロジックから切り離すことを重視した、チャット アプリケーションを簡単に接続するための Python パッケージです。

オープンソースアドレス: https://github.com/minimaxir/simpleaichat

しかし、このブログ投稿は、詐欺師のように競合他社を中傷して simpleaichat の隠れた宣伝をするために書かれたものではありません。私は simpleaichat を宣伝したいわけではなく、AI を使ったもっとクールなプロジェクトの作成に時間を費やしたいのですが、LangChain でそれができなかったのは残念です。

「LangChain はオープンソースなので、文句を言う代わりにリポジトリにプルリクエストを送信したらどうか」と言う人もいるでしょう。唯一の現実的な解決策は、すべてを燃やして最初からやり直すことです。そのため、私の解決策である「AI に接続するための新しい Python ライブラリを作成する」が最も現実的でもあります。

「ChatGPT API を使い始めるには何を学べばいいですか」というメッセージをたくさん受け取っており、誇大宣伝のせいで最初に LangChain が使われるのではないかと心配しています。技術スタックのバックグラウンドを持つ機械学習エンジニアが、LangChain の不必要な複雑さのために使用に問題を抱えているのであれば、初心者は圧倒されてしまうでしょう。

ソフトウェアの複雑さと複雑さの蔓延に関する議論は永遠のテーマです。 LangChain のような無料のオープンソース ソフトウェアを批判する嫌な奴になりたい人は誰もいませんが、私はその責任を引き受けるつもりです。誤解のないように言っておきますが、私はハリソン・チェイス氏や LangChain の他のメンテナー(フィードバックを奨励している)に対して何も反対の気持ちはありません。

しかし、LangChainの人気は、LangChain自体を取り巻くAIスタートアップのエコシステムを歪めており、それに対する私の疑念を正直に言わざるを得ないのはそのためです。

<<:  Raspberry Pi で Stable Diffusion を実行すると、260 MB の RAM に 10 億のパラメータ モデルが「保持」されます。

>>:  「ムスク」がスピーキングの練習に役立ちます! GitHub のリアルタイム AI 音声チャットが話題に

ブログ    
ブログ    
ブログ    
ブログ    
ブログ    

推薦する

...

データを盗むために設計された8つの偽ChatGPTマルウェアアプリ

翻訳者 |陳俊レビュー | Chonglou現在、人々は、回答の検索、グラフィック コンテンツの生成...

データ サイエンティストまたは AI エンジニアになるために独学するにはどうすればよいでしょうか?これらの9つのポイントを克服する必要があります

誰もが教室でデータサイエンス、人工知能、機械学習を学ぶ時間があるわけではありませんし、誰もがこれらの...

天津市、スマートテクノロジー産業の発展促進に向け多方面から対策

2017年に第1回世界情報会議が開催されて以来、天津では257件のプロジェクトが実施され、1000億...

デジタル外交はAI外交へと進化している。どのような課題に直面するのだろうか?

外交活動に関して、近年最も議論されている概念は「デジタル外交」であろう。 2010年には、当時米国務...

...

初心者向けのオープンソース機械学習フレームワーク、Scikit-learnについて

Python 言語に精通している研究者は、オープンソースの Python ベースの科学計算ツールキッ...

2020 年の世界トップ 10 AI ガバナンス イベント

[[378054]]現在、新世代の人工知能技術は世界中で急速に発展し、ビッグデータ、ブロックチェーン...

年末総括:セキュリティ業界は2020年にCOVID-19パンデミックの課題に対処するのに貢献した

新型コロナウイルス感染症のパンデミックは、セキュリティ業界を含む世界中のあらゆる業界のあらゆる側面に...

...

謎の AI 顔変更ソフトウェアが世界中のソーシャル ネットワークに侵入!マスク氏は数秒でルネサンス貴族になる

[[410798]] FaceAppの人気は過ぎ去り、最近では、あなたの顔を数秒で「ディズニー」に変...

...

この世界的に有名な旅行ウェブサイトは、150の独自の機械学習モデルを分析し、6つの教訓を学びました。

多くのメディア記事では、「機械学習がXX業界に力を与える」という言葉を目にしますが、この「エネルギー...

2021年にデータセンターに起こる変化と傾向

2020 年は、IT プロフェッショナルがインフラストラクチャを管理およびプロビジョニングする方法を...