StreamlitとChainlitでlangchainのAgentを試す(その1)

2024/02/28に公開

(その2を公開しました)

はじめに

前からAgentをチャットボットとして使ってみたいと思っていたのですが、Agentの途中経過を確認するためのUIが用意できないため、なかなか実戦投入できていませんでした。

しかし、実はCallbacksという仕組みを使えば、Agentの途中経過をStreamlitのチャットUI上に表示できることがわかったので、今回はそちらを試してみました。

また、これの調査の途中に、Chainlitというチャットボット作成に特化したライブラリがあることがわかったので、それも合わせて試してみました。

今回動かしたコードは以下にありますので、興味があればご覧ください。
※ 動かすためにはOpenAIのAPIキーが必要です。

https://github.com/0msys/agent-test

Agentとは?

通常、LLM(Large Language Models)は入力に対して出力を返すだけなので、実行できるタスクは自然と言語生成に限られます。
これだけもすごいことなのですが、やはりSFのように色々なことを話しかけただけでやってほしくなります。

こういった思いを叶えるための取り組みの一つがAgentです。
Agentの動きを簡単に説明すると以下のような流れになります。

まず、AgentにはあらかじめWeb検索だったり計算器だったりのToolを渡しておきます。
ユーザーからの質問を受け取ると、Agentは持っているToolと照らし合わせて、どうすればその質問に答えられるかを考えます。(←ここにLLMが使われる)

例えば、ユーザーが「東京と大阪の人口を足すと?」と聞いた場合、Agentは「東京の人口」と「大阪の人口」をそれぞれ検索して、その結果を計算器で足せば答えが出ると考えます。
その後、Agentは実際にそれを実行し、結果をユーザーに返します。

こうすることで、単純にLLMに質問するのと比べて正確な結果を受け取ることができますし、
渡しておくToolによって色々なことを実行できるようになります。

詳細は公式のドキュメントを参照してください。
https://python.langchain.com/docs/modules/agents/

非常に便利なAgentなのですが、行動の選択をLLMに任せるため、Toolの選択や使い方を間違える可能性があります。
例えば上の例ですと、東京の人口と大阪の人口を検索せずに、自分の知識で答えることがあります。

そのため、Agentの回答に対しては、途中経過を確認して、正しくToolが使われているかを確認することが重要となります。

Streamlitとは?

Streamlitは、Pythonで簡単にWebアプリケーションを作成できるライブラリです。
公式のドキュメントには以下のように書かれています。

Streamlit is an open-source Python library that makes it easy to create and share beautiful, custom web apps for machine learning and data science. In just a few minutes you can build and deploy powerful data apps. So let's get started!
Streamlit

もともとの目的は機械学習やデータサイエンスのデータを簡単に可視化するためのツールとして作られたようですが、その手軽さから簡単なWebアプリの作成や、チャットボットのUIとしても使われることが増えてきているようです。

Chainlitとは?

ChainlitもStreamlitと同じく、Pythonで簡単にチャットボットを作成できるライブラリです。
Streamlitと違い、チャットボットに特化しており、チャットボットに必要となりそうな機能が最初から組み込まれています。
公式のドキュメントには以下のように書かれています。

Chainlit is an open-source Python package to build production ready Conversational AI.
Chainlit

本番運用を意識して作られているためUIも洗練されており、チャットボットのみを作成する場合はこちらの方が使いやすそうです。

langchainのAgentを試す(Straemlit)

まずはStreamlitの方を試してみます。

実際に業務等で使えるようにしていきたいので、Agent executorにmemoryを持たせることで、継続会話ができるようにしました。

参考にしたのは主に以下のページです。

  • Agent executorの例

https://python.langchain.com/docs/modules/agents/agent_types/openai_functions_agent

  • Streamlitへのcallbacksの組み込み例

https://python.langchain.com/docs/integrations/callbacks/streamlit

  • Streamlitのチャット履歴の組み込み例

https://python.langchain.com/docs/integrations/memory/streamlit_chat_message_history

作成したコード

https://github.com/0msys/agent-test/blob/f7919213d6d06b56beaaa0b7db6840f11071cb60/src/streamlit.py

動作確認

callbackによって中間の思考過程が表示され、duckduckgo_searchが呼ばれ、検索結果から応答が生成されていることが確認できました。
memoryによって、継続的な会話が可能になっていることも確認できます。

langchainのAgentを試す(Chainlit)

次にChainlitの方を試してみます。
以下のページを参考にしました。

  • langchainをとChainlitの統合例

https://docs.chainlit.io/integrations/langchain

  • ChainlitでMRKLを使う例

https://docs.chainlit.io/examples/mrkl

作成したコード

https://github.com/0msys/agent-test/blob/f7919213d6d06b56beaaa0b7db6840f11071cb60/src/chainlit.py

Chainlit自体使うのが初めてで結構苦戦しましたが、最終的には上記のコードで動作するようになりました。

チャット履歴の表示等のUI要素を自分で作成する必要がないため、Streamlitよりも若干コードが少ないです。
(中身がシンプルすぎて誤差ですが・・・)

動作確認

こちらもcallbackによって中間の思考過程が表示され、duckduckgo_searchが呼ばれ、検索結果から応答が生成されていることが確認できました。
memoryによって、継続的な会話が可能になっていることも確認できます。

ただ、こちらではStreamlitでできていたStreaming表示ができませんでした。
しかもLLMの応答がJsonでそのまま表示され、文字コードがそのまま表示されているので、動いてることしかわからないです。
単純なOpenAI APIを使った場合や、AgentExecutorではないAgentを使った場合はできるみたいなので、そのうちできるようになるかもしれませんし、もしかしたら私の使い方が間違っているだけかもしれません。
Chainlitは新しいライブラリなので、探してみてもなかなか情報が見つかりませんでした。

まとめ

StreamlitとChainlitを使って、langchainのAgentを試してみました。
どちらを使用しても、Agentの途中経過を表示できることが確認できたので、今後Agentベースのチャットボットを作ってみたいと思います。

今回わかったそれぞれのメリット/デメリットを簡単にまとめておきます。

  • Streamlitのメリット

    • Streamingで表示できる
    • UI要素の配置が自由にできる
  • Streamlitのデメリット

    • 途中経過は次のメッセージを送ると消えてしまう
      • 保持したいならチャット履歴に保持する仕組みを自分で作る必要がある
    • UIとロジックのコードの混在が起こりやすい
    • 動作が比較的重い
  • Chainlitのメリット

    • 以前の会話の途中経過も保持される
    • UI要素を自分で作る必要がない
    • デザインが洗練されていて見栄えが良い
    • 動作が比較的軽い
    • チャットボットアプリに必要な多くの機能が最初から組み込まれている
      • 「New Chat」ボタン、入力履歴、添付ファイル等
  • Chainlitのデメリット

    • Streamingで表示できない
    • LLMの応答がJsonでそのまま表示されて、日本語だと文字化けしてしまう
    • UI要素の配置が自由にできない
    • 新しいライブラリなので情報が少ない

感想

今回Chainlitを初めて使ってみましたが、思っていた以上に完成度の高いライブラリでした。
Streamlitで自分で作らないといけないと考えていた機能が最初から組み込まれていたり、デザインが洗練されていたりと、かなり感動したので、次にチャットボットを作るときはChainlitを使ってみようと思います。

Chainlitはまだまだ情報が少ないので、自分で試してみたことも積極的に記事にしていければと思います。

Discussion