绑定到 Lua 的 OpenAI HTTP API。兼容任何支持LuaSocket http请求接口的HTTP库。使用lapis.nginx.http
与 OpenResty 兼容。
尽管这个库是手工编写的,但大部分文档、测试套件和 GitHub 工作流程都是由 GPT-4 完全生成的,方法是粘贴整个库的源代码作为提示并要求生成文档和测试。为了清晰起见和语法,对最终输出进行了编辑(在 GPT4 难以编写 MoonScript 的情况下)
使用 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
可以创建聊天会话实例来简化管理与 ChatGPT API 的来回对话的状态。请注意,聊天状态本地存储在内存中,每条新消息都会附加到消息列表中,并且输出会自动附加到下一个请求的列表中。
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 允许发送 LLM 可以根据提示决定调用的函数声明列表。函数调用接口必须与聊天完成以及gpt-4-0613
或gpt-3.5-turbo-0613
或更高版本一起使用。
请参阅 https://github.com/leafo/lua-openai/blob/main/examples/example5.lua 了解实现基本数学函数来计算数字列表的标准差的完整示例
以下是如何在聊天交流中使用功能的快速示例。首先,您需要使用包含一系列可用函数的functions
选项创建一个聊天会话。
功能存储在聊天对象的
functions
字段中。如果以后的消息需要调整功能,可以修改该字段。
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 " }
}
}
}
}
})
您发送的任何提示都会了解所有可用的功能,并可能请求调用其中的任何功能。如果响应包含函数调用请求,则将返回一个对象而不是标准字符串返回值。
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
您可以评估请求的函数和参数并将结果发送回客户端,以便它可以使用role=function
消息对象恢复操作:
由于 LLM 可以幻觉函数调用的每个部分,因此您需要进行可靠的类型验证,以确保函数名称和参数与您的期望相匹配。假设每个阶段都可能失败,包括接收参数格式错误的 JSON。
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
正常情况下,API 会等到整个响应可用后再返回响应。根据提示,这可能需要一些时间。流式 API 可用于一次读取一块输出,从而允许您在生成内容时实时显示内容。
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
openai
模块返回一个包含以下字段的表:
OpenAI
:用于向 OpenAI API 发送请求的客户端。new
: OpenAI
的别名,用于创建 OpenAI 客户端的新实例ChatSession
:用于使用 OpenAI API 管理聊天会话和历史记录的类。VERSION = "1.1.0"
:库的当前版本此类初始化一个新的 OpenAI API 客户端。
new(api_key, config)
OpenAI 客户端的构造函数。
api_key
:您的 OpenAI API 密钥。config
:配置选项的可选表,具有以下形状:http_provider
:指定用于请求的 HTTP 模块名称的字符串,或nil
。如果未提供,库将在 ngx 环境中自动使用“lapis.nginx.http”,否则使用“ssl.https”。 local openai = require ( " openai " )
local api_key = " your-api-key "
local client = openai . new ( api_key )
client:new_chat_session(...)
创建一个新的 ChatSession 实例。聊天会话是对存储聊天历史记录的聊天完成 API 的抽象。您可以将新消息附加到历史记录中并请求从中生成完成信息。默认情况下,完成情况会附加到历史记录中。
client:chat(messages, opts, chunk_callback)
向/chat/completions
端点发送请求。
messages
:消息对象的数组。opts
:聊天的附加选项,直接传递给 API(例如模型、温度等)https://platform.openai.com/docs/api-reference/chatchunk_callback
:当stream = true
传递给opts
时,为解析流输出而调用的函数。返回 HTTP 状态、响应对象和输出标头。如果可能,响应对象将从 JSON 中解码,否则返回原始字符串。
client:completion(prompt, opts)
向/completions
端点发送请求。
prompt
:完成的提示。opts
:完成的附加选项,直接传递给 API(例如模型、温度等)https://platform.openai.com/docs/api-reference/completions返回 HTTP 状态、响应对象和输出标头。如果可能,响应对象将从 JSON 中解码,否则返回原始字符串。
client:embedding(input, opts)
向/embeddings
端点发送请求。
input
:单个字符串或字符串数组opts
:完成的附加选项,直接传递给 API(例如模型)https://platform.openai.com/docs/api-reference/embeddings返回 HTTP 状态、响应对象和输出标头。如果可能,响应对象将从 JSON 中解码,否则返回原始字符串。
此类使用 OpenAI API 管理聊天会话和历史记录。通常使用new_chat_session
创建
字段messages
存储表示聊天历史记录的聊天消息数组。每个消息对象必须符合以下结构:
role
:代表消息发送者角色的字符串。它必须是以下值之一:“system”、“user”或“assistant”。content
:包含消息内容的字符串。name
:表示消息发送者名称的可选字符串。如果没有提供,它应该是nil
。例如,有效的消息对象可能如下所示:
{
role = " user " ,
content = " Tell me a joke " ,
name = " John Doe "
}
new(client, opts)
ChatSession 的构造函数。
client
:OpenAI 客户端的实例。opts
:可选的选项表。messages
:聊天消息的初始数组functions
:函数声明列表temperature
:温度设定model
:使用哪种聊天完成模型,例如。 gpt-4
, gpt-3.5-turbo
chat:append_message(m, ...)
将消息追加到聊天记录中。
m
:消息对象。 chat:last_message()
返回聊天记录中的最后一条消息。
chat:send(message, stream_callback=nil)
将消息附加到聊天历史记录并使用generate_response
触发完成,并将响应作为字符串返回。失败时,返回nil
、错误消息和原始请求响应。
如果响应包含function_call
,则返回整个消息对象而不是内容字符串。您可以通过将role = "function"
对象传递给send
方法来返回函数的结果
message
:消息对象或字符串。stream_callback
:(可选)启用流输出的函数。通过提供stream_callback
,请求将以流模式运行。该函数接收从响应中解析出的块。
这些块具有以下格式:
content
:包含助手生成的响应文本的字符串。例如,一个块可能如下所示:
{
content = " This is a part of the assistant's response. " ,
}
chat:generate_response(append_response, stream_callback=nil)
调用 OpenAI API 为存储的聊天记录生成下一个响应。以字符串形式返回响应。失败时,返回nil
、错误消息和原始请求响应。
append_response
:是否应将响应附加到聊天历史记录中(默认值:true)。stream_callback
:(可选)启用流输出的函数。有关stream_callback
的详细信息,请参阅chat:send