ระบบการจัดการพรอมต์ที่ปลอดภัยและปลอดภัยสำหรับ LLMs ที่จับข้อผิดพลาดก่อนกำหนดบังคับใช้ความปลอดภัยประเภทและเป็นวิธีที่มีโครงสร้างในการจัดการพรอมต์ ใช้โมเดล Pydantic สำหรับการตรวจสอบตัวแปรและเทมเพลต Jinja2 สำหรับการแสดงผลพร้อมท์
หมายเหตุ : ห้องสมุดนี้อยู่ในระหว่างการพัฒนาก่อนและอาจมีการเปลี่ยนแปลง
ฉันมักจะพบว่ามันท้าทายในการจัดการพรอมต์แบบไดนามิกสำหรับ LLM กระบวนการนี้เกิดข้อผิดพลาดได้ง่ายโดยมีปัญหาที่พบบ่อยในรันไทม์เท่านั้น Pyped-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 เป็นค่าสำหรับตัวแปรเสริมจะแสดงผลเป็น
Noneในพรอมต์ เช่น "ตัวอย่างทดสอบ{{var}}จะแสดงเป็นTest example Noneถ้าvarNoneนี่คือพฤติกรรมเริ่มต้นของ jinja ดังนั้นคุณต้องจัดการสิ่งนี้ในเทมเพลต jinja2 ของคุณเช่น{{if var}}หรือ{{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 ทั่วไป:
พรอมต์ระบบ : ให้บริบทหรือคำแนะนำสำหรับโมเดล AI คุณสามารถกำหนดสิ่งนี้ได้สองวิธี:
system_prompt_template พรอมต์ผู้ใช้ : มีแม่แบบพรอมต์จริงที่จะส่งไปยังรุ่น สิ่งนี้ถูกกำหนดไว้เสมอในแอตทริบิวต์คลาส prompt_template
ตัวแปรในการพิมพ์พิมพ์ได้รับการจัดการผ่านกลไกเสริมสามประการ:
ตัวแปรโมเดล : โมเดล 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 )ตัวแปรพิเศษ : ตัวแปรเดียวสามารถส่งผ่านไปยังวิธีการเรนเดอร์โดยตรง
ห้องสมุดดำเนินการตรวจสอบอย่างครอบคลุมเพื่อจับปัญหาทั่วไปก่อน:
สำหรับพรอมต์ที่ซับซ้อนคุณสามารถโหลดเทมเพลตจากไฟล์ภายนอก:
class ComplexPrompt ( BasePrompt [ ComplexVariables ]):
system_prompt_template = Path ( "templates/system_prompt.j2" ). read_text ()
prompt_template : str = Path ( "templates/user_prompt.j2" ). read_text ()หมายเหตุ : ด้วยเครื่องยนต์ templating เช่น Jinja2 คุณสามารถโหลดเทมเพลตการโหลดซ้ำได้ แต่สิ่งนี้ไม่ได้รับการสนับสนุนในการพิมพ์พิมพ์เนื่องจากเทมเพลตได้รับการตรวจสอบในเวลานิยามของชั้นเรียน
คลาสพื้นฐานสำหรับการสร้างพรอมต์ที่มีโครงสร้าง
T : คลาสย่อย basemodel pydantic ที่กำหนดโครงสร้างของตัวแปรเทมเพลต system_prompt_template : ตัวเลือก [STR] - เทมเพลตพรอมต์ระบบprompt_template : STR - เทมเพลตพรอมต์ของผู้ใช้variables : T - อินสแตนซ์ของโมเดลตัวแปร render(**extra_vars) -> RenderOutput : แสดงผลทั้งสองพร้อมกับตัวแปรที่ให้ไว้NamedTuple ให้การเข้าถึงที่มีโครงสร้างเพื่อรับพรอมต์:
system_prompt : เสริม [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
ความสามารถในการกำหนดไม่ใช่แค่พรอมต์ระบบและพรอมต์เดียว แต่เป็นโซ่พร้อม เช่น system_prompt -> user_prompt -> assistant_response -> user_prompt -> assistant_response -> ...