Closed4

LangChainのGetting StartedをGoogle Colaboratoryでやってみる ②Prompt Templates

kun432kun432

2. Prompt Templates

入力をテンプレートに埋め込む

基本

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

llm = OpenAI(temperature=0.9)

prompt = PromptTemplate(
    input_variables=["product"],
    template="What is a good name for a company that makes {product}?",
)
llm(prompt.format(product="colorful socks"))

結果

\n\nColorful Comfort Socks

日本語でも。

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

llm = OpenAI(temperature=0.9)

prompt = PromptTemplate(
    input_variables=["product"],
    template=" {product} を作る会社にふさわしい名前を1つ挙げて下さい。",
)
llm(prompt.format(product="カラフルな靴下"))

結果

\n\n「ソックス・クレイジー」

Prompt templates' Getting Started

プロンプトテンプレートのメリットは再利用できること。

  • 言語モデルへの指示
  • 言語モデルがより精度の高い回答を生成するためのいくつかの例
  • 言語モデルへの質問

こういったものをテンプレートで定義しておくことで、ユーザからの入力値だけを処理すればよいことになる。

from langchain import PromptTemplate
from langchain.llms import OpenAI

llm = OpenAI(temperature=0.9)

template = """
新会社の命名コンサルタントとして振る舞って下さい。

よい会社名の例:

- 検索エンジン、グーグル
- ソーシャルメディア、フェイスブック
- 動画共有、ユーチューブ

会社名は短く、キャッチーで覚えやすいものである必要がある。

{product} を作る会社にふさわしい名前を1つ挙げて下さい。
"""

prompt = PromptTemplate(
    input_variables=["product"],
    template=template,
)
llm(prompt.format(product="カラフルな靴下"))

結果

\n「ピースィーフット」

PromptTemplateクラス

PromptTemplateクラスを使うと単純な埋め込みプロンプトが作れる。

PromptTemplateをインポート。

from langchain import PromptTemplate

PromptTemplateは、input_variablesで変数の配列、templateでテンプレート文字列を引数に取る。

# input_variablesなしの場合
no_input_prompt = PromptTemplate(input_variables=[], template="なにかダジャレを言って下さい。")
no_input_prompt.format()
# -> 'なにかダジャレを言って下さい。'

# input_variablesが1つ
one_input_prompt = PromptTemplate(input_variables=["adjective"], template="なにか{adjective}ダジャレを言って下さい。")
one_input_prompt.format(adjective="面白い")
# -> 'なにか面白いダジャレを言って下さい。'

# input_variablesが複数
multiple_input_prompt = PromptTemplate(input_variables=["adjective", "content"], template="{content}について、なにか{adjective}ダジャレを言って下さい。")
multiple_input_prompt.format(adjective="面白い", content="ニワトリ")
# -> 'ニワトリについて、なにか面白いダジャレを言って下さい。'

Pythonのformat stringとして処理される。またJinja2テンプレートも使えるらしい。

あとより自由度の高いカスタムテンプレートプロンプトというのもあるがこれは後述。

LangChainHubからプロンプトを読み込む

https://github.com/hwchase17/langchain-hub

LangChainHubは、プロンプト・チェーン・エージェントをみんなで共有するためのリソース。ここからすでにあるプロンプトを読み込むこともできる。

以下のConversationのプロンプトを読み込んでみる。

https://github.com/hwchase17/langchain-hub/tree/master/prompts/conversation

READMEを見ると2つのパラメータがある。

  • "history"
    • ここまでの会話の履歴(コンテキストを保持するためのものだと思う)
  • "input"
    • ユーザ側からの入力内容を受け取る

historyをちゃんとやるにはひと手間いるので詳細は割愛。読み込んで使うだけならこれで。

from langchain.prompts import load_prompt

prompt = load_prompt("lc://prompts/conversation/prompt.json")
prompt.format(history="", input="What is 1 + 1?")

ちょっとwarningがでるけども。

WARNING:/usr/local/lib/python3.8/dist-packages/langchain/prompts/loading.py:No `_type` key found, defaulting to `prompt`.

読み出されたテンプレートにinputが埋め込まれている。

The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n\nCurrent conversation:\n\nHuman: What is 1 + 1?\nAI:

ちなみにまだベータかつ日本語は用意されていない。Googleフォームで申請できる。

プロンプトテンプレートに例を渡す

PromptTemplateで単純に埋め込んでしまってもいいけれども、例を追加するためのFewShotPromptTemplateクラスを使うこともできる。

