注意:该库已弃用,现在被分为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
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重试功能。