1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【LangChain】LLMアプリで使用していたモデルをGPT-4からClaude 3に乗り換えてみる

Posted at

前書き

Claude 3の性能がGPT-4を超えたというレビューが多く、Xが賑わいを見せていますね。
気になったので自分のWebアプリにも導入して遊んでみました。

自分のアプリはLangChainを用いて実装していましたが、今までOpenAI製のモデルしか使ったことがなく、他社製のモデルに切り替える手順、工数感も把握しておきたかったというのもありました。

切り替え手順

LangChainを使って実装していればモデルの切り替えは一瞬でできました。
以下の手順を実行して完了です。

項番 内容 作業概要
1 Anthropicのパッケージをインストール pip install langchain-anthropic
2 Anthropic APIの取得 Webブラウザ上での操作
3 コードの変更 モデル指定箇所の更新

python環境にAnthropicのパッケージをインストール

Anthropicのパッケージをインストールするには、ターミナルやコマンドプロンプトで以下のコマンドを実行します:

pip install langchain-anthropic

パッケージの詳細については、PyPIのlangchain-anthropicページを参照してください。
依存関係の管理を楽にするため、Poetryを使用することもお勧めします。Poetryを使用すると、プロジェクトの依存関係を簡単に管理し、より安定した開発環境を維持できます。

Anthropic APIの取得

AnthropicのAPIキーを取得するには、Anthropicの公式ウェブサイトにアクセスしてユーザー登録を行い、APIキーを生成してください。このキーは、プログラムからAnthropicのLLMにアクセスする際に必要です。

コードの変更

使用しているLLMモデルをGPT-4からClaude 3に変更するためには、コード内でモデルを指定している部分を更新する必要があります。

現在(2024-03-17)のモデル対応表は以下です。Langchainから使用する場合は右側の文字列を指定してあげればOKです。

  • Claude 3 Opus -> claude-3-opus-20240229
  • Claude 3 Sonnet -> claude-3-sonnet-20240229
  • Claude 3 Haiku -> claude-3-haiku-20240307

実際の切り替えコード

diff --git a/interpreter/convert.py b/interpreter/convert.py
index ee17ab0..0671a8f 100644
--- a/interpreter/convert.py
+++ b/interpreter/convert.py
@@ -1,8 +1,10 @@
 from langchain_openai import ChatOpenAI
+from langchain_anthropic import ChatAnthropic
 from langchain_core.output_parsers import StrOutputParser
 from langchain.callbacks.tracers import ConsoleCallbackHandler
 
 # Tools
+import os
 from dataclasses import dataclass
 
 # MyLibrary
@@ -32,7 +34,7 @@ def _print_articles(articles: List[SearchArticle]) -> None:
         print(f"Search_Word: {article.search_word} \nTitle: {article.title} \nPrint_Contents: {article.html_content} \n")
 
 
-def _summarize_each_html_contents(llm: ChatOpenAI, articles: List[SearchArticle], summary_word_count: int) -> List[SearchArticle]:
+def _summarize_each_html_contents(llm: ChatOpenAI|ChatAnthropic, articles: List[SearchArticle], summary_word_count: int) -> List[SearchArticle]:
     prompt = summarize_pmt()
     output_parser = StrOutputParser()
     chain = prompt | llm | output_parser
@@ -56,7 +58,7 @@ def _integrate_search_articles(articles: List[SearchArticle]) -> IntegratedSearc
     return summarized_article
 
 
-def _convert_integrated_search_article_into_blog_posting(llm: ChatOpenAI, integrated_search_article: IntegratedSearchArticle, comment_num: int) -> BlogPosting:
+def _convert_integrated_search_article_into_blog_posting(llm: ChatOpenAI|ChatAnthropic, integrated_search_article: IntegratedSearchArticle, comment_num: int) -> BlogPosting:
     prompt_class = MakeConversationPrompt()
     prompt = prompt_class.pmt_tmpl()
     chain_input = prompt_class.variables(integrated_search_article.search_word, integrated_search_article.contents, "ordinary", comment_num)