from langchain import PromptTemplate, FewShotPromptTemplate

examples = [
    {"word": "楽しい", "antonym": "悲しい"},
    {"word": "高い", "antonym": "低い"},
]

example_formatter_template = "単語: {word}\n対義語: {antonym}"

example_prompt = PromptTemplate(
    input_variables=["word", "antonym"],
    template="単語: {word}\n対義語: {antonym}",
)

few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix="それぞれの単語の対義語を教えて下さい。",
    suffix="単語: {input}\n対義語:",
    input_variables=["input"],
    example_separator="\n\n",
)

print(few_shot_prompt.format(input="大きい"))

こうなる

それぞれの単語の対義語を教えて下さい。

単語: 楽しい
対義語: 悲しい

単語: 高い
対義語: 低い

単語: 大きい
対義語:

んー、example_separatorがちょっと冗長になってる気がするけど。それはおいといてfew_shot_promptはこういう出力をしてくれる様子。

{prefix}
{example_separator}
{example_prompt}  # exampleの数だけ繰り返して出力
{example_separator}
{suffix}

プロンプトテンプレートの例を選択する

例が非常に多い場合などはExampleSelectorを使って例を選択することができる。ExampleSelectorは以下の4種類がある様子。

  • LengthBased ExampleSelector
  • Similarity ExampleSelector
  • Maximal Marginal Relevance ExampleSelector
  • NGram Overlap ExampleSelector

それぞれの詳細は後述するとして、まずはLengthBased ExampleSelectorを使ってみる。LengthBased ExampleSelectorは入力の長さに応じて例の数を調整するようになっている。

予め書いておくと、日本語ではうまく動かなかった。英語だと文字数のカウントの仕方がなにかおかしいのかなと思う。

from langchain.prompts.example_selector import LengthBasedExampleSelector

examples = [
    {"word": "happy", "antonym": "sad"},
    {"word": "tall", "antonym": "short"},
    {"word": "energetic", "antonym": "lethargic"},
    {"word": "sunny", "antonym": "gloomy"},
    {"word": "windy", "antonym": "calm"},
]

example_prompt = PromptTemplate(
    input_variables=["word", "antonym"],
    template="Word: {word}\nAntonym: {antonym}",
)

example_selector = LengthBasedExampleSelector(
    examples=examples, 
    example_prompt=example_prompt, 
    max_length=25,
)

dynamic_prompt = FewShotPromptTemplate(
    example_selector=example_selector,
    example_prompt=example_prompt,
    prefix="Give the antonym of every input",
    suffix="Word: {input}\nAntonym:",
    input_variables=["input"],
    example_separator="\n\n",
)

print(dynamic_prompt.format(input="big"))

結果

Give the antonym of every input

Word: happy
Antonym: sad

Word: tall
Antonym: short

Word: energetic
Antonym: lethargic

Word: sunny
Antonym: gloomy

Word: windy
Antonym: calm

Word: big
Antonym:

長い入力が与えられたとする。

long_string = "big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else"
print(dynamic_prompt.format(input=long_string))

結果

Give the antonym of every input

Word: happy
Antonym: sad

Word: big and huge and massive and large and gigantic and tall and much much much much much bigger than everything else
Antonym:

他のExampleSelectorsでは別の基準で例が選択されて、また独自のCustom Selectorを作ることもできる様子。後述。

How-To

さらに以下のようなこともできる。

https://langchain.readthedocs.io/en/latest/modules/prompts/how_to_guides.html

  • Custom Prompt Template
  • Custom Example Selector
  • Few Shot Prompt Templates
  • Example Selectors
  • Prompt Serialization

Custom Prompt Template

https://langchain.readthedocs.io/en/latest/modules/prompts/examples/custom_prompt_template.html

デフォルトでは、プロンプトのテンプレートを用意して、入力値をformat stringで埋め込むようになっている。これを自前で作ることができる。

プロンプトテンプレートで実装が必要なのは以下。

  • プロンプトテンプレートの入力値となるinput_variables 属性
  • input_variablesに対応するキーワード引数を取ってフォーマットされたプロンプトを返す formatメソッド

例として、関数名とソースコードから関数の説明を生成するプロンプトテンプレートをやってみる。

関数のソースコードを返す関数を用意する。

import inspect

def get_source_code(function_name):
    # Get the source code of the function
    return inspect.getsource(function_name)

カスタムプロンプトテンプレートを作成。

from langchain.prompts import BasePromptTemplate
from pydantic import BaseModel, validator

