UNPKG

anylang

Version:

A translator's kit that uses the free APIs of Google Translate, Yandex, Bing, ChatGPT, and other LLMs

95 lines (93 loc) 15 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { z } from 'zod'; export const getPrompt = (text, from, to) => { // use full language name const langFormatter = new Intl.DisplayNames(['en'], { type: 'language' }); const originLang = from == 'auto' ? 'auto' : langFormatter.of(from); const targetLang = langFormatter.of(to); return `You are a text translation service. I will provide an array of texts, and your task is to translate them from language ${originLang} to language ${targetLang}. If I specify the source language as 'auto', you should automatically detect it and translate it into the target language I set. The array in your response must be the same length as the one in the request. Do not add any explanations — translate strictly according to the content. Be careful when creating an array; it must be syntactically correct and do not change quotation marks. Return an array of translated texts while preserving their order. Here is the JSON array of texts: ${JSON.stringify(text)}`; }; export class LLMTranslator { constructor(llm, options) { var _a, _b, _c, _d, _e, _f, _g; this.llm = llm; this.config = { retryLimit: (_b = (_a = options === null || options === void 0 ? void 0 : options.retryOptions) === null || _a === void 0 ? void 0 : _a.retryLimit) !== null && _b !== void 0 ? _b : 3, retryTimeout: (_d = (_c = options === null || options === void 0 ? void 0 : options.retryOptions) === null || _c === void 0 ? void 0 : _c.retryTimeout) !== null && _d !== void 0 ? _d : this.llm.getRequestsTimeout(), maxRetryTimeout: (_e = options === null || options === void 0 ? void 0 : options.retryOptions) === null || _e === void 0 ? void 0 : _e.maxRetryTimeout, retryBackoffFactor: (_f = options === null || options === void 0 ? void 0 : options.retryOptions) === null || _f === void 0 ? void 0 : _f.retryBackoffFactor, getPrompt: (_g = options === null || options === void 0 ? void 0 : options.getPrompt) !== null && _g !== void 0 ? _g : getPrompt, }; } translate(text, from, to) { return __awaiter(this, void 0, void 0, function* () { const translated = yield this.translateBatch([text], from, to); return translated[0]; }); } translateBatch(text, from, to) { return __awaiter(this, void 0, void 0, function* () { let attempt = 0; // Retry loop // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition while (true) { try { // first request without delay if (attempt > 0) { yield this.waitRetryDelay(attempt); } const response = yield this.llm.fetch(this.config.getPrompt(text, from, to)); const validateResult = z .string() .array() .length(text.length, { message: 'The response must be the same length as the requested array', }) .parse(JSON.parse(response)); return validateResult; } catch (error) { attempt++; if (attempt >= this.config.retryLimit) throw error; } } }); } getLengthLimit() { return this.llm.getLengthLimit(); } getRequestsTimeout() { return this.llm.getRequestsTimeout(); } checkLimitExceeding(text) { const plainText = Array.isArray(text) ? text.join('') : text; const extra = plainText.length - this.getLengthLimit(); return extra > 0 ? extra : 0; } /** * Calculates retry delays: starts with retryTimeout, * then increases exponentially (retryTimeout * factor^n) up to maxRetryTimeout (default: 4000). * Default retryBackoffFactor: 1.5 */ waitRetryDelay(attempt) { var _a, _b; const maxTimeout = (_a = this.config.maxRetryTimeout) !== null && _a !== void 0 ? _a : 4000; const factor = (_b = this.config.retryBackoffFactor) !== null && _b !== void 0 ? _b : 1.5; const delay = Math.min(maxTimeout, this.config.retryTimeout * Math.pow(factor, (attempt - 1))); return new Promise((r) => setTimeout(r, delay)); } } //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRyYW5zbGF0b3JzL0xMTVRyYW5zbGF0b3JzL0xMTVRyYW5zbGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQThCeEIsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFHLENBQUMsSUFBYyxFQUFFLElBQVksRUFBRSxFQUFVLEVBQUUsRUFBRTtJQUNyRSx5QkFBeUI7SUFDekIsTUFBTSxhQUFhLEdBQUcsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQztJQUMxRSxNQUFNLFVBQVUsR0FBRyxJQUFJLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEUsTUFBTSxVQUFVLEdBQUcsYUFBYSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUV4QyxPQUFPLDBIQUEwSCxVQUFVLGdCQUFnQixVQUFVOzs7O21DQUluSSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7QUFDMUQsQ0FBQyxDQUFDO0FBRUYsTUFBTSxPQUFPLGFBQWE7SUFHekIsWUFDa0IsR0FBZSxFQUNoQyxPQUdDOztRQUpnQixRQUFHLEdBQUgsR0FBRyxDQUFZO1FBTWhDLElBQUksQ0FBQyxNQUFNLEdBQUc7WUFDYixVQUFVLEVBQUUsTUFBQSxNQUFBLE9BQU8sYUFBUCxPQUFPLHVCQUFQLE9BQU8sQ0FBRSxZQUFZLDBDQUFFLFVBQVUsbUNBQUksQ0FBQztZQUNsRCxZQUFZLEVBQ1gsTUFBQSxNQUFBLE9BQU8sYUFBUCxPQUFPLHVCQUFQLE9BQU8sQ0FBRSxZQUFZLDBDQUFFLFlBQVksbUNBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsRUFBRTtZQUNyRSxlQUFlLEVB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QUFJLENBQUMsTUFBTSxDQUFDLFlBQVksR0FBRyxTQUFBLE1BQU0sRUFBSSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQSxDQUNsRCxDQUFDO1FBRUYsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ2pELENBQUM7Q0FDRCIsImZpbGUiOiJ0cmFuc2xhdG9ycy9MTE1UcmFuc2xhdG9ycy9MTE1UcmFuc2xhdG9yLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgeiB9IGZyb20gJ3pvZCc7XG5cbmltcG9ydCB7IFRyYW5zbGF0b3JJbnN0YW5jZU1lbWJlcnMgfSBmcm9tICcuLi9UcmFuc2xhdG9yJztcbmltcG9ydCB7IExMTUZldGNoZXIgfSBmcm9tICcuJztcblxuZXhwb3J0IHR5cGUgUHJvbXB0R2VuZXJhdG9yID0gKHRleHRzOiBzdHJpbmdbXSwgZnJvbTogc3RyaW5nLCB0bzogc3RyaW5nKSA9PiBzdHJpbmc7XG5cbmV4cG9ydCB0eXBlIExMTVRyYW5zbGF0b3JSZXRyeU9wdGlvbnMgPSB7XG5cdC8qKlxuXHQgKiBNYXhpbXVtIG51bWJlciBvZiByZXRyeSBhdHRlbXB0cyBhZnRlciBhIGZhaWxlZCByZXF1ZXN0XG5cdCAqL1xuXHRyZXRyeUxpbWl0PzogbnVtYmVyO1xuXG5cdC8qKlxuXHQgKiBEZWxheSBiZWZvcmUgZmlyc3QgcmV0cnkgaW4gbXM7IGluY3JlYXNlcyBleHBvbmVudGlhbGx5IHVwIHRvIG1heFJldHJ5VGltZW91dFxuXHQgKi9cblx0cmV0cnlUaW1lb3V0PzogbnVtYmVyO1xuXG5cdC8qKlxuXHQgKiBNYXhpbXVtIGRlbGF5IGJlZm9yZSB0aGUgbmV4dCByZXRyeVxuXHQgKi9cblx0bWF4UmV0cnlUaW1lb3V0PzogbnVtYmVyO1xuXG5cdC8qKlxuXHQgKiBBbiBleHBvbmVudGlhbCBtdWx0aXBsaWVyIHVzZWQgdG8gaW5jcmVhc2UgdGhlIGRlbGF5IGJldHdlZW4gcmV0cnkgYXR0ZW1wdHMuXG5cdCAqIFdpdGggZWFjaCBhdHRlbXB0LCB0aGUgZGVsYXkgZ3Jvd3MgYmFzZWQgb24gdGhpcyBmYWN0b3IuXG5cdCAqL1xuXHRyZXRyeUJhY2tvZmZGYWN0b3I/OiBudW1iZXI7XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0UHJvbXB0ID0gKHRleHQ6IHN0cmluZ1tdLCBmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcpID0+IHtcblx0Ly8gdXNlIGZ1bGwgbGFuZ3VhZ2UgbmFtZVxuXHRjb25zdCBsYW5nRm9ybWF0dGVyID0gbmV3IEludGwuRGlzcGxheU5hbWVzKFsnZW4nXSwgeyB0eXBlOiAnbGFuZ3VhZ2UnIH0pO1xuXHRjb25zdCBvcmlnaW5MYW5nID0gZnJvbSA9PSAnYXV0bycgPyAnYXV0bycgOiBsYW5nRm9ybWF0dGVyLm9mKGZyb20pO1xuXHRjb25zdCB0YXJnZXRMYW5nID0gbGFuZ0Zvcm1hdHRlci5vZih0byk7XG5cblx0cmV0dXJuIGBZb3UgYXJlIGEgdGV4dCB0cmFuc2xhdGlvbiBzZXJ2aWNlLiBJIHdpbGwgcHJvdmlkZSBhbiBhcnJheSBvZiB0ZXh0cywgYW5kIHlvdXIgdGFzayBpcyB0byB0cmFuc2xhdGUgdGhlbSBmcm9tIGxhbmd1YWdlICR7b3JpZ2luTGFuZ30gdG8gbGFuZ3VhZ2UgJHt0YXJnZXRMYW5nfS5cbklmIEkgc3BlY2lmeSB0aGUgc291cmNlIGxhbmd1YWdlIGFzICdhdXRvJywgeW91IHNob3VsZCBhdXRvbWF0aWNhbGx5IGRldGVjdCBpdCBhbmQgdHJhbnNsYXRlIGl0IGludG8gdGhlIHRhcmdldCBsYW5ndWFnZSBJIHNldC5cblRoZSBhcnJheSBpbiB5b3VyIHJlc3BvbnNlIG11c3QgYmUgdGhlIHNhbWUgbGVuZ3RoIGFzIHRoZSBvbmUgaW4gdGhlIHJlcXVlc3QuIERvIG5vdCBhZGQgYW55IGV4cGxhbmF0aW9ucyDigJQgdHJhbnNsYXRlIHN0cmljdGx5IGFjY29yZGluZyB0byB0aGUgY29udGVudC4gXG5CZSBjYXJlZnVsIHdoZW4gY3JlYXRpbmcgYW4gYXJyYXk7IGl0IG11c3QgYmUgc3ludGFjdGljYWxseSBjb3JyZWN0IGFuZCBkbyBub3QgY2hhbmdlIHF1b3RhdGlvbiBtYXJrcy4gUmV0dXJuIGFuIGFycmF5IG9mIHRyYW5zbGF0ZWQgdGV4dHMgd2hpbGUgcHJlc2VydmluZyB0aGVpciBvcmRlci5cbkhlcmUgaXMgdGhlIEpTT04gYXJyYXkgb2YgdGV4dHM6ICR7SlNPTi5zdHJpbmdpZnkodGV4dCl9YDtcbn07XG5cbmV4cG9ydCBjbGFzcyBMTE1UcmFuc2xhdG9yIGltcGxlbWVudHMgVHJhbnNsYXRvckluc3RhbmNlTWVtYmVycyB7XG5cdHByaXZhdGUgcmVhZG9ubHkgY29uZmlnO1xuXG5cdGNvbnN0cnVjdG9yKFxuXHRcdHByaXZhdGUgcmVhZG9ubHkgbGxtOiBMTE1GZXRjaGVyLFxuXHRcdG9wdGlvbnM/OiB7XG5cdFx0XHRnZXRQcm9tcHQ/OiBQcm9tcHRHZW5lcmF0b3I7XG5cdFx0XHRyZXRyeU9wdGlvbnM/OiBMTE1UcmFuc2xhdG9yUmV0cnlPcHRpb25zO1xuXHRcdH0sXG5cdCkge1xuXHRcdHRoaXMuY29uZmlnID0ge1xuXHRcdFx0cmV0cnlMaW1pdDogb3B0aW9ucz8ucmV0cnlPcHRpb25zPy5yZXRyeUxpbWl0ID8/IDMsXG5cdFx0XHRyZXRyeVRpbWVvdXQ6XG5cdFx0XHRcdG9wdGlvbnM/LnJldHJ5T3B0aW9ucz8ucmV0cnlUaW1lb3V0ID8/IHRoaXMubGxtLmdldFJlcXVlc3RzVGltZW91dCgpLFxuXHRcdFx0bWF4UmV0cnlUaW1lb3V0OiBvcHRpb25zPy5yZXRyeU9wdGlvbnM/Lm1heFJldHJ5VGltZW91dCxcblx0XHRcdHJldHJ5QmFja29mZkZhY3Rvcjogb3B0aW9ucz8ucmV0cnlPcHRpb25zPy5yZXRyeUJhY2tvZmZGYWN0b3IsXG5cdFx0XHRnZXRQcm9tcHQ6IG9wdGlvbnM/LmdldFByb21wdCA/PyBnZXRQcm9tcHQsXG5cdFx0fTtcblx0fVxuXG5cdHB1YmxpYyBhc3luYyB0cmFuc2xhdGUodGV4dDogc3RyaW5nLCBmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcpIHtcblx0XHRjb25zdCB0cmFuc2xhdGVkID0gYXdhaXQgdGhpcy50cmFuc2xhdGVCYXRjaChbdGV4dF0sIGZyb20sIHRvKTtcblx0XHRyZXR1cm4gdHJhbnNsYXRlZFswXTtcblx0fVxuXG5cdHB1YmxpYyBhc3luYyB0cmFuc2xhdGVCYXRjaCh0ZXh0OiBzdHJpbmdbXSwgZnJvbTogc3RyaW5nLCB0bzogc3RyaW5nKSB7XG5cdFx0bGV0IGF0dGVtcHQgPSAwO1xuXG5cdFx0Ly8gUmV0cnkgbG9vcFxuXHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5uZWNlc3NhcnktY29uZGl0aW9uXG5cdFx0d2hpbGUgKHRydWUpIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdC8vIGZpcnN0IHJlcXVlc3Qgd2l0aG91dCBkZWxheVxuXHRcdFx0XHRpZiAoYXR0ZW1wdCA+IDApIHtcblx0XHRcdFx0XHRhd2FpdCB0aGlzLndhaXRSZXRyeURlbGF5KGF0dGVtcHQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmxsbS5mZXRjaChcblx0XHRcdFx0XHR0aGlzLmNvbmZpZy5nZXRQcm9tcHQodGV4dCwgZnJvbSwgdG8pLFxuXHRcdFx0XHQpO1xuXG5cdFx0XHRcdGNvbnN0IHZhbGlkYXRlUmVzdWx0ID0gelxuXHRcdFx0XHRcdC5zdHJpbmcoKVxuXHRcdFx0XHRcdC5hcnJheSgpXG5cdFx0XHRcdFx0Lmxlbmd0aCh0ZXh0Lmxlbmd0aCwge1xuXHRcdFx0XHRcdFx0bWVzc2FnZTpcblx0XHRcdFx0XHRcdFx0J1RoZSByZXNwb25zZSBtdXN0IGJlIHRoZSBzYW1lIGxlbmd0aCBhcyB0aGUgcmVxdWVzdGVkIGFycmF5Jyxcblx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdC5wYXJzZShKU09OLnBhcnNlKHJlc3BvbnNlKSk7XG5cblx0XHRcdFx0cmV0dXJuIHZhbGlkYXRlUmVzdWx0O1xuXHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0YXR0ZW1wdCsrO1xuXHRcdFx0XHRpZiAoYXR0ZW1wdCA+PSB0aGlzLmNvbmZpZy5yZXRyeUxpbWl0KSB0aHJvdyBlcnJvcjtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgZ2V0TGVuZ3RoTGltaXQoKSB7XG5cdFx0cmV0dXJuIHRoaXMubGxtLmdldExlbmd0aExpbWl0KCk7XG5cdH1cblxuXHRwdWJsaWMgZ2V0UmVxdWVzdHNUaW1lb3V0KCkge1xuXHRcdHJldHVybiB0aGlzLmxsbS5nZXRSZXF1ZXN0c1RpbWVvdXQoKTtcblx0fVxuXG5cdHB1YmxpYyBjaGVja0xpbWl0RXhjZWVkaW5nKHRleHQ6IHN0cmluZyB8IHN0cmluZ1tdKSB7XG5cdFx0Y29uc3QgcGxhaW5UZXh0ID0gQXJyYXkuaXNBcnJheSh0ZXh0KSA/IHRleHQuam9pbignJykgOiB0ZXh0O1xuXHRcdGNvbnN0IGV4dHJhID0gcGxhaW5UZXh0Lmxlbmd0aCAtIHRoaXMuZ2V0TGVuZ3RoTGltaXQoKTtcblx0XHRyZXR1cm4gZXh0cmEgPiAwID8gZXh0cmEgOiAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGN1bGF0ZXMgcmV0cnkgZGVsYXlzOiBzdGFydHMgd2l0aCByZXRyeVRpbWVvdXQsXG5cdCAqIHRoZW4gaW5jcmVhc2VzIGV4cG9uZW50aWFsbHkgKHJldHJ5VGltZW91dCAqIGZhY3Rvcl5uKSB1cCB0byBtYXhSZXRyeVRpbWVvdXQgKGRlZmF1bHQ6IDQwMDApLlxuXHQgKiBEZWZhdWx0IHJldHJ5QmFja29mZkZhY3RvcjogMS41XG5cdCAqL1xuXHRwcml2YXRlIHdhaXRSZXRyeURlbGF5KGF0dGVtcHQ6IG51bWJlcikge1xuXHRcdGNvbnN0IG1heFRpbWVvdXQgPSB0aGlzLmNvbmZpZy5tYXhSZXRyeVRpbWVvdXQgPz8gNDAwMDtcblx0XHRjb25zdCBmYWN0b3IgPSB0aGlzLmNvbmZpZy5yZXRyeUJhY2tvZmZGYWN0b3IgPz8gMS41O1xuXHRcdGNvbnN0IGRlbGF5ID0gTWF0aC5taW4oXG5cdFx0XHRtYXhUaW1lb3V0LFxuXHRcdFx0dGhpcy5jb25maWcucmV0cnlUaW1lb3V0ICogZmFjdG9yICoqIChhdHRlbXB0IC0gMSksXG5cdFx0KTtcblxuXHRcdHJldHVybiBuZXcgUHJvbWlzZSgocikgPT4gc2V0VGltZW91dChyLCBkZWxheSkpO1xuXHR9XG59XG4iXX0=