-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4295e13
commit 1b17706
Showing
8 changed files
with
166 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import { Lang } from "@/types/client"; | ||
|
||
import { | ||
TranslateDetailSuccessResponse, | ||
TranslateOptions, | ||
} from "@/types/providers/yandextranslate"; | ||
import { TranslateError } from "@/errors"; | ||
import YandexTranslateProvider from "./yandextranslate"; | ||
|
||
/** | ||
* The total limit of characters per request is 10k chars | ||
*/ | ||
export default class YandexGPTProvider extends YandexTranslateProvider { | ||
YAGPT_ORIGIN = "https://neuro.translate.yandex.ru"; | ||
|
||
getSid() { | ||
const timestamp = Date.now().toString(16); | ||
|
||
return ( | ||
timestamp + | ||
Array.from({ length: 16 - timestamp.length }, () => | ||
Math.floor(Math.random() * 16).toString(16), | ||
).join("") | ||
); | ||
} | ||
|
||
isSupportedLLMOptions(options: TranslateOptions) { | ||
return ![ | ||
TranslateOptions.detailAlign, | ||
TranslateOptions.detailAlignAndDetectedLang, | ||
].includes(options); | ||
} | ||
|
||
async llmRawRequest( | ||
text: string | string[], | ||
lang: Lang = "en-ru", | ||
options: TranslateOptions = TranslateOptions.default, | ||
format: "text" | "html" = "text", | ||
) { | ||
if (lang !== "en-ru") { | ||
throw new TranslateError("LLM service support only en-ru lang"); | ||
} | ||
|
||
if (!this.isSupportedLLMOptions(options)) { | ||
throw new TranslateError( | ||
"Detail align options not supported by LLM service", | ||
); | ||
} | ||
|
||
if (!Array.isArray(text)) { | ||
text = [text]; | ||
} | ||
|
||
const sid = this.getSid(); | ||
const params = new URLSearchParams({ | ||
lang, | ||
id: `${sid}-0-0`, | ||
srv: "yabrowser-tr-text-app", | ||
tr_model: "llm_text", | ||
format, | ||
}).toString(); | ||
|
||
const textArray: readonly [string, string][] = text.map((val) => [ | ||
"text", | ||
val, | ||
]); | ||
const body = new URLSearchParams([ | ||
["options", options.toString()], | ||
["lang", lang], | ||
...textArray, | ||
]); | ||
|
||
const res = await this.request<TranslateDetailSuccessResponse>( | ||
`/translate?${params}`, | ||
body, | ||
{ | ||
Origin: this.YAGPT_ORIGIN, | ||
Referer: `${this.YAGPT_ORIGIN}/`, | ||
}, | ||
); | ||
|
||
if (!this.isSuccessProviderRes<TranslateDetailSuccessResponse>(res)) { | ||
throw new TranslateError(res.data); | ||
} | ||
|
||
const { lang: resLang, text: resText = [""], align, detected } = res.data; | ||
|
||
return { | ||
lang: resLang, | ||
translations: resText, | ||
align, | ||
detected, | ||
}; | ||
} | ||
|
||
/** | ||
* You can use this method if you need also get a detected language or align | ||
*/ | ||
async rawTranslate( | ||
text: string | string[], | ||
lang: Lang = "en-ru", | ||
options: TranslateOptions = TranslateOptions.default, | ||
format: "text" | "html" = "text", | ||
) { | ||
if (lang === "en-ru" && this.isSupportedLLMOptions(options)) { | ||
return await this.llmRawRequest(text, lang, options, format); | ||
} | ||
|
||
return await super.rawTranslate(text, lang, options, format); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export const phrase = "The quick brown fox jumps over the lazy dog"; | ||
export const phrase = | ||
"His intemperate youthful idealism, for which he'd done five years of hard time in Siberia, provided the impetus for Crime and Punishment and The Devils; his sensualism and compulsive nature and caustic rationality were the personally destabilizing forces against which he subsequently erected the fortress of The Brother Karamazov and lesser redoubts like The Gambler."; | ||
export const secondPhrase = "Hello world!"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { describe, expect, test } from "bun:test"; | ||
import TranslationClient from "../src"; | ||
import { TranslationService } from "../src/types/client"; | ||
import { phrase, secondPhrase } from "./data"; | ||
|
||
const translationClient = new TranslationClient({ | ||
service: TranslationService.yandexgpt, | ||
}); | ||
|
||
describe("translate", () => { | ||
test("translate phrase", async () => { | ||
const res = await translationClient.translate(phrase); | ||
expect(res.lang).toEqual("en-ru"); | ||
expect(res.translations.length).toEqual(1); | ||
expect(res.translations[0]).toInclude("Бесов"); | ||
}); | ||
test("translate multi phrases", async () => { | ||
const res = await translationClient.translate([phrase, secondPhrase]); | ||
expect(res.lang).toEqual("en-ru"); | ||
expect(res.translations.length).toEqual(2); | ||
}); | ||
}); | ||
|
||
test("detect language", async () => { | ||
const res = await translationClient.detect(phrase); | ||
expect(res.lang).toEqual("en"); | ||
expect(res.score).not.toEqual(null); | ||
}); | ||
|
||
test("get languages", async () => { | ||
const res = await translationClient.getLangs(); | ||
expect(res.length).toBeGreaterThan(0); | ||
}); |