class FunctionExplainerPromptTemplate(BasePromptTemplate, BaseModel):
    """ 
      関数名を入力すると関数のソースコードを取ってきてフォーマットされたプロンプトテンプレートを
      生成するカスタムプロンプトテンプレート
    """

    @validator("input_variables")
    def validate_input_variables(cls, v):
        """ 入力値のバリデーション """
        if len(v) != 1 or "function_name" not in v:
            raise ValueError("function_name must be the only input_variable.")
        return v

    def format(self, **kwargs) -> str:
        # 関数のソースコードを取得
        source_code = get_source_code(kwargs["function_name"])

        # プロンプトを生成
        prompt = f"""
        以下の関数名とソースコードから、関数の説明を日本語で生成して下さい。
        関数名: {kwargs["function_name"].__name__}
        ソースコード:
        {source_code}
        説明:
        """
        return prompt
    
    def _prompt_type(self):
        return "function-explainer"

実際に使う場合はこんな感じ。

fn_explainer = FunctionExplainerPromptTemplate(input_variables=["function_name"])

# Generate a prompt for the function "get_source_code"
prompt = fn_explainer.format(function_name=get_source_code)
print(prompt)

結果。"get_source_code"のソースコードが埋め込まれているのがわかる。インデントがいまいちなのでtextwrapしたほうがい。

        以下の関数名とソースコードから、関数の説明を日本語で生成して下さい。
        関数名: get_source_code
        ソースコード:
        def get_source_code(function_name):
  # Get the source code of the function
  return inspect.getsource(function_name)

        説明:

同じことはデフォルトでもできるけど、ソースコードを取得する部分とプロンプトテンプレートを生成する部分の処理が別れてしまうし、カスタムプロンプトテンプレートとして両方を1ファイルに埋め込んでしまえば、再利用もかんたんにできそう。

For example, you may want to create a prompt template with specific dynamic instructions for your language model.

https://langchain.readthedocs.io/en/latest/modules/prompts/examples/custom_prompt_template.html#why-are-custom-prompt-templates-needed

「動的」ってのはこういうことね。

Custom Example Selector

Example Selectorを自前で作ることができる。実装しないといけないのは以下の2つのメソッド。

  • 例を取り込んでExampleSelectorに追加するadd_exampleメソッド
  • ユーザからの入力値を受け取って、few shotプロンプトで使用するサンプルのリストを返すselect_examplesメソッド

2つの例をランダムに返すExample Selectorを作ってみる。

from langchain.prompts.example_selector.base import BaseExampleSelector
from typing import Dict, List
import numpy as np

class MyCustomExampleSelector(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=2, replace=False)

動かしてみる。

examples = [
    {"foo": "1"},
    {"foo": "2"},
    {"foo": "3"}
]

# example selectorを初期化
example_selector = MyCustomExampleSelector(examples)

# 例を抽出
display(example_selector.examples)
display(example_selector.select_examples({"foo": "foo"}))

# 例を追加する
example_selector.add_example({"foo": "4"})
display(example_selector.examples)

# 例を抽出
display(example_selector.select_examples({"foo": "foo"}))

結果

array([{'foo': '3'}, {'foo': '1'}], dtype=object)
[{'foo': '1'}, {'foo': '2'}, {'foo': '3'}, {'foo': '4'}]
array([{'foo': '2'}, {'foo': '4'}], dtype=object)

Few Shot Prompt Templates

ここは上でも使っているので割愛。

Example Selectors

https://langchain.readthedocs.io/en/latest/modules/prompts/examples/example_selectors.html

標準で用意されているExample Selectorsは以下の4つ。

  • LengthBased ExampleSelector
  • Similarity ExampleSelector
  • Maximal Marginal Relevance ExampleSelector
  • NGram Overlap ExampleSelector

すでに試したLengthBased ExampleSelector以外について見ていく。基本的にLengthBased ExampleSelector以外のものは「類似性」に基づいて例を選択するもので、類似性をどういうロジックでやるか?というところが違いの様子。

なるべく日本語で動かしてみようと思う。

Similarity ExampleSelector

ただしくはSemanticSimilarityExampleSelectorらしい。入力値と最も「意味的」に類似している例を返すExample Selector。

サンプルの例ではChromaが必要なのでインストール。ちなみにインメモリのDuckDBを使っているらしいのでデータは一過性のものになるらしい。

!pip install chromadb

こういう感じで定義。

from langchain import PromptTemplate, FewShotPromptTemplate
from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

