Skip to content

Commit

Permalink
feature: 增加火山翻译;
Browse files Browse the repository at this point in the history
  • Loading branch information
speauty committed Apr 14, 2023
1 parent 6c4254f commit d80f4be
Show file tree
Hide file tree
Showing 11 changed files with 650 additions and 23 deletions.
3 changes: 3 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"anto/dependency/service/translator/niutrans"
"anto/dependency/service/translator/openapi_youdao"
"anto/dependency/service/translator/tencent_cloud_mt"
"anto/dependency/service/translator/volcengine"
"anto/dependency/service/translator/youdao"
"anto/lib/log"
"anto/platform/win"
Expand Down Expand Up @@ -42,12 +43,14 @@ func main() {
ali_cloud_mt.Singleton().Init(cfg.Singleton().AliCloudMT)
caiyunai.Singleton().Init(cfg.Singleton().CaiYunAI)
niutrans.Singleton().Init(cfg.Singleton().Niutrans)
volcengine.Singleton().Init(cfg.Singleton().VolcEngine)

repository.GetTranslators().Register(
huawei_cloud_nlp.Singleton(),
youdao.Singleton(), ling_va.Singleton(), baidu.Singleton(),
tencent_cloud_mt.Singleton(), openapi_youdao.Singleton(),
ali_cloud_mt.Singleton(), caiyunai.Singleton(), niutrans.Singleton(),
volcengine.Singleton(),
)

win.Run(ctx)
Expand Down
6 changes: 5 additions & 1 deletion cfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ caiyun_ai: # 彩云小翻译
max_single_text_length: 5000 # 单次翻译最大长度

niutrans:
app_key:
app_key:

volc_engine:
access_key:
secret_key:
3 changes: 3 additions & 0 deletions cfg/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"anto/dependency/service/translator/niutrans"
"anto/dependency/service/translator/openapi_youdao"
"anto/dependency/service/translator/tencent_cloud_mt"
"anto/dependency/service/translator/volcengine"
"anto/platform/win/ui"
"fmt"
"sync"
Expand All @@ -32,6 +33,7 @@ func Singleton() *Cfg {
apiSingleton.AliCloudMT = ali_cloud_mt.Cfg{}.Default()
apiSingleton.CaiYunAI = caiyunai.Cfg{}.Default()
apiSingleton.Niutrans = niutrans.Cfg{}.Default()
apiSingleton.VolcEngine = volcengine.Cfg{}.Default()
})
return apiSingleton
}
Expand All @@ -47,6 +49,7 @@ type Cfg struct {
AliCloudMT *ali_cloud_mt.Cfg `mapstructure:"ali_cloud_mt"`
CaiYunAI *caiyunai.Cfg `mapstructure:"caiyun_ai"`
Niutrans *niutrans.Cfg `mapstructure:"niutrans"`
VolcEngine *volcengine.Cfg `mapstructure:"volc_engine"`
}

