You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

126 lines
4.3 KiB

package echomeet
import (
"context"
"yunyan/lego/sys/log"
"yunyan/pb"
"yunyan/sys/aliyun/filetrans"
"yunyan/sys/aliyun/translate"
"yunyan/sys/openai"
"fmt"
"strings"
)
// newAliProviders 初始化阿里系单元服务(转写=DashScope 录音文件转写、翻译=阿里翻译、
// 总结=通义千问 DashScope OpenAI 兼容端点),返回组合后的转写/翻译/总结三个 provider。
func newAliProviders(opt ProviderOptions) (Transcriber, Translator, Summarizer) {
if err := filetrans.OnInit(opt.Transcribe); err != nil {
log.Errorf("echomeet: init ali filetrans failed: %v", err)
}
if err := translate.OnInit(opt.Translate); err != nil {
log.Errorf("echomeet: init ali translate failed: %v", err)
}
sys, err := openai.NewSys(
openai.SetBaseURL(opt.Summary.BaseURL),
openai.SetToken(opt.Summary.Token),
openai.SetModel(opt.Summary.Model),
openai.SetMaxfunccall(1),
)
if err != nil {
log.Errorf("echomeet: init ali(qwen) summarizer failed: %v", err)
}
return &aliTranscriber{}, &aliTranslator{}, &aliSummarizer{sys: sys}
}
// 阿里云 DashScope 转写(paraformer-v2,异步)
type aliTranscriber struct{}
func (this *aliTranscriber) Name() pb.TranscribeService {
return pb.TranscribeService_TranscribeService_Ali
}
// dashScopeParaformerV2Langs 是 filetrans 所用模型 paraformer-v2 **实际**支持的语种(DashScope 语言码)。
//
// 坑:core.go 的 bcp47ToDashScope 里还映射了 es/pt/it/vi/tr/pl/nl/uk/th/ar/id/ms/fil,
// 但 paraformer-v2 并不支持它们——把这些语种的音频送进去,引擎识别不出任何内容,
// 转写查询会返回 SUCCESS_WITH_NO_VALID_FRAGMENT(看起来像"音频没声音",实则是模型不认识该语种)。
// 若将来把 filetrans.go 的 Model 换成 Fun-ASR / Qwen-ASR(支持更多语种),需同步放开这里。
var dashScopeParaformerV2Langs = map[string]bool{
"zh": true, "yue": true, "en": true, "ja": true, "ko": true,
"de": true, "fr": true, "ru": true,
}
func (this *aliTranscriber) SupportsLanguage(bcp47 string) bool {
if strings.TrimSpace(bcp47) == "" {
return true // 空 = 不指定 hints,交给 DashScope 自动检测
}
return dashScopeParaformerV2Langs[toDashScopeLang(bcp47)]
}
func (this *aliTranscriber) Submit(_ context.Context, req SubmitRequest) (*SubmitResult, error) {
aliLang := toDashScopeLang(req.Language)
taskID, err := filetrans.CreateTask(req.AudioURL, aliLang, req.EnableSpeaker, req.CallbackURL)
if err != nil {
return nil, fmt.Errorf("ali filetrans create task: %w", err)
}
return &SubmitResult{TaskID: taskID}, nil
}
func (this *aliTranscriber) Query(_ context.Context, taskID, _ string) (*QueryResult, error) {
status, contexts, err := filetrans.QueryTask(taskID)
switch status {
case filetrans.StatusSuccess:
out := make([]*pb.ContextStruct, 0, len(contexts))
for _, c := range contexts {
out = append(out, &pb.ContextStruct{
Content: c.Content,
Starttime: c.StartTime,
Endtime: c.EndTime,
Speaker: c.Speaker,
})
}
return &QueryResult{Status: StatusSuccess, Contexts: out}, nil
case filetrans.StatusRunning:
return &QueryResult{Status: StatusRunning}, nil
default:
return &QueryResult{Status: StatusFailed}, fmt.Errorf("ali filetrans query failed: %w", err)
}
}
// 阿里翻译
type aliTranslator struct{}
func (this *aliTranslator) Name() pb.TranscribeService {
return pb.TranscribeService_TranscribeService_Ali
}
func (this *aliTranslator) Translate(ctx context.Context, from, to string, texts []string) ([]string, error) {
return translate.Translate(ctx, toAliTranslateLang(from), toAliTranslateLang(to), texts)
}
// 通义千问总结(DashScope OpenAI 兼容端点)
type aliSummarizer struct {
sys openai.ISys
}
func (this *aliSummarizer) Name() pb.TranscribeService {
return pb.TranscribeService_TranscribeService_Ali
}
func (this *aliSummarizer) Chat(ctx context.Context, messages []ChatMessage) (string, error) {
if this.sys == nil {
return "", fmt.Errorf("ali summarizer not initialized")
}
msgs := make([]openai.ChatReq, 0, len(messages))
for _, m := range messages {
msgs = append(msgs, openai.ChatReq{Role: m.Role, Content: m.Content, Images: m.Images})
}
resp, err := this.sys.Chat(ctx, msgs)
if err != nil {
return "", err
}
if resp == nil {
return "", fmt.Errorf("ali(qwen) chat: empty response")
}
return resp.Content, nil
}