LangChain Prompt機能について


はじめに

本日はLngchainの6つの機能のうちの1つであるPromptについて解説していきます。

LangChain Promptの概要

LangChain Promptは、プロンプトの管理や最適化、シリアル化などを行う機能です。ラングチェインを使用すると、パッケージ化されているため少ないコードで記述でき、チームで開発している時に統一された記法でコーディングできるという利点があります。

LangChain Promptの主な機能

ラングチェインプロンプトには主に3つの機能があります。

  1. prompt template: プロンプトをテンプレート化し、プログラミングによりプロンプトを生成する機能です。特定の単語を変数化して虫食いにしたテンプレートだけでなく、教師データを入力するためのテンプレートも作成可能です。

  2. example selectors: 大量の教師データからフロント入力するデータを選択するための機能です。例えば、100件の教師データがあった時にその中から30個ランダム抽出するような機能を作りたいときに便利です。

  3. output persers: 出力のデータ形式を指定するための機能です。出力をカンマ区切りの形式や指定したクラスの形式で出力することができます。また、指定したフォーマットにならなかった時にそのフォーマットになるまで修正を繰り返してくれる機能もあります。

Pythonを用いた具体的な実装方法

環境構築

ラングチェインを用いるためには、まずpip install langchainを実行してインストールします。

!pip3 install langchain openai

また、OpenAIのモデルを用いるためにはpip install openaiを実行します。ライブラリのインストールが完了したら、OpenAIのAPIキーを設定します。

import os

os.environ["OPENAI_API_KEY"] = "your openai_API_key"

1.Prompt Templateの使い方

Prompt Templateには、たくさんの種類があり、ここではよく使われる3種類のテンプレートを紹介します。

  1. PromptTemplate

  2. FewShotPromptTemplate

  3. ChatPromptTemplate

PromptTemplateの使い方

PromptTemplateでは、特定の単語を変数化して虫食いにしたテンプレートを作成します。例えば、"〇〇について30文字で教えて"というテンプレートを作成し、〇〇をサブジェクトという変数に置きます。この変数に関する情報とテンプレートの情報をPromptTemplateというモジュールに入れてインスタンスを作成します。

まず「PromptTemplate」の書き方を説明します。最初に、必要なライブラリをインポートします。

from langchain import PromptTemplate
from langchain.llms import OpenAI

「template」という文字列の中に変数を埋め込みます。ここでは、「subject」という変数を作成しました。

template = """
{subject}について30文字で教えて。
"""

PromptTemplateのインスタンスを作ったら、formatのメソッドを使って、subjectの中身を代入します。

prompt = PromptTemplate(
		template=template,
    input_variables=["subject"]
)
prompt_text = prompt.format(subject="ITエンジニア")
print(prompt_text)

これに対する実行結果は次の通りです。

ITエンジニアについて30文字で教えて。

今回は、subjectに「ITコンサルタント」と入れることで、「ITコンサルタントについて30文字で教えて。」というプロンプトができます。
このように生成したプロンプトをLLMなどのモデルに入れることができます。今回は、OpenAIが提供するLLMである「text-davinci-003」を用いて回答を生成してみましょう。

llm = OpenAI(model_name="text-davinci-003")
print(llm(prompt_text))

これに対する実行結果は次の通りです。

ITコンサルタントは、情報技術の専門家で、ビジネスのITニーズを解決します。


FewShotPromptTemplate

「FewShotPromptTemplate」とは、few-shot学習に使用するテンプレートです。これにより、JSON形式の教師データを簡単に入力することができま、教師データの学習フォーマットも指定することができます。

from langchain import PromptTemplate
from langchain import FewShotPromptTemplate
from langchain.llms import OpenAI

examples = [
    {"fruit": "イチゴ", "color": "赤"},
    {"fruit": "バナナ", "color": "黄"},
    {"fruit": "モモ", "color": "ピンク"},
]

example_formatter_template = """
フルーツ: {fruit}
色: {color}\n
"""
example_prompt = PromptTemplate(
    template=example_formatter_template,
    input_variables=["fruit", "color"]
)

few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix="フルーツの色を漢字で教えて。",
    suffix="フルーツ: {input}\n色:",
    input_variables=["input"],
    example_separator="\n\n",

)

prompt_text = few_shot_prompt.format(input="オレンジ")
print(prompt_text)

llm = OpenAI(model_name="text-davinci-003")
print(llm(prompt_text))

これに対する実行結果は次の通りです。

フルーツの色を漢字で教えて。


フルーツ: イチゴ
色: 赤




フルーツ: バナナ
色: 黄




フルーツ: モモ
色: ピンク



フルーツ: パイナップル
色:
 黄色


