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.
112 lines
3.7 KiB
112 lines
3.7 KiB
package echomeet
|
|
|
|
import (
|
|
"context"
|
|
"yunyan/lego/sys/log"
|
|
"yunyan/pb"
|
|
"yunyan/sys/microsoft/speech"
|
|
"yunyan/sys/microsoft/translate"
|
|
"yunyan/sys/openai"
|
|
"fmt"
|
|
)
|
|
|
|
// newMicrosoftProviders 初始化微软系单元服务(转写=Azure Speech、翻译=Azure Translator、
|
|
// 总结=Azure OpenAI 兼容端点),返回组合后的转写/翻译/总结三个 provider。
|
|
func newMicrosoftProviders(opt ProviderOptions) (Transcriber, Translator, Summarizer) {
|
|
if err := speech.OnInit(opt.Transcribe); err != nil {
|
|
log.Errorf("echomeet: init microsoft speech failed: %v", err)
|
|
}
|
|
if err := translate.OnInit(opt.Translate); err != nil {
|
|
log.Errorf("echomeet: init microsoft 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 microsoft(azure openai) summarizer failed: %v", err)
|
|
}
|
|
return µsoftTranscriber{}, µsoftTranslator{}, µsoftSummarizer{sys: sys}
|
|
}
|
|
|
|
// Azure Speech Batch Transcription
|
|
type microsoftTranscriber struct{}
|
|
|
|
func (this *microsoftTranscriber) Name() pb.TranscribeService {
|
|
return pb.TranscribeService_TranscribeService_Microsoft
|
|
}
|
|
|
|
// Azure Speech 支持的语种较广,原生使用 BCP-47 locale,不做白名单限制;
|
|
// 不支持时由 Azure 直接返回错误,统一在 Submit 失败路径处理。
|
|
func (this *microsoftTranscriber) SupportsLanguage(_ string) bool {
|
|
return true
|
|
}
|
|
|
|
func (this *microsoftTranscriber) Submit(_ context.Context, req SubmitRequest) (*SubmitResult, error) {
|
|
taskID, err := speech.CreateTask(req.AudioURL, req.Language, req.EnableSpeaker, req.CallbackURL)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("microsoft speech create task: %w", err)
|
|
}
|
|
return &SubmitResult{TaskID: taskID}, nil
|
|
}
|
|
|
|
func (this *microsoftTranscriber) Query(_ context.Context, taskID, _ string) (*QueryResult, error) {
|
|
status, contexts, err := speech.QueryTask(taskID)
|
|
switch status {
|
|
case speech.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 speech.StatusRunning:
|
|
return &QueryResult{Status: StatusRunning}, nil
|
|
default:
|
|
return &QueryResult{Status: StatusFailed}, fmt.Errorf("microsoft speech query failed: %w", err)
|
|
}
|
|
}
|
|
|
|
// Azure Translator
|
|
type microsoftTranslator struct{}
|
|
|
|
func (this *microsoftTranslator) Name() pb.TranscribeService {
|
|
return pb.TranscribeService_TranscribeService_Microsoft
|
|
}
|
|
|
|
func (this *microsoftTranslator) Translate(ctx context.Context, from, to string, texts []string) ([]string, error) {
|
|
return translate.Translate(ctx, toMicrosoftTranslateLang(from), toMicrosoftTranslateLang(to), texts)
|
|
}
|
|
|
|
// Azure OpenAI 总结(OpenAI 兼容端点)
|
|
type microsoftSummarizer struct {
|
|
sys openai.ISys
|
|
}
|
|
|
|
func (this *microsoftSummarizer) Name() pb.TranscribeService {
|
|
return pb.TranscribeService_TranscribeService_Microsoft
|
|
}
|
|
|
|
func (this *microsoftSummarizer) Chat(ctx context.Context, messages []ChatMessage) (string, error) {
|
|
if this.sys == nil {
|
|
return "", fmt.Errorf("microsoft 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("microsoft(azure openai) chat: empty response")
|
|
}
|
|
return resp.Content, nil
|
|
}
|
|
|