Przeglądaj źródła

add: 提交迁移780EXX 的 deepseek到8000上

梁健 5 miesięcy temu
rodzic
commit
733e2334f6

+ 61 - 0
module/Air8000/demo/deepseek/main.lua

@@ -0,0 +1,61 @@
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "deepseek"
+VERSION = "1.0.0"
+
+sys = require "sys"
+require "sysplus"
+openai = require "openai"
+
+local uartid = 2
+
+local opts = {
+    apikey = "sk-e3d44d7c15a",--此处填用户自己去https://platform.deepseek.com/api_keys这里获取的key
+    apiurl = "https://api.deepseek.com",
+    model = "deepseek-chat",
+}
+uart.setup(uartid, 115200)
+
+-- 收取数据会触发回调, 这里的"receive" 是固定值
+uart.on(uartid, "receive", function(id, len)
+    local s = ""
+    repeat
+        s = uart.read(id, 1024)
+        if #s > 0 then -- #s 是取字符串的长度
+            log.info("uart", "receive", id, #s, s)
+            uart.write(uartid,
+                "消息发送成功,请等待回复,若串口60S没有回复,请检查luatools打印的日志\r\n")
+            sys.publish("uart_rx", s)
+        end
+    until s == ""
+end)
+
+sys.taskInit(function()
+    sys.waitUntil("IP_READY")
+    sys.wait(2000)
+
+    local chat = openai.completions(opts)
+    if chat then
+        uart.write(uartid, "大语言模型初始化完成,可以开始对话了\r\n")
+    else
+        uart.write(uartid, "大语言模型初始化失败,请检查代码\r\n")
+    end
+    -- -- uart交互演示
+    while 1 do
+        local re, data = sys.waitUntil("uart_rx")
+        if data then
+            local resp = chat:talk(data)
+            if resp and type(resp) == "table" then
+                log.info("deepseek回复", resp.content)
+                uart.write(uartid, resp.content)
+            else
+                local re_data = "大语言模型返回失败,错误原因:\r\n"
+                log.info(re_data,resp)
+                uart.write(uartid,re_data)
+                uart.write(uartid,resp)
+            end
+        end
+    end
+end)
+
+sys.run()
+

+ 160 - 0
module/Air8000/demo/deepseek/openai.lua

@@ -0,0 +1,160 @@
+--[[
+@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