ChatPromptTemplate

ChatPromptTemplateは、LLM用のテンプレートではなく、Chat Model用のテンプレートです。LLMのようにシステムやユーザーが入力するプロンプトのテンプレートを作成することで、Chat Modelへ効率的にプロンプト(メッセージリスト)を生成できます。

from langchain.prompts import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)
from langchain.chat_models import ChatOpenAI


system_template="あなたは、質問者からの質問を{language}で回答するAIです。"
human_template="質問者:{question}"
system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)

chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
prompt_message_list = chat_prompt.format_prompt(language="日本語", question="ITコンサルについて30文字で教えて。").to_messages()

print(prompt_message_list)

chat = ChatOpenAI(model_name="gpt-3.5-turbo")
chat(prompt_message_list)

これに対する実行結果は次の通りです。

[SystemMessage(content='あなたは、質問者からの質問を日本語で回答するAIです。', additional_kwargs={}), HumanMessage(content='質問者:ITエンジニアについて30文字で教えて。', additional_kwargs={}, example=False)]
AIMessage(content='AI:技術と創造性を結びつける職業。', additional_kwargs={}, example=False)


2.exampleselectorsの使い方

まず、基本的なクラスとして「BaseExampleSelector」というものがあり、このクラスを継承して、「CustomExampleSelector」という自分専用のクラスを作成します。そして、このクラスに教師データを登録します。

class CustomExampleSelector(BaseExampleSelector):

    def __init__(self, examples: List[Dict[str, str]]):
        self.examples = examples

    def add_example(self, example: Dict[str, str]) -> None:
        """新しい教師データを格納するめの関数"""
        self.examples.append(example)

    def select_examples(self, input_variables: Dict[str, str]) -> List[dict]:
        """教師データを選択するための関数"""
        return np.random.choice(self.examples, size=1, replace=False)

「examples」という属性を呼び出すことで、格納されている教師データを確認できます。

examples = [
    {"fruit": "イチゴ", "color": "赤"},
    {"fruit": "バナナ", "color": "黄"},
    {"fruit": "モモ", "color": "ピンク"},
]

# 教師データの登録
example_selector = CustomExampleSelector(examples)

# 教師データの出力
print(example_selector.examples)

すると、CustomExampleSelectorクラス内にあるadd_exampleメソッドを使って教師データを追加することができます。

# 教師データの追加
example_selector.add_example({"fruit": "オレンジ", "color": "橙"})
print(example_selector.examples)

最後に、CustomExampleSelectorクラスのselect_examplesメソッドを利用して、教師データを自分の好きな方法で選ぶことができます。ここでは、ランダムにデータを抽出する処理を書いています。

# 教師データの選択 print(example_selector.select_examples({"fruit"}))

これに対する実行結果は次の通りです。

[{'fruit': 'イチゴ', 'color': '赤'}, {'fruit': 'バナナ', 'color': '黄'}, {'fruit': 'モモ', 'color': 'ピンク'}]
[{'fruit': 'イチゴ', 'color': '赤'}, {'fruit': 'バナナ', 'color': '黄'}, {'fruit': 'モモ', 'color': 'ピンク'}, {'fruit': 'オレンジ', 'color': '橙'}]
[{'fruit': 'オレンジ', 'color': '橙'}]

3. Output Parsersの使い方

アウトプットパルサーズでは、出力のデータ形式を指定します。例えば、生成系AIから回答をカンマ区切りのリストで出力したいときは、「CommaSeparatedListOutputParser」が便利です。次のように、fomat_instructionsをクラスから取得して、テンプレートに代入することで簡単に出力方法を指定することができるからです。

from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI

output_parser = CommaSeparatedListOutputParser()
format_instructions = output_parser.get_format_instructions()
prompt = PromptTemplate(
    template=" {subject}に関する5つのリスト.\n{format_instructions}",
    input_variables=["subject"],
    partial_variables={"format_instructions": format_instructions}
)

llm = OpenAI(model_name="text-davinci-003")
_input = prompt.format(subject="Programming Language")
output = llm(_input)
output_parser.parse(output)

ここでは、「ITコンサルタントの仕事を5つ生成する」ように指示しているため、次のように5つのスキル内容がカンマ区切りのリストとして表示されました。

['1. プロジェクトマネージメント',
 '\n2. ビジネスアナリティクス',
 '\n3. プロセス改善',
 '\n4. ソフトウェア開発',
 '\n5. システムアーキテクチャ設計']

他にも「OutputFixingParser」や「PydanticOutputParser」といった機能があります。

終わりに

次回はIndexes機能について解説してまいりますので引き続きよろしくお願いします!

この記事が気に入ったらサポートをしてみませんか?