Ligações à API HTTP OpenAI para Lua. Compatível com qualquer biblioteca HTTP que suporte a interface de solicitação http do LuaSocket. Compatível com OpenResty usando lapis.nginx.http
.
Embora esta biblioteca tenha sido escrita à mão, grande parte da documentação, do conjunto de testes e do fluxo de trabalho do GitHub foram totalmente gerados pelo GPT-4 colando o código-fonte de toda a biblioteca como um prompt e solicitando a geração de documentação e testes. O resultado final foi editado para maior clareza e sintaxe (nos casos em que GPT4 teve dificuldade para escrever MoonScript)
Instale usando 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
Uma instância de sessão de bate-papo pode ser criada para simplificar o gerenciamento do estado de uma conversa de ida e volta com a API ChatGPT. Observe que o estado do chat é armazenado localmente na memória, cada nova mensagem é anexada à lista de mensagens e a saída é automaticamente anexada à lista para a próxima solicitação.
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 permite enviar uma lista de declarações de função que o LLM pode decidir chamar com base no prompt. A interface de chamada de função deve ser usada com conclusões de bate-papo e modelos gpt-4-0613
ou gpt-3.5-turbo-0613
ou posteriores.
Consulte https://github.com/leafo/lua-openai/blob/main/examples/example5.lua para obter um exemplo completo que implementa funções matemáticas básicas para calcular o desvio padrão de uma lista de números
Aqui está um exemplo rápido de como usar funções em uma troca de chat. Primeiro você precisará criar uma sessão de chat com a opção functions
contendo uma série de funções disponíveis.
As funções são armazenadas no campo
functions
do objeto de chat. Caso as funções precisem ser ajustadas para mensagens futuras, o campo poderá ser modificado.
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 " }
}
}
}
}
})
Qualquer prompt que você enviar estará ciente de todas as funções disponíveis e poderá solicitar que qualquer uma delas seja chamada. Se a resposta contiver uma solicitação de chamada de função, um objeto será retornado em vez do valor de retorno da string padrão.
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
Você pode avaliar a função e os argumentos solicitados e enviar o resultado de volta ao cliente para que ele possa retomar a operação com um objeto de mensagem role=function
:
Como o LLM pode alucinar cada parte da chamada de função, você desejará fazer uma validação de tipo robusta para garantir que o nome e os argumentos da função correspondam ao que você espera. Suponha que todos os estágios possam falhar, incluindo o recebimento de JSON malformado para os argumentos.
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
Em circunstâncias normais, a API aguardará até que toda a resposta esteja disponível antes de retornar a resposta. Dependendo da solicitação, isso pode levar algum tempo. A API de streaming pode ser usada para ler a saída, um pedaço por vez, permitindo exibir o conteúdo em tempo real à medida que ele é gerado.
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
O módulo openai
retorna uma tabela com os seguintes campos:
OpenAI
: Um cliente para enviar solicitações à API OpenAI.new
: um alias para OpenAI
para criar uma nova instância do cliente OpenAIChatSession
: Uma classe para gerenciar sessões de chat e histórico com a API OpenAI.VERSION = "1.1.0"
: A versão atual da bibliotecaEsta classe inicializa um novo cliente API OpenAI.
new(api_key, config)
Construtor para o cliente OpenAI.
api_key
: sua chave de API OpenAI.config
: uma tabela opcional de opções de configuração, com o seguinte formato:http_provider
: uma string especificando o nome do módulo HTTP usado para solicitações ou nil
. Se não for fornecido, a biblioteca usará automaticamente "lapis.nginx.http" em um ambiente ngx ou "ssl.https" caso contrário. local openai = require ( " openai " )
local api_key = " your-api-key "
local client = openai . new ( api_key )
client:new_chat_session(...)
Cria uma nova instância de ChatSession. Uma sessão de chat é uma abstração da API de conclusão de chat que armazena o histórico do chat. Você pode anexar novas mensagens ao histórico e solicitar que conclusões sejam geradas a partir dele. Por padrão, a conclusão é anexada ao histórico.
client:chat(messages, opts, chunk_callback)
Envia uma solicitação para o endpoint /chat/completions
.
messages
: uma matriz de objetos de mensagem.opts
: Opções adicionais para o chat, passadas diretamente para a API (por exemplo, modelo, temperatura, etc.) https://platform.openai.com/docs/api-reference/chatchunk_callback
: uma função a ser chamada para saída de streaming analisada quando stream = true
é passado para opts
.Retorna o status HTTP, o objeto de resposta e os cabeçalhos de saída. O objeto de resposta será decodificado do JSON, se possível, caso contrário, a string bruta será retornada.
client:completion(prompt, opts)
Envia uma solicitação para o endpoint /completions
.
prompt
: O prompt para a conclusão.opts
: opções adicionais para o preenchimento, passadas diretamente para a API (por exemplo, modelo, temperatura, etc.) https://platform.openai.com/docs/api-reference/completionsRetorna o status HTTP, o objeto de resposta e os cabeçalhos de saída. O objeto de resposta será decodificado do JSON, se possível, caso contrário, a string bruta será retornada.
client:embedding(input, opts)
Envia uma solicitação para o endpoint /embeddings
.
input
: uma única string ou um array de stringsopts
: opções adicionais para o preenchimento, passadas diretamente para a API (por exemplo, modelo) https://platform.openai.com/docs/api-reference/embeddingsRetorna o status HTTP, o objeto de resposta e os cabeçalhos de saída. O objeto de resposta será decodificado do JSON, se possível, caso contrário, a string bruta será retornada.
Esta classe gerencia sessões de chat e histórico com a API OpenAI. Normalmente criado com new_chat_session
O campo messages
armazena uma série de mensagens de bate-papo que representam o histórico do bate-papo. Cada objeto de mensagem deve estar em conformidade com a seguinte estrutura:
role
: Uma string que representa a função do remetente da mensagem. Deve ser um dos seguintes valores: "sistema", "usuário" ou "assistente".content
: uma string contendo o conteúdo da mensagem.name
: uma string opcional que representa o nome do remetente da mensagem. Se não for fornecido, deverá ser nil
.Por exemplo, um objeto de mensagem válido pode ter esta aparência:
{
role = " user " ,
content = " Tell me a joke " ,
name = " John Doe "
}
new(client, opts)
Construtor para ChatSession.
client
: uma instância do cliente OpenAI.opts
: uma tabela opcional de opções.messages
: uma matriz inicial de mensagens de bate-papofunctions
: uma lista de declarações de funçõestemperature
: configuração de temperaturamodel
: Qual modelo de conclusão de chat usar, por exemplo. gpt-4
, gpt-3.5-turbo
chat:append_message(m, ...)
Acrescenta uma mensagem ao histórico de bate-papo.
m
: Um objeto de mensagem. chat:last_message()
Retorna a última mensagem do histórico do chat.
chat:send(message, stream_callback=nil)
Acrescenta uma mensagem ao histórico de chat e aciona uma conclusão com generate_response
e retorna a resposta como uma string. Em caso de falha, retorna nil
, uma mensagem de erro e a resposta bruta da solicitação.
Se a resposta incluir um function_call
, todo o objeto da mensagem será retornado em vez de uma string do conteúdo. Você pode retornar o resultado da função passando o objeto role = "function"
para o método send
message
: um objeto de mensagem ou uma string.stream_callback
: (opcional) Uma função para habilitar a saída de streaming. Ao fornecer um stream_callback
, a solicitação será executada no modo de streaming. Esta função recebe pedaços à medida que são analisados a partir da resposta.
Esses pedaços têm o seguinte formato:
content
: uma string contendo o texto da resposta gerada pelo assistente.Por exemplo, um pedaço pode ter a seguinte aparência:
{
content = " This is a part of the assistant's response. " ,
}
chat:generate_response(append_response, stream_callback=nil)
Chama a API OpenAI para gerar a próxima resposta para o histórico de chat armazenado. Retorna a resposta como uma string. Em caso de falha, retorna nil
, uma mensagem de erro e a resposta bruta da solicitação.
append_response
: se a resposta deve ser anexada ao histórico do chat (padrão: true).stream_callback
: (opcional) Uma função para habilitar a saída de streaming. Consulte chat:send
para obter detalhes sobre stream_callback