Skip to content

Commit

Permalink
feat(speauty#12): 新增SweetApi翻译(https://api.sweetyun.com/), 属于OpenAI类; @…
Browse files Browse the repository at this point in the history
…todo: 翻译不完整;
  • Loading branch information
speauty committed Feb 5, 2024
1 parent 1c165e9 commit 164d6f0
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
tidy:
go mod tidy

BinName=anto-v3.5.0-windows.exe
BinName=anto-v3.6.0-windows.exe

deploy: rs build

Expand Down
3 changes: 3 additions & 0 deletions bootstrap/boot.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"anto/domain/service/translator/huawei_cloud_nlp"
"anto/domain/service/translator/niutrans"
"anto/domain/service/translator/openai"
"anto/domain/service/translator/openai_sweet"
"anto/domain/service/translator/openapi_youdao"
"anto/domain/service/translator/tencent_cloud_mt"
"anto/domain/service/translator/volcengine"
Expand Down Expand Up @@ -45,6 +46,7 @@ func Boot(_ context.Context) {
g_deepl_x.API().Init(cfg.Singleton().YouDao)
google_cloud.API().Init(cfg.Singleton().GoogleCloud)
openai.API().Init(cfg.Singleton().OpenAI)
openai_sweet.API().Init(cfg.Singleton().OpenAISweet)
deepl.API().Init(cfg.Singleton().DeepL)
deepl_pro.API().Init(cfg.Singleton().DeepLPro)

Expand All @@ -54,5 +56,6 @@ func Boot(_ context.Context) {
ali_cloud_mt.API(), caiyunai.API(), niutrans.API(),
volcengine.API(), g_deepl_x.API(),
google_cloud.API(), openai.API(), deepl.API(), deepl_pro.API(),
openai_sweet.API(),
)
}
3 changes: 3 additions & 0 deletions cfg/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"anto/domain/service/translator/ling_va"
"anto/domain/service/translator/niutrans"
"anto/domain/service/translator/openai"
"anto/domain/service/translator/openai_sweet"
"anto/domain/service/translator/openapi_youdao"
"anto/domain/service/translator/tencent_cloud_mt"
"anto/domain/service/translator/volcengine"
Expand Down Expand Up @@ -44,6 +45,7 @@ func Singleton() *Cfg {
apiSingleton.YouDao = new(youdao.Config).Default().(*youdao.Config)
apiSingleton.GoogleCloud = new(google_cloud.Config).Default().(*google_cloud.Config)
apiSingleton.OpenAI = new(openai.Config).Default().(*openai.Config)
apiSingleton.OpenAISweet = new(openai_sweet.Config).Default().(*openai_sweet.Config)
apiSingleton.DeepL = new(deepl.Config).Default().(*deepl.Config)
apiSingleton.DeepLPro = new(deepl_pro.Config).Default().(*deepl_pro.Config)
})
Expand All @@ -66,6 +68,7 @@ type Cfg struct {
GDeeplX *g_deepl_x.Config `mapstructure:"g_deepl_x"`
GoogleCloud *google_cloud.Config `mapstructure:"google_cloud"`
OpenAI *openai.Config `mapstructure:"openai"`
OpenAISweet *openai_sweet.Config `mapstructure:"openai_sweet"`
DeepL *deepl.Config `mapstructure:"deepl"`
DeepLPro *deepl_pro.Config `mapstructure:"deepl_pro"`

Expand Down
13 changes: 7 additions & 6 deletions cmd/sandbox/main.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package main

import (
"fmt"
"github.com/OwO-Network/gdeeplx"
"github.com/imroc/req/v3"
)

func main() {
result, err := gdeeplx.Translate("Hello World!", "EN", "ZH", 0)
testClient := req.C()
testClient.SetProxyURL("sock5://hello:[email protected]:4532")

res, err := testClient.R().Get("https://www.google.com")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
panic(err)
}
fmt.Println(result)
print(res.Status)
}
2 changes: 1 addition & 1 deletion common/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package common
const (
AppName = "anto"
Author = "speauty"
Version = "v3.5.0"
Version = "v3.6.0"
DownloadLatestVersionUrl = "http://kodo.app.speauty.cn/anto-latest-windows.exe"

GoUidLen = 8
Expand Down
74 changes: 74 additions & 0 deletions domain/service/translator/openai_sweet/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package openai_sweet

import (
"anto/domain/service/translator"
"github.com/spf13/viper"
)

type Config struct {
*translator.DefaultConfig
AppKey string `mapstructure:"app_key"`
ProjectKey string `mapstructure:"project_key"`
QPS int `mapstructure:"qps"`
MaxCharNum int `mapstructure:"max_single_text_length"`
MaxCoroutineNum int `mapstructure:"max_coroutine_num"`
}

func (config *Config) Default() translator.ImplConfig {
return &Config{
AppKey: "", ProjectKey: "gpt-3.5-turbo",
MaxCharNum: 2000, QPS: 1, MaxCoroutineNum: 1,
}
}

func (config *Config) SyncDisk(currentViper *viper.Viper) error {
tagAndVal := config.JoinAllTagAndValue(API(), config, "mapstructure")

for tag, val := range tagAndVal {
currentViper.Set(tag, val)
}
return nil
}

func (config *Config) GetAK() string { return config.AppKey }
func (config *Config) GetProjectKey() string { return config.ProjectKey }
func (config *Config) GetQPS() int { return config.QPS }
func (config *Config) GetMaxCharNum() int { return config.MaxCharNum }
func (config *Config) GetMaxCoroutineNum() int { return config.MaxCoroutineNum }

func (config *Config) SetAK(str string) error {
if err := config.ValidatorStr(str); err != nil {
return err
}
config.AppKey = str
return nil
}

func (config *Config) SetProjectKey(projectKey string) error {
if projectKey == "" {
projectKey = "gpt-3.5-turbo"
}
config.ProjectKey = projectKey
return nil
}

func (config *Config) SetQPS(num int) error {
config.QPS = 1
return nil
}

func (config *Config) SetMaxCharNum(num int) error {
if err := config.ValidatorNum(num); err != nil {
return err
}
if num > 2000 {
num = 2000
}
config.MaxCharNum = num
return nil
}

func (config *Config) SetMaxCoroutineNum(num int) error {
config.MaxCoroutineNum = 1
return nil
}
10 changes: 10 additions & 0 deletions domain/service/translator/openai_sweet/lang.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package openai_sweet

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

var langSupported = []translator.LangPair{
{"Chinese", "中文"},
{"English", "英语"},
}
160 changes: 160 additions & 0 deletions domain/service/translator/openai_sweet/translator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package openai_sweet

import (
"anto/domain/service/translator"
"anto/lib/log"
"context"
"encoding/json"
"fmt"
"github.com/golang-module/carbon"
"strings"
"sync"
)

const apiTranslate = "https://api.sweetyun.com/v1/chat/completions"

var (
apiSingleton *Translator
onceSingleton sync.Once
)

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

func New() *Translator {
return &Translator{
id: "openai_sweet",
name: "OpenAI_Sweet",
sep: "\n",
langSupported: langSupported,
}
}

type Translator struct {
id string
name string
cfg translator.ImplConfig
langSupported []translator.LangPair
sep string
currentFromLang string
currentToLang string
currentMessages *translateRequest
}

func (customT *Translator) Init(cfg translator.ImplConfig) { customT.cfg = cfg }

func (customT *Translator) GetId() string { return customT.id }
func (customT *Translator) GetShortId() string { return "oas" }
func (customT *Translator) GetName() string { return customT.name }
func (customT *Translator) GetCfg() translator.ImplConfig { return customT.cfg }
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.GetAK() != "" }

