NOTA: Esta biblioteca está depreciada, agora é dividida em Zod-GPT e LLM-API.

O kit de ferramentas de engenharia de engenharia do TypeScript-primeiro para trabalhar com grandes modelos de idiomas baseados em bate-papo (LLMS).
O LLamaFlow é a camada de middleware que fica entre o seu software e o modelo de IA, adiciona os seguintes recursos no topo da API de conclusão de bate -papo padrão:
Com o LlamaFlow, você pode simplesmente consultar o modelo ChatGPT do OpenAI como assim:
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[]; Este pacote está hospedado no NPM:
npm i llama-flow
yarn add llama-flow
Para configurar sua base de código, inicialize uma nova instância com o modelo que você deseja (apenas OpenAI é suportado por enquanto). Observe que você também pode adicionar o modelo padrão e a configuração de bate -papo (como temperatura, tempo limite, tentativas) ao inicializar. Estes são apenas inadimplentes e sempre podem ser substituídos posteriormente por bate-papo ou por solicitação.
import { OpenAI } from 'llama-flow' ;
const model = new OpenAI (
{ apiKey : 'YOUR_OPENAI_KEY' } ,
{ model : 'gpt-3.5-turbo' } ,
) ;Um bate -papo é uma conversa entre o "usuário" (seu software) e o agente da IA. O LLamaFlow cuidará de gerenciar a memória de bate -papo, para que você possa simplesmente continuar a conversa enviando outra solicitação. Observe que diferentes estratégias de gerenciamento de memória serão adicionadas no futuro, como podar a memória, conforme necessário, a fim de ajustar a janela de contexto.
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 ,
) } ` ,
) ;Um prompt é uma mensagem para um bate -papo de IA com uma expectativa de um formato de resposta específico. As mensagens de tipo de prompt são validadas para garantir que o formatado definido seja retornado exatamente ou o erro. Existem diferentes tipos de instruções para diferentes formatos. Aqui está um exemplo de um prompt de 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 ) ) ,
} ) ; Observe que o objeto Prompt separa a message principal e formatMessage . Isso é usado para tentativas. Quando o LLamaFlow usa esse prompt, ele solicitará o modelo com a mensagem principal e de formato. Se o modelo retornar com uma resposta formatada incorretamente, solicitará ao modelo que corrija a saída anterior, usando apenas o formatMessage .
Você também pode criar seus próprios objetos rápidos com validadores personalizados. O LLamaFlow fornece uma maneira fácil e extensível de criar qualquer tipo de validador. Aqui estão alguns exemplos de validadores personalizados:
Tomando o exemplo imediato acima, mas desta vez solicitará ao modelo que apenas responda em pontos de bala reais em vez de matrizes JSON. Isso é útil porque, às vezes, o modelo (ESP <GPT-4) não é o melhor para seguir instruções específicas de formatação, especialmente quando se trata de estruturas de dados complicadas.
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.' ,
} ) ,
) ,
} ) ; Agora, vamos levar isso ainda mais longe. Você pode criar um prompt que use o modelo (ou alguma outra fonte externa) para validar sua própria saída. Você pode fazer isso passando em um método validate assíncrono personalizado. Observe que esse método substituirá outras propriedades relacionadas à validação, como formatMessage , parseResponse , schema .. etc.
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.' ,
) ,
) ;Como isso é uma API, geralmente é útil continuar solicitando o mesmo bate -papo. Muitas vezes, o histórico de mensagens servirá de contexto para a próxima solicitação. Um bom exemplo de caso de uso é um prompt para escrever primeiro algum conteúdo, depois extrair entidades e, finalmente, fornecer algumas opções para o título.
// 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 ,
} ) ,
) ; Um erro comum com o LLM APIs é o uso do token - você só pode ajustar uma certa quantidade de dados na janela de contexto. No caso do llamaflow, isso significa que você é limitado no número total de mensagens que você pode enviar (se retainMemory estiver definido como true ) e o comprimento do conteúdo das mensagens.
O LLamaFlow determinará automaticamente se a solicitação violará o limite do token antes de enviar a solicitação real ao provedor de modelos (por exemplo, OpenAI). Isso salvará uma chamada de ida e volta de uma rede e permitirá que você lide com esse tipo de erro de maneira responsiva. A maneira típica de lidar com esses erros é remover as mensagens no histórico de mensagens (se você estiver usando o bate -papo com o conjunto retainMemory ) ou dividir seu conteúdo em clusters menores e processá -los em várias solicitações.
Aqui está um exemplo de captura do erro de transbordamento do token. Observe que o minimumResponseTokens está definido como um valor alto para acionar explicitamente esse erro ( gpt-3.5-turbo tem um limite máximo de contexto de 4096; portanto, definir o limite mínimo para 4095 significa que restam apenas 1 token para o prompt real, o que não é suficiente para o exemplo abaixo.)
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 } ` ,
) ;
}
} Uma maneira comum de lidar com problemas de limite de token é dividir seu conteúdo. O LLamaFlow fornece um método ajudante útil que envolve o método chat.request e dividirá automaticamente seu texto com base em uma configuração de chunk de entrada. É inteligente o suficiente para dividir seu texto apenas se determinar que está acima do limite do token e tentará preservar o máximo possível do texto original.
const response = await chat . requestWithSplit (
'hello world, testing overflow logic' ,
( text ) =>
prompt . text ( {
message : `Add other required prompts first, then add your content: ${ text } ` ,
} ) ,
) ; Observe que agora, o conteúdo principal do prompt é enviado primeiro. Este é o conteúdo que será dividido pelo divisor de texto (ao longo do n . , e Personagens primeiro, para rasgar). Você pode adicionar os prompts necessários adicionais e combiná -lo com o prompt de conteúdo no parâmetro responseFn .
LLAMAFLOW Usese O módulo debug para mensagens de log e erro. Para executar no modo de depuração, defina a variável DEBUG Env:
DEBUG=llamaflow:* yarn playground
Você também pode especificar diferentes tipos de registro via:
DEBUG=llamaflow:error yarn playground DEBUG=llamaflow:log yarn playground
O LLAMAFLOW também vem com suporte para os modelos Openai do Azure. A versão do Azure é geralmente muito mais rápida e confiável que os pontos de extremidade da API da OpenAI. Para usar os pontos de extremidade do Azure, você deve incluir 2 opções específicas do Azure ao inicializar o modelo OpenAI, azureDeployment e azureEndpoint . O campo apiKey também agora será usado para a chave da API do Azure.
Você pode encontrar a chave da API do Azure e o ponto final no portal do Azure. A implantação do Azure deve ser criada no portal do Azure AI.
Observe que o parâmetro model no ModelConfig será ignorado ao usar o Azure. Isso ocorre porque no sistema do Azure, o model é selecionado na criação de implantação, não no tempo de execução.
const model = new OpenAI ( {
apiKey : 'AZURE_OPENAI_KEY' ,
azureDeployment : 'AZURE_DEPLOYMENT_NAME' ,
azureEndpoint : 'AZURE_ENDPOINT' ,
} ) ; O único suporte ao modelo LlamaFlow suporta atualmente são os modelos baseados em bate -papo da OpenAI.
const model = new OpenAI ( openAiConfig , modelConfig ) ; interface OpenAIConfig {
apiKey : string ;
} Esses mapas de configuração de modelo para a configuração do OpenAI diretamente, consulte Doc: 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 ;
} Quando stream é definido como true , você pode acessar saídas parciais das solicitações do modelo, passando em um emissor de eventos para ChatRequestOptions ao fazer solicitações. As saídas parciais serão enviadas como uma string sobre o evento data .
Para fazer uma solicitação ao modelo, você precisa primeiro criar o objeto rápido. Os avisos fornecem uma maneira de adicionar validação e tentar novamente a lógica a cada solicitação.
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 ) ; Você pode solicitar como uma string ou como um RawPrompt .
interface RawPrompt < T = string > {
message : string ;
parse ?: (
response : ChatResponse < string > ,
) => MaybePromise <
{ success : false ; retryPrompt ?: string } | { success : true ; data : T }
> ;
promptRetries ?: number ;
}Mensagem Este é o texto enviado ao modelo.
Parse, você pode implementar um analisador personalizado definindo um método seu próprio parse .
Ao definir um método parse personalizado que retorna um tipo de dados personalizado, você pode adicionar um tipo genérico ao RawPrompt , que lançará automaticamente o tipo de retorno de parse no genérico. Ele também propagará o tipo todo o método chat.request .
Se os dados retornados pelo modelo forem malformados, você poderá retornar uma string retryPrompt personalizada, que fará com que o llamaflow reavalie o modelo.
O Promptretries define quantas vezes reavaliar o modelo antes que a solicitação lançará um erro. Padrões para 3. Observe que parse deve devolver um retryPrompt válido para que todas as tentativas sejam tentadas.
interface BooleanPrompt {
message : string ;
promptRetries ?: number ;
} Use este prompt se desejar fazer ao modelo uma pergunta em que você espera apenas uma resposta true ou false .
Envie uma mensagem para a consulta para enviar para o modelo. Este prompt anexará automaticamente as instruções de formatação à mensagem enviada ao modelo que informa ao modelo para formatar sua resposta como booleano, para que você possa incluir a consulta na message , sem escrever nenhuma declaração de formatação adicional.
interface BulletPointsPrompt {
message : string ;
amount ?: number ;
length ?: number ;
promptRetries ?: number ;
}Use este prompt se desejar que o modelo retorne uma lista de strings.
Envie uma mensagem para a consulta para enviar para o modelo. Este prompt anexará automaticamente as instruções de formatação à mensagem que informa ao modelo como formatar a resposta.
valor o número de pontos de bala que devem ser devolvidos.
comprimento O número máximo de caracteres que devem estar em cada ponto de bala.
interface JSONPrompt < T extends z . ZodType > {
message : string ;
schema : T ;
parseResponse ?: ( res : string ) => MaybePromise < z . infer < T > > ;
retryMessage ?: string ;
promptRetries ?: number ;
}mensagem a mensagem para enviar para o modelo. Ao contrário dos avisos booleanos ou de pontos de bala, esse prompt não gera automaticamente instruções de formação para o modelo. Portanto, como parte da sua mensagem para o modelo, você deve incluir instruções de formatação para retornar dados no formato JSON, bem como a forma do JSON.
Esquema Este é o esquema ZOD que será usado para analisar e digitar a resposta do modelo.
O ParseResponse se você solicitar ao modelo para não retornar dados no formato JSON, poderá definir um analisador personalizado para analisar a string de retorno no JSON, antes de enviá -lo para schema para validação.
RETRYMESSAGE se a análise do esquema falhar, isso será usado como parte da mensagem enviada ao modelo para reasçar para uma resposta corretamente formatada. Observe que este prompt gerará automaticamente a mensagem reask, dependendo dos erros de análise de esquema (por exemplo, se uma chave específica estiver ausente, o llamaflow solicitará ao modelo que inclua essa chave específica). Portanto, este campo é apenas para dar um contexto adicional ao modelo no reask.
O objeto de bate -papo armazena uma sessão de bate -papo com o modelo. A sessão cuidará de armazenar o histórico de mensagens, para que você possa simplesmente continuar a conversa com o modelo fazendo outra solicitação.
const chat = model . chat ( config : ChatConfig ) ;Opções Você pode definir o comportamento de retenção de memória, bem como as opções de solicitação padrão para cada solicitação enviada neste bate -papo.
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 ;
} Para enviar uma solicitação para uma sessão de bate -papo:
const res : ChatResponse = await chat . request ( prompt , options : ChatRequestOptions ) ;Opções Você pode substituir as opções de solicitação padrão através deste parâmetro. Uma solicitação será aplicada automaticamente se houver um erro de rateLimit ou servidor.
Observe que uma nova tentativa na solicitação não conta para um reask prompt definido na seção Prompt acima.
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 ;
} ; As respostas de bate -papo estão no seguinte formato:
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 ;
} ;
}O conteúdo analisou e tipou o conteúdo do prompt. Os tipos serão definidos automaticamente, dependendo do prompt que você usou.
Modele o modelo específico usado para a conclusão (por exemplo, gpt-3.5-turbo-0301 )
Dados de uso de token de uso , isso mapeia a resposta de uso diretamente do OpenAI.
Se você deseja redefinir o histórico de mensagens em um histórico de bate -papo, existe um método simples auxiliar:
chat . reset ( ) ;Observe que este método é uma escotilha de fuga. É melhor apenas instanciar uma nova sessão de bate -papo se você quiser fazer uma nova solicitação com uma lista limpa. Lógica complexa, onde você está redefinindo uma sessão de bate -papo várias vezes pode ser difícil de rastrear e difícil de depurar.
Observe que, se você deseja ignorar a lógica de gerenciamento de bate -papo da LLamaflow e enviar uma solicitação para o modelo subjacente diretamente, você pode enviar uma solicitação diretamente para o modelo sem instantar um bate -papo:
const model = new OpenAI ( openAiConfig , modelConfig ) ;
const res = await model . request ( messages : Message [ ] , options : ChatRequestOptions ) ; Isso ignorará qualquer gerenciamento de histórico de bate -papo, formatação rápida e análise, bem como lógica persona. Você ainda pode fazer uso do recurso API VECRIBIÇÕES via ChatRequestOptions .