func (customC *Cfg) NewUITitle() string {
Expand Down
5 changes: 5 additions & 0 deletions cfg/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ func (customC *Cfg) Sync() error {
viper.Set("niutrans.app_key", customC.Niutrans.AppKey)
}

{ // sync volcengine
viper.Set("volc_engine.access_key", customC.VolcEngine.AccessKey)
viper.Set("volc_engine.secret_key", customC.VolcEngine.SecretKey)
}

if err := viper.WriteConfig(); err != nil {
return fmt.Errorf("写入配置失败, 错误: %s", err)
}
Expand Down
6 changes: 5 additions & 1 deletion common/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ caiyun_ai: # 彩云小翻译
max_single_text_length: 5000 # 单次翻译最大长度
niutrans:
app_key:
app_key:
volc_engine:
access_key:
secret_key:
`
)
10 changes: 10 additions & 0 deletions dependency/service/translator/volcengine/cfg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package volcengine

type Cfg struct {
AccessKey string `mapstructure:"access_key"`
SecretKey string `mapstructure:"secret_key"`
}

func (customC Cfg) Default() *Cfg {
return &Cfg{AccessKey: "", SecretKey: ""}
}
15 changes: 15 additions & 0 deletions dependency/service/translator/volcengine/lang.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package volcengine

import (
"anto/dependency/service/translator"
)

var langSupported = []translator.LangPair{
{"zh", "中文"},
{"en", "英语"},
{"ja", "日语"},
{"ru", "俄语"},
{"fr", "法语"},
{"ko", "韩语"},
{"de", "德语"},
}
163 changes: 163 additions & 0 deletions dependency/service/translator/volcengine/translator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package volcengine

import (
"anto/dependency/service/translator"
"anto/lib/log"
"encoding/json"
"fmt"
"github.com/golang-module/carbon"
"github.com/volcengine/volc-sdk-golang/base"
"net/http"
"net/url"
"strings"
"sync"
"time"
)

const (
host = "open.volcengineapi.com"
service = "translate"
version = "2020-06-01"
)

var (
apiSingleton *Translator
onceSingleton sync.Once
)

func Singleton() *Translator {
onceSingleton.Do(func() {
apiSingleton = New()
})
return apiSingleton
}

func New() *Translator {
return &Translator{
id: "volcengine",
name: "火山翻译",
qps: 10,
procMax: 20,
textMaxLen: 5000,
sep: "\n",
langSupported: langSupported,
}
}

type Translator struct {
id string
name string
cfg *Cfg
qps int
procMax int
textMaxLen int
langSupported []translator.LangPair
sep string
mtClient *base.Client
}

func (customT *Translator) Init(cfg interface{}) { customT.cfg = cfg.(*Cfg) }

func (customT *Translator) GetId() string { return customT.id }
func (customT *Translator) GetName() string { return customT.name }
func (customT *Translator) GetCfg() interface{} { return nil }
func (customT *Translator) GetQPS() int { return customT.qps }
func (customT *Translator) GetProcMax() int { return customT.procMax }
func (customT *Translator) GetTextMaxLen() int { return customT.textMaxLen }
func (customT *Translator) GetLangSupported() []translator.LangPair { return customT.langSupported }
func (customT *Translator) GetSep() string { return customT.sep }
func (customT *Translator) IsValid() bool {
return customT.cfg != nil && customT.cfg.AccessKey != "" && customT.cfg.SecretKey != ""
}

func (customT *Translator) Translate(args *translator.TranslateArgs) (*translator.TranslateRes, error) {
timeStart := carbon.Now()

params := &translateRequestParams{
SourceLanguage: args.FromLang,
TargetLanguage: args.ToLang,
}
params.TextList = append(params.TextList, args.TextContent)
jsonBytes, _ := json.Marshal(params)
respBytes, _, err := customT.client().Json("TranslateText", nil, string(jsonBytes))
if err != nil {
return nil, err
}

resp := new(translateResponse)
if err = json.Unmarshal(respBytes, resp); err != nil {
log.Singleton().Error(fmt.Sprintf("解析报文异常, 引擎: %s, 错误: %s", customT.GetName(), err))
return nil, fmt.Errorf("解析报文出现异常, 错误: %s", err.Error())
}

if resp.ResponseMetaData.Error.Code != "" {
log.Singleton().Error(fmt.Sprintf("接口响应异常, 引擎: %s, 错误: %s(%s)", customT.GetName(), resp.ResponseMetaData.Error.Message, resp.ResponseMetaData.Error.Code))
return nil, fmt.Errorf("接口响应异常, 引擎: %s, 错误: %s", customT.GetName(), resp.ResponseMetaData.Error.Message)
}
srcTexts := strings.Split(args.TextContent, customT.GetSep())
tgtTexts := strings.Split(resp.TranslationList[0].Translation, customT.GetSep())
if len(srcTexts) != len(tgtTexts) {
log.Singleton().Error(fmt.Sprintf("响应解析错误, 引擎: %s, 错误: 译文和原文数量匹配失败", customT.GetName()))
return nil, fmt.Errorf("翻译异常, 错误: 源文和译文数量不对等")
}

ret := new(translator.TranslateRes)

for textIdx, textTarget := range tgtTexts {
ret.Results = append(ret.Results, &translator.TranslateResBlock{
Id: srcTexts[textIdx], TextTranslated: textTarget,
})
}

ret.TimeUsed = int(carbon.Now().DiffAbsInSeconds(timeStart))
return ret, nil

}

func (customT *Translator) client() *base.Client {
if customT.mtClient == nil {
serviceInfo := &base.ServiceInfo{
Timeout: 5 * time.Second, Host: host,
Header: http.Header{"Accept": []string{"application/json"}},
Credentials: base.Credentials{Region: base.RegionCnNorth1, Service: service},
}

apiInfoList := map[string]*base.ApiInfo{
"TranslateText": {
Method: http.MethodPost, Path: "/",
Query: url.Values{"Action": []string{"TranslateText"}, "Version": []string{version}},
},
}
client := base.NewClient(serviceInfo, apiInfoList)
client.SetAccessKey(customT.cfg.AccessKey)
client.SetSecretKey(customT.cfg.SecretKey)
customT.mtClient = client
}

return customT.mtClient
}

type translateRequestParams struct {
SourceLanguage string
TargetLanguage string
TextList []string
}

type translateResponse struct {
ResponseMetaData struct {
RequestId string `json:"RequestId"`
Action string `json:"Action"`
Version string `json:"Version"`
Service string `json:"Service"`
Region string `json:"Region"`
Error struct {
Code string `json:"Code"`
Message string `json:"Message"`
} `json:"Error"`
} `json:"ResponseMetaData"`
TranslationList []struct {
Translation string `json:"Translation"`
//DetectedSourceLanguage string `json:"DetectedSourceLanguage"`
//Extra interface{} `json:"Extra"`
} `json:"TranslationList"`
}
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ require (
github.com/spf13/viper v1.15.0
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.628
github.com/twharmon/gouid v0.5.2
github.com/volcengine/volc-sdk-golang v1.0.95
)

require (
github.com/cenkalti/backoff/v4 v4.1.2 // indirect
github.com/gobuffalo/envy v1.7.0 // indirect
github.com/gobuffalo/packd v0.3.0 // indirect
github.com/gobuffalo/packr v1.30.1 // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/joho/godotenv v1.3.0 // indirect
github.com/jonboulle/clockwork v0.3.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
Expand All @@ -33,6 +36,7 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/net v0.8.0 // indirect
gopkg.in/Knetic/govaluate.v3 v3.0.0 // indirect
)

Expand Down
Loading

0 comments on commit d80f4be

Please sign in to comment.