Lanchchain 데코레이터는 구문 설탕을 제공하는 랑 체인 위에있는 층입니까? Custom Langchain 프롬프트와 체인을 작성합니다
참고 : 이것은 Langchain 라이브러리의 비공식 애드온입니다. 더 쉽게 사용하기 위해 경쟁하려고하지 않습니다. 여기에 많은 아이디어가 전적으로 의견이 있습니다
다음은 Langchain 데코레이터 로 작성된 코드의 간단한 예입니다.
@ llm_prompt
def write_me_short_post ( topic : str , platform : str = "twitter" , audience : str = "developers" ) -> str :
"""
Write me a short header for my post about {topic} for {platform} platform.
It should be for {audience} audience.
(Max 15 words)
"""
return
# run it naturaly
write_me_short_post ( topic = "starwars" )
# or
write_me_short_post ( topic = "starwars" , platform = "redit" )주요 원칙 및 혜택 :
pythonic 방법빠른 시작
신속한 선언
LLM 함수 (OpenAi 함수)
단순화 된 스트리밍
자동 LLM 선택
더 복잡한 구조
프롬프트를 물체에 바인딩합니다
사용자 정의 설정 정의
디버깅
메모리 전달, 콜백, 중지 등
다른
pip install langchain_decorators시작 방법에 대한 좋은 아이디어는 여기에서 예제를 검토하는 것입니다.
기본적으로 프롬프트는 전체 기능 문서입니다. 프롬프트를 표시하지 않는 한
코드 블록을 언어 태그
@ llm_prompt
def write_me_short_post ( topic : str , platform : str = "twitter" , audience : str = "developers" ):
"""
Here is a good way to write a prompt as part of a function docstring, with additional documentation for devs.
It needs to be a code block, marked as a `<prompt>` language
```<prompt>
Write me a short header for my post about {topic} for {platform} platform.
It should be for {audience} audience.
(Max 15 words)
```
Now only the code block above will be used as a prompt, and the rest of the docstring will be used as a description for developers.
(It also has a nice benefit that IDE (like VS code) will display the prompt properly (not trying to parse it as markdown, and thus not showing new lines properly))
"""
return 채팅 모델의 경우 메시지 템플릿 세트로 프롬프트를 정의하는 데 매우 유용합니다. 다음 방법은 다음과 같습니다.
@ llm_prompt
def simulate_conversation ( human_input : str , agent_role : str = "a pirate" ):
"""
## System message
- note the `:system` sufix inside the <prompt:_role_> tag
```<prompt:system>
You are a {agent_role} hacker. You must act like one.
You reply always in code, using python or javascript code block...
for example:
... do not reply with anything else.. just with code - respecting your role.
```
# human message
(we are using the real role that are enforced by the LLM - GPT supports system, assistant, user)
``` <prompt:user>
Helo, who are you
```
a reply:
``` <prompt:assistant>
``` python <<- escaping inner code block with that should be part of the prompt
def hello():
print("Argh... hello you pesky pirate")
```
```
we can also add some history using placeholder
```<prompt:placeholder>
{history}
```
```<prompt:user>
{human_input}
```
Now only the code block above will be used as a prompt, and the rest of the docstring will be used as a description for developers.
(It also has a nice benefit that IDE (like VS code) will display the prompt properly (not trying to parse it as markdown, and thus not showing new lines properly))
"""
pass여기서의 역할은 모델 기본 역할 (Assistant, User, ChatGpt 용 시스템)입니다.
이에 대한 구문은 다음과 같습니다.
@ llm_prompt
def prompt_with_optional_partials ():
"""
this text will be rendered always, but
{? anything inside this block will be rendered only if all the {value}s parameters are not empty (None | "") ?}
you can also place it in between the words
this too will be rendered{? , but
this block will be rendered only if {this_value} and {this_value}
are not empty?} !
""" # this code example is complete and should run as it is
from langchain_decorators import llm_prompt
@ llm_prompt
def write_name_suggestions ( company_business : str , count : int ) -> list :
""" Write me {count} good name suggestions for company that {company_business}
"""
pass
write_name_suggestions ( company_business = "sells cookies" , count = 5 )현재 최신 OpenAI 채팅 모델에 대해서만 지원됩니다
@llm_function 데코레이터로 기능을 주석을 달기 만하면됩니다.
LLM에 대한 설명이 구문 분석됩니다 (첫 번째 코 히어 런트 단락은 함수 설명으로 간주됩니다).
ASO 매개 변수 설명 (Google, Numpy 및 Spihnx 표기법이 현재 지원됩니다)
기본적으로 docstring 형식이 자동으로 해결되지만 Docstring의 형식을 설정하면 속도가 약간 상승 할 수 있습니다. auto (기본값) : 형식은 DocString에서 자동으로 추론됩니다 - google : DocString은 Markdown으로 구문 분석됩니다 (Google Docstring Format 참조) numpy : Docstring은 Markdown으로 구문 분석됩니다 (Numpy Docstring 형식 참조) sphinx : Sphinx 형식 참조).
열거를 정의하는 가장 좋은 방법은 Literal 사용하여 유형 주석을 통한 것입니다.
@ llm_function
def do_magic ( spell : str , strength : Literal [ "light" , "medium" , "strong" ]):
"""
Do some kind of magic
Args:
spell (str): spall text
strength (str): the strength of the spell
""" 열거적인 대안 인수와 같은 "Enum" 에 주석을 달기 위해 대안으로 , 당신은이 "typescript"를 형식처럼 사용할 수 있습니다 : ["value_a" | "value_b"] ... 만약 구문 분석 될 경우. 이 텍스트는 설명의 일부가 될 것입니다 ... 원하지 않으면이 표기법을 유형 표기법으로 사용할 수 있습니다. 예:
Args:
message_type (["email" | "sms"]): type of a message / channel how to send the message
그런 다음이 기능을 인수로 전달하고 @llm_prompt (인수의 이름은 functions 로 지정되어야합니다.
사용 방법은 다음과 같습니다.
from langchain . agents import load_tools
from langchian_decorators import llm_function , llm_prompt , GlobalSettings
@ llm_function
def send_message ( message : str , addressee : str = None , message_type : Literal [ "email" , "whatsapp" ] = "email" ):
""" Use this if user asks to send some message
Args:
message (str): message text to send
addressee (str): email of the addressee... in format [email protected]
message_type (str, optional): style of message by platform
"""
if message_type == "email" :
send_email ( addressee , message )
elif message_type == "whatsapp" :
send_whatsapp ( addressee , message )
# load some other tools from langchain
list_of_other_tools = load_tools (
tool_names = [...],
llm = GlobalSettings . get_current_settings (). default_llm )
@ llm_prompt
def do_what_user_asks_for ( user_input : str , functions : List [ Union [ Callable , BaseTool ]]):
"""
```<prompt:system>
Your role is to be a helpful asistant.
```
```<prompt:user>
{user_input}
```
"""
user_input = "Yo, send an email to John Smith that I will be late for the meeting"
result = do_what_user_asks_for (
user_input = user_input ,
functions = [ send_message , * list_of_other_tools ]
)
if result . is_function_call :
result . execute ()
else :
print ( result . output_text )또한 GPT 동작을 제어하기 위해 LLM 프롬프트에
function_call인수를 추가 할 수도 있습니다.
- 값을 "없음"으로 설정하면 - 기능 호출을 비활성화하지만 여전히 볼 수 있습니다 (함수를 호출하기 전에 어떤 추론/계획에 유용합니다)
- 값을 "자동"으로 설정 한 경우 -GPT는 기능을 사용하거나 사용하도록 선택합니다.
- 값을 함수 이름으로 설정 / 또는 기능 IT 자체 (데코레이터는 스키마에서 사용 된 것과 동일한 이름을 해결하는 것을 처리합니다) GPT가 해당 함수를 사용하도록 강요합니다.
함수 인수를 사용하는 경우 출력은 항상 OutputWithFunctionCall 됩니다.
class OutputWithFunctionCall ( BaseModel ):
output_text : str
output : T
function_name : str = None
function_arguments : Union [ Dict [ str , Any ], str , None ]
function : Callable = None
function_async : Callable = None
@ property
def is_function_call ( self ):
...
@ property
def support_async ( self ):
...
@ property
def support_sync ( self ):
...
async def execute_async ( self ):
"""Executes the function asynchronously."""
...
def execute ( self ):
""" Executes the function synchronously.
If the function is async, it will be executed in a event loop.
"""
...
def to_function_message ( self , result = None ):
"""
Converts the result to a FunctionMessage...
you can override the result collected via execute with your own
"""
... 스키마가 어떻게 빌드되었는지 확인하려면 Decorator가 기능에 추가되는 get_function_schema 메서드를 사용할 수 있습니다.
from langchain_decorators import get_function_schema
@ llm_function
def my_func ( arg1 : str ):
...
f_schema = get_function_schema ( my_func . get_function_schema )
print ( f_schema ) Memory / Agent_ScratchPad에 결과를 추가하려면 to_function_message 사용하여 LLM이 도구 / 기능 결과로 해석 할 기능 메세이를 생성 할 수 있습니다.
함수 제공 업체를 사용하면 입력을 기반으로 함수 목록과 같은 LLM 기능 세트를보다 동적으로 제공 할 수 있습니다. 또한이 LLM 실행에 대해 각 기능에 고유 한 이름을 제공 할 수 있습니다. 이것은 두 가지 이유로 유용 할 수 있습니다.
기능 스키마 (및 특히 설명)는 LLM을 안내하는 데 중요한 도구입니다. 동적 함수 선언을 활성화하면 LLM_Function 구성표에서도 기본 프롬프트에 동일한 프롬프트 속성을 사용할 수 있습니다.
@ llm_function ( dynamic_schema = True )
def db_search ( query_input : str ):
"""
This function is useful to search in our database.
{?Here are some examples of data available:
{closest_examples}?}
"""
@ llm_prompt
def run_agent ( query_input : str , closest_examples : str , functions ):
"""
Help user. Use a function when appropriate
"""
closest_examples = get_closest_examples ()
run_agent ( query_input , closest_examples , functions = [ db_search , ...])이것은 그림을위한 것입니다. 코드 예제에서 완전히 실행 가능한 예제는 여기에서 사용할 수 있습니다.
스트리밍을 활용하려면 :
이런 식으로 우리는 어떤 프롬프트를 스트리밍 해야하는지 표시하고, 우리가 어떤 LLM을 사용해야하는지, 생성을 주위에 전달하고 스트리밍 핸들러를 체인의 특정 부분에 배포 할 필요가 없습니다 ... 프롬프트/프롬프트 유형에서 스트리밍을 켜거나 끄십시오 ...
스트리밍은 스트리밍 컨텍스트에서 호출하는 경우에만 발생합니다 ... 여기서 스트림을 처리하는 간단한 기능을 정의 할 수 있습니다.
# this code example is complete and should run as it is
from langchain_decorators import StreamingContext , llm_prompt
# this will mark the prompt for streaming (useful if we want stream just some prompts in our app... but don't want to pass distribute the callback handlers)
# note that only async functions can be streamed (will get an error if it's not)
@ llm_prompt ( capture_stream = True )
async def write_me_short_post ( topic : str , platform : str = "twitter" , audience : str = "developers" ):
"""
Write me a short header for my post about {topic} for {platform} platform.
It should be for {audience} audience.
(Max 15 words)
"""
pass
# just an arbitrary function to demonstrate the streaming... wil be some websockets code in the real world
tokens = []
def capture_stream_func ( new_token : str ):
tokens . append ( new_token )
# if we want to capture the stream, we need to wrap the execution into StreamingContext...
# this will allow us to capture the stream even if the prompt call is hidden inside higher level method
# only the prompts marked with capture_stream will be captured here
with StreamingContext ( stream_to_stdout = True , callback = capture_stream_func ):
result = await run_prompt ()
print ( "Stream finished ... we can distinguish tokens thanks to alternating colors" )
print ( " n We've captured" , len ( tokens ), "tokens? n " )
print ( "Here is the result:" )
print ( result )실생활에서는 상황이 사용중인 기본 모델의 창을 통해 컨텍스트가 커지는 상황 (예 : 긴 채팅 기록)이있을 수 있습니다. 그러나 이것은 때때로 발생할 수 있으므로이 시나리오에서 더 큰 컨텍스트 창을 가진 (일반적으로 더 비싼) 모델이 사용되는 경우에만 좋을 것입니다. 그렇지 않으면 더 저렴한 것을 사용합니다.
이제 llmselector와 함께 할 수 있습니다
from langchain_decorators import LlmSelector
my_llm_selector = LlmSelector (
generation_min_tokens = 0 , # how much token at min. I for generation I want to have as a buffer
prompt_to_generation_ratio = 1 / 3 # what percentage of the prompt length should be used for generation buffer
)
. with_llm_rule ( ChatGooglePalm (), max_tokens = 512 ) # ... if you want to use LLM whose window is not defined in langchain_decorators.common.MODEL_LIMITS (only OpenAI and Anthropic are there)
. with_llm ( ChatOpenAI ( model = "gpt-3.5-turbo" )) # these models are known, therefore we can just pass them and the max window will be resolved
. with_llm ( ChatOpenAI ( model = "gpt-3.5-turbo-16k-0613" ))
. with_llm ( ChatOpenAI ( model = "claude-v1.3-100k" ))이 클래스를 사용하면 프롬프트 길이와 예상 생성 길이를 기준으로 규칙을 가진 LLM 시퀀스를 정의 할 수 있으며 임계 값이 전달 된 후에 만 더 비싼 모델이 자동으로 사용됩니다.
GlobalSettings로 정의 할 수 있습니다.
langchain_decorators . GlobalSettings . define_settings (
llm_selector = my_llm_selector # pass the selector into global settings
)참고 : 버전 v0.0.10 현재 LLMSLECTERCER가 사전 정의 된 기본 설정에 있습니다. 자신의 자신을 제공하거나 기본 LLM 또는 기본 스트리밍 LLM을 설정하여 재정의 할 수 있습니다.
또는 특정 프롬프트 유형으로 :
from langchain_decorators import PromptTypes
class MyCustomPromptTypes ( PromptTypes ):
MY_TUBO_PROMPT = PromptTypeSettings ( llm_selector = my_llm_selector )Dict / Pydantic의 경우 서식 지침을 지정해야합니다 ... 이것은 지루할 수 있으므로 출력 파서가 모델 (Pydantic)을 기반으로 지침을 생성하도록 할 수 있습니다.
from langchain_decorators import llm_prompt
from pydantic import BaseModel , Field
class TheOutputStructureWeExpect ( BaseModel ):
name : str = Field ( description = "The name of the company" )
headline : str = Field ( description = "The description of the company (for landing page)" )
employees : list [ str ] = Field ( description = "5-8 fake employee names with their positions" )
@ llm_prompt ()
def fake_company_generator ( company_business : str ) -> TheOutputStructureWeExpect :
""" Generate a fake company that {company_business}
{FORMAT_INSTRUCTIONS}
"""
return
company = fake_company_generator ( company_business = "sells cookies" )
# print the result nicely formatted
print ( "Company name: " , company . name )
print ( "company headline: " , company . headline )
print ( "company employees: " , company . employees ) from pydantic import BaseModel
from langchain_decorators import llm_prompt
class AssistantPersonality ( BaseModel ):
assistant_name : str
assistant_role : str
field : str
@ property
def a_property ( self ):
return "whatever"
def hello_world ( self , function_kwarg : str = None ):
"""
We can reference any {field} or {a_property} inside our prompt... and combine it with {function_kwarg} in the method
"""
@ llm_prompt
def introduce_your_self ( self ) -> str :
"""
``` <prompt:system>
You are an assistant named {assistant_name}.
Your role is to act as {assistant_role}
```
```<prompt:user>
Introduce your self (in less than 20 words)
```
"""
personality = AssistantPersonality ( assistant_name = "John" , assistant_role = "a pirate" )
print ( personality . introduce_your_self ( personality )) 여기서 우리는 단지 llm_prompt 데코레이터의 프롬프트로 기능을 표시하여 효과적으로 llmchain으로 전환합니다. 그것을 실행하는 대신
표준 llmchain은 입력 _variables만으로 훨씬 더 많은 Init 매개 변수를 사용하고 프롬프트 ... 여기에 데코레이터에 숨겨진이 구현 세부 사항은 다음과 같습니다. 작동 방식은 다음과 같습니다.
글로벌 설정 사용 :
# define global settings for all prompty (if not set - chatGPT is the current default)
from langchain_decorators import GlobalSettings
GlobalSettings . define_settings (
default_llm = ChatOpenAI ( temperature = 0.0 ), this is default ... can change it here globally
default_streaming_llm = ChatOpenAI ( temperature = 0.0 , streaming = True ), this is default ... can change it here for all ... will be used for streaming
)사전 정의 된 프롬프트 유형을 사용합니다
#You can change the default prompt types
from langchain_decorators import PromptTypes , PromptTypeSettings
PromptTypes . AGENT_REASONING . llm = ChatOpenAI ()
# Or you can just define your own ones:
class MyCustomPromptTypes ( PromptTypes ):
GPT4 = PromptTypeSettings ( llm = ChatOpenAI ( model = "gpt-4" ))
@ llm_prompt ( prompt_type = MyCustomPromptTypes . GPT4 )
def write_a_complicated_code ( app_idea : str ) -> str :
...데코레이터의 설정을 직접 정의하십시오
from langchain . llms import OpenAI
@ llm_prompt (
llm = OpenAI ( temperature = 0.7 ),
stop_tokens = [ " n Observation" ],
...
)
def creative_writer ( book_title : str ) -> str :
...이 중 하나를 전달하려면 기능에서 선언하거나 (또는 Kwargs를 사용하여 무엇이든 전달하십시오).
(반드시 선언 될 필요는 없지만 사용하려는 경우 좋은 관행입니다).
@ llm_prompt ()
async def write_me_short_post ( topic : str , platform : str = "twitter" , memory : SimpleMemory = None ):
"""
{history_key}
Write me a short header for my post about {topic} for {platform} platform.
It should be for {audience} audience.
(Max 15 words)
"""
pass
await write_me_short_post ( topic = "old movies" ) 콘솔에 로그인 한 출력을 제어하는 방법에는 몇 가지 옵션이 있습니다. 가장 쉬운 방법은 ENV 변수를 정의하는 것입니다 : LANGCHAIN_DECORATORS_VERBOSE 는 "true"로 설정합니다.
여기에 표시된대로 글로벌 설정을 정의 하여이 프로그래밍 방식 으로이 프로그래밍 방식으로 제어 할 수 있습니다.
마지막 옵션은 프롬프트에서 Verbose Mode에서 Turing을 통해 각 경우에 따라 제어하는 것입니다.
@llm_prompt(verbose=True)
def your_prompt(param1):
...
PromptWatch IO는 Langchain 실행에서 진행중인 모든 것에 대한 세부 사항을 추적하고 추적하는 플랫폼입니다. 입구 포인트 코드를 래핑하여 한 줄의 줄이 통합을 삭제할 수 있습니다.
with PromptWatch():
run_your_code()
PromptWatch에 대해 자세히 알아보십시오. www.promptwatch.io
피드백, 기여 및 PR이 환영합니다