コンテンツにスキップ

PromptoGen

LLMとPythonをシームレスにつなぐ。

Releases Test Package version Supported Python versions


ドキュメンテーション: https://promptogen.zawakin.dev

ソースコード: https://github.com/zawakin/promptogen

クイックスタートガイドはこちら

English | 日本語


PromptoGen: LLMとの効率的で拡張可能なコミュニケーションを実現

ビジョン

"LLMとPythonの間のギャップをシームレスに繋ぐことで、効率的で未来を見据えたコミュニケーションを実現する。"

LLMライブラリの主な課題

  • プロンプトエンジニアリングのエコシステムが不足: プロンプトの作成や共有が困難になる
  • 特定のLLMバージョンへの強い依存性: 高頻度なLLMの更新に対して脆弱になる
  • 実装が複雑: カスタマイズが困難になる

PromptoGenを選ぶ理由は?

  1. LLM I/OとPythonオブジェクト間のシームレスな変換: LLMとのインタラクションを合理化します
  2. 柔軟でユニークなインターフェース: ユーザーのカスタマイズと拡張性を保証します
  3. 将来の設計: LLMの進化に対する依存を減少させて将来に備えます

他のライブラリとの比較: 多くは特定のLLMバージョンに結びついており、将来の適応性に課題があります。Pydanticデータクラスライブラリだけに依存するPromptoGenは、LLM文字列とPythonオブジェクトとの間を橋渡しすることに特化しています。

主な機能

  • Prompt データクラス: LLM通信を標準化し、プロンプトエンジニアリングをサポート
  • TextLLM インターフェース: LLMの詳細からの独立
  • PromptFormatter インターフェース: ユーザーのための高いカスタマイズ性

利点

  • モジュラー&拡張可能: 自由に組み合わせ、カスタムコンポーネントを追加
  • 未来の変更に強い: 新しいモデルのアップデートに強く立つ
  • 維持しやすい: 異なるLLMのためのデバッグや微調整が容易

サポートされていない機能

  • LLMとの直接通信: 直接のLLMとの会話よりも効率的なインターフェースを優先します
  • プロンプトのバージョン管理: シンプルに保つため、バージョンの複雑さを追加することを避けます
  • 特定のLLMの最適化: 単一のLLMのための最適化よりもLLM全体の適応性に焦点を当てます

詳細について

PromptoGenとはを参照してください。

動作環境

Python 3.8 以上

インストール

pip install promptogen

インポート

import promptogen as pg

使い方

TextLLM: 柔軟なLLM連携

pg.TextLLMを介すことで、PromptoGenは多種多様な大規模言語モデル(LLM)との連携を実現します。

TextLLMインターフェイスの実装例
import promptogen as pg

class YourTextLLM(pg.TextLLM):
    def __init__(self, model: str):
        self.model = model

    def generate(self, text: str) -> str:
        return generate_by_your_text_llm(text, self.model)

text_llm = YourTextLLM(model="your-model")

このインターフェイスの採用により、PromptoGenは異なるLLMやそのバージョンをスムーズに組み込むことが可能になります。ユーザーはLLMによらない一貫した方法で、様々なLLMを活用できるようになります。

プロンプトの作成

import promptogen as pg

summarizer = pg.Prompt(
    name="Text Summarizer and Keyword Extractor",
    description="Summarize text and extract keywords.",
    input_parameters=[
        pg.ParameterInfo(name="text", description="Text to summarize"),
    ],
    output_parameters=[
        pg.ParameterInfo(name="summary", description="Summary of text"),
        pg.ParameterInfo(name="keywords", description="Keywords extracted from text"),
    ],
    template=pg.IOExample(
        input={'text': "This is a sample text to summarize."},
        output={
            'summary': "This is a summary of the text.",
            'keywords': ["sample", "text", "summarize"],
        },
    ),
    examples=[
        pg.IOExample(
            input={
                'text': "One sunny afternoon, a group of friends decided to gather at the nearby park to engage in various games and activities. They played soccer, badminton, and basketball, laughing and enjoying each other's company while creating unforgettable memories together."},
            output={
                'summary': "A group of friends enjoyed an afternoon playing sports and making memories at a local park.",
                'keywords': ["friends", "park", "sports", "memories"],
            },
        )
    ],
)

プロンプトのフォーマット

Prompt クラスのインスタンスを実際にLLMに送信するために、文字列に変換する必要があります。PromptoGenでは、pg.PromptFormatterを使用して、プロンプトを任意の形式の文字列に変換することができます。

PromptoGenでは様々な形式のフォーマットをサポートしています。

  • KeyValue形式フォーマット key: value
  • JSON形式フォーマット {"key": "value"}
  • etc.

プロンプトフォーマット基本構造

プロンプト文字列は、以下のような基本的な構造を持ちます。

Prompt Description
<プロンプト説明>

