エラーを早期にキャッチし、タイプの安全性を実施し、プロンプトを管理するための構造化された方法を提供するLLMSのタイプセーフ、検証されたプロンプト管理システム。可変検証にはPydanticモデルを使用し、Jinja2テンプレートを迅速なレンダリングに使用します。
注:このライブラリは早期に開発されており、変更される場合があります。
LLMSの動的プロンプトを管理するのは常に困難だと感じています。このプロセスはエラーが発生しやすく、多くの場合、実行時にのみ発見されます。 Typed-Promptは、エラーを早期にキャッチし、タイプの安全性を実施するプロンプトを管理するための構造化されたタイプセーフの方法を提供することにより、この問題を解決することを目指しています。
免責事項:これは、過去に持っていた不満を解決するための個人的なプロジェクトであり、どの組織にも提携していません。それは進行中の作業であり、変更される可能性があります。
将来、さらに機能と例を追加します。提案やフィードバックがある場合は、お気軽に問題を開いてください!
from typed_prompt import BasePrompt
from pydantic import BaseModel
from typing import Optional
# Define your variables
class UserVars ( BaseModel ):
name : str
expertise : str
# This works - all template variables are defined
class ValidPrompt ( BasePrompt [ UserVars ]):
"""Helping {{name}} with {{expertise}} level knowledge."""
prompt_template : str = "Explain {{topic}} to me"
variables : UserVars
def render ( self , * , topic : str , ** extra_vars ) -> RenderOutput :
extra_vars [ "topic" ] = topic
return super (). render ( ** extra_vars )
# This fails immediately - 'unknown_var' not defined
class InvalidPrompt ( BasePrompt [ UserVars ]):
prompt_template : str = "What is {{unknown_var}}?" # ValueError!
variables : UserVars
# This fails - 'expertise' defined but never used
class UnusedVarPrompt ( BasePrompt [ UserVars ]):
prompt_template : str = "Hello {{name}}" # ValueError!
variables : UserVars from typing import Union
class TemplateVars ( BaseModel ):
user_type : Union [ "expert" , "beginner" ]
name : str
preferences : Optional [ dict ] = None
class ConditionalPrompt ( BasePrompt [ TemplateVars ]):
"""{% if user_type == 'expert' %}
Technical advisor for {{name}}
{% else %}
Friendly helper for {{name}}
{% endif %}"""
prompt_template : str = """
{% if preferences %}
Considering your preferences: {% for k, v in preferences.items() %}
- {{k}}: {{v}}{% endfor %}
{% endif %}
How can I help with {{topic}}?
"""
variables : TemplateVars
def render ( self , * , topic : str , ** extra_vars ) -> RenderOutput :
extra_vars [ "topic" ] = topic
return super (). render ( ** extra_vars ) from typed_prompt import RenderOutput
from pydantic import BaseModel , Field
class MyConfig ( BaseModel ):
temperature : float = Field ( default = 0.7 , ge = 0 , le = 2 )
model : str = Field ( default = "gpt-4" )
class MyPrompt ( BasePrompt [ UserVars ]):
"""Assistant for {{name}}"""
prompt_template : str = "Help with {{topic}}"
variables : UserVars
config : MyConfig = Field ( default_factory = MyConfig )
def render ( self , * , topic : str , ** extra_vars ) -> RenderOutput :
extra_vars [ "topic" ] = topic
return super (). render ( ** extra_vars )
# Use custom config
prompt = MyPrompt (
variables = UserVars ( name = "Alice" , expertise = "intermediate" ),
config = MyConfig ( temperature = 0.9 , model = "gpt-3.5-turbo" )
)注:オプションの変数の値としてなしを使用すると、プロンプトには
Noneにレンダリングされます。たとえば、「テストの例{{var}}、var{{if var}}None場合、Test example Noneにレンダリングされます。これはjinjaのデフォルト動作です。したがって、Jinja2{{var | default('default value')}}でこれを処理する必要があります。
ライブラリは、クラスの定義中にプロンプトテンプレートを検証します。
すべての変数はPydanticを通じて検証されます。
カスタム構成をプロンプトに添付します。
この例を考えてみましょう。
# Without typed-prompt
def create_prompt ( user_data ):
template = "Hello {{username}}, your level is {{level}}"
# Error only discovered when rendering with wrong data
return template . format ( ** user_data ) # KeyError at runtime!
# With typed-prompt
class UserPrompt ( BasePrompt [ UserVars ]):
prompt_template : str = "Hello {{unknown_var}}" # Error immediately!
variables : UserVarsライブラリは、定義時にテンプレートエラーをキャッチします。
uv add tpyed-promptまたは
pip install typed-promptその他の例と詳細なドキュメントについては、例ディレクトリを確認してください。
例を実行するには:
uv run python examples/user.pyTyped-Promptは、一般的なLLM相互作用パターンに一致する2部構成のプロンプト構造を使用します。
システムプロンプト:AIモデルのコンテキストまたは命令を提供します。これを2つの方法で定義できます。
system_prompt_templateクラス属性としてユーザープロンプト:モデルに送信される実際のプロンプトテンプレートが含まれています。これは、常にprompt_templateクラス属性で定義されます。
タイプされたプロムプトの変数は、3つの相補的メカニズムを通じて処理されます。
変数モデル:コア変数を定義するPydanticモデルのプロンプトニーズ:
class UserVariables ( BaseModel ):
name : str
age : int
occupation : Optional [ str ] = Noneレンダリングメソッドパラメーター:追加の変数は、カスタムレンダリングメソッドのキーワードのみの引数として定義できます。
def render ( self , * , learning_topic : str , ** extra_vars ) -> RenderOutput :
extra_vars [ "learning_topic" ] = learning_topic
return super (). render ( ** extra_vars )余分な変数:1回限りの変数をレンダリング方法に直接渡すことができます。
ライブラリは、一般的な問題を早期にキャッチするために包括的な検証を実行します。
複雑なプロンプトの場合、外部ファイルからテンプレートをロードできます。
class ComplexPrompt ( BasePrompt [ ComplexVariables ]):
system_prompt_template = Path ( "templates/system_prompt.j2" ). read_text ()
prompt_template : str = Path ( "templates/user_prompt.j2" ). read_text ()注:JINJA2のようなテンプレートエンジンを使用すると、通常はホットリロードテンプレートを使用できますが、クラスの定義時にテンプレートが検証されるため、これはタイプ付きプロンプトではサポートされていません。
構造化されたプロンプトを作成するための基礎クラス。
T :テンプレート変数の構造を定義するPydantic Basemodelサブクラスsystem_prompt_template :optional [str] - システムプロンプトテンプレートprompt_template :str-ユーザープロンプトテンプレートvariables :T-変数モデルのインスタンスrender(**extra_vars) -> RenderOutput :提供された変数で両方のプロンプトをレンダリングするレンダリングされたプロンプトへの構造化されたアクセスを提供する名前のtuple:
system_prompt :Optional [str] - レンダリングされたシステムプロンプトuser_prompt :str-レンダリングされたユーザープロンプト最大の読みやすさと保守性のためにテンプレートを構成します。
システムプロンプトにDocStringsを使用します。可能であれば、より良いコード組織のためにクラスのドキュストリングのシステムプロンプトを定義します。
class UserPrompt ( BasePrompt [ UserVariables ]):
"""You are having a conversation with {{name}}, a {{age}}-year-old {{occupation}}."""
prompt_template : str = "What would you like to discuss?"個別の複雑なテンプレート:長いテンプレートの場合、外部ファイルを使用します。
system_prompt_template = Path ( "templates/system_prompt.j2" ). read_text ()動的なコンテンツには、Jinja2の条件付き構文を使用します。
class DynamicPrompt ( BasePrompt [ Variables ]):
prompt_template : str = """
{% if expert_mode %}
Provide a detailed technical explanation of {{topic}}
{% else %}
Explain {{topic}} in simple terms
{% endif %}
""" 貢献は大歓迎です!
このプロジェクトは、MITライセンスに基づいてライセンスされています。詳細については、ライセンスファイルを参照してください。
オプションはNoneプロンプトになしでレンダリングされます。
Jinja2をオプションにします(非常に単純なテンプレートの場合、文字列フォーマットを使用してf"Hello {name}" )。たぶん、はっきりしたはずです笑。
OpenAI互換メッセージオブジェクトを出力します。
システムプロンプトと単一のプロンプトだけでなく、プロンプトチェーンを定義する機能。 Eg system_prompt -> user_prompt -> assistant_response -> user_prompt -> assistant_response -> ...