有没有同学在用Eino调用阿里全模态模型的时候,特别是传音频的时候,但是又不想直接传音频的base64格式,而是直接输入音频的公网url,遇到了一些问题。
这是阿里官网的格式:
messages=[
{
"role": "user",
"content": [
{
"type": "input_audio",
"input_audio": {
"data": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250211/tixcef/cherry.wav",
"format": "wav",
},
},
{"type": "text", "text": "这段音频在说什么"},
],
},
],
那我们怎么移植到go的Eino框架里面呢?
audio := schema.MessageInputAudio{
MessagePartCommon: schema.MessagePartCommon{
URL: &audioURL,
MIMEType: "audio/wav",
},
}
AudioPart := schema.MessageInputPart{
Type: schema.ChatMessagePartTypeAudioURL,
Audio: &audio,
}
multiAut := schema.Message{
Role: "user",
UserInputMultiContent: []schema.MessageInputPart{AudioPart},
}
messages := []*schema.Message{
{
Role: schema.System,
Content: `你好你是语音情感助手!,请先转录用户的音频
`,
},
&multiAut,
}
这里我们可以看到我们直接传入URL会报错,官方源码直接把我们的url判定为非空,然后直接返回错误了,这就是错误的根源。
case schema.ChatMessagePartTypeAudioURL:
if part.Audio == nil {
return comMessage, errors.New("the 'audio' field is required for parts of type 'audio_url'")
}
if part.Audio.Base64Data != nil {
format, ok := mimeType2AudioFormat[part.Audio.MIMEType]
if !ok {
return comMessage, fmt.Errorf("the 'format' field is required when type is audio_url, use SetMessageInputAudioFormat to set it")
}
comMessage.MultiContent = append(comMessage.MultiContent, openai.ChatMessagePart{
Type: openai.ChatMessagePartTypeInputAudio,
InputAudio: &openai.ChatMessageInputAudio{
Data: *part.Audio.Base64Data,
Format: format,
},
})
} else if part.Audio.URL != nil {
format, ok := mimeType2AudioFormat[part.Audio.MIMEType]
if !ok {
return comMessage, fmt.Errorf("the 'format' field is required when type is audio_url, use SetMessageInputAudioFormat to set it")
}
comMessage.MultiContent = append(comMessage.MultiContent, openai.ChatMessagePart{
Type: openai.ChatMessagePartTypeInputAudio,
InputAudio: &openai.ChatMessageInputAudio{
Data: *part.Audio.URL,
Format: format,
},
})
} else {
return comMessage, errors.New("audio message part must have url or base64 data")
}
简化版 Debug & 代码修改流程
- 从业务代码
model.Stream(ctx, messages) 点进 Stream 方法;
- 在
Stream 方法里找到 cm.cli.Stream(ctx, in, opts...),继续点进该底层实现;
- 找到请求构建代码
genRequest,在其中定位到消息构建的分支逻辑,选择 buildMessageFromUserInputMultiContent 方法并点击进入;
- 在该方法的
for _, part := range inMsg.UserInputMultiContent 循环里,找到 part.Audio.URL != nil 分支;
- 将该分支内的代码替换为指定的音频格式校验和消息构建代码。
总结:这算是Eino留下来的一个坑吧,从多模态的字段上看他是支持URL,但是实际情况把把这条路堵死了,就只能从stream一步一步追溯,修改他原本的逻辑了。