【AI插件开发】Notepad++ AI插件开发实践:支持多平台多模型

引言

上篇文章我们的Notepad++插件介绍到Dock窗口集成,本篇将继续完善插件功能,主要包括两个部分:

  • 支持多平台、多模型
  • 支持多种授权验证、接口类型

一、多平台

原先的配置项很简单:

// PluginConf.h
class PlatformConf {
public:std::string _baseUrl;      // API基础地址std::string _apiSkey;      // 认证密钥std::string _modelName;    // 模型标识std::string _generateEndpoint; // 生成接口std::string _chatEndpoint; // 对话接口
};

但是插件本身可能需要接入多个平台,因此有必要支持多平台,因此需要重新设计配置文件,如下:

{// 当前选用的运行平台标识// 必须与下方platforms对象中的某个平台键名完全一致// 系统将根据此字段加载对应的平台配置"platform": "OurCopDev",// 多平台环境配置集合// 支持预定义多个平台的配置参数,便于快速切换环境// 每个键名代表平台标识,建议采用有明确含义的命名(如环境类型/业务线)"platforms": {// Infini平台配置(示例第三方系统集成)// 可包含API地址、认证信息、超时设置等参数"infini": {// 平台配置项示例:// "api_endpoint": "https://api.infini.ai",// "auth_token": "xxx-xxx-xxx"},// 生产环境配置// 通常包含正式环境地址、生产用密钥等敏感信息"OurCopProd": {// 平台配置项示例:},// 开发环境配置// 一般包含测试服务器地址、调试参数等非生产配置"OurCopDev": {// 典型配置项}}
}

这样,插件根据当前的配置平台名称platform支持使用不同的AI平台

二、多模型

因为一般平台会提供多个内置的模型,因此需要在此基础上,支持用户选择不同的模型。

此外,不同的平台接口也不一样,有的是https,有的是http,有的是post接口,有的是get接口,因此针对各种情况需要抽象细化需求,最终整理设计的平台配置内容如下:

{// SSL配置开关// true: 启用HTTPS协议,所有请求将通过加密通道传输// false: 使用HTTP协议(不建议生产环境使用)// 注意:启用时需确保服务端配置了有效的SSL证书"enable_ssl": true,// 基础服务地址// API请求的根域名/地址,所有接口路径将基于此地址拼接// 示例:https://cloud.infini-ai.com/maas/v1/..."base_url": "cloud.infini-ai.com",// 当前激活的模型名称// 必须与models列表中某个值完全匹配// 用于默认的API请求参数"model_name": "deepseek-r1-distill-qwen-32b",// 可用模型清单// 平台支持的全部模型列表(可动态更新)// 可通过models_endpoint接口自动获取或手动维护"models": [ "deepseek-r1-distill-qwen-32b","deepseek-r1","deepseek-v3"],// 文本生成接口配置// 用于单轮文本生成的API端点设置// prompt字段当前未使用(可能为兼容旧版本保留)"generate_endpoint": {"method": "post",    // HTTP请求方法"api": "/maas/v1/completions",  // 接口路径"prompt": ""        // 保留字段(未来可能用于预设提示词)},// 对话接口配置// 支持多轮对话的API端点设置// prompt字段当前未使用(可能用于会话初始化模板)"chat_endpoint": {"method": "post","api": "/maas/v1/chat/completions","prompt": ""},// 模型列表接口配置// 用于动态获取可用模型列表的API配置// 需要至少包含method和api字段才能启用自动更新// 示例可添加://   "method": "get",//   "api": "/maas/v1/models",//   "auth_required": true  // 是否需要鉴权"models_endpoint": {}  
}

补充说明:

  1. 接口路径均基于base_url拼接,如最终生成接口地址为:
    https://cloud.infini-ai.com/maas/v1/completions
  2. models_endpoint若配置正确,系统可自动更新models列表(目前尚未实现),否则需手动维护
  3. prompt字段的保留设计可能用于未来支持预设提示词模板功能
