@gringow/gringow 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +279 -43
- package/dist/config.d.mts +7 -8
- package/dist/config.mjs +32 -20
- package/dist/config.test.mjs +39 -25
- package/dist/constants/default-config.mjs +4 -3
- package/dist/data/check-cache.mjs +33 -63
- package/dist/data/clear-cache.mjs +32 -20
- package/dist/data/create-cache-dir.mjs +32 -20
- package/dist/data/delete-cache-item.mjs +32 -20
- package/dist/data/get-cache.mjs +32 -20
- package/dist/data/get-or-create-cache.mjs +32 -20
- package/dist/data/save-cache.mjs +32 -20
- package/dist/data/write-cache-to-disk.mjs +32 -20
- package/dist/gringow.mjs +84 -491
- package/dist/index.mjs +84 -491
- package/dist/io/ask-llm.d.mts +3 -1
- package/dist/io/ask-llm.mjs +77 -449
- package/dist/schemas/config.shcema.d.mts +40 -47
- package/dist/schemas/config.shcema.mjs +26 -15
- package/dist/types/index.d.mts +3 -25
- package/gringow.config.js.example +2 -4
- package/gringow.config.json.example +4 -2
- package/package.json +2 -5
- package/dist/io/anthropic/ask.d.mts +0 -11
- package/dist/io/anthropic/ask.mjs +0 -190
- package/dist/io/anthropic/commit-response.d.mts +0 -21
- package/dist/io/anthropic/commit-response.mjs +0 -10
- package/dist/io/anthropic/index.d.mts +0 -14
- package/dist/io/anthropic/index.mjs +0 -208
- package/dist/io/anthropic/parse.d.mts +0 -20
- package/dist/io/anthropic/parse.mjs +0 -10
- package/dist/io/gemini/ask.d.mts +0 -11
- package/dist/io/gemini/ask.mjs +0 -232
- package/dist/io/gemini/commit-response.d.mts +0 -11
- package/dist/io/gemini/commit-response.mjs +0 -7
- package/dist/io/gemini/index.d.mts +0 -14
- package/dist/io/gemini/index.mjs +0 -248
- package/dist/io/gemini/parse.d.mts +0 -20
- package/dist/io/gemini/parse.mjs +0 -11
- package/dist/io/huggingface/ask.d.mts +0 -13
- package/dist/io/huggingface/ask.mjs +0 -405
- package/dist/io/huggingface/commit-response.d.mts +0 -39
- package/dist/io/huggingface/commit-response.mjs +0 -14
- package/dist/io/huggingface/index.d.mts +0 -13
- package/dist/io/huggingface/index.mjs +0 -426
- package/dist/io/huggingface/languages-map.d.mts +0 -191
- package/dist/io/huggingface/languages-map.mjs +0 -187
- package/dist/io/huggingface/parse.d.mts +0 -20
- package/dist/io/huggingface/parse.mjs +0 -9
package/dist/index.mjs
CHANGED
|
@@ -4,9 +4,7 @@ import { z } from 'zod';
|
|
|
4
4
|
import fs from 'fs/promises';
|
|
5
5
|
import { dirname, resolve, parse } from 'path';
|
|
6
6
|
import { mkdir, stat, statSync, mkdirSync } from 'fs';
|
|
7
|
-
import
|
|
8
|
-
import { GoogleGenerativeAI } from '@google/generative-ai';
|
|
9
|
-
import { env, pipeline } from '@huggingface/transformers';
|
|
7
|
+
import { igniteEngine, Message } from 'multi-llm-ts';
|
|
10
8
|
|
|
11
9
|
// src/config.ts
|
|
12
10
|
|
|
@@ -22,19 +20,34 @@ var defaultConfig = {
|
|
|
22
20
|
prefix: "grw",
|
|
23
21
|
write: true
|
|
24
22
|
},
|
|
25
|
-
keys: {},
|
|
26
23
|
sourceLanguage: "en-US",
|
|
24
|
+
defaultLanguage: "pt-BR",
|
|
27
25
|
languages: ["pt-BR", "fr-CA"],
|
|
28
26
|
llm: {
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
provider: "openai",
|
|
28
|
+
apiKey: void 0,
|
|
29
|
+
model: "gpt-4o-mini",
|
|
31
30
|
temperature: 1,
|
|
32
31
|
sleep: 0
|
|
33
32
|
},
|
|
34
33
|
globby: "./src/**/*.{js,jsx,ts,tsx}"
|
|
35
34
|
};
|
|
36
35
|
var languageSchema = z.string().regex(/^[a-z]{2,3}(-[A-Z]{2})?$/);
|
|
37
|
-
var
|
|
36
|
+
var llmProviderSchema = z.enum([
|
|
37
|
+
"anthropic",
|
|
38
|
+
"gemini",
|
|
39
|
+
"openai",
|
|
40
|
+
"groq",
|
|
41
|
+
"mistral",
|
|
42
|
+
"ollama",
|
|
43
|
+
"xai",
|
|
44
|
+
"deepseek",
|
|
45
|
+
"openrouter",
|
|
46
|
+
"cerebras",
|
|
47
|
+
"lmstudio",
|
|
48
|
+
"azure",
|
|
49
|
+
"meta"
|
|
50
|
+
]);
|
|
38
51
|
var configSchema = z.object({
|
|
39
52
|
debug: z.boolean().optional(),
|
|
40
53
|
log: z.object({
|
|
@@ -46,14 +59,13 @@ var configSchema = z.object({
|
|
|
46
59
|
prefix: z.string(),
|
|
47
60
|
write: z.boolean().optional()
|
|
48
61
|
}),
|
|
49
|
-
keys: z.object({
|
|
50
|
-
anthropicApiKey: z.string().optional(),
|
|
51
|
-
geminiApiKey: z.string().optional()
|
|
52
|
-
}),
|
|
53
62
|
sourceLanguage: languageSchema,
|
|
63
|
+
defaultLanguage: languageSchema,
|
|
54
64
|
languages: z.array(languageSchema),
|
|
55
65
|
llm: z.object({
|
|
56
|
-
|
|
66
|
+
provider: llmProviderSchema,
|
|
67
|
+
apiKey: z.string().optional(),
|
|
68
|
+
baseURL: z.string().optional(),
|
|
57
69
|
model: z.string().nullable(),
|
|
58
70
|
temperature: z.number().optional(),
|
|
59
71
|
sleep: z.number().optional(),
|
|
@@ -67,17 +79,15 @@ var configSchema = z.object({
|
|
|
67
79
|
globby: z.string().regex(/^\.\/.*/).optional()
|
|
68
80
|
}).refine(
|
|
69
81
|
(data) => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (data.llm.choice === "anthropic" && !data.keys.anthropicApiKey) {
|
|
74
|
-
return false;
|
|
82
|
+
const noApiKeyRequired = ["ollama", "lmstudio"];
|
|
83
|
+
if (noApiKeyRequired.includes(data.llm.provider)) {
|
|
84
|
+
return true;
|
|
75
85
|
}
|
|
76
|
-
return
|
|
86
|
+
return !!data.llm.apiKey;
|
|
77
87
|
},
|
|
78
88
|
{
|
|
79
|
-
message: "The API key
|
|
80
|
-
path: ["
|
|
89
|
+
message: "The API key must be present in llm.apiKey for the chosen provider.",
|
|
90
|
+
path: ["llm", "apiKey"]
|
|
81
91
|
}
|
|
82
92
|
);
|
|
83
93
|
|
|
@@ -119,7 +129,7 @@ Your task is to translate a given text and output **only one valid JSON object**
|
|
|
119
129
|
|
|
120
130
|
Follow these rules strictly:
|
|
121
131
|
|
|
122
|
-
1. The original text is written in English.
|
|
132
|
+
1. The original text is written in English or Spanish.
|
|
123
133
|
2. You will receive additional user parameters under the variable 'extraInstructions'. These may specify tone, persona, style, context, or any relevant translation guideline.
|
|
124
134
|
- Examples: \u201Ctranslate as if you were a Shakespearean narrator\u201D or \u201Cuse a formal business tone suitable for a corporate presentation.\u201D
|
|
125
135
|
- Apply these creatively but **without altering the meaning or punctuation** of the original text.
|
|
@@ -152,10 +162,10 @@ Translate the following text faithfully:
|
|
|
152
162
|
function defaultPostPrompt(_config) {
|
|
153
163
|
return "";
|
|
154
164
|
}
|
|
155
|
-
function prePrompt(config,
|
|
165
|
+
function prePrompt(config, prepend, replace) {
|
|
156
166
|
return [
|
|
157
167
|
// ...(append ? ['[SPECIFIC_INPUTS]', String(append), '[/SPECIFIC_INPUTS]'] : []),
|
|
158
|
-
replace ? String(replace) : defaultPrePrompt(config,
|
|
168
|
+
replace ? String(replace) : defaultPrePrompt(config, prepend)
|
|
159
169
|
].join(" ").trim();
|
|
160
170
|
}
|
|
161
171
|
function postPrompt(config, prepend, replace) {
|
|
@@ -472,53 +482,11 @@ async function getOrCreateCache() {
|
|
|
472
482
|
return rawCache ? JSON.parse(rawCache?.toString()) : {};
|
|
473
483
|
}
|
|
474
484
|
|
|
475
|
-
// src/logger.ts
|
|
476
|
-
var Dim = "\x1B[2m";
|
|
477
|
-
var FgGreen = "\x1B[32m";
|
|
478
|
-
var FgYellow = "\x1B[33m";
|
|
479
|
-
var FgCyan = "\x1B[36m";
|
|
480
|
-
var FgWhite = "\x1B[37m";
|
|
481
|
-
var BgRed = "\x1B[41m";
|
|
482
|
-
var Clear = "\x1B[0m";
|
|
483
|
-
var Colors = {
|
|
484
|
-
debug: `${Dim}${FgGreen}`,
|
|
485
|
-
trace: `${Dim}${FgCyan}`,
|
|
486
|
-
info: `${FgCyan}`,
|
|
487
|
-
error: `${BgRed}${FgWhite}`,
|
|
488
|
-
warn: `${FgYellow}`,
|
|
489
|
-
verbose: `${FgWhite}`
|
|
490
|
-
};
|
|
491
|
-
var isProd = process.env.NODE_ENV === "production";
|
|
492
|
-
function log(level, ...params) {
|
|
493
|
-
console.log(`${!isProd ? Colors[level] : ""}${String(level).toUpperCase()} `, ...params, `${!isProd ? Clear : ""}`);
|
|
494
|
-
}
|
|
495
|
-
var logger = {
|
|
496
|
-
debug(...params) {
|
|
497
|
-
return log("debug", ...params);
|
|
498
|
-
},
|
|
499
|
-
trace(...params) {
|
|
500
|
-
return log("trace", ...params);
|
|
501
|
-
},
|
|
502
|
-
info(...params) {
|
|
503
|
-
return log("info", ...params);
|
|
504
|
-
},
|
|
505
|
-
warn(...params) {
|
|
506
|
-
return log("warn", ...params);
|
|
507
|
-
},
|
|
508
|
-
error(...params) {
|
|
509
|
-
return log("error", ...params);
|
|
510
|
-
},
|
|
511
|
-
verbose(...params) {
|
|
512
|
-
return log("verbose", ...params);
|
|
513
|
-
}
|
|
514
|
-
};
|
|
515
|
-
var logger_default = logger;
|
|
516
|
-
|
|
517
485
|
// src/data/check-cache.ts
|
|
518
486
|
async function checkCache(cacheId) {
|
|
519
487
|
const cache = await getOrCreateCache();
|
|
520
488
|
if (cache?.[cacheId]) {
|
|
521
|
-
|
|
489
|
+
console.log(`Cache hit, id:${cacheId}`);
|
|
522
490
|
return cache[cacheId];
|
|
523
491
|
}
|
|
524
492
|
return void 0;
|
|
@@ -562,445 +530,62 @@ function flatTemplateString(givenStrings, givenValues) {
|
|
|
562
530
|
}, "");
|
|
563
531
|
return flatted;
|
|
564
532
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
${postPrompt2}`).trim();
|
|
584
|
-
const response = await anthropic.messages.create({
|
|
585
|
-
model: config.llm.model,
|
|
586
|
-
max_tokens: 1024,
|
|
587
|
-
messages: [
|
|
588
|
-
{
|
|
589
|
-
role: "user",
|
|
590
|
-
content: fullPrompt
|
|
591
|
-
}
|
|
592
|
-
]
|
|
593
|
-
});
|
|
594
|
-
return response;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// src/io/anthropic/commit-response.ts
|
|
598
|
-
function commitResponseAnthropic(response) {
|
|
599
|
-
const result2 = response.content.reduce((acc, item) => {
|
|
600
|
-
const nextAcc = acc + (item.type === "text" ? item.text : "");
|
|
601
|
-
return nextAcc;
|
|
602
|
-
}, "");
|
|
603
|
-
return result2;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
// src/io/anthropic/parse.ts
|
|
607
|
-
function parseAnthropic(unparsed) {
|
|
608
|
-
if (typeof unparsed !== "string") {
|
|
609
|
-
throw new Error("CommitResponse should be a string here.");
|
|
610
|
-
}
|
|
611
|
-
const parsed = JSON.parse(unparsed);
|
|
533
|
+
var providerEngineMap = {
|
|
534
|
+
anthropic: "anthropic",
|
|
535
|
+
gemini: "google",
|
|
536
|
+
openai: "openai",
|
|
537
|
+
groq: "groq",
|
|
538
|
+
mistral: "mistralai",
|
|
539
|
+
ollama: "ollama",
|
|
540
|
+
xai: "xai",
|
|
541
|
+
deepseek: "deepseek",
|
|
542
|
+
openrouter: "openrouter",
|
|
543
|
+
cerebras: "cerebras",
|
|
544
|
+
lmstudio: "lmstudio",
|
|
545
|
+
azure: "azure",
|
|
546
|
+
meta: "meta"
|
|
547
|
+
};
|
|
548
|
+
function parseResponse(responseText) {
|
|
549
|
+
const cleaned = responseText.replace(/```json/g, "").replace(/```/g, "").trim();
|
|
550
|
+
const parsed = JSON.parse(cleaned);
|
|
612
551
|
return parsed;
|
|
613
552
|
}
|
|
614
|
-
async function
|
|
615
|
-
try {
|
|
616
|
-
if (!config.keys.geminiApiKey) {
|
|
617
|
-
throw new Error("Gemini API key is not set in the config");
|
|
618
|
-
}
|
|
619
|
-
const generativeAIClient = new GoogleGenerativeAI(config.keys.geminiApiKey);
|
|
620
|
-
const model = generativeAIClient.getGenerativeModel({
|
|
621
|
-
model: config.llm.model,
|
|
622
|
-
generationConfig: {
|
|
623
|
-
temperature: config.llm.temperature ?? 0.8
|
|
624
|
-
}
|
|
625
|
-
});
|
|
626
|
-
if (config.debug) {
|
|
627
|
-
console.log("Gemini model prompt:", JSON.stringify({ prompt }));
|
|
628
|
-
}
|
|
629
|
-
const response = await model.generateContent([prompt]);
|
|
630
|
-
return response;
|
|
631
|
-
} catch (err) {
|
|
632
|
-
const error = err;
|
|
633
|
-
console.log("Error details from Gemini model", JSON.stringify({ error }, null, 2));
|
|
634
|
-
const retryDelay = error?.errorDetails?.find(
|
|
635
|
-
(detail) => detail?.["@type"] === "type.googleapis.com/google.rpc.RetryInfo"
|
|
636
|
-
)?.retryDelay ?? void 0;
|
|
637
|
-
if (error.status === 429 && retryDelay !== void 0) {
|
|
638
|
-
const sleepTime = config.llm.sleep ?? 3;
|
|
639
|
-
console.warn(
|
|
640
|
-
`Rate limit exceeded when generating response from Gemini model, retrying in... ${retryDelay} + ${sleepTime / 1e3}s`
|
|
641
|
-
);
|
|
642
|
-
await new Promise((resolve2) => setTimeout(resolve2, (parseInt(retryDelay, 10) + sleepTime / 1e3) * 1e3));
|
|
643
|
-
return generateResponse(prompt, config);
|
|
644
|
-
}
|
|
645
|
-
console.error("Error generating response from Gemini model", { error });
|
|
646
|
-
throw error;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
async function askGemini(prompt, prePrompt2, postPrompt2) {
|
|
553
|
+
async function askLLM(prompt, prePrompt2, postPrompt2) {
|
|
650
554
|
const config = await awaitedConfig;
|
|
651
|
-
|
|
652
|
-
|
|
555
|
+
const provider = config.llm.provider;
|
|
556
|
+
const engineName = providerEngineMap[provider];
|
|
557
|
+
if (!engineName) {
|
|
558
|
+
throw new Error(`Unknown LLM provider: ${provider}`);
|
|
653
559
|
}
|
|
654
|
-
if (!config.
|
|
655
|
-
throw new Error(
|
|
560
|
+
if (!config.llm.apiKey) {
|
|
561
|
+
throw new Error(`API key for ${provider} is not configured in llm.apiKey`);
|
|
656
562
|
}
|
|
657
|
-
if (config.
|
|
658
|
-
|
|
563
|
+
if (config.llm.sleep && config.llm.sleep > 0) {
|
|
564
|
+
await new Promise((resolve2) => setTimeout(resolve2, config.llm.sleep));
|
|
659
565
|
}
|
|
660
|
-
const
|
|
566
|
+
const engine = igniteEngine(engineName, {
|
|
567
|
+
apiKey: config.llm.apiKey,
|
|
568
|
+
...config.llm.baseURL ? { baseURL: config.llm.baseURL } : {}
|
|
569
|
+
});
|
|
570
|
+
const fullPrompt = `${prePrompt2}
|
|
661
571
|
|
|
662
572
|
|
|
663
573
|
${prompt}
|
|
664
574
|
|
|
665
575
|
|
|
666
|
-
${postPrompt2}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
if (responseString.startsWith("{") && responseString.endsWith("}")) {
|
|
672
|
-
response = maybeResponse;
|
|
673
|
-
break;
|
|
674
|
-
}
|
|
675
|
-
if (config.debug) {
|
|
676
|
-
console.log("Gemini model response is not valid, contains no JSON:", JSON.stringify({ maybeResponse }));
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
if (config.debug) {
|
|
680
|
-
console.log("Gemini model response:", JSON.stringify({ response }));
|
|
681
|
-
}
|
|
682
|
-
if (!response) {
|
|
683
|
-
throw new Error("Gemini model response is not valid");
|
|
684
|
-
}
|
|
685
|
-
return response;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// src/io/gemini/commit-response.ts
|
|
689
|
-
function commitResponseGemini(response) {
|
|
690
|
-
const result2 = response.response.text();
|
|
691
|
-
return result2;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
// src/io/gemini/parse.ts
|
|
695
|
-
function parseGemini(unparsed) {
|
|
696
|
-
if (typeof unparsed !== "string") {
|
|
697
|
-
throw new Error("CommitResponse should be a string here.");
|
|
698
|
-
}
|
|
699
|
-
const cleaned = unparsed.replace(/```json/g, "").replace(/```/g, "");
|
|
700
|
-
const parsed = JSON.parse(cleaned);
|
|
701
|
-
return parsed;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// src/io/huggingface/languages-map.ts
|
|
705
|
-
var languagesMap = {
|
|
706
|
-
"en-US": "eng_Latn",
|
|
707
|
-
"en-GB": "eng_Latn",
|
|
708
|
-
"pt-BR": "por_Latn",
|
|
709
|
-
"pt-PT": "por_Latn",
|
|
710
|
-
"es-ES": "spa_Latn",
|
|
711
|
-
"es-MX": "spa_Latn",
|
|
712
|
-
"fr-FR": "fra_Latn",
|
|
713
|
-
"fr-CA": "fra_Latn",
|
|
714
|
-
"de-DE": "deu_Latn",
|
|
715
|
-
"it-IT": "ita_Latn",
|
|
716
|
-
"nl-NL": "nld_Latn",
|
|
717
|
-
"pl-PL": "pol_Latn",
|
|
718
|
-
"ru-RU": "rus_Cyrl",
|
|
719
|
-
"uk-UA": "ukr_Cyrl",
|
|
720
|
-
"bg-BG": "bul_Cyrl",
|
|
721
|
-
"hr-HR": "hrv_Latn",
|
|
722
|
-
"cs-CZ": "ces_Latn",
|
|
723
|
-
"sk-SK": "slk_Latn",
|
|
724
|
-
"hu-HU": "hun_Latn",
|
|
725
|
-
"ro-RO": "ron_Latn",
|
|
726
|
-
"fi-FI": "fin_Latn",
|
|
727
|
-
"sv-SE": "swe_Latn",
|
|
728
|
-
"da-DK": "dan_Latn",
|
|
729
|
-
"no-NO": "nob_Latn",
|
|
730
|
-
"is-IS": "isl_Latn",
|
|
731
|
-
"et-EE": "est_Latn",
|
|
732
|
-
"lv-LV": "lav_Latn",
|
|
733
|
-
"lt-LT": "lit_Latn",
|
|
734
|
-
"mt-MT": "mlt_Latn",
|
|
735
|
-
"ga-IE": "gle_Latn",
|
|
736
|
-
"cy-GB": "cym_Latn",
|
|
737
|
-
"eu-ES": "eus_Latn",
|
|
738
|
-
"ca-ES": "cat_Latn",
|
|
739
|
-
"gl-ES": "glg_Latn",
|
|
740
|
-
"oc-FR": "oci_Latn",
|
|
741
|
-
"br-FR": "bre_Latn",
|
|
742
|
-
"gd-GB": "gla_Latn",
|
|
743
|
-
"kw-GB": "cor_Latn",
|
|
744
|
-
"fur-IT": "fur_Latn",
|
|
745
|
-
"rm-CH": "roh_Latn",
|
|
746
|
-
"lb-LU": "ltz_Latn",
|
|
747
|
-
"fy-NL": "fry_Latn",
|
|
748
|
-
"af-ZA": "afr_Latn",
|
|
749
|
-
"zh-CN": "zho_Hans",
|
|
750
|
-
"zh-TW": "zho_Hant",
|
|
751
|
-
"zh-HK": "zho_Hant",
|
|
752
|
-
"ja-JP": "jpn_Jpan",
|
|
753
|
-
"ko-KR": "kor_Hang",
|
|
754
|
-
"th-TH": "tha_Thai",
|
|
755
|
-
"vi-VN": "vie_Latn",
|
|
756
|
-
"id-ID": "ind_Latn",
|
|
757
|
-
"ms-MY": "zsm_Latn",
|
|
758
|
-
"tl-PH": "tgl_Latn",
|
|
759
|
-
"my-MM": "mya_Mymr",
|
|
760
|
-
"km-KH": "khm_Khmr",
|
|
761
|
-
"lo-LA": "lao_Laoo",
|
|
762
|
-
"bn-BD": "ben_Beng",
|
|
763
|
-
"bn-IN": "ben_Beng",
|
|
764
|
-
"hi-IN": "hin_Deva",
|
|
765
|
-
"ur-PK": "urd_Arab",
|
|
766
|
-
"ur-IN": "urd_Arab",
|
|
767
|
-
"pa-IN": "pan_Guru",
|
|
768
|
-
"gu-IN": "guj_Gujr",
|
|
769
|
-
"or-IN": "ory_Orya",
|
|
770
|
-
"as-IN": "asm_Beng",
|
|
771
|
-
"ml-IN": "mal_Mlym",
|
|
772
|
-
"ta-IN": "tam_Tamil",
|
|
773
|
-
"te-IN": "tel_Telu",
|
|
774
|
-
"kn-IN": "kan_Knda",
|
|
775
|
-
"si-LK": "sin_Sinh",
|
|
776
|
-
"ne-NP": "nep_Deva",
|
|
777
|
-
"dz-BT": "dzo_Tibt",
|
|
778
|
-
"bo-CN": "bod_Tibt",
|
|
779
|
-
"mn-MN": "khk_Cyrl",
|
|
780
|
-
"ka-GE": "kat_Geor",
|
|
781
|
-
"hy-AM": "hye_Armn",
|
|
782
|
-
"az-AZ": "azj_Latn",
|
|
783
|
-
"tr-TR": "tur_Latn",
|
|
784
|
-
"fa-IR": "pes_Arab",
|
|
785
|
-
"fa-AF": "pes_Arab",
|
|
786
|
-
"ps-AF": "pbt_Arab",
|
|
787
|
-
"ku-TR": "kmr_Latn",
|
|
788
|
-
"he-IL": "heb_Hebr",
|
|
789
|
-
"ar-SA": "arb_Arab",
|
|
790
|
-
"ar-EG": "arb_Arab",
|
|
791
|
-
"ar-MA": "arb_Arab",
|
|
792
|
-
"ar-DZ": "arb_Arab",
|
|
793
|
-
"ar-TN": "arb_Arab",
|
|
794
|
-
"ar-LY": "arb_Arab",
|
|
795
|
-
"ar-SD": "arb_Arab",
|
|
796
|
-
"ar-IQ": "arb_Arab",
|
|
797
|
-
"ar-SY": "arb_Arab",
|
|
798
|
-
"ar-JO": "arb_Arab",
|
|
799
|
-
"ar-LB": "arb_Arab",
|
|
800
|
-
"ar-KW": "arb_Arab",
|
|
801
|
-
"ar-AE": "arb_Arab",
|
|
802
|
-
"ar-QA": "arb_Arab",
|
|
803
|
-
"ar-BH": "arb_Arab",
|
|
804
|
-
"ar-OM": "arb_Arab",
|
|
805
|
-
"ar-YE": "arb_Arab",
|
|
806
|
-
"ar-SO": "arb_Arab",
|
|
807
|
-
"ar-DJ": "arb_Arab",
|
|
808
|
-
"ar-KM": "arb_Arab",
|
|
809
|
-
"ar-TD": "arb_Arab",
|
|
810
|
-
"ar-ER": "arb_Arab",
|
|
811
|
-
"ar-IL": "arb_Arab",
|
|
812
|
-
"ar-PS": "arb_Arab",
|
|
813
|
-
"ar-001": "arb_Arab",
|
|
814
|
-
"sw-KE": "swh_Latn",
|
|
815
|
-
"sw-TZ": "swh_Latn",
|
|
816
|
-
"am-ET": "amh_Ethi",
|
|
817
|
-
"om-ET": "gaz_Latn",
|
|
818
|
-
"so-SO": "som_Latn",
|
|
819
|
-
"ha-NG": "hau_Latn",
|
|
820
|
-
"yo-NG": "yor_Latn",
|
|
821
|
-
"ig-NG": "ibo_Latn",
|
|
822
|
-
"zu-ZA": "zul_Latn",
|
|
823
|
-
"xh-ZA": "xho_Latn",
|
|
824
|
-
"rw-RW": "kin_Latn",
|
|
825
|
-
"lg-UG": "lug_Latn",
|
|
826
|
-
"ak-GH": "aka_Latn",
|
|
827
|
-
"tw-GH": "twi_Latn",
|
|
828
|
-
"ee-GH": "ewe_Latn",
|
|
829
|
-
"ff-SN": "fuv_Latn",
|
|
830
|
-
"wo-SN": "wol_Latn",
|
|
831
|
-
"sn-ZW": "sna_Latn",
|
|
832
|
-
"nd-ZW": "nde_Latn",
|
|
833
|
-
"ny-MW": "nya_Latn",
|
|
834
|
-
"st-ZA": "sot_Latn",
|
|
835
|
-
"tn-BW": "tsn_Latn",
|
|
836
|
-
"ts-ZA": "tso_Latn",
|
|
837
|
-
"ve-ZA": "ven_Latn",
|
|
838
|
-
"ss-ZA": "ssw_Latn",
|
|
839
|
-
"nr-ZA": "nbl_Latn",
|
|
840
|
-
"qu-PE": "quy_Latn",
|
|
841
|
-
"qu-BO": "quy_Latn",
|
|
842
|
-
"qu-EC": "quy_Latn",
|
|
843
|
-
"ay-BO": "aym_Latn",
|
|
844
|
-
"gn-PY": "grn_Latn",
|
|
845
|
-
"ht-HT": "hat_Latn",
|
|
846
|
-
"jv-ID": "jav_Latn",
|
|
847
|
-
"su-ID": "sun_Latn",
|
|
848
|
-
"ceb-PH": "ceb_Latn",
|
|
849
|
-
"ilo-PH": "ilo_Latn",
|
|
850
|
-
"war-PH": "war_Latn",
|
|
851
|
-
"bjn-ID": "bjn_Latn",
|
|
852
|
-
"ban-ID": "ban_Latn",
|
|
853
|
-
"mad-ID": "mad_Latn",
|
|
854
|
-
"min-ID": "min_Latn",
|
|
855
|
-
"ace-ID": "ace_Latn",
|
|
856
|
-
"bug-ID": "bug_Latn",
|
|
857
|
-
"gor-ID": "gor_Latn",
|
|
858
|
-
"mak-ID": "mak_Latn",
|
|
859
|
-
"mdr-ID": "mdr_Latn",
|
|
860
|
-
"sas-ID": "sas_Latn",
|
|
861
|
-
"shn-MM": "shn_Mymr",
|
|
862
|
-
"kac-MM": "kac_Latn",
|
|
863
|
-
"lzh-CN": "lzh_Hant",
|
|
864
|
-
"wuu-CN": "wuu_Hans",
|
|
865
|
-
"yue-CN": "yue_Hant",
|
|
866
|
-
"nan-TW": "nan_Hant",
|
|
867
|
-
"hak-TW": "hak_Hant",
|
|
868
|
-
"cjy-CN": "cjy_Hans",
|
|
869
|
-
"cmn-CN": "cmn_Hans",
|
|
870
|
-
"cmn-TW": "cmn_Hant",
|
|
871
|
-
"cmn-SG": "cmn_Hans",
|
|
872
|
-
"cmn-HK": "cmn_Hant",
|
|
873
|
-
"cmn-MO": "cmn_Hant",
|
|
874
|
-
"cmn-001": "cmn_Hans",
|
|
875
|
-
"haw-US": "haw_Latn",
|
|
876
|
-
"mi-NZ": "mri_Latn",
|
|
877
|
-
"sm-WS": "smo_Latn",
|
|
878
|
-
"to-TO": "ton_Latn",
|
|
879
|
-
"fj-FJ": "fij_Latn",
|
|
880
|
-
"ty-PF": "tah_Latn",
|
|
881
|
-
"co-FR": "cos_Latn",
|
|
882
|
-
"eu-FR": "eus_Latn",
|
|
883
|
-
"kk-KZ": "kaz_Cyrl",
|
|
884
|
-
"ky-KG": "kir_Cyrl",
|
|
885
|
-
"uz-UZ": "uzn_Latn",
|
|
886
|
-
"tg-TJ": "tgk_Cyrl",
|
|
887
|
-
"tk-TM": "tuk_Latn"
|
|
888
|
-
};
|
|
889
|
-
|
|
890
|
-
// src/io/huggingface/ask.ts
|
|
891
|
-
function getLanguageCode(language) {
|
|
892
|
-
return languagesMap[language];
|
|
893
|
-
}
|
|
894
|
-
function progressCallback(progress) {
|
|
895
|
-
process.stdout.clearLine(0);
|
|
896
|
-
process.stdout.cursorTo(0);
|
|
897
|
-
if (progress.status === "download") {
|
|
898
|
-
process.stdout.write("Downloading...");
|
|
899
|
-
} else if (progress.status === "initiate") {
|
|
900
|
-
process.stdout.write("Initializing...");
|
|
901
|
-
} else if (progress.status === "done") {
|
|
902
|
-
process.stdout.write("Done!");
|
|
903
|
-
} else if (progress.status === "progress" && "progress" in progress && "loaded" in progress && "total" in progress) {
|
|
904
|
-
process.stdout.write(
|
|
905
|
-
`Downloading: ${Number(progress.progress).toFixed(2)}%, loaded: ${progress.loaded}/${progress.total}`
|
|
906
|
-
);
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
async function pipeLanguage(pipe, original, srcLanguage, targetLanguage) {
|
|
910
|
-
const response = await pipe(original, {
|
|
911
|
-
src_lang: srcLanguage,
|
|
912
|
-
tgt_lang: targetLanguage,
|
|
913
|
-
temperature: 1
|
|
576
|
+
${postPrompt2}`.trim();
|
|
577
|
+
const messages = [new Message("user", fullPrompt)];
|
|
578
|
+
const model = config.llm.model ?? "gpt-4o-mini";
|
|
579
|
+
const response = await engine.complete(engine.buildModel(model), messages, {
|
|
580
|
+
temperature: config.llm.temperature
|
|
914
581
|
});
|
|
915
|
-
|
|
916
|
-
}
|
|
917
|
-
async function askHuggingface(original) {
|
|
918
|
-
const config = await awaitedConfig;
|
|
919
|
-
const cacheDir = `${config.cache.dir}/.cache`;
|
|
920
|
-
env.cacheDir = cacheDir;
|
|
921
|
-
const pipe = await pipeline("translation", config.llm.model, {
|
|
922
|
-
progress_callback: progressCallback,
|
|
923
|
-
cache_dir: cacheDir
|
|
924
|
-
});
|
|
925
|
-
const { languages } = config;
|
|
926
|
-
let responses = [];
|
|
927
|
-
for await (const language of languages) {
|
|
928
|
-
const response = await pipeLanguage(
|
|
929
|
-
pipe,
|
|
930
|
-
original,
|
|
931
|
-
getLanguageCode(config.sourceLanguage),
|
|
932
|
-
getLanguageCode(language)
|
|
933
|
-
);
|
|
934
|
-
if (Array.isArray(response)) {
|
|
935
|
-
responses = responses.concat(
|
|
936
|
-
response.map((r) => ({
|
|
937
|
-
...r,
|
|
938
|
-
targetLanguage: language
|
|
939
|
-
}))
|
|
940
|
-
);
|
|
941
|
-
} else {
|
|
942
|
-
responses.push({
|
|
943
|
-
...response,
|
|
944
|
-
targetLanguage: language
|
|
945
|
-
});
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
return { responses, original };
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
// src/io/huggingface/commit-response.ts
|
|
952
|
-
function commitResponseHuggingface(response) {
|
|
953
|
-
const { responses, original } = response;
|
|
954
|
-
const translation = responses.reduce((acc, curr) => {
|
|
955
|
-
acc[curr.targetLanguage] = curr.translation_text;
|
|
956
|
-
return acc;
|
|
957
|
-
}, {});
|
|
958
|
-
return {
|
|
959
|
-
translation,
|
|
960
|
-
original
|
|
961
|
-
};
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
// src/io/huggingface/parse.ts
|
|
965
|
-
function parseHuggingface(unparsed) {
|
|
966
|
-
if (typeof unparsed === "string") {
|
|
967
|
-
throw new Error("CommitResponse should not be a string here.");
|
|
968
|
-
}
|
|
969
|
-
return unparsed;
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
// src/io/ask-llm.ts
|
|
973
|
-
var llmChoices = {
|
|
974
|
-
anthropic: {
|
|
975
|
-
ask: askAnthropic,
|
|
976
|
-
commitResponse: commitResponseAnthropic,
|
|
977
|
-
parse: parseAnthropic
|
|
978
|
-
},
|
|
979
|
-
gemini: {
|
|
980
|
-
ask: askGemini,
|
|
981
|
-
commitResponse: commitResponseGemini,
|
|
982
|
-
parse: parseGemini
|
|
983
|
-
},
|
|
984
|
-
huggingface: {
|
|
985
|
-
ask: askHuggingface,
|
|
986
|
-
commitResponse: commitResponseHuggingface,
|
|
987
|
-
parse: parseHuggingface
|
|
582
|
+
if (config.debug) {
|
|
583
|
+
console.log("LLM response:", JSON.stringify({ provider, model: config.llm.model, response: response.content }));
|
|
988
584
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
const response = await llmChoice.ask(prompt, prePrompt2, postPrompt2);
|
|
992
|
-
const unparsed = llmChoice.commitResponse(response);
|
|
993
|
-
const parsed = llmChoice.parse(unparsed);
|
|
994
|
-
return parsed;
|
|
995
|
-
}
|
|
996
|
-
async function askLLM(prompt, prePrompt2, postPrompt2) {
|
|
997
|
-
const config = await awaitedConfig;
|
|
998
|
-
const llmChoiceName = config.llm.choice;
|
|
999
|
-
const llmChoice = llmChoices[llmChoiceName];
|
|
1000
|
-
if (!llmChoice) {
|
|
1001
|
-
throw new Error("LLMChoice not found");
|
|
585
|
+
if (!response.content) {
|
|
586
|
+
throw new Error("LLM response content is empty");
|
|
1002
587
|
}
|
|
1003
|
-
return
|
|
588
|
+
return parseResponse(response.content);
|
|
1004
589
|
}
|
|
1005
590
|
|
|
1006
591
|
// src/gringow.ts
|
|
@@ -1018,6 +603,10 @@ async function rebuild(cacheId) {
|
|
|
1018
603
|
const cached = await checkCache(cacheId);
|
|
1019
604
|
if (!cached) throw new Error("Cache item not found");
|
|
1020
605
|
const { prepend, append } = getPrependAndAppend(config, cached);
|
|
606
|
+
if (config.debug) {
|
|
607
|
+
console.log(`rebuild::prepend ${cacheId}:`, { prepend });
|
|
608
|
+
console.log(`rebuild::append ${cacheId}:`, { append });
|
|
609
|
+
}
|
|
1021
610
|
const translation = await askLLM(cached.original, prepend, append);
|
|
1022
611
|
const output = {
|
|
1023
612
|
...translation,
|
|
@@ -1043,6 +632,10 @@ async function Gringow(strings, ...values) {
|
|
|
1043
632
|
return { cacheId, translation: cached };
|
|
1044
633
|
}
|
|
1045
634
|
const { prepend, append } = getPrependAndAppend(config, cached);
|
|
635
|
+
if (config.debug) {
|
|
636
|
+
console.log(`asking::prepend ${cacheId}:`, { prepend });
|
|
637
|
+
console.log(`asking::append ${cacheId}:`, { append });
|
|
638
|
+
}
|
|
1046
639
|
const translation = await askLLM(flatten, prepend, append);
|
|
1047
640
|
const output = {
|
|
1048
641
|
...translation,
|
package/dist/io/ask-llm.d.mts
CHANGED
|
@@ -9,9 +9,11 @@ import '../data/get-cache.mjs';
|
|
|
9
9
|
import '../flat-template-string.mjs';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Asks an LLM for a response.
|
|
12
|
+
* Asks an LLM for a response using multi-llm-ts.
|
|
13
13
|
*
|
|
14
14
|
* @param prompt - The prompt to ask the model.
|
|
15
|
+
* @param prePrompt - The pre-prompt to prepend.
|
|
16
|
+
* @param postPrompt - The post-prompt to append.
|
|
15
17
|
* @returns The parsed response.
|
|
16
18
|
*/
|
|
17
19
|
declare function askLLM(prompt: string, prePrompt: string, postPrompt: string): Promise<GringowCacheItem>;
|