| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- --[[
- @module openai
- @summary 对接OpenAI兼容的平台,例如deepseek
- @version 1.0
- @date 2025.1.27
- @author wendal
- @tag LUAT_USE_NETWORK
- @demo openai
- @usage
- -- 对接deepseek演示 请阅demo/openai
- -- 本API正在积极设计中
- ]] local openai = {
- conf = {}
- }
- -- 定义默认参数表
- local defaultOpts = {
- apikey = "123456",
- apiurl = "https://api.deepseek.com",
- model = "deepseek-chat"
- }
- --比较传入的table和默认table,如果传入的值里少了某个值,默认table顶上去
- local function mergeWithDefaults(opts, defaults)
- -- 创建一个新的表来存储合并结果
- local mergedOpts = {}
-
- -- 先加载默认值
- for k, v in pairs(defaults) do
- mergedOpts[k] = v
- end
-
- -- 使用传入的 opts 表覆盖默认值
- for k, v in pairs(opts) do
- mergedOpts[k] = v
- end
- return mergedOpts
- end
- local function talk(self, msg)
- local rheaders = {
- ['Content-Type'] = "application/json",
- ['Accept'] = "application/json",
- ['Authorization'] = "Bearer " .. self.opts.apikey
- }
- if not msg then
- return
- end
- if type(msg) == "table" then
- table.insert(self.msgs, msg)
- else
- table.insert(self.msgs, {
- role = "user",
- content = msg
- })
- end
- local rbody = {
- model = self.opts.model,
- messages = self.msgs,
- stream = false
- }
- local url = self.opts.apiurl .. "/chat/completions"
- -- log.info("openai", "request", url, json.encode(rheaders), json.encode(rbody))
- local code, headers, body = http.request("POST", url, rheaders, (json.encode(rbody)), {
- timeout = 60 * 1000
- }).wait()
- local tag = ""
- -- log.info("openai", code, json.encode(headers) or "", body or "")
- if code == 200 then
- -- log.info("openai", "执行完成!!!")
- local jdata = json.decode(body)
- if jdata and jdata.choices and #jdata.choices > 0 then
- -- 自动选用第一个回应
- local ch = jdata.choices[1].message
- table.insert(self.msgs, {
- role = ch.role,
- content = ch.content
- })
- return ch
- end
- elseif code == 400 then
- tag = "请求体格式错误,请根据错误信息提示修改请求体"
- log.warn(tag)
- elseif code == 401 then
- tag = "API key错误,认证失败,请检查您的API key是否正确,如没有API key,请先创建API key"
- log.warn(tag)
- elseif code == 402 then
- tag = "账号余额不足,请充值"
- log.warn(tag)
- elseif code == 422 then
- tag = "请求体参数错误,请根据错误信息提示修改请求体"
- log.warn(tag)
- elseif code == 429 then
- tag = "请求速率(TPM 或 RPM)达到上限,请稍后再试"
- log.warn(tag)
- elseif code == 500 then
- tag = "服务器内部故障,请等待后重试,若问题一直存在,请联系deepseek官方解决"
- log.warn(tag)
- elseif code == 503 then
- tag = "服务器负载过高,请稍后重试您的请求"
- log.warn(tag)
- elseif code < 0 then
- tag = "异常,大概率是服务器问题" .. code
- if code == -8 then
- tag = "链接服务超时或读取数据超时" .. code
- end
- end
- log.info("openai", code, json.encode(headers) or "", body or "")
- return tag
- end
- --[[
- 创建一个对话
- @api openai.completions(opts, prompt)
- @table 调用选项,有必填参数,请看实例
- @string 起始提示语,可选
- @return 对话实例
- @usage
- -- 以deepseek为例, 请填充真实的apikey
- sys = require "sys"
- require "sysplus"
- openai = require "openai"
- local opts = {
- apikey = "sk-123456",
- apiurl = "https://api.deepseek.com",
- model = "deepseek-chat"
- }
- local chat = openai.completions(opts)
- sys.taskInit(function()
- sys.waitUntil("IP_READY")
- sys.wait(100)
- -- 固定问答演示
- local resp = chat:talk("你好,请问LuatOS是什么软件?应该如何学习呢?")
- if resp then
- log.info("deepseek回复", resp.content)
- else
- log.info("deepseek执行失败")
- end
- end)
- ]]
- function openai.completions(opts, prompt)
- opts = mergeWithDefaults(opts, defaultOpts)
- local chat = {
- opts = opts,
- talk = talk,
- msgs = {prompt and {
- role = "system",
- content = prompt
- }}
- }
- return chat
- end
- return openai
|