Input Parameters:
  - <入力パラメーター1の説明>
  - <入力パラメーター2の説明>
  - ...

Output Parameters:
    - <出力パラメーター1の説明>
    - <出力パラメーター2の説明>
    - ...

Template:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の例>
<入力パラメーター2の名前>: <入力パラメーター2の例>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の例>
<出力パラメーター2の名前>: <出力パラメーター2の例>
...

Example 1:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の値>
<出力パラメーター2の名前>: <出力パラメーター2の値>
...

...

--------

Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
Input Parameters
<プロンプト説明>

Input Parameters:
  - <入力パラメーター1の説明>
  - <入力パラメーター2の説明>
  - ...

Output Parameters:
    - <出力パラメーター1の説明>
    - <出力パラメーター2の説明>
    - ...

Template:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の例>
<入力パラメーター2の名前>: <入力パラメーター2の例>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の例>
<出力パラメーター2の名前>: <出力パラメーター2の例>
...

Example 1:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の値>
<出力パラメーター2の名前>: <出力パラメーター2の値>
...

...

--------

Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
Output Parameters
<プロンプト説明>

Input Parameters:
  - <入力パラメーター1の説明>
  - <入力パラメーター2の説明>
  - ...

Output Parameters:
    - <出力パラメーター1の説明>
    - <出力パラメーター2の説明>
    - ...

Template:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の例>
<入力パラメーター2の名前>: <入力パラメーター2の例>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の例>
<出力パラメーター2の名前>: <出力パラメーター2の例>
...

Example 1:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の値>
<出力パラメーター2の名前>: <出力パラメーター2の値>
...

...

--------

Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
Template
<プロンプト説明>

Input Parameters:
  - <入力パラメーター1の説明>
  - <入力パラメーター2の説明>
  - ...

Output Parameters:
    - <出力パラメーター1の説明>
    - <出力パラメーター2の説明>
    - ...

Template:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の例>
<入力パラメーター2の名前>: <入力パラメーター2の例>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の例>
<出力パラメーター2の名前>: <出力パラメーター2の例>
...

Example 1:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の値>
<出力パラメーター2の名前>: <出力パラメーター2の値>
...

...

--------

Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
Few-shot Examples
<プロンプト説明>

Input Parameters:
  - <入力パラメーター1の説明>
  - <入力パラメーター2の説明>
  - ...

Output Parameters:
    - <出力パラメーター1の説明>
    - <出力パラメーター2の説明>
    - ...

Template:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の例>
<入力パラメーター2の名前>: <入力パラメーター2の例>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の例>
<出力パラメーター2の名前>: <出力パラメーター2の例>
...

Example 1:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の値>
<出力パラメーター2の名前>: <出力パラメーター2の値>
...

...

--------

Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
Input Value
<プロンプト説明>

Input Parameters:
  - <入力パラメーター1の説明>
  - <入力パラメーター2の説明>
  - ...

Output Parameters:
    - <出力パラメーター1の説明>
    - <出力パラメーター2の説明>
    - ...

Template:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の例>
<入力パラメーター2の名前>: <入力パラメーター2の例>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の例>
<出力パラメーター2の名前>: <出力パラメーター2の例>
...

Example 1:
Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:
<出力パラメーター1の名前>: <出力パラメーター1の値>
<出力パラメーター2の名前>: <出力パラメーター2の値>
...

...

--------

Input:
<入力パラメーター1の名前>: <入力パラメーター1の値>
<入力パラメーター2の名前>: <入力パラメーター2の値>
...
Output:

key: value 形式のプロンプトのフォーマットを使用するには、pg.KeyValuePromptFormatterを使用します。 パラメータ情報やテンプレートを表示するかどうかは PromptFormatterConfig で設定できます。

formatter.format_prompt メソッドを使用して、プロンプトとそれに対する入力を文字列に変換できます。

import promptogen as pg

summarizer = pg.Prompt(
    name="Text Summarizer and Keyword Extractor",
    # ...
)

formatter = pg.KeyValuePromptFormatter()

input_value = {
    "text": "In the realm of software engineering, ...",
}
print(formatter.format_prompt(summarizer, input_value))
import promptogen as pg

summarizer = pg.Prompt(
    name="Text Summarizer and Keyword Extractor",
    # ...
)

formatter = pg.JsonPromptFormatter()

input_value = {
    "text": "In the realm of software engineering, ...",
}
print(formatter.format_prompt(summarizer, input_value))
Console Output
Summarize text and extract keywords.

Input Parameters:
  - text: Text to summarize

Output Parameters:
  - summary: Summary of text
  - keywords: Keywords extracted from text

Template:
Input:
text: "This is a sample text to summarize."
Output:
summary: "This is a summary of the text."
keywords: ['sample', 'text', 'summarize']

