2024.12.24
ビジネスが急速に変化する現代は「OODAサイクル」と親和性が高い 流通卸売業界を取り巻く5つの課題と打開策
リンクをコピー
記事をブックマーク
大嶋勇樹氏:ということで、ざっとOpenAIのChat APIについて復習してきましたが、ここからはLangChainでのOpenAIのChat APIの使い方の基本を見ていきます。
まずそもそものLangChainについて簡単に紹介すると、LangChainは大規模言語モデルを使ったアプリケーション開発のフレームワークです。実装としてはPythonとJavaScript、TypeScriptの2つがあります。機械学習関連分野によくあることですが、Pythonのほうがやはり開発は活発です。
今日もPythonを使って、3日前(登壇時点)のリリースのバージョンを使っていきます。LangChainはほぼ毎日新しいバージョンがリリースされているので、今はたぶん(バージョン)218とかまで出ているんじゃないかと思いますが、3日前のバージョンを使わせてもらいます。
LangChainは要約やチャットボット、ドキュメントへのQ&Aなど、LLMを使ったさまざまなアプリケーションで活用できるフレームワークとなっています。
そんなLangChainですが、モジュールがいろいろ整理されています。現在だとLanguage modelsやPrompt templates、Chain、Data connection、Memory、Agentsと、大きなモジュールの整理があって、その中にたくさんクラスが存在するように実装されています。
そして、このLangChainで先ほど紹介したOpenAIのChat APIを使う時は、ChatOpenAIというクラスを使います。
このあたりはドキュメントを見ていくともちろん載っていることではありますが、LangChainでChatOpenAIを使う時は、実装方法が2つあります。
スライドだと見にくいかもしれないので、コードを実際に見てみようと思います。(画面を示して)これがLangChainでChatOpenAIというクラスを使ってgpt-3.5-turboのモデルを呼び出す、使う例です。
下の部分はいったんコメントアウトします。
messagesとして、リストの形式でHumanMessage、つまり人間側のメッセージとして「content="Hello!"」「Hello!」と言います。それをchat(messages)のように、APIを呼び出して結果を表示しています。これを実行してみようと思います。
このコードを実行すると……。実行結果は毎回多少違う可能性はありますが、gpt-3.5-turboからの応答が返ってきますね。「Hello!」に対して、「Hello! How can I assist you today?」ということで、こんな応答が返ってきます。これがLangChainでgpt-3.5-turboを呼び出す、すごくシンプルなコードです。
実は呼び出し方はほかにもあります。このほかにも、下に書いてあるように、「chat = ChatOpenAI」に対してchat(messages)と呼ぶ代わりに、chat.predictのように呼び出すこともできます。上側をコメントアウトして、呼び出せることをもう一度実行して確認してみようと思います。
たまたまtemperatureが0というのもあって同じような応答が返ってきましたが、この「.predict」という呼びだし方もできるんですね。chat(messages)でもchat.predictでも、このChatOpenAIは呼び出せます。
実はこれが同じような挙動になっているということを、LangChainのソースコードリーディングのまあまあ簡単ではありますが、1つの例として見ていこうと思います。
(画面を示して)まず、コードが2種類使えるということを見て思うことは、上の「HumanMessage(content="Hello!")」については、おそらく内部で「"role": "user", "content": "Hello!"」みたいに組み立てられて実行されています。
一方で下のpredictについては、HumanMessageのような……。このメッセージが人間のメッセージなのか……。HumanMessage以外にAIMessageでも使えるんですが、そういうのを指定せずに呼んでいます。なので、たぶん内部で勝手にHumanMessageと解釈されて、上と同じような呼び出しになっているんじゃないかと想像できるかと思います。
本当にそうなっているかを、ソースコード上で見ていこうと思います。比較的簡単なテーマではありますが、ソースコードを読むにあたってChat APIの形式がわかっていると、なんとなくこの呼び出し方は疑問に思います。もしもどういうことをやろうとしているかイメージがつかないなどあれば、Q&Aなどに質問をもらえれば、少し補足します。
いったんこのテーマでLangChainのソースコードを読んでみようと思います。ここからは資料はなく、実際に画面にLangChainのソースコードを映しながらやっていきます。
(画面を示して)ソースコードを読む時に、やり方はいろいろありますが、まずはGoolge検索で「LangChain GitHub」と検索してみることにします。公式のLangChain……。公式というか、LangChainの「GitHub」のリポジトリが見つかりますね。
ソースコードを読む時にローカルで読むか、GitHubで読むか。人によってやり方はいろいろありますが、GitHub上で見ていくのも楽なので、まずはGitHub上で見ていこうと思います。
今質問をもらっていますが、急ぎじゃなくてもよさそうな内容だと思うので、いったん進めて、いいタイミングで回答できればと思います。
まずGitHub上でこのChatOpenAIクラスの呼び出し方を見ていこうと思いますが、この時どうするか。最初の一歩をどうするかは、いろいろなやり方があると思います。例えばGitHubの検索欄で検索するとか、ソースコードのツリーを見ていくとか、いろいろあると思いますが、特にLangChainのようなアップデートの激しいものを扱う上で僕がお勧めしたいのは、まずはバージョンを合わせることですね。
まずバージョンを合わせるのが一番ポイントだと思います。(今回は)0.0.219ですね。4時間前に最新版がリリースされて、今(画面に)表示されているのは0.0.219か、さらに新しいバージョンです。0.0.219のリリースのところが表示されているので、まずはGitHubのReleasesから、少し過去のバージョンをたどっていきます。
先ほどのサンプルコードで使っているのは0.0.215なので、0.0.215のタグマークをクリックすると、GitHubのトップページ的な、ソースツリーのトップになります。
ここがv0.0.215、URLもv0.0.215となって、その時点のソースコードのツリーの表示になっています。この状態でChatOpenAIクラスの呼び出し方を見ていきます。いったん確認してみると、このChatOpenAIクラスは「from langchain.chat_models」とimportしています。
importしているパスにもヒントになることがけっこうあったりしますね。実際にLangChainのソースツリーのトップを見ると、重要なソースコードは、おそらくlangchain以下にありそうだなと(わかります)。ここを見ていきます。
するといろいろなモジュール、ディレクトリに括られているわけですが、chat_modelsというディレクトリが見つかるので、これを見てみます。
エディタなどのように左側にも出ていますね。langchain以下のchat_models以下を開いてみました。
この中に、ChatOpenAIクラスがあるんじゃないかと当たりをつけて見ていこうと思います。(画面を示して)これを見ると、openai.pyにあるんじゃないかとなんとなく思えると思います。もっと確実に検索したりして、ちゃんと探す方法も後で説明しようと思いますが、僕は「なんとなくここにありそうだな」という当たりをつけて見ていくこともよくあります。
openai.pyを開くと、右側にどんなクラスがあるかとか……。最近のGitHubはこのあたりをわかりやすく出してくれるんですが、ChatOpenAIクラスがあることが出ていますね。
実際に下側を見ていくか右をクリックすると、openai.pyにChatOpenAIというクラスがあることがわかりました。(画面を示して)こんなふうに、ChatOpenAIクラスを見つけられました。
今の目標は、このchat(messages)とchat.predictがどんな対応にあるかを見ていきたいわけですが、まずchat(messages)から見ていこうと思います。
このchat(messages)は、文法的にPythonの何なのかが1個の大事な要素です。これはPythonの実践入門みたいな本とかを読んだことがあれば知っていることだと思うんですが、chat.__call__というものと同じですね。
このchat(messages)は、call、特殊メソッドといったりしますが、これを呼び出しているわけです。これが省略されているようなものです。(画面を示して)実際にこうやって書いてあげても動くはずです。同じような応答が返ってきますね。
このChatOpenAIのインスタンスに対するchat(messages)という呼び出しは、実は__call__というメソッドの呼び出しでした。なので、ChatOpenAIの__call__というメソッドを探していきたいわけです。そうすれば、実装が見つかるはずです。
GitHubの設定次第だったかもしれませんが、GitHubを使っていると、シンボルの一覧みたいなものが右側に出て、ChatOpenAIクラスに定義されているメソッド、defで定義されている関数を見ることができますが、__call__は見当たりません。
これはなぜかというと、ChatOpenAIはBaseChatModelを継承しているからです。BaseChatModelを継承、拡張して、ChatOpenAIになっているからですね。
なので、ここではBaseChatModelという親のクラスを見にいきます。(画面を示して)最近のGitHubは、選択すると右側の定義に移動するようなリンクが表示されるので、これでBaseChatModelを見ていきます。
隣のタブで開きました。(画面を示して)こんなふうに「class BaseChatModel」が「langchain/chat_models/base.py」というファイルにあることがわかりました。
このBaseChatModelに探していた__call__というメソッドがあるかを見ると……。ありますね。定義されています。
List[BaseMessage]のBaseMessageは、HumanMessageやAIMessageなどが含まれるものですが、__call__はmessagesや、(その他にも)必要に応じていろいろ追加で受け取って、いろいろ実行されていきます。
その中ではgenerateという別のメソッドを呼び出したりしていて、さらにgenerateを深掘りしていくと、「このgenerateの中で実際の文書の生成のAPIを呼んでいそうだな」ということがなんとなく推測できます。
ということで、chat(messages)は__call__という特殊メソッドの呼び出しで、親クラスに(あることを)見つけられました。今度は、これと比較したい、もう1つの呼び出し方のpredictを見ていきます。
predictについても、まずはChatOpenAIクラスの中にpredictというメソッドがあるか見ようとすると、やはりこれもないんですね。
predictについても実は親クラスのほうにあるんじゃないかなと思って、ChatOpenAIの親クラスのBaseChatModelをもう一度見にいきます。BaseChatModelのメソッドを探してみると、predictがありますね。
このpredictが、textという引数を文字列型で受け取るように、こんなふうにタイプヒントが書かれていますね。
そしてその中で処理しています。「self([HumanMessage(content=text)], stop=_stop, **kwargs)」となっていますね。このself()はself.__call__と同じですね。これは__call__という特殊メソッドの呼び出しです。
つまり、chat.predictは、中でchat(messages)をやっていることが、ソースコードで読み取れました。
確かに受け取った文字列をHumanMessageに詰め込んで、__call__のほうの特殊メソッドを呼んでいる挙動になっていますね。
ということで、最初の一歩として比較的シンプルな例ですけれども、ChatOpenAIクラスの2つの呼び出し方がちゃんと中の実装で互換性があるというか、もう一方の呼び出しに対応しているのを見てきました。
(次回につづく)
関連タグ:
大嶋勇樹氏が解説する「OpenAIの文書生成API」の基本 モデルの種類、APIの種類と違い、今使うべきもの
「chat(messages)」と「chat.predict」は同じ挙動を示すのか? ChatOpenAIクラスの2つの呼び出し方の互換性
「GitHub検索欄を使う」「定義から見る」「grepコマンドを使う」 「ソースコードを読む」以外のChatOpenAIクラスの見つけ方
LangChainの「Chain」や「Agent」を使う時は注意が必要 「Chat APIの形式を活かした実装かどうか」の確認方法
時間を溶かさないためにもLangChainの過去バージョンは確認しよう ネット上では公開されていないドキュメントの見つけ方
2025.01.09
マッキンゼーのマネージャーが「資料を作る前」に準備する すべてのアウトプットを支える論理的なフレームワーク
2025.01.08
職場にいる「嫌われた上司」がたどる末路 よくあるダメな嫌われ方・良い嫌われ方の違いとは
2025.01.07
資料は3日前に完成 「伝え方」で差がつく、マッキンゼー流プレゼン準備術
2025.01.10
プレゼンで突っ込まれそうなポイントの事前準備法 マッキンゼー流、顧客や上司の「意思決定」を加速させる工夫
2025.01.06
上司からの「ふわっとした指示」に対し、デキる人がやっていること 4タイプ別で見る、仕事を依頼された時に重要なスタンス
2025.01.08
どんなに説明しても話が伝わらない“マトリョーシカ現象”とは? マッキンゼー流、メッセージが明確になる構造的アプローチ
2025.01.07
1月から始めたい「日記」を書く習慣 ビジネスパーソンにおすすめな3つの理由
2025.01.09
記憶力に自信がない人におすすめな「メモ」の取り方 無理に覚えようとせず、精神的にも楽になる仕事術
2025.01.09
職場に必要なのは「仲良し集団」ではなく「対立」 メンバーのやる気を引き出すチームビルディング理論
2025.01.10
職場にいる「できる上司」と「できない上司」の違いとは 優秀な人が辞めることも…マネジメントのNGパターン