func (customT *Translator) Translate(ctx context.Context, args *translator.TranslateArgs) (*translator.TranslateRes, error) {
timeStart := carbon.Now()
prompt := fmt.Sprintf(
"You are an excellent simultaneous translator in both %s and %s. I will provide you with %s line by line, and you will translate it into %s line by line. The number of lines in both %s and %s is the same. Do you understand?",
customT.currentFromLang, args.ToLang, customT.currentFromLang, args.ToLang, customT.currentFromLang, args.ToLang,
)
// 初始化
if customT.currentMessages == nil || customT.currentMessages.Model == "" {
customT.currentMessages = new(translateRequest)
customT.currentMessages.Model = customT.cfg.GetProjectKey()
customT.currentMessages.Messages = []MessageItem{}
}
// 预置条件, 语种必须保持一致, 否则就视为新开
if customT.currentFromLang == "" || customT.currentToLang == "" || customT.currentFromLang != args.FromLang || customT.currentToLang != args.ToLang {
if len(customT.currentMessages.Messages) > 0 {
customT.currentMessages.Messages = []MessageItem{}
}
customT.currentMessages.Messages = append(customT.currentMessages.Messages, MessageItem{
Role: "system", Content: prompt,
})
}
customT.currentMessages.Messages = append(customT.currentMessages.Messages, MessageItem{
Role: "user", Content: args.TextContent,
})
cntTokens := 0
for _, message := range customT.currentMessages.Messages {
cntTokens += len(message.Content)
}

if cntTokens < 2048 {

} else {
customT.currentMessages.Messages = []MessageItem{}
customT.currentMessages.Messages = append(customT.currentMessages.Messages, MessageItem{
Role: "system", Content: prompt,
}, MessageItem{
Role: "user", Content: args.TextContent,
})
}

reqBytes, _ := json.Marshal(customT.currentMessages)
headers := map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", customT.cfg.GetAK()),
}
respBytes, err := translator.RequestSimpleHttp(ctx, customT, apiTranslate, true, reqBytes, headers)
if err != nil {
return nil, err
}

resp := new(translateResponse)
if err = json.Unmarshal(respBytes, resp); err != nil {
log.Singleton().ErrorF("解析报文异常, 引擎: %s, 错误: %s", customT.GetName(), err)
return nil, fmt.Errorf("解析报文出现异常, 错误: %s", err.Error())
}
if resp.Usage.CompletionTokens <= 0 {
log.Singleton().ErrorF("接口响应异常, 引擎: %s, 错误: 无响应, 数据: %s", customT.GetName(), string(respBytes))
return nil, fmt.Errorf("接口响应异常, 引擎: %s, 错误: %s", customT.GetName(), "无响应")
}

srcTexts := strings.Split(args.TextContent, customT.GetSep())
tgtTexts := strings.Split(resp.Choices[0].Message.Content, customT.GetSep())
ret := new(translator.TranslateRes)
if len(srcTexts) != len(tgtTexts) {
ret.TimeUsed = int(carbon.Now().DiffAbsInSeconds(timeStart))
return ret, nil
}

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
}

type translateRequest struct {
Model string `json:"model"`
Messages []MessageItem `json:"messages"`
}

type MessageItem struct {
Role string `json:"role"`
Content string `json:"content"`
}

type translateResponse struct {
Id string `json:"id"`
Object string `json:"object"`
Created int `json:"created"`
Model string `json:"model"`
Choices []struct {
Index int `json:"index"`
Message MessageItem `json:"message"`
FinishReason string `json:"finish_reason"`
} `json:"choices"`
Usage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
} `json:"usage"`
}

0 comments on commit 164d6f0

Please sign in to comment.