examples = [
    {"input": "楽しい", "output": "悲しい"},
    {"input": "高い", "output": "低い"},
    {"input": "エネルギッシュ", "output": "無気力"},
    {"input": "晴れた", "output": "天気がうっとうしい"},
    {"input": "風が強い", "output": "穏やか"},
]

example_prompt = PromptTemplate(
    input_variables=["input", "output"],
    template="Input: {input}\nOutput: {output}",
)

example_selector = SemanticSimilarityExampleSelector.from_examples(
    # 例の配列
    examples, 
    # 意味的な類似性を算出するためのembeddingsを生成するためのクラスを指定。ここではOpenA IAPIのものを使う。
    # embeddingsについて https://note.com/npaka/n/n95d9b6b33309 が詳しかった。
    OpenAIEmbeddings(), 
    # embeddingsを保存しておくためのVectorStoreクラス
    Chroma, 
    # 生成する例の数
    k=1
)
similar_prompt = FewShotPromptTemplate(
    example_selector=example_selector,
    example_prompt=example_prompt,
    prefix="以下の単語の対義語を生成して下さい。",
    suffix="input: {adjective}\noutput:", 
    input_variables=["adjective"],
)

出力してみる。

print(similar_prompt.format(adjective="少ない"))

結果

以下の単語の対義語を生成して下さい。

Input: 高い
Output: 低い

input: 少ない
output:

別の単語で。

print(similar_prompt.format(adjective="幸せ"))

結果

以下の単語の対義語を生成して下さい。

Input: 楽しい
Output: 悲しい

input: 幸せ

Maximal Marginal Relevance ExampleSelector

MaxMarginalRelevanceExampleSelector は、どの例が入力と最も類似しているかという組み合わせに基づいて例を選択し、同時に多様性を最適化するものである。これは、入力とのコサイン類似度が最も高い埋め込みを持つ例を見つけ、既に選択された例との近さにペナルティを課しながら繰り返し追加していくことで実現されます。

んー、難しい。。。。とりあえずやってみる。

FAISSが必要になるのでインストール。ColaboratoryでGPUを有効していない場合は以下。

!pip install faiss-cpu

GPUを有効化しているなら以下でも行けるんじゃないかな。未確認。

!pip install faiss-gpu

こういう感じで定義。

from langchain import PromptTemplate, FewShotPromptTemplate
from langchain.prompts.example_selector import MaxMarginalRelevanceExampleSelector
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS

examples = [
    {"input": "楽しい", "output": "悲しい"},
    {"input": "高い", "output": "低い"},
    {"input": "エネルギッシュ", "output": "無気力"},
    {"input": "晴れた", "output": "天気がうっとうしい"},
    {"input": "風が強い", "output": "穏やか"},
]

example_prompt = PromptTemplate(
    input_variables=["input", "output"],
    template="Input: {input}\nOutput: {output}",
)

example_selector = MaxMarginalRelevanceExampleSelector.from_examples(
    # 例の配列
    examples, 
    # 意味的な類似性を算出するためのembeddingsを生成するためのクラスを指定。ここではOpenA IAPIのものを使う。
    # embeddingsについて https://note.com/npaka/n/n95d9b6b33309 が詳しかった。
    OpenAIEmbeddings(), 
    # embeddingsを保存しておくためのVectorStoreクラス
    FAISS, 
    # 生成する例の数
    k=2
)

mmr_prompt = FewShotPromptTemplate(
    # We provide an ExampleSelector instead of examples.
    example_selector=example_selector,
    example_prompt=example_prompt,
    prefix="以下の単語の対義語を生成して下さい。",
    suffix="input: {adjective}\noutput:", 
    input_variables=["adjective"],
)

出力してみる。

print(mmr_prompt.format(adjective="少ない"))
以下の単語の対義語を生成して下さい。

Input: 高い
Output: 低い

Input: 風が強い
Output: 穏やか

input: 少ない
output:

別の単語で。

print(mmr_prompt.format(adjective="幸せ"))

結果

以下の単語の対義語を生成して下さい。

Input: 楽しい
Output: 悲しい

Input: エネルギッシュ
Output: 無気力

input: 幸せ
output:

NGram Overlap ExampleSelector

NGramOverlapExampleSelector は、ngram オーバーラップスコアに従って、どの例が入力と最も類似しているかに基づいて例を選択し、順序付けする。ngram オーバーラップスコアは 0.0 から 1.0 の間の浮動小数点数です。

