Remarque: Cette bibliothèque est obsolète, elle est désormais divisée en ZOD-GPT et LLM-API.

La boîte à outils d'ingénierie rapide TypeScript-First pour travailler avec les modèles de grande langue basés sur le chat (LLMS).
Llamaflow est la couche middleware qui se trouve entre votre logiciel et le modèle AI, il ajoute les capacités suivantes en plus de l'API de complétion de chat standard:
Avec Llamaflow, vous pouvez simplement interroger le modèle Chatgpt d'Openai comme ça:
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[]; Ce package est hébergé sur NPM:
npm i llama-flow
yarn add llama-flow
Pour configurer votre base de code, initialisez une nouvelle instance avec le modèle que vous souhaitez (seul OpenAI est soutenu pour l'instant). Notez que vous pouvez également ajouter le modèle par défaut et la configuration de chat (comme la température, les délais d'expiration, les tentatives) lors de l'initialisation. Ce ne sont que des défauts et peuvent toujours être écrasés plus tard sur une base par chat ou par refonte.
import { OpenAI } from 'llama-flow' ;
const model = new OpenAI (
{ apiKey : 'YOUR_OPENAI_KEY' } ,
{ model : 'gpt-3.5-turbo' } ,
) ;Une conversation est une conversation entre «l'utilisateur» (votre logiciel) et l'agent d'IA. Llamaflow s'occupera de gérer la mémoire du chat, vous pouvez donc simplement continuer la conversation en envoyant une autre demande. Notez que différentes stratégies de gestion de la mémoire seront ajoutées à l'avenir, telles que l'élagage de la mémoire selon les besoins afin de s'adapter à la fenêtre de contexte.
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 ,
) } ` ,
) ;Une invite est un message à une conversation sur l'IA avec l'attente d'un format de réponse spécifique. Les messages de type d'invite sont validés pour s'assurer que le format défini est renvoyé exactement, ou il errera. Il existe différents types d'invites pour différents formats. Voici un exemple d'invite 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 ) ) ,
} ) ; Notez que l'objet Prompt sépare le message principal et formatMessage . Ceci est utilisé pour les tentatives. Lorsque Llamaflow utilise cette invite, elle demandera au modèle avec le message principal et de format. Si le modèle revient avec une réponse mal formatée, il demandera au modèle de corriger la sortie précédente, en utilisant le formatMessage uniquement.
Vous pouvez également créer vos propres objets invités avec des validateurs personnalisés. Llamaflow offre un moyen facile et extensible de construire tout type de validateurs. Voici quelques exemples de validateurs personnalisés:
Prenant l'exemple rapide ci-dessus, mais cette fois, il demandera au modèle de simplement répondre dans des puces réelles au lieu des tableaux JSON. Ceci est utile car parfois le modèle (ESP <gpt-4) n'est pas le meilleur pour suivre des instructions de mise en forme spécifiques, en particulier en ce qui concerne les structures de données compliquées.
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.' ,
} ) ,
) ,
} ) ; Maintenant, allons encore plus loin. Vous pouvez créer une invite qui utilise le modèle (ou une autre source externe) pour valider sa propre sortie. Vous pouvez le faire en transmettant une méthode validate asynchronisée personnalisée. Notez que cette méthode remplacera d'autres propriétés liées à la validation, telles que 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.' ,
) ,
) ;Parce qu'il s'agit d'une API, il est souvent utile de continuer à demander à partir du même chat. Souvent, l'historique des messages servira de contexte pour la prochaine demande. Un bon exemple de cas d'utilisation est une invite pour d'abord écrire du contenu, puis extraire des entités et, enfin, donner quelques options pour le titre.
// 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 ,
} ) ,
) ; Une erreur courante avec les API LLM est l'utilisation de jetons - vous n'êtes autorisé à ajuster qu'une certaine quantité de données dans la fenêtre de contexte. Dans le cas de Llamaflow, cela signifie que vous êtes limité dans le nombre total de messages que vous pouvez envoyer (si retainMemory est défini sur true ) et la longueur du contenu des messages.
Llamaflow déterminera automatiquement si la demande franchira la limite de jeton avant d'envoyer la demande réelle au fournisseur de modèles (par exemple OpenAI). Cela enregistrera un appel aller-retour réseau et vous permettra de gérer ce type d'erreurs de manière réactive. La façon typique de gérer ces erreurs consiste à supprimer les messages dans l'historique des messages (si vous utilisez le chat avec un ensemble retainMemory ), ou divisez votre contenu en clusters plus petits et les traitez dans plusieurs demandes.
Voici un exemple de capture de l'erreur de débordement de jeton. Notez que minimumResponseTokens est défini sur une valeur élevée pour déclencher explicitement cette erreur ( gpt-3.5-turbo a une limite de contexte maximale de 4096, donc définir la limite minimale à 4095 signifie qu'il ne reste que 1 jeton pour l'invite réelle, ce qui n'est pas suffisant pour l'exemple ci-dessous.)
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 } ` ,
) ;
}
} Une façon courante de gérer les problèmes de limite de jetons est de diviser votre contenu. Llamaflow fournit une méthode d'assistance utile qui enveloppe la méthode chat.request et divisera automatiquement votre texte en fonction d'une configuration de morceau d'entrée. Il est suffisamment intelligent pour diviser votre texte que s'il détermine qu'il est au-dessus de la limite de jeton et essaiera de préserver autant de texte d'origine que possible.
const response = await chat . requestWithSplit (
'hello world, testing overflow logic' ,
( text ) =>
prompt . text ( {
message : `Add other required prompts first, then add your content: ${ text } ` ,
} ) ,
) ; Notez que maintenant, le contenu principal de l'invite est d'abord soumis. Ceci est le contenu qui sera divisé par le séparateur de texte (le long , n . Personnages d'abord, pour le choisir). Vous pouvez ajouter toutes les invites requises supplémentaires et la combiner avec l'invite de contenu dans le paramètre responseFn .
Llamaflow Usese le module debug pour les messages de journalisation et d'erreur. Pour exécuter en mode débogage, définissez la variable DEBUG Env:
DEBUG=llamaflow:* yarn playground
Vous pouvez également spécifier différents types de journalisation via:
DEBUG=llamaflow:error yarn playground DEBUG=llamaflow:log yarn playground
Llamaflow est également livré avec le soutien des modèles OpenAI d'Azure. La version Azure est généralement beaucoup plus rapide et plus fiable que les propres points de terminaison API d'Openai. Afin d'utiliser les points de terminaison Azure, vous devez inclure 2 options spécifiques Azure lors de l'initialisation du modèle OpenAI, azureDeployment et azureEndpoint . Le champ apiKey sera désormais également utilisé pour la clé API Azure.
Vous pouvez trouver la clé Azure API et le point de terminaison dans le portail Azure. Le déploiement Azure doit être créé sous le portail Azure AI.
Notez que le paramètre model dans ModelConfig sera ignoré lors de l'utilisation d'Azure. En effet, dans le système Azure, le model est sélectionné sur la création de déploiement, pas sur le temps d'exécution.
const model = new OpenAI ( {
apiKey : 'AZURE_OPENAI_KEY' ,
azureDeployment : 'AZURE_DEPLOYMENT_NAME' ,
azureEndpoint : 'AZURE_ENDPOINT' ,
} ) ; Le seul modèle que Llamaflow supporte actuellement est les modèles basés sur le chat d'Openai.
const model = new OpenAI ( openAiConfig , modelConfig ) ; interface OpenAIConfig {
apiKey : string ;
} Ces modèles de configuration sont directement sur la configuration d'Openai directement, voir 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 ;
} Lorsque stream est défini sur true , vous pouvez accéder aux sorties partielles des demandes du modèle en transmettant un émetteur d'événements à ChatRequestOptions lors de la demande de demandes. Les sorties partielles seront envoyées sous forme de chaîne sur l'événement data .
Pour faire une demande au modèle, vous devez d'abord construire l'objet rapide. Les invites fournissent un moyen d'ajouter la validation et de réessayer la logique à chaque demande.
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 ) ; Vous pouvez soit demander en tant que chaîne, soit en tant que RawPrompt .
interface RawPrompt < T = string > {
message : string ;
parse ?: (
response : ChatResponse < string > ,
) => MaybePromise <
{ success : false ; retryPrompt ?: string } | { success : true ; data : T }
> ;
promptRetries ?: number ;
}Message Il s'agit du texte envoyé au modèle.
Parse Vous pouvez implémenter un analyseur personnalisé en définissant une méthode d'analyse de votre propre parse .
Lors de la définition d'une méthode parse personnalisée qui renvoie un type de données personnalisé, vous pouvez ajouter un type générique à RawPrompt , qui lancera automatiquement le type de retour de parse au générique. Il propagera également le type tout au long de la méthode chat.request .
Si les données renvoyées par le modèle sont mal formées, vous pouvez renvoyer une chaîne retryPrompt personnalisée, ce qui entraînera Rlamaflow le modèle.
PromPtretries définit le nombre de fois où réaffirmer le modèle avant que la demande ne lance une erreur. Par défaut, notez que parse doit renvoyer un retryPrompt valide pour que toutes les tentatives soient tentées.
interface BooleanPrompt {
message : string ;
promptRetries ?: number ;
} Utilisez cette invite si vous souhaitez poser au modèle une question où vous vous attendez uniquement à une réponse true ou false .
Envoyez la requête à envoyer au modèle. Cette invite ajoutera automatiquement les instructions de mise en forme au message envoyé au modèle qui indique au modèle de formater sa réponse en tant que booléen, vous pouvez donc simplement inclure la requête dans message , sans écrire de relevés de format supplémentaires.
interface BulletPointsPrompt {
message : string ;
amount ?: number ;
length ?: number ;
promptRetries ?: number ;
}Utilisez cette invite si vous souhaitez que le modèle renvoie une liste de chaînes.
Envoyez la requête à envoyer au modèle. Cette invite ajoutera automatiquement les instructions de mise en forme du message qui indique au modèle comment formater la réponse.
Montant le nombre de puces qui doivent être renvoyées.
longueur le nombre maximum de caractères qui devraient être dans chaque puce.
interface JSONPrompt < T extends z . ZodType > {
message : string ;
schema : T ;
parseResponse ?: ( res : string ) => MaybePromise < z . infer < T > > ;
retryMessage ?: string ;
promptRetries ?: number ;
}Message le message à envoyer au modèle. Contrairement aux invites booléennes ou par balle, cette invite ne génère pas automatiquement des instructions de format pour le modèle. Donc, dans le cadre de votre message au modèle, vous devez inclure des instructions de formatage pour retourner les données au format JSON, ainsi que la forme du JSON.
schéma Il s'agit du schéma ZOD qui sera utilisé pour analyser et typasser la réponse du modèle.
ParseResponse Si vous demandez au modèle de ne pas retourner de données au format JSON, vous pouvez définir un analyseur personnalisé pour analyser la chaîne de retour dans JSON, avant de l'envoyer pour schema pour la validation.
RetryMessage Si l'analyse du schéma échoue, cela sera utilisé dans le cadre du message envoyé au modèle pour réaffirmer une réponse correctement formatée. Notez que cette invite générera automatiquement le message REALK en fonction des erreurs d'analyse de schéma (par exemple, si une clé spécifique est manquante, Llamaflow demandera au modèle d'inclure cette clé spécifique). Ce champ est donc purement pour donner un contexte supplémentaire au modèle sur REAB.
L'objet de chat stocke une session de chat avec le modèle. La session s'occupera de stocker l'historique des messages, vous pouvez donc simplement continuer la conversation avec le modèle en faisant une autre demande.
const chat = model . chat ( config : ChatConfig ) ;Options Vous pouvez définir le comportement de rétention de la mémoire ainsi que les options de demande par défaut pour chaque demande envoyée dans ce chat.
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 ;
} Pour envoyer une demande à une session de chat:
const res : ChatResponse = await chat . request ( prompt , options : ChatRequestOptions ) ;Options Vous pouvez remplacer les options de demande par défaut via ce paramètre. Une demande sera automatiquement rejetée en cas d'erreur de ratelimit ou de serveur.
Notez qu'une nouvelle tentative dans la demande ne compte pas pour un REAVK invite défini dans la section invite ci-dessus.
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 ;
} ; Les réponses de chat sont dans le format suivant:
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 ;
} ;
}Contenu analysé et contenu typique à partir de l'invite. Les types seront définis automatiquement en fonction de l'invite que vous avez utilisée.
Modèle le modèle spécifique utilisé pour l'achèvement (par exemple gpt-3.5-turbo-0301 )
Les données d'utilisation des jetons d'utilisation, cela mappe directement la réponse d'utilisation de l'OpenIA.
Si vous souhaitez réinitialiser l'historique des messages dans un historique de chat, il existe une méthode d'assistance simple:
chat . reset ( ) ;Notez que cette méthode est une trappe d'évacuation. Il vaut mieux instancier une nouvelle session de chat si vous souhaitez faire une nouvelle demande avec une ardoise propre. Logique complexe où vous réinitialisez une session de chat plusieurs fois peut être difficile à suivre et difficile à déboguer.
Notez que si vous souhaitez contourner la logique de gestion du chat de Llamaflow et envoyer directement une demande au modèle sous-couche, vous pouvez envoyer une demande directement au modèle sans instancier un chat:
const model = new OpenAI ( openAiConfig , modelConfig ) ;
const res = await model . request ( messages : Message [ ] , options : ChatRequestOptions ) ; Cela contournera toute gestion de l'historique de chat, le formatage rapide et l'analyse, ainsi que la logique Persona. Vous pouvez toujours utiliser la fonctionnalité API Retries via ChatRequestOptions .