写点什么

为 NeoAI 增加千帆大模型支持

作者:SkyFire
  • 2023-10-14
    中国香港
  • 本文字数:3309 字

    阅读完需:约 11 分钟

背景

NeoAIhttps://github.com/Bryley/neoai.nvim)是一个Neovim插件,它将OpenAIGPT-4的强大功能直接引入Neovim编辑器。它可以帮助你生成代码、重写文本,甚至在与你的代码上下文相符的情况下提供建议。该插件采用了用户友好的界面,使你可以轻松地与人工智能进行交互,获取所需的帮助。该插件的主要动机是在你的Neovim编程工作流中提供无缝集成的AI聊天助手,如ChatGPT。而作者目前的实现也仅支持ChatGPT。对于中国用户来说,多少有点不便。


在一段时间前,我向作者提了一个issue(https://github.com/Bryley/neoai.nvim/issues/50),并且实现了基于科大讯飞Spark的集成实现(https://github.com/Bryley/neoai.nvim/pull/52)。不过仓库的作者截至目前也没有评审代码和回复(可能比较忙),因此,我fork了一份到自己的仓库(https://github.com/skyfireitdiy/neoai.nvim),并将其他的一些pr合入。


现在既然千帆大模型开放了,那么,今天就将千帆大模型接入NeoAI

测试

创建应用

千帆大模型的配置参数主要有API Key/Secret Key,由此通过调用远端API获取access_token,后续根据access_token调用服务。


接下来获取API Key/Secret Key


在百度云控制台“应用接入”创建应用,即可拿到API Key/Secret Key


开通付费

在“计费管理”页面开通想要使用的模型的付费,才能从API调用。


测试接口

在“人工智能 AI”可以直接进行测试,并生成对应的接口代码。


编写一个命令行工具

接下来,将接口代码下载下来,加以改造,使其接受命令行参数。


代码如下:


#!/usr/bin/env python3import requestsimport jsonimport argparse

urls = { "ErnieBot": "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant", "ErnieBot-turbo": "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant",}

def chat(api_key, secret_key, messages, m): url = urls[m] + "?access_token=" + get_access_token(api_key, secret_key)
payload = json.dumps({ "messages": messages }) headers = { 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text)

def get_access_token(api_key, secret_key): url = "https://aip.baidubce.com/oauth/2.0/token" params = {"grant_type": "client_credentials", "client_id": api_key, "client_secret": secret_key} return str(requests.post(url, params=params).json().get("access_token"))

if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('api_key') parser.add_argument('secret_key') parser.add_argument('messages') parser.add_argument('model') args = parser.parse_args() chat(args.api_key, args.secret_key, args.messages, args.model)
复制代码


测试如下:


集成进 NeoAI

之前集成过讯飞Spark,因此本次集成千帆就比较简单了。

集成配置

AI配置位于:neoai.nvim/lua/neoai/config.lua


  1. 在模型配置中增加千帆配置:


models = {    {        name = "openai",        model = "gpt-3.5-turbo",        params = nil,    },    {        name = "spark",        model = "v1",        params = nil,    },    {        name = "qianfan",        model = "ErnieBot-turbo",        params = nil,    }},
复制代码


  1. 增加千帆认证信息配置


qianfan = {    api_key = {        secret_env = "QIANFAN_SECRET",        apikey_env = "QIANFAN_APIKEY",        secret = nil,        apikey = nil,        get = function()            if not M.options.qianfan.api_key.secret then                M.options.qianfan.api_key.secret = os.getenv(M.options.qianfan.api_key.secret_env)            end            if not M.options.qianfan.api_key.apikey then                M.options.qianfan.api_key.apikey = os.getenv(M.options.qianfan.api_key.apikey_env)            end            if M.options.qianfan.api_key.secret and M.options.qianfan.api_key.apikey then                return M.options.qianfan.api_key.secret, M.options.qianfan.api_key.apikey            end            local msg =  M.options.qianfan.api_key.secret_env .. "/"            .. M.options.qianfan.api_key.apikey_env .. " environment variable is not set"            logger.error(msg)            error(msg)        end    },},
复制代码


本质上是从环境变量 QIANFAN_SECRETQIANFAN_APIKEY获取认证信息。


  1. 使用认证信息,调用脚本


neoai.nvim/lua/neoai/chat/models/中创建qianfan.lua:


local utils = require("neoai.utils")local config = require("neoai.config")
---@type ModelModulelocal M = {}
M.name = "Qianfan"
M._chunks = {}local raw_chunks = {}
M.get_current_output = function() return table.concat(M._chunks, "")end
---@param chunk string---@param on_stdout_chunk fun(chunk: string) Function to call whenever a stdout chunk occursM._recieve_chunk = function(chunk, on_stdout_chunk) local raw_json = chunk
table.insert(raw_chunks, raw_json)
local ok, path = pcall(vim.json.decode, raw_json) if not ok then on_stdout_chunk("111") return end
path = path.result if path == nil then on_stdout_chunk("222") return end
on_stdout_chunk(path) -- append_to_output(path, 0) table.insert(M._chunks, path)end
---@param chat_history ChatHistory---@param on_stdout_chunk fun(chunk: string) Function to call whenever a stdout chunk occurs---@param on_complete fun(err?: string, output?: string) Function to call when model has finishedM.send_to_model = function(chat_history, on_stdout_chunk, on_complete) local secret, apikey = config.options.qianfan.api_key.get() local model = config.options.models[config.options.selected_model_index+1].model
local get_script_dir = function() local info = debug.getinfo(1, "S") local script_path = info.source:sub(2) return script_path:match("(.*/)") end
local py_script_path = get_script_dir() .. "qianfan.py"
os.execute("chmod +x "..py_script_path)
chunks = {} raw_chunks = {} on_stdout_chunk(apikey) on_stdout_chunk(secret) on_stdout_chunk(vim.json.encode(chat_history.messages)) on_stdout_chunk(model) utils.exec(py_script_path, { apikey, secret, vim.json.encode(chat_history.messages), model, }, function(chunk) M._recieve_chunk(chunk, on_stdout_chunk) end, function(err, _) local total_message = table.concat(raw_chunks, "") local ok, json = pcall(vim.json.decode, total_message) if ok then if json.error ~= nil then on_complete(json.error.message, nil) return end end on_complete(err, M.get_current_output())end)end
return M
复制代码


lua脚本会调用相同目录下的qianfan.py脚本,与千帆对话交互。


  1. 在初始化中配置使用千帆大模型


let $QIANFAN_APIKEY = "xxxxxxxxxx"let $QIANFAN_SECRET = "yyyyyyyyyyyyyyyyyyyyyyy"
lua<<EOFrequire("neoai").setup({ selected_model_index = 2,})EOF
复制代码


上述配置在插件配置中配置。

效果


整体还是很不错的。


欢迎大家试用:https://github.com/skyfireitdiy/neoai.nvim

发布于: 刚刚阅读数: 5
用户头像

SkyFire

关注

这个cpper很懒,什么都没留下 2018-10-13 加入

会一点点cpp的苦逼码农

评论

发布
暂无评论
为NeoAI增加千帆大模型支持_neovim_SkyFire_InfoQ写作社区