Liaisons à l'API HTTP OpenAI pour Lua. Compatible avec toute bibliothèque HTTP prenant en charge l'interface de requête http de LuaSocket. Compatible avec OpenResty en utilisant lapis.nginx.http
.
Bien que cette bibliothèque ait été écrite à la main, de grandes parties de la documentation, de la suite de tests et du flux de travail GitHub ont été entièrement générées par GPT-4 en collant le code source de l'intégralité de la bibliothèque sous forme d'invite et en demandant de générer de la documentation et des tests. Le résultat final a été modifié pour plus de clarté et de syntaxe (dans les cas où GPT4 avait du mal à écrire MoonScript)
Installez à l'aide de LuaRocks :
luarocks install lua-openai
local openai = require ( " openai " )
local client = openai . new ( os.getenv ( " OPENAI_API_KEY " ))
local status , response = client : chat ({
{ role = " system " , content = " You are a Lua programmer " },
{ role = " user " , content = " Write a 'Hello world' program in Lua " }
}, {
model = " gpt-3.5-turbo " , -- this is the default model
temperature = 0.5
})
if status == 200 then
-- the JSON response is automatically parsed into a Lua object
print ( response . choices [ 1 ]. message . content )
end
Une instance de session de chat peut être créée pour simplifier la gestion de l'état d'une conversation aller-retour avec l'API ChatGPT. Notez que l'état du chat est stocké localement en mémoire, chaque nouveau message est ajouté à la liste des messages et la sortie est automatiquement ajoutée à la liste pour la requête suivante.
local openai = require ( " openai " )
local client = openai . new ( os.getenv ( " OPENAI_API_KEY " ))
local chat = client : new_chat_session ({
-- provide an initial set of messages
messages = {
{ role = " system " , content = " You are an artist who likes colors " }
}
})
-- returns the string response
print ( chat : send ( " List your top 5 favorite colors " ))
-- the chat history is sent on subsequent requests to continue the conversation
print ( chat : send ( " Excluding the colors you just listed, tell me your favorite color " ))
-- the entire chat history is stored in the messages field
for idx , message in ipairs ( chat . messages ) do
print ( message . role , message . content )
end
-- You can stream the output by providing a callback as the second argument
-- the full response concatenated is also returned by the function
local response = chat : send ( " What's the most boring color? " , function ( chunk )
io.stdout : write ( chunk . content )
io.stdout : flush ()
end )
OpenAI permet d'envoyer une liste de déclarations de fonctions que le LLM peut décider d'appeler en fonction de l'invite. L'interface d'appel de fonction doit être utilisée avec les complétions de chat et les modèles gpt-4-0613
ou gpt-3.5-turbo-0613
ou versions ultérieures.
Voir https://github.com/leafo/lua-openai/blob/main/examples/example5.lua pour un exemple complet qui implémente des fonctions mathématiques de base pour calculer l'écart type d'une liste de nombres
Voici un exemple rapide de la façon d'utiliser les fonctions dans un échange de chat. Vous devrez d’abord créer une session de discussion avec l’option functions
contenant un éventail de fonctions disponibles.
Les fonctions sont stockées dans le champ
functions
de l'objet de discussion. Si les fonctions doivent être ajustées pour un futur message, le champ peut être modifié.
local chat = openai : new_chat_session ({
model = " gpt-3.5-turbo-0613 " ,
functions = {
{
name = " add " ,
description = " Add two numbers together " ,
parameters = {
type = " object " ,
properties = {
a = { type = " number " },
b = { type = " number " }
}
}
}
}
})
Toute invite que vous envoyez connaîtra toutes les fonctions disponibles et pourra demander à l'une d'entre elles d'être appelée. Si la réponse contient une demande d'appel de fonction, un objet sera renvoyé à la place de la valeur de retour de chaîne standard.
local res = chat : send ( " Using the provided function, calculate the sum of 2923 + 20839 " )
if type ( res ) == " table " and res . function_call then
-- The function_call object has the following fields:
-- function_call.name --> name of function to be called
-- function_call.arguments --> A string in JSON format that should match the parameter specification
-- Note that res may also include a content field if the LLM produced a textual output as well
local cjson = require " cjson "
local name = res . function_call . name
local arguments = cjson . decode ( res . function_call . arguments )
-- ... compute the result and send it back ...
end
Vous pouvez évaluer la fonction et les arguments demandés et renvoyer le résultat au client afin qu'il puisse reprendre le fonctionnement avec un objet de message role=function
:
Étant donné que le LLM peut halluciner chaque partie de l'appel de fonction, vous souhaiterez effectuer une validation de type robuste pour vous assurer que le nom de la fonction et les arguments correspondent à ce que vous attendez. Supposons que chaque étape puisse échouer, y compris la réception d'un JSON mal formé pour les arguments.
local name , arguments = ... -- the name and arguments extracted from above
if name == " add " then
local value = arguments . a + arguments . b
-- send the response back to the chat bot using a `role = function` message
local cjson = require " cjson "
local res = chat : send ({
role = " function " ,
name = name ,
content = cjson . encode ( value )
})
print ( res ) -- Print the final output
else
error ( " Unknown function: " .. name )
end
Dans des circonstances normales, l'API attendra que la réponse complète soit disponible avant de renvoyer la réponse. Selon l'invite, cela peut prendre un certain temps. L'API de streaming peut être utilisée pour lire la sortie un morceau à la fois, vous permettant d'afficher le contenu en temps réel au fur et à mesure de sa génération.
local openai = require ( " openai " )
local client = openai . new ( os.getenv ( " OPENAI_API_KEY " ))
client : chat ({
{ role = " system " , content = " You work for Streak.Club, a website to track daily creative habits " },
{ role = " user " , content = " Who do you work for? " }
}, {
stream = true
}, function ( chunk )
io.stdout : write ( chunk . content )
io.stdout : flush ()
end )
print () -- print a newline
Le module openai
renvoie un tableau avec les champs suivants :
OpenAI
: Un client pour envoyer des requêtes à l'API OpenAI.new
: Un alias vers OpenAI
pour créer une nouvelle instance du client OpenAIChatSession
: Une classe pour gérer les sessions de chat et l'historique avec l'API OpenAI.VERSION = "1.1.0"
: La version actuelle de la bibliothèqueCette classe initialise un nouveau client API OpenAI.
new(api_key, config)
Constructeur pour le client OpenAI.
api_key
: Votre clé API OpenAI.config
: Un tableau facultatif d'options de configuration, avec la forme suivante :http_provider
: Une chaîne spécifiant le nom du module HTTP utilisé pour les requêtes, ou nil
. Si elle n'est pas fournie, la bibliothèque utilisera automatiquement "lapis.nginx.http" dans un environnement ngx, ou "ssl.https" dans le cas contraire. local openai = require ( " openai " )
local api_key = " your-api-key "
local client = openai . new ( api_key )
client:new_chat_session(...)
Crée une nouvelle instance ChatSession. Une session de discussion est une abstraction de l'API de fin de discussion qui stocke l'historique des discussions. Vous pouvez ajouter de nouveaux messages à l'historique et demander que des complétions soient générées à partir de celui-ci. Par défaut, la complétion est ajoutée à l'historique.
client:chat(messages, opts, chunk_callback)
Envoie une requête au point de terminaison /chat/completions
.
messages
: un tableau d’objets de message.opts
: Options supplémentaires pour le chat, transmises directement à l'API (ex. modèle, température, etc.) https://platform.openai.com/docs/api-reference/chatchunk_callback
: Une fonction à appeler pour la sortie de streaming analysée lorsque stream = true
est transmis à opts
.Renvoie l'état HTTP, l'objet de réponse et les en-têtes de sortie. L'objet de réponse sera décodé à partir de JSON si possible, sinon la chaîne brute est renvoyée.
client:completion(prompt, opts)
Envoie une requête au point de terminaison /completions
.
prompt
: L’invite pour l’achèvement.opts
: Options supplémentaires pour la complétion, transmises directement à l'API (ex. modèle, température, etc.) https://platform.openai.com/docs/api-reference/completionsRenvoie l'état HTTP, l'objet de réponse et les en-têtes de sortie. L'objet de réponse sera décodé à partir de JSON si possible, sinon la chaîne brute est renvoyée.
client:embedding(input, opts)
Envoie une requête au point de terminaison /embeddings
.
input
: Une seule chaîne ou un tableau de chaînesopts
: Options supplémentaires pour la complétion, transmises directement à l'API (ex. model) https://platform.openai.com/docs/api-reference/embeddingsRenvoie l'état HTTP, l'objet de réponse et les en-têtes de sortie. L'objet de réponse sera décodé à partir de JSON si possible, sinon la chaîne brute est renvoyée.
Cette classe gère les sessions de chat et l'historique avec l'API OpenAI. Généralement créé avec new_chat_session
Les messages
de champ stockent un tableau de messages de discussion représentant l'historique des discussions. Chaque objet de message doit être conforme à la structure suivante :
role
: Une chaîne représentant le rôle de l’expéditeur du message. Il doit s'agir de l'une des valeurs suivantes : "système", "utilisateur" ou "assistant".content
: Une chaîne contenant le contenu du message.name
: Une chaîne facultative représentant le nom de l’expéditeur du message. S’il n’est pas fourni, il devrait être nil
.Par exemple, un objet message valide pourrait ressembler à ceci :
{
role = " user " ,
content = " Tell me a joke " ,
name = " John Doe "
}
new(client, opts)
Constructeur pour la ChatSession.
client
: Une instance du client OpenAI.opts
: un tableau d'options facultatif.messages
: un premier tableau de messages de discussionfunctions
: Une liste de déclarations de fonctionstemperature
: réglage de la températuremodel
: quel modèle de complétion de discussion utiliser, par exemple. gpt-4
, gpt-3.5-turbo
chat:append_message(m, ...)
Ajoute un message à l'historique des discussions.
m
: Un objet de message. chat:last_message()
Renvoie le dernier message de l'historique des discussions.
chat:send(message, stream_callback=nil)
Ajoute un message à l'historique des discussions, déclenche une complétion avec generate_response
et renvoie la réponse sous forme de chaîne. En cas d'échec, renvoie nil
, un message d'erreur et la réponse brute à la requête.
Si la réponse inclut un function_call
, alors l'intégralité de l'objet message est renvoyée au lieu d'une chaîne du contenu. Vous pouvez renvoyer le résultat de la fonction en passant l'objet role = "function"
à la méthode send
message
: Un objet message ou une chaîne.stream_callback
: (facultatif) Une fonction pour activer la sortie en streaming. En fournissant un stream_callback
, la requête s'exécutera en mode streaming. Cette fonction reçoit des morceaux au fur et à mesure qu'ils sont analysés à partir de la réponse.
Ces morceaux ont le format suivant :
content
: Une chaîne contenant le texte de la réponse générée par l'assistant.Par exemple, un morceau pourrait ressembler à ceci :
{
content = " This is a part of the assistant's response. " ,
}
chat:generate_response(append_response, stream_callback=nil)
Appelle l'API OpenAI pour générer la réponse suivante pour l'historique des discussions stocké. Renvoie la réponse sous forme de chaîne. En cas d'échec, renvoie nil
, un message d'erreur et la réponse brute à la requête.
append_response
: indique si la réponse doit être ajoutée à l'historique des discussions (par défaut : true).stream_callback
: (facultatif) Une fonction pour activer la sortie en streaming. Voir chat:send
pour plus de détails sur stream_callback