【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; // 对话接口
};

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

json 复制代码
{
  // 当前选用的运行平台标识
  // 必须与下方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接口,因此针对各种情况需要抽象细化需求,最终整理设计的平台配置内容如下:

json 复制代码
{
  // 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(防篡改签名)

  • 原理:客户端与服务端共享密钥,对请求内容(时间戳、请求体)生成签名。

  • 典型场景

    • 金融风控模型调用、支付验证等高安全场景。
    • 防止请求被篡改或重放攻击。
  • 示例头

    http 复制代码
    Authorization: HMAC-SHA256 key_id="123", signature="abc123..."
  • 优势:确保请求完整性和身份真实性。

5. Basic Auth(基础认证)

  • 原理 :HTTP 头携带 username:password 的 Base64 编码。

  • 典型场景

    • 内部测试环境或低风险 AI 服务调用。
    • 配合 HTTPS 使用以加密传输。
  • 示例头

    http 复制代码
    Authorization: Basic base64encode("user:pass")
  • 局限:明文传输风险,需严格依赖 HTTPS。

6. 授权实现

基于常见的类型,本插件自持不同的header方式的认证授权方式。
授权流程 Header Para DeliveryType 认证配置解析 构造HTTP头 构造请求参数 Basic认证编码 Bearer Token拼接 API Key处理 Base64加密 注入认证信息 完成请求准备

抽象定义结构对象
cpp 复制代码
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保障安全)
定义配置加载函数
cpp 复制代码
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);
}
实现接口授权信息的设置
cpp 复制代码
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
设置授权认证信息
cpp 复制代码
// 初始化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. 配置模板

json 复制代码
{
    "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": {

            }
        }
    }
}
相关推荐
巷95520 分钟前
OpenCV图像金字塔详解:原理、实现与应用
人工智能·opencv·计算机视觉
科技小E27 分钟前
WebRTC实时音视频通话技术EasyRTC嵌入式音视频通信SDK,助力智慧物流打造实时高效的物流管理体系
人工智能·音视频
BioRunYiXue36 分钟前
一文了解氨基酸的分类、代谢和应用
人工智能·深度学习·算法·机器学习·分类·数据挖掘·代谢组学
IT古董2 小时前
【漫话机器学习系列】255.独立同分布(Independent and Identically Distributed,简称 IID)
人工智能·机器学习
fytianlan2 小时前
机器学习 day6 -线性回归练习
人工智能·机器学习·线性回归
算家云2 小时前
通义千问席卷日本!开源界“卷王”阿里通义千问成为日本AI发展新基石
人工智能·开源·通义千问·算家云·国产ai·租算力,到算家云·日本ai
ai产品老杨3 小时前
AI赋能安全生产,推进数智化转型的智慧油站开源了。
前端·javascript·vue.js·人工智能·ecmascript
明月醉窗台3 小时前
[20250507] AI边缘计算开发板行业调研报告 (2024年最新版)
人工智能·边缘计算
Blossom.1184 小时前
低代码开发:开启软件开发的新篇章
人工智能·深度学习·安全·低代码·机器学习·计算机视觉·数据挖掘
安特尼4 小时前
招行数字金融挑战赛数据赛道赛题一
人工智能·python·机器学习·金融·数据分析