Bindungen an die OpenAI HTTP API für Lua. Kompatibel mit jeder HTTP-Bibliothek, die die http-Anforderungsschnittstelle von LuaSocket unterstützt. Kompatibel mit OpenResty unter Verwendung von lapis.nginx.http
.
Obwohl diese Bibliothek von Hand geschrieben wurde, wurden große Teile der Dokumentation, der Testsuite und des GitHub-Workflows vollständig von GPT-4 generiert, indem der Quellcode der gesamten Bibliothek als Eingabeaufforderung eingefügt und zum Generieren von Dokumentation und Tests aufgefordert wurde. Die endgültige Ausgabe wurde aus Gründen der Klarheit und Syntax bearbeitet (in Fällen, in denen GPT4 Schwierigkeiten beim Schreiben von MoonScript hatte)
Installation mit 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
Eine Chat-Sitzungsinstanz kann erstellt werden, um die Verwaltung des Status einer Hin- und Her-Konversation mit der ChatGPT-API zu vereinfachen. Beachten Sie, dass der Chat-Status lokal im Speicher gespeichert wird, jede neue Nachricht an die Nachrichtenliste angehängt wird und die Ausgabe bei der nächsten Anfrage automatisch an die Liste angehängt wird.
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 ermöglicht das Senden einer Liste von Funktionsdeklarationen, deren Aufruf der LLM basierend auf der Eingabeaufforderung entscheiden kann. Die Funktionsaufrufschnittstelle muss mit Chat-Abschlüssen und den Modellen gpt-4-0613
oder gpt-3.5-turbo-0613
oder höher verwendet werden.
Unter https://github.com/leafo/lua-openai/blob/main/examples/example5.lua finden Sie ein vollständiges Beispiel, das grundlegende mathematische Funktionen implementiert, um die Standardabweichung einer Liste von Zahlen zu berechnen
Hier ist ein kurzes Beispiel für die Verwendung von Funktionen in einem Chat-Austausch. Zuerst müssen Sie eine Chat-Sitzung mit der Option functions
erstellen, die eine Reihe verfügbarer Funktionen enthält.
Die Funktionen werden im
functions
des Chat-Objekts gespeichert. Wenn die Funktionen für zukünftige Nachrichten angepasst werden müssen, kann das Feld geändert werden.
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 " }
}
}
}
}
})
Jede von Ihnen gesendete Eingabeaufforderung erkennt alle verfügbaren Funktionen und fordert möglicherweise den Aufruf einer dieser Funktionen an. Wenn die Antwort eine Funktionsaufrufanforderung enthält, wird anstelle des Standard-String-Rückgabewerts ein Objekt zurückgegeben.
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
Sie können die angeforderte Funktion und die angeforderten Argumente auswerten und das Ergebnis an den Client zurücksenden, damit dieser den Betrieb mit einem role=function
Nachrichtenobjekt wieder aufnehmen kann:
Da das LLM jeden Teil des Funktionsaufrufs halluzinieren kann, sollten Sie eine robuste Typvalidierung durchführen, um sicherzustellen, dass Funktionsname und Argumente Ihren Erwartungen entsprechen. Gehen Sie davon aus, dass jede Phase fehlschlagen kann, einschließlich des Empfangs von fehlerhaftem JSON für die Argumente.
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
Unter normalen Umständen wartet die API, bis die gesamte Antwort verfügbar ist, bevor sie die Antwort zurückgibt. Je nach Aufforderung kann dies einige Zeit dauern. Mit der Streaming-API kann die Ausgabe Stück für Stück gelesen werden, sodass Sie Inhalte in Echtzeit anzeigen können, während sie generiert werden.
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
Das openai
-Modul gibt eine Tabelle mit den folgenden Feldern zurück:
OpenAI
: Ein Client zum Senden von Anfragen an die OpenAI-API.new
: Ein Alias für OpenAI
um eine neue Instanz des OpenAI-Clients zu erstellenChatSession
: Eine Klasse zum Verwalten von Chat-Sitzungen und -Verläufen mit der OpenAI-API.VERSION = "1.1.0"
: Die aktuelle Version der BibliothekDiese Klasse initialisiert einen neuen OpenAI-API-Client.
new(api_key, config)
Konstruktor für den OpenAI-Client.
api_key
: Ihr OpenAI-API-Schlüssel.config
: Eine optionale Tabelle mit Konfigurationsoptionen mit der folgenden Form:http_provider
: Eine Zeichenfolge, die den für Anforderungen verwendeten HTTP-Modulnamen angibt, oder nil
. Wenn nicht angegeben, verwendet die Bibliothek in einer NGX-Umgebung automatisch „lapis.nginx.http“ oder andernfalls „ssl.https“. local openai = require ( " openai " )
local api_key = " your-api-key "
local client = openai . new ( api_key )
client:new_chat_session(...)
Erstellt eine neue ChatSession-Instanz. Eine Chat-Sitzung ist eine Abstraktion der Chat-Abschluss-API, die den Chat-Verlauf speichert. Sie können neue Nachrichten an den Verlauf anhängen und daraus generierte Vervollständigungen anfordern. Standardmäßig wird die Vervollständigung an den Verlauf angehängt.
client:chat(messages, opts, chunk_callback)
Sendet eine Anfrage an den Endpunkt /chat/completions
.
messages
: Ein Array von Nachrichtenobjekten.opts
: Zusätzliche Optionen für den Chat, direkt an die API übergeben (z. B. Modell, Temperatur usw.) https://platform.openai.com/docs/api-reference/chatchunk_callback
: Eine Funktion, die für die geparste Streaming-Ausgabe aufgerufen wird, wenn stream = true
an opts
übergeben wird.Gibt den HTTP-Status, das Antwortobjekt und die Ausgabeheader zurück. Das Antwortobjekt wird nach Möglichkeit aus JSON dekodiert, andernfalls wird die Rohzeichenfolge zurückgegeben.
client:completion(prompt, opts)
Sendet eine Anfrage an den /completions
-Endpunkt.
prompt
: Die Eingabeaufforderung für den Abschluss.opts
: Zusätzliche Optionen für die Vervollständigung, direkt an die API übergeben (z. B. Modell, Temperatur usw.) https://platform.openai.com/docs/api-reference/completionsGibt den HTTP-Status, das Antwortobjekt und die Ausgabeheader zurück. Das Antwortobjekt wird nach Möglichkeit aus JSON dekodiert, andernfalls wird die Rohzeichenfolge zurückgegeben.
client:embedding(input, opts)
Sendet eine Anfrage an den /embeddings
-Endpunkt.
input
: Eine einzelne Zeichenfolge oder ein Array von Zeichenfolgenopts
: Zusätzliche Optionen für die Vervollständigung, direkt an die API übergeben (z. B. Modell) https://platform.openai.com/docs/api-reference/embeddingsGibt den HTTP-Status, das Antwortobjekt und die Ausgabeheader zurück. Das Antwortobjekt wird nach Möglichkeit aus JSON dekodiert, andernfalls wird die Rohzeichenfolge zurückgegeben.
Diese Klasse verwaltet Chat-Sitzungen und den Verlauf mit der OpenAI-API. Wird normalerweise mit new_chat_session
erstellt
Das Feld messages
speichert eine Reihe von Chat-Nachrichten, die den Chat-Verlauf darstellen. Jedes Nachrichtenobjekt muss der folgenden Struktur entsprechen:
role
: Eine Zeichenfolge, die die Rolle des Nachrichtensenders darstellt. Es muss einer der folgenden Werte sein: „system“, „user“ oder „assistant“.content
: Eine Zeichenfolge, die den Inhalt der Nachricht enthält.name
: Eine optionale Zeichenfolge, die den Namen des Absenders der Nachricht darstellt. Wenn nicht angegeben, sollte es nil
sein.Ein gültiges Nachrichtenobjekt könnte beispielsweise so aussehen:
{
role = " user " ,
content = " Tell me a joke " ,
name = " John Doe "
}
new(client, opts)
Konstruktor für die ChatSession.
client
: Eine Instanz des OpenAI-Clients.opts
: Eine optionale Tabelle mit Optionen.messages
: Eine erste Reihe von Chat-Nachrichtenfunctions
: Eine Liste von Funktionsdeklarationentemperature
: Temperatureinstellungmodel
: Welches Chat-Abschlussmodell verwendet werden soll, z. gpt-4
, gpt-3.5-turbo
chat:append_message(m, ...)
Fügt eine Nachricht an den Chatverlauf an.
m
: Ein Nachrichtenobjekt. chat:last_message()
Gibt die letzte Nachricht im Chatverlauf zurück.
chat:send(message, stream_callback=nil)
Hängt eine Nachricht an den Chat-Verlauf an, löst eine Vervollständigung mit generate_response
aus und gibt die Antwort als Zeichenfolge zurück. Bei einem Fehler werden nil
, eine Fehlermeldung und die Rohanfrageantwort zurückgegeben.
Wenn die Antwort einen function_call
enthält, wird das gesamte Nachrichtenobjekt anstelle einer Zeichenfolge des Inhalts zurückgegeben. Sie können das Ergebnis der Funktion zurückgeben, indem Sie das Objekt role = "function"
an die send
übergeben
message
: Ein Nachrichtenobjekt oder eine Zeichenfolge.stream_callback
: (optional) Eine Funktion zum Aktivieren der Streaming-Ausgabe. Durch die Bereitstellung eines stream_callback
wird die Anfrage im Streaming-Modus ausgeführt. Diese Funktion empfängt Chunks, während sie aus der Antwort analysiert werden.
Diese Chunks haben das folgende Format:
content
: Eine Zeichenfolge, die den Text der vom Assistenten generierten Antwort enthält.Ein Block könnte beispielsweise so aussehen:
{
content = " This is a part of the assistant's response. " ,
}
chat:generate_response(append_response, stream_callback=nil)
Ruft die OpenAI-API auf, um die nächste Antwort für den gespeicherten Chatverlauf zu generieren. Gibt die Antwort als Zeichenfolge zurück. Bei einem Fehler werden nil
, eine Fehlermeldung und die Rohanfrageantwort zurückgegeben.
append_response
: Ob die Antwort an den Chatverlauf angehängt werden soll (Standard: true).stream_callback
: (optional) Eine Funktion zum Aktivieren der Streaming-Ausgabe. Weitere Informationen zum stream_callback
finden Sie unter chat:send