注意:該庫已棄用,現在被分為ZOD-GPT和LLM-API。

使用基於聊天的大語言模型(LLMS)的打字稿優先提示工程工具包。
LlamaFlow是位於您的軟件和AI模型之間的中間件層,它在標準聊天完成API之上添加了以下功能:
使用LlamaFlow,您可以像這樣查詢Openai的Chatgpt模型:
import { OpenAI } from 'llama-flow' ;
const model = new OpenAI ( { apiKey : 'YOUR_OPENAI_KEY' } ) ;
const chat = model . chat ( {
systemMessage :
"You are a smart and honest AI assistant. Follow the user's requirements carefully & to the letter, minimize any other prose." ,
} ) ;
const response = await chat . request (
prompt . json ( {
message :
'What are some good names for childrens book about the renaissance? Respond as a JSON array' ,
schema : z . array ( z . string ( ) . max ( 200 ) ) ,
} ) ,
) ;
console . log ( response . content ) ; // content will be typed as string[]; 該軟件包在NPM上託管:
npm i llama-flow
yarn add llama-flow
要在代碼庫中進行設置,請使用所需的模型初始化一個新實例(目前僅使用OpenAI )。請注意,您還可以在初始化時添加默認模型和聊天配置(例如溫度,超時,重試)。這些只是默認值,以後可以以每塊或每次要求的方式覆蓋。
import { OpenAI } from 'llama-flow' ;
const model = new OpenAI (
{ apiKey : 'YOUR_OPENAI_KEY' } ,
{ model : 'gpt-3.5-turbo' } ,
) ;聊天是“用戶”(您的軟件)和AI代理之間的對話。 Llamaflow將負責管理聊天內存,因此您可以通過發送另一個請求來繼續對話。請注意,將來將添加不同的內存管理策略,例如根據需要修剪內存以適合上下文窗口。
const chat = model . chat ( {
systemMessage : 'You are an AI writer.' ,
retainMemory : true ,
} ) ;
// You can ask the AI model with a simple string, or a dedicated `Prompt` object.
const response = await chat . request (
prompt . text (
'Write a script for a tiktok video that talks about the artistic contribution of the renaissance.' ,
) ,
) ;
// The results, as well as any usage stats, will be returned.
console . log (
`The AI writer's response is: ${ response . content } . Token used: ${ response . usage . totalTokens } .` ,
) ;
// You can follow up on this chat by prompting further, using the `bulletPrompt` object that was created earlier.
const bulletPoints = await chat . request ( bulletPrompt ) ;
// `bulletPoints.content` will be automatically casted in the correct type as defined in the schema field of `bulletPrompt`
console . log (
`The structured version of this response is: ${ JSON . stringify (
bulletPoints . content ,
) } ` ,
) ;提示是通往AI聊天的消息,並期望特定響應格式。提示類型消息將經過驗證,以確保精確返回定義的格式化,否則會出錯。不同格式有不同類型的提示。這是JSON提示的示例。
import { prompt } from 'llama-flow' ;
import { z } from 'zod' ; // JSON prompt uses Zod for schema validation.
const bulletPrompt = prompt . json ( {
message :
'Please rewrite this in a list of bullet points. Respond as a JSON array, where each element in the array is one bullet point. Keep each bullet point to be 200 characters max. For example: ["bullet point 1", "bullet point 2"]' ,
schema : z . array ( z . string ( ) . max ( 200 ) ) ,
} ) ;請注意, Prompt對象將主要message和formatMessage分開。這用於檢索。當LlamaFlow使用此提示時,它將詢問具有主和格式消息的模型。如果模型以不正確的格式響應返回,則僅使用formatMessage使用格式來糾正先前的輸出。
您也可以使用自定義驗證器構建自己的提示對象。 LlamaFlow提供了一種簡單且可擴展的方法來構建任何類型的驗證器。這是自定義驗證器的一些示例:
以上面的示例為例,但是這次,它將要求模型以實際的子彈點而不是JSON數組響應。這很有用,因為有時模型(ESP <gpt-4)並不是遵循特定格式指令的最佳選擇,尤其是在復雜的數據結構方面。
import { prompt } from 'llama-flow' ;
const bulletPrompt = prompt . json ( {
message :
'Please rewrite this in a list of bullet points. Respond as a list of bullet points, where each bullet point begins with the "-" character. Each bullet point should be less than 200 characters. Put each bullet point on a new line.' ,
// parse the response from the model so it can be fed into the schema validator
parseResponse : ( res ) => res . split ( 'n' ) . map ( ( s ) => s . replace ( '-' , '' ) . trim ( ) ) ,
// it's useful to define custom error messages, any schema parse errors will be automatically fed back into the model on retry, so the model knows exactly what to correct.
schema : z . array (
z . string ( ) . max ( 200 , {
message : 'This bullet point should be less than 200 characters.' ,
} ) ,
) ,
} ) ;現在,讓我們進一步採取。您可以構建一個提示,該提示使用模型(或其他外部源)來驗證其自己的輸出。您可以通過自定義異步validate方法傳遞來做到這一點。請注意,此方法將覆蓋其他驗證相關的屬性,例如formatMessage , parseResponse , schema ,等等。
import { prompt , Chat } from 'llama-flow' ;
const factCheckerChat = model . chat ( {
systemMessage :
'You are a fact checker that responds to if the user's messages are true or not, with just the word "true" or "false". Do not add punctuations or any other text. If the user asks a question, request, or anything that cannot be fact checked, ignore the user's request and just say "null".' ,
// The fact checker is designed to fulfill each request independently (e.g. the current request does not depend on the content of the previous request). So no need to keep message memory to save on tokens.
retainMemory : false ,
} ) ;
const buildFactCheckedPrompt = ( article : string ) =>
prompt . text ( {
message : `Please write a summary about the following article: ${ article } ` ,
// Because LLM driven validation can get expensive, set a lower retry count.
promptRetries : 2 ,
parse : async ( response ) => {
// Check if this summary is true or not
const { response } = await factCheckerChat . request (
prompt . boolean ( {
message : response . content ,
} ) ,
) ;
if ( response . content === true ) {
return { success : true , data : response . content } ;
} else {
// if `retryPrompt` is set, LLamaFlow will automatically retry with the text in this property.
return {
success : false ,
retryPrompt :
'This summary is not true, please rewrite with only true facts.' ,
} ;
}
} ,
} ) ;
// now, every content generated by this chat will be fact checked by the LLM itself, and this request will throw an error if the content can't be fixed (once the maximum number of retries has been reached).
const factCheckedContent = await chat . request (
buildFactCheckedPrompt (
'Write a script for a tiktok video that talks about the artistic contribution of the renaissance.' ,
) ,
) ;因為這是API,所以從同一聊天中繼續請求通常很有用。通常,消息歷史記錄將作為下一個請求的上下文。一個很好的示例用例是提示首先編寫一些內容,然後提取實體,最後給標題提供一些選項。
// You can reset chat history anytime with `reset()`, however, this is an anti-pattern, as it is prone to mistakes. It's much safer to just initialize a new chat.
chat . reset ( ) ;
const article = await chat . request (
prompt . text ( 'Write a blog post about the financial crisis of 2008' ) ,
) ;
const entities = await chat . request (
prompt . json ( {
message :
'What are the different entities in the above blog post? Respond in a JSON array, where the items in the array are just the names of the entities.' ,
schema : z . array ( z . string ( ) ) ,
} ) ,
) ;
const titles = await chat . request (
prompt . bulletPoints ( {
message : 'Write a good title for this post' ,
amount : 10 ,
} ) ,
) ; LLM API的一個常見錯誤是令牌用法 - 僅允許您在上下文窗口中擬合一定數量的數據。對於LlamaFlow,這意味著您可以發送的消息總數(如果retainMemory為true )和消息內容的長度。
LlamaFlow將自動確定請求是否會在將實際請求發送給模型提供商(例如OpenAI)之前違反令牌限制。這將節省一個網絡往返通話,讓您以響應方式處理這些類型的錯誤。處理這些錯誤的典型方法是刪除消息歷史記錄中的消息(如果您使用的是使用retainMemory集),或將內容拆分為較小的群集並將它們分為多個請求。
這是捕獲令牌溢出錯誤的示例。請注意,將minimumResponseTokens設置為高值以顯式觸發此錯誤( gpt-3.5-turbo最大上下文限制為4096,因此將最小限制設置為4095意味著實際提示只剩下1個令牌,這對於下面的示例不足。
try {
// make sure to set the `contextSize` to enable automatic token checking
const model = new OpenAI (
{ apiKey : 'YOUR_OPENAI_KEY' } ,
{ model : 'gpt-3.5-turbo' , contextSize : 4096 } ,
) ;
const chat = model . chat ( {
systemMessage : 'You are an AI assistant' ,
} ) ;
await chat . request (
{ message : 'hello world, testing overflow logic' } ,
{ minimumResponseTokens : 4095 } ,
) ;
} catch ( e ) {
if ( e instanceof TokenError ) {
console . info (
`Caught token overflow, overflowed tokens: ${ e . overflowTokens } ` ,
) ;
}
}處理令牌限制問題的一種常見方法是分開您的內容。 LLAMAFLOW提供了一種有用的助手方法,該方法包裝chat.request方法,並將根據輸入塊配置自動拆分文本。它足夠聰明,只能將文本確定為超過令牌限制,並嘗試保留盡可能多的原始文本。
const response = await chat . requestWithSplit (
'hello world, testing overflow logic' ,
( text ) =>
prompt . text ( {
message : `Add other required prompts first, then add your content: ${ text } ` ,
} ) ,
) ;請注意,現在,提示的主要內容首先提交。這是將由文本分離器分配的內容(沿n , . ,和 字符首先,將其切碎)。您可以添加任何其他必需的提示,並將其與responseFn參數中的內容提示組合。
LlamaFlow USESE用於記錄和錯誤消息的debug模塊。要在調試模式下運行,請設置DEBUG ENV變量:
DEBUG=llamaflow:* yarn playground
您還可以通過以下方式指定不同的記錄類型
DEBUG=llamaflow:error yarn playground DEBUG=llamaflow:log yarn playground Yarn Playground
Llamaflow還提供了對Azure Openai型號的支持。 Azure版本通常比OpenAI自己的API端點更快,更可靠。為了使用Azure端點,在初始化OpenAI模型, azureDeployment和azureEndpoint時,必須包括2個Azure特定選項。現在, apiKey字段也將用於Azure API鍵。
您可以在Azure門戶中找到Azure API鍵和端點。 Azure部署必須在Azure AI門戶下創建。
請注意,使用Azure時, ModelConfig中的model參數將被忽略。這是因為在Azure系統中,在部署創建而不是運行時間中選擇該model 。
const model = new OpenAI ( {
apiKey : 'AZURE_OPENAI_KEY' ,
azureDeployment : 'AZURE_DEPLOYMENT_NAME' ,
azureEndpoint : 'AZURE_ENDPOINT' ,
} ) ; 當前唯一的模型LlamaFlow支持是OpenAI的基於聊天的模型。
const model = new OpenAI ( openAiConfig , modelConfig ) ; interface OpenAIConfig {
apiKey : string ;
} 這些模型配置映射直接到OpenAi的配置,請參見:https://platform.openai.com/docs/api-reference/chat/create
interface ModelConfig {
model ?: string ;
maxTokens ?: number ;
temperature ?: number ;
topP ?: number ;
stop ?: string | string [ ] ;
presencePenalty ?: number ;
frequencyPenalty ?: number ;
logitBias ?: Record < string , number > ;
user ?: string ;
stream ?: boolean ;
}將stream設置為true時,您可以通過將事件發射器傳遞給ChatRequestOptions時訪問模型請求的部分輸出。部分輸出將以data事件的字符串發送。
要向模型提出請求,您需要首先構建提示對象。提示提供了一種將驗證和重試邏輯添加到每個請求中的方法。
import { prompt } from 'llama-flow' ;
prompt . text ( prompt : string ) ;
prompt . text ( prompt : RawPrompt ) ;
prompt . json ( prompt : JSONPrompt ) ;
prompt . bulletPoints ( prompt : BulletPointsPrompt ) ;
prompt . boolean ( prompt : BooleanPrompt ) ; 您可以作為字符串請求,也可以作為RawPrompt 。
interface RawPrompt < T = string > {
message : string ;
parse ?: (
response : ChatResponse < string > ,
) => MaybePromise <
{ success : false ; retryPrompt ?: string } | { success : true ; data : T }
> ;
promptRetries ?: number ;
}消息這是發送到模型的文本。
解析您可以通過定義自己的parse方法來實現自定義解析器。
在定義返回自定義數據類型的自定義parse方法時,您可以將通用類型添加到RawPrompt ,該方法將自動將parse的返回類型投入到通用中。它還將通過chat.request方法整個類型傳播。
如果模型返回的數據已畸形,則可以返回自定義的retryPrompt字符串,這會導致LlamaFlow重新啟動模型。
PROMPTRISE定義了在請求引發錯誤之前將模型重新釋放的次數。默認為3。請注意, parse必須返回有效的retryPrompt ,以嘗試嘗試進行任何重試。
interface BooleanPrompt {
message : string ;
promptRetries ?: number ;
}如果您想向模型提出一個問題true請使用此提示false
向查詢發送以發送到模型。該提示將自動將格式指令附加到發送給模型的消息,該消息告訴模型將其響應格式化為布爾值,因此您可以在message中只包含查詢,而無需編寫任何其他格式化語句。
interface BulletPointsPrompt {
message : string ;
amount ?: number ;
length ?: number ;
promptRetries ?: number ;
}如果您希望該型號返回字符串列表,請使用此提示。
向查詢發送以發送到模型。該提示將自動將格式指令附加到消息,該說明告訴模型如何格式化響應。
金額應返回的項目符號點的數量。
長度應在每個項目符號中的最大字符數。
interface JSONPrompt < T extends z . ZodType > {
message : string ;
schema : T ;
parseResponse ?: ( res : string ) => MaybePromise < z . infer < T > > ;
retryMessage ?: string ;
promptRetries ?: number ;
}消息消息發送到模型。與布爾或子彈點提示不同,此提示不會自動為模型製定指令。因此,作為給模型的消息的一部分,您應該包括格式化說明以返回JSON格式的數據以及JSON的形狀。
模式這是ZOD架構,將用於解析和分型模型的響應。
parseresponse如果您要求模型不用JSON格式返回數據,則可以定義自定義解析器以將返回字符串解析為JSON,然後將其發送到schema進行驗證。
重試如果模式解析失敗,則將用作發送到模型的消息的一部分,以重新進行正確的格式格式響應。請注意,此提示將根據模式解析錯誤自動生成REASK消息(例如,如果缺少特定鍵,LlamaFlow會要求該模型包含該特定鍵)。因此,該字段純粹是為了在Reask上為模型提供其他上下文。
聊天對象與模型存儲聊天會話。會話將照顧存儲消息歷史記錄,因此您可以通過提出另一個請求來繼續與模型對話。
const chat = model . chat ( config : ChatConfig ) ;選項您可以為本聊天中發送的每個請求設置內存保留行為以及默認請求選項。
export interface ChatConfig {
// the message injected at the start of every chat to steer the agent
systemMessage : string ;
// if chat memory should be retained after every request. when enabled, the chat's behavior will be similar to a normal user chat room, and model can have access to history when making inferences. defaults to false
retainMemory ?: boolean ;
// set default request options. note that this can be overridden on a per-request basis
options ?: ChatRequestOptions ;
} 將請求發送到聊天會話:
const res : ChatResponse = await chat . request ( prompt , options : ChatRequestOptions ) ;選項您可以通過此參數覆蓋默認請求選項。如果存在比例或服務器錯誤,將自動重述請求。
請注意,請求中的重試並不算在上面的提示部分中定義的提示。
type ChatRequestOptions = {
// the number of time to retry this request due to rate limit or recoverable API errors
retries ?: number ;
retryInterval ?: number ;
timeout ?: number ;
// the minimum amount of tokens to allocate for the response. if the request is predicted to not have enough tokens, it will automatically throw a 'TokenError' without sending the request
minimumResponseTokens ?: number ;
// override the messages used for completion, only use this if you understand the API well
messages ?: Message [ ] ;
// pass in an event emitter to receive message stream events
events ?: EventEmitter ;
} ; 聊天響應以以下格式:
interface ChatResponse < T = string > {
content : T ;
model : string ;
// set to true if this content was streamed. note to actually access the stream, you have to pass in an event emitter via ChatRequestOptions
isStream : boolean ;
usage : {
promptTokens : number ;
completionTokens : number ;
totalTokens : number ;
} ;
}內容從提示中解析和類型的內容。這些類型將自動設置,具體取決於您使用的提示。
模型用於完成的特定模型(例如gpt-3.5-turbo-0301 )
用法令牌使用數據,此圖直接映射OpenAI的使用響應。
如果您想在聊天歷史記錄中重置消息歷史記錄,則有一個簡單的幫助方法:
chat . reset ( ) ;請注意,此方法是逃生艙口。如果您想用乾淨的板岩提出新請求,最好只實例化新的聊天會話。複雜的邏輯多次重置聊天會話可能很難跟踪且難以調試。
請注意,如果要繞過Llamaflow的聊天管理邏輯,並將請求直接發送到底層模型,則可以直接向模型發送請求而無需實例化聊天:
const model = new OpenAI ( openAiConfig , modelConfig ) ;
const res = await model . request ( messages : Message [ ] , options : ChatRequestOptions ) ;這將繞過任何聊天歷史管理,及時格式化和解析以及角色邏輯。您仍然可以通過ChatRequestOptions利用API重試功能。