Example 1:
Input:
text: "One sunny afternoon, a group of friends decided to gather at the nearby park to engage in various games and activities. They played soccer, badminton, and basketball, laughing and enjoying each other's company while creating unforgettable memories together."
Output:
summary: "A group of friends enjoyed an afternoon playing sports and making memories at a local park."
keywords: ['friends', 'park', 'sports', 'memories']

--------

Input:
text: "In the realm of software engineering, ..."
Output:
Console Output
Summarize text and extract keywords.

Output a JSON-formatted string without outputting any other strings.
Be careful with the order of brackets in the json.

Input Parameters:
  - text: Text to summarize

Output Parameters:
  - summary: Summary of text
  - keywords: Keywords extracted from text

Template:
Input:
```json
{
 "text": "This is a sample text to summarize."
}```
Output:
```json
{
 "summary": "This is a summary of the text.",
 "keywords": [
  "sample",
  "text",
  "summarize"
 ]
}```

Example 1:
Input:
```json
{
 "text": "One sunny afternoon, a group of friends decided to gather at the nearby park to engage in various games and activities. They played soccer, badminton, and basketball, laughing and enjoying each other's company while creating unforgettable memories together."
}```
Output:
```json
{
 "summary": "A group of friends enjoyed an afternoon playing sports and making memories at a local park.",
 "keywords": [
  "friends",
  "park",
  "sports",
  "memories"
 ]
}```

--------

Input:
```json
{
 "text": "In the realm of software engineering, ..."
}```
Output:

大規模言語モデルからの出力のパース

さきほどのプロンプト文字列を入力として、大規模言語モデル(GPT-3.5, GPT-4など)から出力を得ます。

LLM Output
summary: "This is a summary of the text."
keywords: ['sample', 'text', 'summarize']
LLM Output
```json
{
    "summary": "This is a summary of the text.",
    "keywords": ["sample", "text", "summarize"]
}
```

formatter.parse を使って、出力をパースしてみます。

import promptogen as pg

formatter = pg.KeyValuePromptFormatter()

raw_resp = """summary: "This is a summary of the text."
keywords: ['sample', 'text', 'summarize']"""
summarized_resp = formatter.parse(summarizer, raw_resp)
print(summarized_resp)
Console Output
{'summary': 'This is a summary of the text.', 'keywords': ['sample', 'text', 'summarize']}
import promptogen as pg

formatter = pg.JsonPromptFormatter()

raw_resp = """```json
{
    "summary": "This is a summary of the text.",
    "keywords": ["sample", "text", "summarize"]
}
```"""
summarized_resp = formatter.parse(summarizer, raw_resp)
print(summarized_resp)
Console Output
{'summary': 'This is a summary of the text.', 'keywords': ['sample', 'text', 'summarize']}

プロンプトの保存

summarizer.to_json_file("summarizer.json")

プロンプトの読み込み

import promptogen as pg

summarizer = pg.Prompt.from_json_file("summarizer.json")

PromptRunner: プロンプト実行、効率的に

pg.PromptRunnerは、プロンプトの実行をシンプルに、かつ効率的にサポートします。

PromptRunnerを使ったプロンプト実行
import promptogen as pg

# `pg.TextLLM`インターフェイスを実装したLLMを用意
text_llm = YourTextLLM(model="your-model")

formatter = pg.KeyValuePromptFormatter()
runner = pg.TextLLMPromptRunner(llm=text_llm, formatter=formatter)

summarizer = pg.Prompt(
    name="Text Summarizer and Keyword Extractor",
    # ...
)

input_value = {
    "text": "In the realm of software engineering, ...",
}

output_value = runner.run_prompt(summarizer, input_value)
print(output_value)

このツールの利点:

  1. 抽象化: ユーザーは具体的なLLMの実装を意識せずにプロンプトを実行できます。
  2. 一貫性: 同じプロンプトを異なるLLMで実行する際の変更を最小限に抑えられます。
  3. 拡張性: 新しいプロンプトの追加や既存プロンプトの修正が簡単です。

pg.PromptRunnerは、PromptoGenを使ったプロンプトの実行をより直感的で効率的にするためのキーとなるツールです。

クイックスタートガイド

クイックスタートガイドを参照してください。

応用例

応用例を参照してください。

依存ライブラリ

制限事項

  • PromptoGenのアップデートに伴い、json出力したプロンプトの互換性が失われる可能性があります。
  • 動作検証に使用した大規模言語モデルは、OpenAI Chat API の gpt-3.5-turbo, gpt-3.5-tubrbo-16k, gpt-4 や Meta の Llama 2 です。その他の大規模言語モデルでは動作検証を行っていません。特に、パーサーが正しく動作しないケースがある可能性があるため、ご注意ください。

コントリビューション

バグの報告、新機能の提案、プルリクエスト等は大歓迎です!詳しくはコントリビューションをご覧ください。

ライセンス

MITライセンス