เชื่อมโยงกับ OpenAI HTTP API สำหรับ Lua เข้ากันได้กับไลบรารี HTTP ใด ๆ ที่รองรับอินเทอร์เฟซคำขอ http ของ LuaSocket เข้ากันได้กับ OpenResty โดยใช้ lapis.nginx.http
แม้ว่าไลบรารีนี้จะเขียนด้วยมือ แต่เอกสาร ชุดทดสอบ และเวิร์กโฟลว์ 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 APInew
: นามแฝงของ OpenAI
เพื่อสร้างอินสแตนซ์ใหม่ของไคลเอ็นต์ OpenAIChatSession
: คลาสสำหรับจัดการเซสชันการแชทและประวัติด้วย OpenAI APIVERSION = "1.1.0"
: เวอร์ชันปัจจุบันของไลบรารีคลาสนี้เริ่มต้นไคลเอ็นต์ OpenAI API ใหม่
new(api_key, config)
ตัวสร้างสำหรับไคลเอนต์ OpenAI
api_key
: คีย์ OpenAI API ของคุณconfig
: ตารางทางเลือกของตัวเลือกการกำหนดค่า ที่มีรูปร่างดังต่อไปนี้:http_provider
: สตริงที่ระบุชื่อโมดูล HTTP ที่ใช้สำหรับคำขอ หรือ nil
หากไม่ได้ระบุไว้ ไลบรารีจะใช้ "lapis.nginx.http" โดยอัตโนมัติในสภาพแวดล้อม ngx หรือ "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
: อินสแตนซ์ของไคลเอนต์ OpenAIopts
: ตารางตัวเลือกเพิ่มเติม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
อ็อบเจ็กต์ข้อความทั้งหมดจะถูกส่งกลับแทนที่จะเป็นสตริงของเนื้อหา คุณสามารถส่งคืนผลลัพธ์ของฟังก์ชันได้โดยการส่ง object 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
: ควรเพิ่มการตอบกลับเข้ากับประวัติการแชทหรือไม่ (ค่าเริ่มต้น: จริง)stream_callback
: (เป็นทางเลือก) ฟังก์ชั่นเพื่อเปิดใช้งานเอาต์พุตการสตรีม ดู chat:send
เพื่อดูรายละเอียดใน stream_callback