@@ -68,7 +70,7 @@ def _convert_integrated_search_article_into_blog_posting(llm: ChatOpenAI, integr
     return BlogPosting(integrated_search_article.search_word, resp_title, resp_contents)
 
 
-def _make_title_from_contents(llm: ChatOpenAI, contents: str) -> str:
+def _make_title_from_contents(llm: ChatOpenAI|ChatAnthropic, contents: str) -> str:
     prompt_class = MakeTitlePrompt()
     prompt = prompt_class.pmt_tmpl()
     chain_input = prompt_class.variables(article_contents=contents)
@@ -78,11 +80,22 @@ def _make_title_from_contents(llm: ChatOpenAI, contents: str) -> str:
     return llm_resp
 
 
+def _create_llm_model() -> ChatOpenAI | ChatAnthropic:
+    use_model = os.environ["LLM_MODEL_NAME"]
+    if use_model == "GPT":
+        # 環境変数OPENAI_API_KEYを参照します。
+        llm = ChatOpenAI(model_name="gpt-4-0125-preview", temperature=0.7, request_timeout=180)
+    elif use_model == "CLAUDE":
+        # 環境変数ANTHROPIC_API_KEYを参照します。
+        llm = ChatAnthropic(model_name="claude-3-haiku-20240307")
+    return llm
+
+
 def convert_search_articles_into_blog_posting(articles: List[SearchArticle], summary_word_count: int = 1000, comment_num: int = 25, need_summary: bool = False) -> BlogPosting:
     """
     summary_word_count: 記事要約の文字数。この文字数*要約記事数(だいたい3くらい)がLLMに入力される。
     """
-    llm = ChatOpenAI(model_name="gpt-4-0125-preview", temperature=0.7, request_timeout=180)
+    llm = _create_llm_model()
     each_articles = _summarize_each_html_contents(llm, articles, summary_word_count) if need_summary else articles
     _print_articles(each_articles)
     integrated = _integrate_search_articles(each_articles)

コレ↑だけで動くようになりました。今後さらに切り替え候補モデルが増えることを考慮してモデル切り替え用関数_create_llm_model()を作っていますが、もっと簡単に切り替えたい場合は

llm = ChatOpenAI(model_name="gpt-4-0125-preview", temperature=0.7, request_timeout=180)

llm = ChatAnthropic(model_name="claude-3-haiku-20240307")

に変えるだけでも大丈夫です。

上記変更をしたコミットログ

Claude 3 Haikuで実行してみた感想

python main.py 桜 開花予想 2024 東京

このコマンドは、2024年の東京における桜の開花予想についての情報をWebから取得し、その情報を基にClaude 3 Haikuがブログ記事を生成します。

このあたりの動作の詳細は自分のWebアプリ紹介記事を参照していただけるとより理解しやすいかと思います。

結果としては以下のようなファイルが出来上がりました。

スクリーンショット 2024-03-17 19.13.59.png

結論として、上記のように、Claude 3MaxOutput=4092トークン制限に引っかかってしまい、最後まで書いてくれませんでした。

スクリーンショット 2024-03-17 21.11.24.png

この制限が存在するため、後続の処理がある場合、エラーになる可能性があります。
記事が完全には生成されないことがあるため、より短い内容に調整するか、複数回に分けて生成する必要があることがわかりました。

生成クオリティ

Claude3(claude-3-haiku-20240307)が書いてくれた内容を見てみると、内容として破綻している感じはありませんでした。

生成されたタイトル: 東京の桜の開花予想をチェック!2024年の最新情報

:laughing: 東京の桜の開花はいつ頃かな?毎年楽しみにしているけど、なかなかタイミングが合わないんだよね。

:joy: >>1
東京は平年よりも少し早めに開花するみたいだよ。3月下旬頃が見頃になるって予想されているみたいだよ。

:smiley: 去年はめちゃくちゃ早く咲いたからね。今年はどうなるか楽しみだわ。

:smiley: 都内の主要な桜スポットの開花と満開の予想を見てみると、だいたん3月下旬から4月上旬にかけて見頃を迎えそうだね。

:laughing: >>2
そうなんだ、それはうれしいニュースだわ。外出の機会も増えそうだし、都心部の桜を散策するのが楽しみだ。

:smiley: >>5
そうだね。定番のスポットはもちろん、意外な場所の桜も見つかるかもしれないよ。今年は例年よりゆっくり桜を楽しめそうだ。

:smiley: 都内の桜の開花予想見てきた。やっぱり私が行きたい上野公園は3月下旬に開花するみたい。お弁当も用意して、のんびり花見に行きたいな。

:angry: >>7
上野公園は毎年人気ありますからね。でも、人混みが嫌だったら、もしかしたらあまり知られていない隠れた桜スポットを見つけられるかもしれないよ。

用途にもよりますが、例えばブログ記事のベースとなる下書きを頼む程度であれば、破綻してなければ良いかなと思いますので、そういった用途にはClaude3 Haikuの時点で十分な性能を持っています。

ちなみにGPT-4 Turbo(gpt-4-0125-preview)で実行すると↓のような感じです。

生成されたタイトル: 2024年東京の桜開花予想とお花見計画に対する期待と懸念

:laughing: 今年の桜の開花予想、もう出てる?
東京でお花見したいんだけど、計画立てたいなあ。

:joy: >>1
実はもう出てるよ!東京は3月18日に開花するって予想されてるみたい。全国的にも平年より早い開花が予想されてるんだって。

:smiley: あれ、でも他のところでは3月22日って見た気がする…どっちが正しいんだろう?

:angry: >>3 東京の開花予想日はいくつかの情報源で差があるみたい。ウェザーニュースは3月18日、NHKでは3月22日って予想してる。

:scream: そういえば、去年は記録的な早さで開花したって話だけど、今年はどうなんだろう?

:joy: >>5
今年は全国的に平年より早い開花が予想されてるけど、東京は特に早いみたい。でも、開花直前の天候によっては予想が変わることもあるから注意が必要だね。

:laughing: 開花日って結構気温に左右されるよね。今年は暖冬だったから、その影響で早まってるのかな?

:neckbeard: 満開の桜を見るタイミングって計画するの難しいよね。開花予想からどれくらいで満開になるんだろう?

:joy: >>7
そうそう、この冬は全国的に平年より高い気温だったから、桜の生長も早まってるみたい。ただ、冬の寒波で気温の変動があったから、地域によっては開花のタイミングが違うかも。

:angry: >>8
だいたい開花から5日〜2週間ほどで満開を迎えることが多いみたい。でも、今年みたいに平年より早い開花だと、そのペースも変わるかもしれないね。

なんとなくこっちの方が詳しく書いてくれてますかね?
GPT-4の出力はより詳細な情報を提供してくれる傾向にあるように感じました。

実行時間

スクリーンショット 2024-03-17 19.57.00.png

青線がGPT-4 Turboの実行ログ。緑線がClaude 3 Haikuの実行ログです。
①は記事タイトル生成タスク、②は記事内容生成タスクです。

長い記事の生成や、複雑な質問への回答など、処理に時間がかかるタスクでは、Claude 3 HaikuGPT-4 Turboよりも大幅に高速に動作することが観察されました。②ではClaude 3 HaikuGPT-4 Turboの10倍近く早くなってますね。

LangSmithを使用して計測しました。神ツールなので使っていない方がいればぜひ使ってみてください。

実行料金

LangSmithにClaude 3のコスト計算機能が実装されていないようで、上記実行ログ画像にコストが表示されませんでした。参考として、現在(2024-03-17)の規定料金を載せておきます。

Model Input Output
GPT-3 Turbo $0.50 / 1M tokens $1.50 / 1M tokens
GPT-4 Turbo $10.00 / 1M tokens $30.00 / 1M tokens
Claude 3 Haiku $0.25 / 1M tokens $1.25 / 1M tokens
Claude 3 Opus $15.00 / 1M tokens $75.00 / 1M tokens

まとめ

途中まで生成されている出力のクオリティ的にはHaikuの時点でGPT-4 Turboに劣らないレベルで生成できており、これからに期待が持てますね。
Opusは高そうだったので検証してませんm()m (値段を考えるとGPT-4 TurboとはOpusで比較するべきだったかも...)

ただ、トークンの出力制限が4096なのは結構厳しめの印象で、現状だとまだここがネックで切り替えづらいこともあるかなと感じました。

この制限が緩和された場合は、Claude 3GPT-4を差し置いて第一候補のモデルになる人も多くいるかと思いました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?