Files
LingvAI/utils/replicate-translate.ts

84 lines
2.5 KiB
TypeScript
Raw Normal View History

import { readSettings } from "./settings-store";
type ReplicateOutput = string | string[] | { translation?: string; translated_text?: string; output?: string };
export async function replicateTranslate(
text: string,
targetLanguage: string
): Promise<string> {
const settings = readSettings();
if (!settings.replicateApiToken) {
throw new Error("Replicate API token not configured");
}
if (!settings.jigsawApiKey) {
throw new Error("JigsawStack API key not configured");
}
const body = {
version: settings.modelVersion,
input: {
text,
api_key: settings.jigsawApiKey,
target_language: targetLanguage
}
};
const response = await fetch("https://api.replicate.com/v1/predictions", {
method: "POST",
headers: {
"Authorization": `Bearer ${settings.replicateApiToken}`,
"Content-Type": "application/json",
"Prefer": "wait"
},
body: JSON.stringify(body)
});
if (!response.ok) {
const err = await response.text();
throw new Error(`Replicate API error: ${response.status} ${err}`);
}
const data = await response.json();
if (data.error) {
throw new Error(`Replicate model error: ${data.error}`);
}
// Extract translated text from various output formats
const output: ReplicateOutput = data.output;
if (typeof output === "string") return output;
if (Array.isArray(output)) return output.join("");
if (output && typeof output === "object") {
return output.translation ?? output.translated_text ?? output.output ?? String(output);
}
throw new Error("Unexpected output format from Replicate");
}
// Batch translate using separator trick to minimize API calls
const SEPARATOR = "\n{{SEP}}\n";
export async function replicateTranslateBatch(
texts: string[],
targetLanguage: string
): Promise<string[]> {
if (texts.length === 0) return [];
if (texts.length === 1) {
return [await replicateTranslate(texts[0], targetLanguage)];
}
const joined = texts.join(SEPARATOR);
const translated = await replicateTranslate(joined, targetLanguage);
// Try to split on the separator; fall back to individual calls if it got translated
const parts = translated.split(SEPARATOR);
if (parts.length === texts.length) {
return parts;
}
// Fallback: translate individually
return Promise.all(texts.map(t => replicateTranslate(t, targetLanguage)));
}