セレクタでは、閾値のスコアを設定することができます。ngram オーバーラップスコアがしきい値以下である例は除外されます。デフォルトでは、しきい値は-1.0に設定されているので、例を除外することはなく、並べ替えるだけです。しきい値を0.0に設定すると、入力とngramが重複していない例が除外されます。

これ日本語だとMecabとか入れてちゃんと分かち書きしてやらないといけないんじゃないかなー。NGram Overlap ExampleSelectorのコードは以下だけど、普通に使っているだけに見えるので、多分日本語は無理なんじゃないかという気がする、試してないけど。

https://github.com/hwchase17/langchain/blob/master/langchain/prompts/example_selector/ngram_overlap.py

ということで英語で。

from langchain.prompts import PromptTemplate, FewShotPromptTemplate
from langchain.prompts.example_selector.ngram_overlap import NGramOverlapExampleSelector

examples = [
    {"input": "See Spot run.", "output": "Ver correr a Spot."},
    {"input": "My dog barks.", "output": "Mi perro ladra."},
    {"input": "Spot can run.", "output": "Spot puede correr."},
    {"input": "Spot plays fetch.", "output": "Spot juega a buscar."},
]

example_prompt = PromptTemplate(
    input_variables=["input", "output"],
    template="Input: {input}\nOutput: {output}",
)
example_selector = NGramOverlapExampleSelector(
    # 例の配列
    examples=examples, 
    # 例のプロンプトテンプレート
    example_prompt=example_prompt, 
    # しきい値、デフォルトは-1.0
    threshold=-1.0,
)

dynamic_prompt = FewShotPromptTemplate(
    # We provide an ExampleSelector instead of examples.
    example_selector=example_selector,
    example_prompt=example_prompt,
    prefix="Give the Spanish translation of every input",
    suffix="Input: {sentence}\nOutput:", 
    input_variables=["sentence"],
)

出力してみる。

print(dynamic_prompt.format(sentence="Spot can run fast."))

デフォルト(-1.0)だと単に例が並べ替えられるだけ。

Give the Spanish translation of every input

Input: Spot can run.
Output: Spot puede correr.

Input: See Spot run.
Output: Ver correr a Spot.

Input: Spot plays fetch.
Output: Spot juega a buscar.

Input: My dog barks.
Output: Mi perro ladra.

Input: Spot can run fast.
Output:

threshold=0.0にする。

example_selector.threshold=0.0
print(dynamic_prompt.format(sentence="Spot can run fast."))