成功
失败
已配置
未配置
启用认证
Basic
Bearer
ApiKey
成功
失败
插件启动
读取配置文件
解析platform字段
匹配platforms配置
加载对应平台参数
使用默认配置
初始化HTTP客户端
检查models_endpoint
自动拉取模型列表
使用预设models列表
更新models配置
用户选择模型
构建API请求
检查认证配置
调用GetAuthorizationHeader
认证类型判断
生成Basic头
生成Bearer头
生成API Key头
合并请求头
发送HTTP请求
响应处理
返回结果
重试/报错

三、兼容不同的授权方式

1. API Key(最常见)

  • 原理:客户端在请求头或参数中携带唯一密钥,服务端验证密钥有效性。
  • 典型场景
    • OpenAI、讯飞星火等大模型 API 调用(如 X-API-Key: your_key)。
    • 云服务商提供的 AI 服务(如图像识别、自然语言处理)。
  • 优势:轻量、易集成,适合开放平台和第三方调用。
  • 安全建议
    • 限制密钥权限范围(如绑定 IP、设置调用频率)。
    • 定期轮换密钥,防范泄露风险。

2. OAuth 2.0(第三方授权)

  • 原理:通过授权服务器颁发 access_token,客户端携带令牌访问 AI 服务。
  • 典型场景
    • 需要用户授权的 AI 服务(如企业级模型调用、个性化推荐)。
    • 微信/QQ 登录后调用 AI 能力。
  • 流程
    1. 用户授权 → 2. 获取 code → 3. 兑换 access_token → 4. 调用 API。
  • 优势:支持细粒度权限控制,适合生态化平台。

3. JWT(无状态令牌)

  • 原理:服务端生成含用户信息和过期时间的加密 Token,客户端后续请求携带。
  • 典型场景
    • 分布式 AI 服务调用(如多模型协同推理)。
    • 移动端或单页应用调用 AI 接口(如语音合成、对话机器人)。
  • 结构Header.Payload.Signature(如 xxxxx.yyyyy.zzzzz)。
  • 优势:无状态,减轻服务端压力;支持短时效+刷新机制。

4. HMAC(防篡改签名)

  • 原理:客户端与服务端共享密钥,对请求内容(时间戳、请求体)生成签名。
  • 典型场景
    • 金融风控模型调用、支付验证等高安全场景。
    • 防止请求被篡改或重放攻击。
  • 示例头
    Authorization: HMAC-SHA256 key_id="123", signature="abc123..."
    
  • 优势:确保请求完整性和身份真实性。

5. Basic Auth(基础认证)

  • 原理:HTTP 头携带 username:password 的 Base64 编码。
  • 典型场景
    • 内部测试环境或低风险 AI 服务调用。
    • 配合 HTTPS 使用以加密传输。
  • 示例头
    Authorization: Basic base64encode("user:pass")
    
  • 局限:明文传输风险,需严格依赖 HTTPS。

6. 授权实现

基于常见的类型,本插件自持不同的header方式的认证授权方式。

授权流程
Header
Para
DeliveryType
认证配置解析
构造HTTP头
构造请求参数
Basic认证编码
Bearer Token拼接
API Key处理
Base64加密
注入认证信息
完成请求准备
抽象定义结构对象
class AuthorizationConf : public IConfig
{
public:// 授权类型枚举,定义支持的认证授权方式 enum class AuthType{None,    // 无认证授权 Basic,   // 基础认证(用户名+密码的Base64编码)Bearer,  // Bearer Token认证(如JWT/OAuth 2.0令牌)ApiKey   // API Key认证(支持云服务/AI模型调用场景)};// 参数传递方式枚举,定义认证信息传输位置 enum class DeliveryType{Header,  // 通过HTTP请求头传递(如Authorization头)Para     // 通过请求参数传递(如URL参数或POST参数)};AuthType eAuthType = AuthType::None;          // 当前配置的授权类型,默认关闭认证 DeliveryType eDeliveryType = DeliveryType::Header; // 认证信息传递方式,默认使用请求头 // 认证授权数据,内容格式与授权类型强相关:// - Basic: "username:password"的Base64编码 // - Bearer: "access_token"字符串 // - ApiKey: 明文密钥(如"X-API-Key: your_key")std::string auth_data; 
};

