LangChainのChatPromptTemplateでSystemMessage・HumanMessageのプレースホルダーが置換されない理由と対応方法 #LangChain

ジェネラティブエージェンツの大嶋です。

この記事では、LangChainのChatPromptTemplateでSystemMessage・HumanMessageのプレースホルダーが置換されない理由と対応方法を紹介します。

ChatPromptTemplateの基本的な使い方

LangChainのChatPromptTemplateを使用すると、プロンプトのテンプレートを扱うことができます。 以下のコードでは{lang}{message}の箇所がプレースホルダーとして扱われ、prompt.invokeとするとその箇所が置き換えられます。

from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "Speak in {lang}."),
        ("human", "{message}"),
    ],
)

prompt_value = prompt.invoke({"lang": "日本語", "message": "こんにちは"})
print(prompt_value.to_string())

上記のコードの実行結果は次のようになります。

System: Speak in 日本語.
Human: こんにちは

想定通り動作しないコード

ここで、ChatPromptTemplate.from_messagesにSystemMessageやHumanMessageを使用してみます。

from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages(
    [
        SystemMessage("Speak in {lang}."),
        HumanMessage("{message}"),
    ],
)

prompt_value = prompt.invoke({"lang": "日本語", "message": "こんにちは"})
print(prompt_value.to_string())

上記のコードの実行結果は次のようになります。

System: Speak in {lang}.
Human: {message}

この例では、{lang}{message}の箇所が置換されていません。

この原因を一言で言うと、SystemMessageやHumanMessageのようなBaseMessageを継承したクラスは、テンプレートではなくメッセージを表すためです。

SystemMessagePromptTemplate・HumanMessagePromptTemplate

実はLangChainには、SystemMessageやHumanMessageのテンプレート版であるSystemMessagePromptTemplate・HumanMessagePromptTemplateといったクラスがあります。

ChatPromptTemplateにSystemMessagePromptTemplateやHumanMessagePromptTemplateを与えると、想定通り動作します。

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts.chat import (
    HumanMessagePromptTemplate,
    SystemMessagePromptTemplate,
)

prompt = ChatPromptTemplate.from_messages(
    [
        SystemMessagePromptTemplate.from_template("Speak in {lang}."),
        HumanMessagePromptTemplate.from_template("{message}"),
    ],
)

prompt_value = prompt.invoke({"lang": "日本語", "message": "こんにちは"})
print(prompt_value.to_string())

上記のコードの実行結果は次のようになります。

System: Speak in 日本語.
Human: こんにちは

実は("system", "Speak in {lang}.")SystemMessagePromptTemplate.from_template("Speak in {lang}.")と同じ意味なのです。

SystemMessageやHumanMessageを使ってプレースホルダーが置換されずに困っているときは、最初の例のように("system", "Speak in {lang}.")("human", "{message}")のような書き方をすれば解決ということです。

まとめ

以上、LangChainのChatPromptTemplateでSystemMessage・HumanMessageのプレースホルダーが置換されない理由と対応方法を紹介しました。

この動作で困っている方の参考になれば幸いです。

なお、この記事のコードはGoogle Colab上のlangchain-core==0.3.45で動作確認しました。

参考)ソースコードの該当箇所

LangChainのソースコードの該当箇所が気になる方は、以下のあたりを参照してみてください。