1 前言
OpenAI API开放后激发了行业内对人工智能技术的进一步探索和创新。本文探讨如何搭建一个自己的适配OpenAI API接口的协议规范的OpenAPI接口。
2 OpenAPI协议规范
OpenAPI 是一种规范或标准,用于定义和描述 API(应用程序编程接口)的格式和功能。
为实现一个适配OpenAI API接口协议的OpenAPI,首先需要梳理实现该API接口,需要有哪些功能。
需求 | 子需求 | 详细描述 | 备注 |
---|---|---|---|
API功能需求 | 面向人群 | 面向个人、企业租户 | |
- | 交互协议 | Https | Https |
- | 输入输出内容格式 | 输入支持:json、form file等,支持文本、图像、视频、文件等内容输入 输出支持:json、sse、file等,支持文本、图像、视频、文件等内容输出 | |
- | 用户鉴权 | 支持根据用户身份进行鉴权,避免非法访问 | |
- | 计量计费 | 支持按用户维度、用户+模型等维度进行计量并计费 | |
- | 频控限流 | 支持按用户、模型等维度进行频控限流,避免超出服务承载能力 | |
- | 错误码规范 | 支持按不同类型错误返回错误,进而提示用户进行错误处理。如可以分鉴权错误码、限流错误码、参数错误等 | |
- | 内容安全 | 支持用户输入、模型输出合规信息检查,避免因合规问题影响整个平台 | |
- | 版本管理 | 支持接口分版本,后续方便接口升级维护 | |
- | 客户端兼容 | 支持不同类型的客户端,如兼容OpenAI python客户端 | |
运营需求 | 模型管理 | 支持模型基础信息CRUD,模型的上线、下线、计量计费模式等修改 | |
- | 计量计费管理 | 支持不同类型的计量计费模型,如按调用次数计量、按token数、按生成图片/视频数量等 | |
- | 用户管理 | 支持对用户进行管理,如用户黑白名单管理,用户Api Key生成修改等 | |
- | 调用统计 | 支持按用户、模型等维度进行调用统计情况查看,了解现有接口使用情况 | |
- | 监控告警 | 对API服务进行监控,支持接口qps、接口延迟,服务cpu、mem等情况进行监控,并对一些异常情况进行告警,保证服务运行稳定 |
3 标准OpenAPI详细设计
3.1 OpenAPI 接口主要工作流程
3.2 OpenAPI 主要的架构
- API网关:完成用户身份鉴权、流量控制、API版本管理、参数解析/协议转换、错误码封装、监控等功能
- 流量限制,根据用户ID、设备ID等进行频控,频控策略可以自行制定,如1min限制访问5次
- 用户鉴权,根据用户身份鉴权信息,如API KEY 进行用户身份校验,黑白名单校验等,校验通过后,传递到下游API服务
- API版本管理,根据请求版本,提取不同版本的请求参数
- 参数协议转换,将http协议参数转换为内部的rpc 框架使用的参数协议,如继续使用http、thrift、grpc等
- 错误码封装,对下游API服务返回的rpc错误进行封装,封装成统一的错误码、错误信息,如都转换成OpenAI协议的error错误
- 监控,监控API网关,对异常的API访问进行监控,避免下游服务超出承载上限
- API核心服务:完成API核心的主流程逻辑封装,串联起上下游服务功能
- 模型信息校验,校验当前模型是否存在、是否在线等,避免无意义的模型调用
- 模型参数校验,校验当前用户输入的参数是否合法,如参数类型、参数取值范围等等
- 计量计费额度校验,校验当前用户使用当前模型的额度是否超出
- 内容合规检查,校验用户输入、模型输出的文本、图片、视频等是否合规
- 计量计费服务:完成API接口的计量计费功能
- 支持多种计量方式,如按次、按token、按生成量等计量
- 支持多种计费模式,如按量计费、时间周期计费等,需对接具体下游的支付等服务
- 媒体存储服务:完成API 输入、输出内容的存储
- 支持图片、视频、文件等资源上传、下载
- 媒体资源文件url下发,将媒体文件以url形式暴露到公网等
- 媒体资源等内容审核,避免媒体存储服务出现安全合规问题
- 内容审核服务:完成API接口内容输入、输出内容的审核
- 支持文本、图片、视频等内容合规检查
- 支持自定义设置敏感词等
- 模型服务
- 具体模型的部署服务,可以集群化部署在GPU集群上,本文不涉及此处,不作详细描述
- 基础设施
- 关系型DB,存储OpenAPI所需的关键业务数据
- 缓存,加速数据存取
- MQ,业务间数据交互解耦
- 向量存储,模型服务所需的向量数据存储
- 对象存储,媒体存储所需的对象存储,可以存储媒体资源、模型信息等
- 时序数据,存储监控数据等
3.3 OpenAPI 技术实现介绍
3.3.1 基础设施选型
- 关系型DB 采用Mysql
- 缓存 采用Redis
- MQ 使用RocketMQ
- 向量存储 Milvus
- 时序数据库:Prometheus + VictoriaMetrics
3.3.2 业务主要实体
业务实体 | 包含主要字段 | 详细描述 | 备注 |
---|---|---|---|
用户信息 | 用户ID、昵称、API KEY、联系方式、状态、创建时间 | 记录用户的基础信息,其中昵称、联系方式等需加密存取,包含用户隐私信息 | |
模型信息 | 模型ID、名称、描述、状态、模型访问地址、创建时间 | 记录模型的基础信息,以便于模型信息对外展示,模型调用的校验 | Https |
用户计量信息 | 用户ID、模型ID、计量方式、计量值、创建时间 | 以用户+模型为维度记录模型调用量 | |
用户计费信息 | 用户ID、模型ID、计费方式、额度值、创建时间、有效期 | 以用户+模型为维度记录模型剩余额度 | |
用户黑白名单信息 | 用户ID、API KEY、黑白名单标识、创建时间、有效期 | 维护黑白名单用户 | |
内容审核关键词信息 | ID、关键词、创建时间、有效期 | 关键词等信息,可在紧急时添加生效,避免平台出现合规风险 | |
媒体存储元信息 | ID、对象存储地址、类型、状态、创建时间、有效期 | 记录媒体存储的元信息 |
3.3.3 OpenAPI主要实现逻辑
- 主流的Java SpringBoot 快速搭建各个业务服务(不涉及模型服务)
- 微服务间仍使用http进行通信
- 微服务内大致实现逻辑
- Controller 封装对外接口
- Service 实现主要业务逻辑,分领域实现
- API service,API 服务主要逻辑
- model service,模型服务
- audit service,审核服务
- billing service,计费服务
- user service,用户服务
- ...
- SSE 逻辑
- 返回SseEmitter对象
- 在线程池中开启一个工作线程,该工作线程执行剩余的 模型服务调用等逻辑,并将模型结果通过SseEmitter发送给用户
- Dao 实现底层的数据访问,使用Mybatis
- Entity 定义业务服务主要实体
- param 对外API 接口参数实体
- dto 定义业务内交互实体
- entity 定义dao层各个实体,与Mysql
- Util 工具,封装各种服务工具,如time、json、http、cache、rpc、trace_id、metrics等常用工具
- http、rpc工具,封装微服务间访问的逻辑,如何RestTemplate封装 http调用逻辑
- cache,封装使用的缓存组件的访问逻辑,如RedisTemplate 封装redis调用逻辑
- trace_id,封装服务的日志链路id信息
- metrics,封装埋点上报的逻辑