注解说明:

  1. AuthType 枚举:覆盖主流认证方式,其中:

    • Basic 对应HTTP基础认证,需配合HTTPS使用
    • Bearer 适用于JWT/OAuth 2.0等令牌体系
    • ApiKey 常用于云服务商API调用(如阿里云OSS的C++ SDK)
  2. DeliveryType 枚举:区分认证信息的传输载体:

    • Header 符合RESTful API设计规范(如Authorization: Bearer xxx
    • Para 多用于简易场景或兼容旧系统
  3. auth_data 格式:需根据认证类型动态调整内容:

    • Basic认证需按user:pass格式Base64编码
    • API Key通常直接使用明文密钥(需HTTPS保障安全)
定义配置加载函数
virtual void from_json(const nlohmann::json& j) override
{std::string strVal;if (Util::JsonGet(j, "type", strVal)){eAuthType = AuthType::None;if (!Util::icasecompare(strVal, "Basic")){eAuthType = AuthType::Basic;}if (!Util::icasecompare(strVal, "Bearer")){eAuthType = AuthType::Bearer;}if (!Util::icasecompare(strVal, "ApiKey")){eAuthType = AuthType::ApiKey;}}Util::JsonGet(j, "data", auth_data);
}
实现接口授权信息的设置
bool AiModel::GetAuthorizationHeader(const AuthorizationConf& auth, std::string& hkey, std::string& hval)
{hkey = "";  // 初始化HTTP头键名hval = "";  // 初始化HTTP头值const std::string& auth_data = auth.auth_data;  // 获取认证配置数据switch (auth.eAuthType) {// 无认证授权时直接返回成功(空头信息)case AuthorizationConf::AuthType::None:return true;  // 无认证场景直接通过case AuthorizationConf::AuthType::Basic: {// Basic认证需要"username:password"格式size_t colonPos = auth_data.find(':');if (colonPos == std::string::npos) return false;  // 缺少分隔符格式错误std::string encoded = Util::Base64Encode(auth_data);  // 对凭证进行Base64编码hkey = "Authorization";  // 固定使用标准HTTP头hval = "Basic " + encoded;  // 符合RFC 7617规范return true;}case AuthorizationConf::AuthType::Bearer:{if (auth_data.empty()) return false;  // 空Token无效hkey = "Authorization";  // 标准Bearer Token头hval = "Bearer " + auth_data;  // 符合RFC 6750规范return true;}case AuthorizationConf::AuthType::ApiKey: {if (auth.eDeliveryType == AuthorizationConf::DeliveryType::Header) {// 支持自定义头格式或默认X-API-Key头size_t colonPos = auth_data.find(':');if (colonPos != std::string::npos) {// 用户自定义头格式(如"X-Custom-Key: value")hkey = Util::Trim(auth_data.substr(0, colonPos));  // 提取头名称hval = Util::Trim(auth_data.substr(colonPos + 1));  // 提取头值}else {// 默认使用行业通用的X-API-Key头hkey = "X-API-Key";hval = auth_data;}return true;}// 参数传递需在URL构造阶段处理,此处无法支持return false;}default:return false;  // 未知认证类型处理失败}return true;  // 默认返回(实际不可达)
}

注解说明:

  1. 函数职责:根据认证配置生成HTTP请求头的键值对,支持多种认证方式的动态适配

  2. Basic认证实现

    • 严格校验username:password格式
    • 使用Base64编码但非加密(需配合HTTPS)
  3. Bearer Token处理

    • 直接拼接Bearer 前缀,符合RFC 6750规范
    • 适用于JWT/OAuth 2.0等令牌体系
  4. API Key机制

    • 支持灵活的头定义(如云服务商特定要求)
    • 默认使用X-API-Key头(遵循行业惯例)
    • 参数传递方式需在URL构造时实现(如?api_key=xxx
设置授权认证信息
// 初始化HTTP请求头,设置默认的Content-Type为JSON格式,确保数据以UTF-8编码传输
std::unordered_map<std::string, std::string> headers = {{"Content-Type", "application/json; charset=UTF-8"}
};// 从授权配置中提取认证名称和值,若获取成功且认证名称非空则添加到请求头
std::string authName, authValue;
if (GetAuthorizationHeader(plat.authorization, authName, authValue) && !authName.empty()) {headers[authName] = authValue;  // 动态添加认证信息到请求头
}// 将构建完成的请求头绑定到HTTP客户端实例,后续请求将自动携带这些头信息
cli.SetHeaders(headers);

注解说明:

  1. headers初始化块通过显式设置Content-Type声明了数据交换格式,这符合RESTful接口的通用规范
  2. GetAuthorizationHeader的返回值校验结合了空值检查,确保认证字段有效性(如Bearer Token或API Key)
  3. 使用unordered_mapoperator[]进行键值操作,保证认证头的高效存取(O(1)时间复杂度)
  4. SetHeaders调用将配置固化到客户端实例,符合C++ RAII(Resource Acquisition Is Initialization)设计原则

四、总结说明

1. 架构设计核心价值

本AI插件通过分层解耦设计实现了三大核心能力:

  • 平台无关性:通过platforms配置体系(如OurCopDev/infini)实现多环境快速切换
  • 模型动态适配:支持models_endpoint自动发现机制,结合手动配置保障兼容性
  • 认证统一抽象:封装主流授权方式(Basic/Bearer/ApiKey等),满足从测试到生产的全场景需求

2. 未来演进方向

模块当前状态规划能力
模型管理手动维护models列表实现models_endpoint自动同步
授权体系支持Header传递扩展DeliveryType::Para参数级认证
协议支持HTTP/HTTPS双模增加WebSocket实时接口支持
性能优化单线程请求引入异步协程提升并发能力

3. 配置模板

{"platform": "OurCopDev","timeout": 90,"platforms": {"infini": {"enable_ssl": true,"base_url": "cloud.infini-ai.com","authorization": {"type": "Bearer","data": "sk-**"},"model_name": "deepseek-r1-distill-qwen-32b","models": [ "deepseek-r1-distill-qwen-32b", "deepseek-r1", "deepseek-v3" ],"generate_endpoint": {"method": "post","api": "/maas/v1/completions","prompt": ""},"chat_endpoint": {"method": "post","api": "/maas/v1/chat/completions","prompt": ""},"models_endpoint": {}},"OurCopProd": {"enable_ssl": true,"base_url": "open.arbboter.com.cn","authorization": {"type": "ApiKey","data": "api-key:k****"},"model_name": "qwq_32b","models": [ "qwq_32b", "deepseek_v3_0324", "deepseek_r1_671b" ],"generate_endpoint": {"method": "post","api": "/maas/v1/completions","prompt": ""},"chat_endpoint": {"method": "post","api": "/prod/llm/personal/v1/chat/completions","prompt": ""},"models_endpoint": {}},"OurCopDev": {"enable_ssl": false,"base_url": "openapi.arbboter.com","authorization": {"type": "ApiKey","data": "api-key:k****"},"model_name": "deepseek_r1_671b","models": [ "qwq_32b", "deepseek_v3_0324", "deepseek_r1_671b" ],"generate_endpoint": {"method": "post","api": "/maas/v1/completions","prompt": ""},"chat_endpoint": {"method": "post","api": "/test/llm/personal/v1/chat/completions","prompt": ""},"models_endpoint": {}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/901864.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C#】Socket通信的使用

在C#中&#xff0c;Socket通信是一种用于实现网络通信的底层技术。通过Socket&#xff0c;程序可以在网络上与其他设备进行数据交换。以下是如何使用C#中的System.Net.Sockets命名空间来实现Socket通信的详细步骤。 1. Socket通信的基本概念 Socket: 一个Socket是网络通信的端…

2024年第九届团队程序设计天梯赛c++题解L1-L3-1(附PTA网址)

L1-1 编程解决一切 5分 L1-097 编程解决一切 - 团体程序设计天梯赛-练习集 (pintia.cn)https://pintia.cn/problem-sets/994805046380707840/exam/problems/type/7?problemSetProblemId1781658570803388416 #include<bits/stdc.h> #define int long long using namesp…

ICMAN防水触摸芯片 - 复杂环境下精准交互,提升触控体验

▍核心优势 ◆ 超强抗干扰能力 ◆ 工业级设计&#xff0c;一致性和稳定性好 ▍提供场景化解决方案 【智能厨电矩阵】抽油烟机档位调节 | 电磁炉火力触控 | 洗碗机模式切换 【卫浴设备方案】淋浴房雾化玻璃控制 | 智能马桶触控面板 | 浴缸水位感应 【工业控制应用】仪器仪…

Golang|抽奖相关

文章目录 抽奖核心算法生成抽奖大转盘抽奖接口实现 抽奖核心算法 我们可以根据 单商品库存量/总商品库存量 得到每个商品被抽中的概率&#xff0c;可以想象这样一条 0-1 的数轴&#xff0c;数轴上的每一段相当于一种商品&#xff0c;概率之和为1。 抽奖时&#xff0c;我们会生…

OpenCV 图形API(43)颜色空间转换-----将 BGR 图像转换为 LUV 色彩空间函数BGR2LUV()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将图像从BGR色彩空间转换为LUV色彩空间。 该函数将输入图像从BGR色彩空间转换为LUV。B、G和R通道值的传统范围是0到255。 输出图像必须是8位无符…

【Python】用Python写一个俄罗斯方块玩玩

【Python】用Python写一个俄罗斯方块玩玩 一、引言1.成品效果展示 二、思考准备1.思考设计2.代码设计2.1 游戏页面2.2 控件设计2.2.1 方块生成2.2.2 方块碰撞2.2.3 方块消融2.2.4 游戏主循环2.2.5 游戏窗口 三、游戏完整版 一、引言 今日看到侄子在玩游戏&#xff0c;凑近一看…

维港首秀!沃飞长空AE200亮相香港特别行政区

4月13日-16日&#xff0c;第三届香港国际创科展在香港会议展览中心盛大举办。 作为国内领先、国际一流的eVTOL主机厂&#xff0c;沃飞长空携旗下AE200批产构型登陆国际舞台&#xff0c;以前瞻性的创新技术与商业化应用潜力&#xff0c;吸引了来自全球17个国家及地区的行业领袖…

Openfein实现远程调用的方法(实操)

文章目录 环境准备一、URL中接收参数二、接收一个参数三、接收多个参数四、传递对象五、传递JSON格式数据 环境准备 下面的配置&#xff0c;服务调用方加入即可。 依赖导入&#xff1a; <!-- openfeign依赖--><dependency><groupId>org.springframe…

Bright+Data网页解锁器:旅游行业数据革命的“隐形引擎”

在数字经济浪潮中&#xff0c;旅游行业正经历前所未有的变革。当消费者指尖滑动间完成跨国酒店预订&#xff0c;当航空公司每秒调整万次舱位价格&#xff0c;背后是一场无声的数据战争。而在这场战争中&#xff0c;BrightData网页解锁器正成为旅游企业破局的关键武器——它像一…

OpenCV 图形API(38)图像滤波-----Sobel 算子操作函数Sobel()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::gapi::Sobel 函数是 OpenCV 的 G-API 模块中用于执行 Sobel 算子操作的一个函数&#xff0c;主要用于图像的边缘检测。Sobel 算子通过计算图…

CS5346 - Interactivity in Visualization 可视化中的交互

文章目录 Visualization representation interactionInteraction &#xff08;交互&#xff09;Benefits (好处)Typical Interaction Techniques&#xff08;交互技术&#xff09;SelectFilteringAbstract / Elaborate几何放缩&#xff08;Geometric zoom)语义放缩&#xff0…

第十六届蓝桥杯大赛软件赛省赛 C++ 大学 B 组 部分题解

赛时参加的是Python组&#xff0c;这是赛后写的题解&#xff0c;还有两题暂时还不会&#xff0c;待更新 题目链接题目列表 - 洛谷 | 计算机科学教育新生态 A 移动距离 答案&#xff1a;1576 C 可分解的正整数 Python3 import itertools from functools import cmp_to_ke…

Vue 解决 Error: please transfer a valid prop path to form item!

在 Vue.js 中使用表单验证库&#xff08;如 VeeValidate 或 Element UI 的表单组件时&#xff09;&#xff0c;遇到错误信息 "please transfer a valid prop path to form item!" 通常指的是在表单项的属性绑定中&#xff0c;路径&#xff08;prop path&#xff09;不…

在 Visual Studio Code 中安装通义灵码 - 智能编码助手

高效的编码工具对于提升开发效率和代码质量至关重要。 通义灵码作为一款智能编码助手&#xff0c;为开发者提供了全方位的支持。 本文将详细介绍如何在 Visual Studio Code&#xff08;简称 VSCode&#xff09;中安装通义灵码&#xff0c;以及如何进行相关配置以开启智能编码…

SQL 解析 with as dual sysdate level

目录 sql的运行顺序 with as EXTRACT ​编辑 dual sysdate level ​编辑 ​编辑 Oracle中的日期存储 核心部分 拆解字符串并计算最小值 关联子查询 NVL 函数 REGEXP_SUBSTR() sql的运行顺序 <select id="getTrendList" parameterType="java.uti…

快手OneRec 重构推荐系统:从检索排序到生成统一的跃迁

文章目录 1. 背景2. 方法2.1 OneRec框架2.2 Preliminary2.3 生成会话列表2.4 利用奖励模型进行迭代偏好对齐2.4.1 训练奖励模型2.4.2 迭代偏好对齐 3. 总结 昨天面试的时候聊到了OneRec&#xff0c;但是由于上次看这篇文章已经是一个月之前&#xff0c;忘得差不多了&#xff0c…

软考高级系统架构设计师-第11章 系统架构设计

【本章学习建议】 根据考试大纲&#xff0c;本章不仅考查系统架构设计师单选题&#xff0c;预计考12分左右&#xff0c;而且案例分析和论文写作也是必考&#xff0c;对应第二版教材第7章&#xff0c;属于重点学习的章节。 软考高级系统架构设计师VIP课程https://edu.csdn.net/…

selenium之文件下载

Selenium 自动化测试&#xff1a;轻松搞定文件下载 在 Web 自动化测试中&#xff0c;经常会遇到需要验证文件下载功能的场景。例如&#xff0c;测试报告的导出、用户上传文件的下载、PDF 文档的生成与下载等等。Selenium 本身并没有直接处理文件下载的内置方法&#xff0c;但我…

基于迁移学习实现肺炎X光片诊断分类

大家好&#xff0c;我是带我去滑雪&#xff01; 肺炎是全球范围内致死率较高的疾病之一&#xff0c;尤其是在老年人、免疫系统较弱的患者群体中&#xff0c;更容易引发严重并发症。传统上&#xff0c;肺炎的诊断依赖于医生的临床经验以及影像学检查&#xff0c;尤其是X光片&…

工业数据治理范式革新:时序数据库 TDengine虚拟表技术解析

小T导读&#xff1a;在工业数字化过程中&#xff0c;数据如何从设备采集顺利“爬坡”到上层应用&#xff0c;一直是个难题。传统“单列模型”虽贴合设备协议&#xff0c;却让上层分析举步维艰。TDengine 用一种更聪明的方法打通了这条数据通路&#xff1a;不强求建模、不手动转…