前言
前边写了很多和AI相关模块的设计,可能会有些糊涂这个软件里AI到底是怎么调用的,这边博客用来详细阐述AI的具体调用实现,也算是我自己的一个相关总结和反思。
一、AI Orchestrator
这是AI能力编排服务,协调整个AI能力调用流程,包括事件管理、余额检查、模型调用和计费。包含一个处理AI能力请求的函数(process),给这个函数提供用户id和AI能力请求,首先会获取这个AI能力具体是什么(TTS还是LLM等),然后调用获取对应能力的函数,在注册表中寻找;
创建一个状态为待处理的AI事件,预估所需Credits,检查并预扣用户的余额,预扣成功才把AI事件状态变为处理中,防止进行本次活动之后发现用户余额不足。
调用能力执行,然后根据实际用量调整扣费,将AI事件状态改为成功。
这个类还定义了四种AI能力的便捷调用方法:
①TTS便捷调用:
参数列表封装文本以及声音,将参数和AI能力类型(TTS)构建请求对象,然后调用process函数,提取结果中的音频url。
②STT便捷调用:
参数列表封装音频url以及参考语言,将参数和AI能力类型(STT)构建请求对象,然后调用process函数,提取结果中的文本。
③LLM便捷调用
参数列表封装消息列表,具体格式为 [{role: "user/assistant/system", content: "..."}],将参数和AI能力类型(STT)构建请求对象,然后调用process函数,提取结果中的字符串回复。
④文生图便捷调用
参数列表封装提示词以及图片尺寸,将参数和AI能力类型(STT)构建请求对象,然后调用process函数,提取结果中的图片url。
二、AI能力注册表
注册表在一开始就查找所有实现AI能力的统一接口的类,然后获取他们的AI能力类型,进行注册,这样让Orchestrator只依赖注册表不用写复杂的if-else语句。然后通过get方法,返回具体AI能力实现类的实例对象。
三、AI能力的统一接口
所有AI能力都应满足这个接口,这个接口定义了四个函数,分别是能力标识类型、具体执行、预估价格、计量单位,这样防止了不同AI能力的函数不同,实现了统一调用AI,同时也方便创建新的AI能力。
四、AI模型适配器注册表
注册表在一开始就查找所有实现ModelAdapter接口的类,获取他们的模型,然后从他们的配置文件中获取模型能力等配置进行注册,分别注册两个Map,一个用来注册模型的能力,比如:
modelsByCapability = { "LLM": [GPT4Adapter, QwenAdapter, WenxinAdapter], "TTS": [AliyunTtsAdapter, AzureTtsAdapter], "STT": [AliyunSttAdapter] }还有一个用来注册模型的名字,用于检索:
modelsByName = { "gpt-4": GPT4Adapter实例, "qwen-max": QwenAdapter实例, "aliyun-tts": AliyunTtsAdapter实例 }然后初始化API密钥池,为了管理调用AI模型所需的所有API密钥,实现负载均衡、故障转移和智能调度。
这个模型注册表还包括根据模型能力来获取该能力的所有模型,以及获取可用模型(配置文件可用以及模型自己认为可用)等函数。
五、模型适配器统一接口
每个具体模型需要实现此接口,具体包括获取模型名称、获取供应商名称、调用具体模型、检查模型是否可用、计算本次调用成本。
六、API密钥池管理组件
每个密钥状态包含五个属性:真实的API密钥,是否可用(连续失败3次后变为false),限流恢复时间,连续失败次数(记录连续失败次数,成功时归零),最后使用时间。采取轮询负载均衡策略,每次调用一个模型的时候,首先获取所有可用的api,然后利用轮询选择密钥,如果一个密钥被调用三次都失败了则把它熔断,同时对于频繁调用的密钥进行限流,防止频繁使用被限制。
七、模型路由器
7.1 接口
设置一个模型路由器接口,输入需要的AI能力以及可用模型列表,返回最合适的模型,所有的AI能力模型将实现这个接口。
7.2 LLM路由器
想法很简单,如果请求包含图片则选用qwen-vl-plus,如果不包含图片则选用qwen-plus,但为了防止这两个模型出错,还设置了备选方案,当这两个模型在可用模型列表找不到的时候,就使用可用模型列表的第一个模型。
7.3 TTS、文生图路由器
采用最简单的策略:直接选择第一个可用的模型。
八、具体AI能力
8.1 LLM能力
LlmCapability是AiCapability接口的具体实现,负责处理所有大语言模型对话请求.
LLm的请求是消息列表,首先提取请求中的消息,然后在模型注册表中寻找类型是LLm的可用模型,通过路由器选择最合适的模型,从ApiKeyPool获取可用密钥,然后构建模型请求调用真正的模型,调用成功标记密钥成功,调用失败标记密钥失败,最后获取对应的响应。
剩下的TTS、STT、文生图能力流程与LLM类似,不赘述了。
8.2 语音评测能力
这个流程和前边的几个类似,唯一的不同在于它设置了很严格的验证输入,它需要检验文本是否为空以及长度限制,在这里分为两类,一类是朗读句子,一类是朗读章节,这两类文本长度限制不同;还需要检查音频文件是否为空以及大小限制,同时还有音标检验,音标检验是在验证音标注解的格式是否正确,这是讯飞ISE API特有的功能,用于指导用户如何正确发音。都通过检验后才开始走流程。
九、具体AI模型适配器
9.1 LLM模型
9.1.1 Qwen-Plus 模型适配器
首先提取请求中的消息,然后转换消息格式,从Map格式转换为DashScope的Message格式,因为阿里云DashScope SDK的API设计要求传入的是强类型的List<Message>,而不是灵活的List<Map>:
[
{
"role": "system",
"content": "你是一个热情好客的导游,专门介绍北京的历史文化。"
},
{
"role": "user",
"content": "你好,我想去北京旅游。"
},
{
"role": "assistant",
"content": "欢迎来到北京!我是您的导游,故宫、长城等都是必去景点。"
},
{
"role": "user",
"content": "请详细介绍一下故宫的开放时间。"
}
]
构建Generation请求参数,把DashScope的Message格式,转换成阿里云DashScope API能够识别的具体参数。然后真正发送请求到阿里云DashScope API并接收响应,层层提取回复内容,将回复封装到响应中,返回给前端。
9.1.2 Qwen-VL-Plus 模型适配器
整体流程与Qwen-Plus相似,唯一不同是Qwen-Plus请求内容是string,而Qwen-VL-Plus请求类型是object(content可以是复杂结构),所以需要把不同格式的content统一转换成DashScope 多模态 API要求的列表格式,如果是纯文本需要转化为list,如果是含有图片和纯文本则不需要转换本身就是list。
此外,阿里云的多模态对话API每次调用只能接收一条消息,而不是完整的对话历史,所以每次只发送最后一条消息。
9.2 image模型适配器-Qwen-Image-Plus
首先提取请求中的提示词,构建一个符合阿里云多模态API要求的消息对象,然后构建参数,包括水印设置、提示词扩展、负面提示词、图片尺寸等。构建Generation请求参数,然后真正发送请求到阿里云DashScope API并接收响应,层层提取回复的图片url,将回复封装到响应中,返回给前端。
9.3 STT模型适配器-Qwen3-ASR-Flash
首先提取请求中的audioUrl、语言、逆文本标准化(用于控制是否将识别出的口语化数字转换成书面格式);然后分别构建用户消息和系统消息,用户消息封装着用户提供的音频文件,系统消息用于配置定制化识别的上下文。然后配置语音识别的参数,因为阿里云ASR API无法直接识别提取出来的语言、逆文本标准化。
构建DashScope请求参数,然后真正发送请求到阿里云DashScope API并接收响应,层层提取回复的文本,将回复封装到响应中,返回给前端。
9.4 TTS模型适配器-Qwen3-TTS-Flash
首先提取请求中的文本、声音、语言类型;然后直接构建DashScope请求参数,然后真正发送请求到阿里云DashScope API并接收响应,层层提取回复的音频url,把阿里云TTS生成的临时音频文件,转存到自己的OSS上,获取一个永久有效的访问链接。将回复封装到响应中,返回给前端。