79 lines
2.4 KiB
JavaScript
79 lines
2.4 KiB
JavaScript
const OLLAMA_API_URL = process.env.OLLAMA_API_URL;
|
|
const OLLAMA_API_KEY = process.env.OLLAMA_API_KEY;
|
|
|
|
async function sleep(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
// Utility: strip markdown artifacts
|
|
function cleanText(str) {
|
|
return str
|
|
.replace(/^#+\s*/gm, "") // remove headers
|
|
.replace(/\*\*(.*?)\*\*/g, "$1") // remove bold
|
|
.replace(/[*_`]/g, "") // remove stray formatting
|
|
.replace(/\s+/g, " ") // normalize whitespace
|
|
.trim();
|
|
}
|
|
|
|
export async function callOllama(prompt, model = "gemma3n:e4b", retries = 5, stepName = "unknown") {
|
|
const isUsingOpenWebUI = !!OLLAMA_API_KEY;
|
|
|
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
try {
|
|
const promptCharCount = prompt.length;
|
|
const promptWordCount = prompt.split(/\s+/).length;
|
|
|
|
console.log(`\n[${stepName}] Sending prompt (attempt ${attempt}/${retries})`);
|
|
console.log(`Prompt: ${promptCharCount} chars, ~${promptWordCount} words`);
|
|
|
|
const headers = { "Content-Type": "application/json" };
|
|
|
|
if (isUsingOpenWebUI) {
|
|
headers["Authorization"] = `Bearer ${OLLAMA_API_KEY}`;
|
|
}
|
|
|
|
const body = isUsingOpenWebUI
|
|
? {
|
|
model,
|
|
messages: [{ role: "user", content: prompt }],
|
|
}
|
|
: {
|
|
model,
|
|
messages: [{ role: "user", content: prompt }],
|
|
stream: false,
|
|
};
|
|
|
|
const response = await fetch(OLLAMA_API_URL, {
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify(body),
|
|
});
|
|
|
|
if (!response.ok) throw new Error(`Ollama request failed: ${response.status} ${response.statusText}`);
|
|
|
|
const data = await response.json();
|
|
|
|
const rawText = isUsingOpenWebUI
|
|
? data.choices?.[0]?.message?.content
|
|
: data.message?.content;
|
|
|
|
if (!rawText) throw new Error("No response from Ollama");
|
|
|
|
const cleaned = cleanText(rawText);
|
|
|
|
console.log(`[${stepName}] Received: ${rawText.length} chars, ~${rawText.split(/\s+/).length} words`);
|
|
// console.log(`Raw output:\n${rawText}\n`);
|
|
// console.log(`Cleaned output:\n${cleaned}\n`);
|
|
|
|
return cleaned;
|
|
|
|
} catch (err) {
|
|
console.warn(`[${stepName}] Attempt ${attempt} failed: ${err.message}`);
|
|
if (attempt === retries) throw err;
|
|
const delay = 1000 * Math.pow(2, attempt) + Math.random() * 500;
|
|
console.log(`Retrying in ${Math.round(delay / 1000)}s...`);
|
|
await sleep(delay);
|
|
}
|
|
}
|
|
}
|