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.
108 lines
3.5 KiB
108 lines
3.5 KiB
package echomeet
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"yunyan/pb"
|
|
"yunyan/sys/bytedance/audomodel"
|
|
bdtranslate "yunyan/sys/bytedance/translate"
|
|
"yunyan/sys/doubao"
|
|
)
|
|
|
|
// 字节系单元服务实例(由 provider_registry.go 按服务池字段构造):
|
|
// 转写=audomodel(短音频 flash 同步 + 长音频异步)、翻译=火山翻译、总结=豆包。
|
|
// 语言支持过滤已上移到编排层(服务池 languages 字段),此处只做语言码转换。
|
|
|
|
// 字节跳动转写:短音频 RecognizeFlash(同步) + 长音频 CreateTask+QueryTask(异步)
|
|
type byteDanceTranscriber struct {
|
|
sys audomodel.ISys
|
|
}
|
|
|
|
const (
|
|
byteDanceFlashMaxSeconds = 7200
|
|
byteDanceFlashMaxBytes = 1024 * 1024 * 100
|
|
)
|
|
|
|
func (this *byteDanceTranscriber) Submit(_ context.Context, req SubmitRequest) (*SubmitResult, error) {
|
|
lang, _ := toByteDanceLang(req.Language)
|
|
// 短音频走 flash 同步通道
|
|
if req.Seconds <= byteDanceFlashMaxSeconds && req.SizeBytes <= byteDanceFlashMaxBytes {
|
|
statusCode, _, contexts, err := this.sys.RecognizeFlash(req.Uid, req.AudioURL, req.EnableSpeaker, lang)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("bytedance flash err: status=%s %w", statusCode, err)
|
|
}
|
|
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 &SubmitResult{Done: true, Contexts: out}, nil
|
|
}
|
|
// 长音频走异步 submit(CallbackURL 由编排层按部署对外地址拼好传入)
|
|
taskID, logID, err := this.sys.CreateTask(req.Uid, req.AudioURL, req.EnableSpeaker, lang, req.CallbackURL, req.CallbackData)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("bytedance create task: %w", err)
|
|
}
|
|
return &SubmitResult{TaskID: taskID, LogID: logID}, nil
|
|
}
|
|
|
|
func (this *byteDanceTranscriber) Query(_ context.Context, taskID, logID string) (*QueryResult, error) {
|
|
code, contexts, err := this.sys.QueryTask(taskID, logID)
|
|
switch code {
|
|
case "20000000":
|
|
if err != nil {
|
|
return &QueryResult{Status: StatusFailed}, err
|
|
}
|
|
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 "20000001", "20000002":
|
|
return &QueryResult{Status: StatusRunning}, nil
|
|
default:
|
|
return &QueryResult{Status: StatusFailed}, fmt.Errorf("bytedance query failed code=%s err=%v", code, err)
|
|
}
|
|
}
|
|
|
|
// 火山翻译
|
|
type byteDanceTranslator struct {
|
|
sys bdtranslate.ISys
|
|
}
|
|
|
|
func (this *byteDanceTranslator) Translate(ctx context.Context, from, to string, texts []string) ([]string, error) {
|
|
return this.sys.Translate(ctx, toByteDanceTranslateLang(from), toByteDanceTranslateLang(to), texts)
|
|
}
|
|
|
|
// 豆包总结
|
|
type doubaoSummarizer struct {
|
|
sys doubao.ISys
|
|
}
|
|
|
|
func (this *doubaoSummarizer) Chat(ctx context.Context, messages []ChatMessage) (string, error) {
|
|
if this.sys == nil {
|
|
return "", fmt.Errorf("doubao summarizer not initialized")
|
|
}
|
|
msgs := make([]doubao.Message, 0, len(messages))
|
|
for _, m := range messages {
|
|
msgs = append(msgs, doubao.Message{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("doubao chat: empty response")
|
|
}
|
|
return resp.Content, nil
|
|
}
|
|
|