threshold=0.0だとngramで重複がないものが除外される。my dog barksには`入力のどの単語も含まれていない。

Give the Spanish translation of every input

Input: Spot can run.
Output: Spot puede correr.

Input: See Spot run.
Output: Ver correr a Spot.

Input: Spot plays fetch.
Output: Spot juega a buscar.

Input: Spot can run fast.
Output:

しきい値を変えていろいろ試してみると良い。

example_selector.threshold=0.09
print(dynamic_prompt.format(sentence="Spot can run fast."))
Give the Spanish translation of every input

Input: Spot can run.
Output: Spot puede correr.

Input: Spot can run fast.
Output:

Prompt Serialization

プロンプトテンプレートを設定ファイルとして記述し、読み出して使う。

  • JSON/YAMLをサポート
  • ファイルにすべて記述することも、テンプレート・例といったコンポーネントごとに別ファイルに分けて記述するのも両方OK

load_promptをインポートする。

from langchain.prompts import load_prompt

Prompt Templateをファイルから読みだす

以下のようなファイルを用意する。JSONとYAMLそれぞれ書いてみる。

simple_prompts.yaml
input_variables:
    ["adjective", "content"]
template: 
    {content}についての{adjective}ダジャレを言ってみて下さい。
simple_prompts.json
{
    "input_variables": ["adjective", "content"],
    "template": "{content}についての{adjective}ダジャレを言ってみて下さい。"
}

ファイルを置いて、以下のようにして読み出す。

from langchain.prompts import load_prompt

prompt = load_prompt("simple_prompt.json")
print(prompt.format(adjective="面白い", content="ニワトリ"))

結果。warning出てるけどとりあえず動いてる。

WARNING:/usr/local/lib/python3.8/dist-packages/langchain/prompts/loading.py:No `_type` key found, defaulting to `prompt`.
ニワトリについての面白いダジャレを言ってみて下さい。
kun432kun432

FewShotPromptTemplateをファイルから読みだす

FewShotPromptには例が必要になるので以下のようなファイルを作成する。

examples.yaml
- 単語: 楽しい
  対義語: 悲しい
- 単語: 高い
  対義語: 低い
- 単語: エネルギッシュ
  対義語: 無気力
- 単語: 晴れた
  対義語: 鬱陶しい
- 単語: 風が強い
  対義語: 風が穏やか
examples.json
examples = [
    {"単語": "楽しい", "対義語": "悲しい"},
    {"単語": "高い", "対義語": "低い"},
    {"単語": "エネルギッシュ", "対義語": "無気力"},
    {"単語": "晴れた", "対義語": "鬱陶しい"},
    {"単語": "風が強い", "対義語": "風が穏やか"},
]

次にFewShotPromptTemplateの設定ファイルを用意する。

few_shot_prompt.yaml
_type: few_shot
input_variables:
    ["adjective"]
prefix: 
    以下の単語の対義語を生成して下さい。
example_prompt:
    input_variables:
        ["単語", "対義語"]
    template:
        "単語: {単語}\n対義語: {対義語}"
examples:
    examples.yaml
suffix:
    "単語: {adjective}\n対義語:"
few_shot_prompt.json
{
    "_type": "few_shot",
    "input_variables": ["adjective"],
    "prefix": "以下の単語の対義語を生成して下さい。",
    "example_prompt": {
        "input_variables": ["単語", "対義語"],
        "template": "単語: {単語}\対義語: {対義語}"
    },
    "examples": "examples.json",
    "suffix": "単語: {adjective}\n対義語:"
}   

呼び出してみる。今度はYAMLで。

from langchain.prompts import load_prompt

prompt = load_prompt("few_shot_prompt.yaml")
print(prompt.format(adjective="にぎやか"))

結果

WARNING:/usr/local/lib/python3.8/dist-packages/langchain/prompts/loading.py:No `_type` key found, defaulting to `prompt`.
以下の単語の対義語を生成して下さい。

単語: 楽しい
対義語: 悲しい

単語: 高い
対義語: 低い

単語: エネルギッシュ
対義語: 無気力

単語: 晴れた
対義語: 鬱陶しい

単語: 風が強い
対義語: 風が穏やか

単語: にぎやか
対義語:

例をFewShotPromptTemplateの設定ファイルに直接埋め込むこともできる。

few_shot_prompt_embedded_examples.yaml
_type: few_shot
input_variables:
    ["adjective"]
prefix: 
    以下の単語の対義語を生成して下さい。
example_prompt:
    input_variables:
        ["単語", "対義語"]
    template:
        "単語: {単語}\n対義語: {対義語}"
examples:
    - 単語: 楽しい
      対義語: 悲しい
    - 単語: 高い
      対義語: 低い
    - 単語: エネルギッシュ
      対義語: 無気力
    - 単語: 晴れた
      対義語: 鬱陶しい
    - 単語: 風が強い
      対義語: 風が穏やか
suffix:
    "単語: {adjective}\n対義語:"

JSONでも同じような感じでいける。

さらにPromptTemplateもFewShotPromptTemplateから切り離してファイルにする。

example_prompt.yaml
input_variables:
    ["単語", "対義語"]
template:
    "単語: {単語}\n対義語: {対義語}"
example_prompt.json
{
    "input_variables": ["単語", "対義語"],
    "template": "単語: {単語}\対義語: {対義語}"
}

FewShotPromptTemplateの設定ファイルからはexample_prompt_pathで呼び出す。

_type: few_shot
input_variables:
    ["adjective"]
prefix: 
    以下の単語の対義語を生成して下さい。
example_prompt_path:
    example_prompt.yaml
examples:
    examples.yaml
suffix:
    "単語: {adjective}\n対義語:"
{
    "_type": "few_shot",
    "input_variables": ["adjective"],
    "prefix": "以下の単語の対義語を生成して下さい。",
    "example_prompt_path":  "example_prompt.json",
    "examples": "examples.json",
    "suffix": "単語: {adjective}\n対義語:"
}   

一気に設定ファイル感が出る。あー、これはFewShotPromptTemplateをコードで書くよりも楽ちんだわ。

kun432kun432

まとめ

  • プロンプトテンプレートを使うことで再利用が可能になる
  • Few Shot Prompt で便利な例もテンプレート化できる
  • example_selectorを使えば、入力値に応じて例を動的に選択できる
  • その他
    • Prompt Template, example selectorは自作もできる
    • examples, example prompt template, few shot prompt templateはそれぞれ設定ファイルのようにして読み出して使うこともできる
このスクラップは2023/02/27にクローズされました