@tiens.nguyen/gonext-local-worker 1.0.217 → 1.0.219
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/gonext-local-worker.mjs +54 -18
- package/package.json +1 -1
package/gonext-local-worker.mjs
CHANGED
|
@@ -1229,11 +1229,44 @@ function normalizeCorrection(raw, originalText) {
|
|
|
1229
1229
|
* correction/translation, e.g. base "https://ollama1.gomarsic.cc" model "qwen3:14b".
|
|
1230
1230
|
* `think:false` suppresses reasoning models' <think> preamble so we get clean text.
|
|
1231
1231
|
*/
|
|
1232
|
+
const OCR_CORRECT_SYSTEM_PROMPT =
|
|
1233
|
+
"You are a text correction assistant. Fix grammar and language errors in the " +
|
|
1234
|
+
"provided text while preserving the original meaning and language. " +
|
|
1235
|
+
"Return only the corrected text without any explanation.";
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Call an OpenAI-compatible chat endpoint (POST {base}/v1/chat/completions) for text
|
|
1239
|
+
* correction — e.g. an MLX `mlx_lm.server` (the agent model server) at
|
|
1240
|
+
* http://127.0.0.1:8080/v1 serving qwen3:14b. Strips any <think> preamble.
|
|
1241
|
+
*/
|
|
1242
|
+
async function correctOcrTextViaOpenAI(extractedText, base, model) {
|
|
1243
|
+
const b = base.replace(/\/+$/, "");
|
|
1244
|
+
const url = /\/v1$/.test(b) ? `${b}/chat/completions` : `${b}/v1/chat/completions`;
|
|
1245
|
+
const res = await fetch(url, {
|
|
1246
|
+
method: "POST",
|
|
1247
|
+
headers: { "Content-Type": "application/json" },
|
|
1248
|
+
body: JSON.stringify({
|
|
1249
|
+
model,
|
|
1250
|
+
stream: false,
|
|
1251
|
+
temperature: 0,
|
|
1252
|
+
messages: [
|
|
1253
|
+
{ role: "system", content: OCR_CORRECT_SYSTEM_PROMPT },
|
|
1254
|
+
{ role: "user", content: `Text:\n${extractedText}` },
|
|
1255
|
+
],
|
|
1256
|
+
}),
|
|
1257
|
+
signal: AbortSignal.timeout(OCR_CORRECT_TIMEOUT_MS),
|
|
1258
|
+
});
|
|
1259
|
+
if (!res.ok) {
|
|
1260
|
+
throw new Error(`MLX ${b} returned ${res.status}`);
|
|
1261
|
+
}
|
|
1262
|
+
const json = await res.json();
|
|
1263
|
+
let corrected = json?.choices?.[0]?.message?.content?.trim() || "";
|
|
1264
|
+
corrected = corrected.replace(/<think>[\s\S]*?<\/think>/gi, "").trim();
|
|
1265
|
+
return normalizeCorrection(corrected, extractedText);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1232
1268
|
async function correctOcrTextViaOllama(extractedText, base, model) {
|
|
1233
|
-
const systemPrompt =
|
|
1234
|
-
"You are a text correction assistant. Fix grammar and language errors in the " +
|
|
1235
|
-
"provided text while preserving the original meaning and language. " +
|
|
1236
|
-
"Return only the corrected text without any explanation.";
|
|
1269
|
+
const systemPrompt = OCR_CORRECT_SYSTEM_PROMPT;
|
|
1237
1270
|
const res = await fetch(`${base.replace(/\/+$/, "")}/api/chat`, {
|
|
1238
1271
|
method: "POST",
|
|
1239
1272
|
headers: { "Content-Type": "application/json" },
|
|
@@ -1260,24 +1293,27 @@ async function correctOcrTextViaOllama(extractedText, base, model) {
|
|
|
1260
1293
|
return normalizeCorrection(corrected, extractedText);
|
|
1261
1294
|
}
|
|
1262
1295
|
|
|
1263
|
-
async function correctOcrText(extractedText) {
|
|
1296
|
+
async function correctOcrText(extractedText, correction) {
|
|
1264
1297
|
if (OCR_SKIP_CORRECTION) {
|
|
1265
1298
|
console.log("[gonext-worker] OCR correction skipped (GONEXT_OCR_SKIP_CORRECTION=1)");
|
|
1266
1299
|
return extractedText;
|
|
1267
1300
|
}
|
|
1268
1301
|
|
|
1269
|
-
//
|
|
1270
|
-
//
|
|
1302
|
+
// The API resolves the backend from the user's settings and bakes {backend,url,model}
|
|
1303
|
+
// into the job payload — DEFAULT is "mlx" (the agent MLX model server, OpenAI /v1).
|
|
1304
|
+
// Absent (older jobs / no settings) → fall back to the legacy managed-Ollama default.
|
|
1305
|
+
const backend = correction?.backend === "mlx" ? "mlx" : "ollama";
|
|
1306
|
+
const url = (correction?.url || "").trim() || OCR_TRANSLATE_OLLAMA_URL;
|
|
1307
|
+
const model = (correction?.model || "").trim() || OCR_TRANSLATE_OLLAMA_MODEL;
|
|
1271
1308
|
console.log(
|
|
1272
|
-
`[gonext-worker] OCR correction via
|
|
1309
|
+
`[gonext-worker] OCR correction via ${backend} ${url} model=${model}`
|
|
1273
1310
|
);
|
|
1274
1311
|
console.log(`[gonext-worker] OCR correction input: ${extractedText.slice(0, 300)}`);
|
|
1275
1312
|
try {
|
|
1276
|
-
const corrected =
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
);
|
|
1313
|
+
const corrected =
|
|
1314
|
+
backend === "mlx"
|
|
1315
|
+
? await correctOcrTextViaOpenAI(extractedText, url, model)
|
|
1316
|
+
: await correctOcrTextViaOllama(extractedText, url, model);
|
|
1281
1317
|
console.log(`[gonext-worker] OCR correction output: ${corrected.slice(0, 300)}`);
|
|
1282
1318
|
console.log(
|
|
1283
1319
|
`[gonext-worker] OCR correction done: ${extractedText.length} → ${corrected.length} chars`
|
|
@@ -1286,7 +1322,7 @@ async function correctOcrText(extractedText) {
|
|
|
1286
1322
|
} catch (e) {
|
|
1287
1323
|
const msg = e instanceof Error ? e.message : String(e);
|
|
1288
1324
|
console.warn(
|
|
1289
|
-
`[gonext-worker] OCR correction
|
|
1325
|
+
`[gonext-worker] OCR correction (${backend}) failed (using raw OCR text): ${msg.slice(0, 200)}`
|
|
1290
1326
|
);
|
|
1291
1327
|
return extractedText;
|
|
1292
1328
|
}
|
|
@@ -1434,10 +1470,10 @@ async function runOcrJob(job) {
|
|
|
1434
1470
|
} finally {
|
|
1435
1471
|
await rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
|
1436
1472
|
}
|
|
1437
|
-
// Post-process: correct grammar/language via the
|
|
1438
|
-
//
|
|
1439
|
-
//
|
|
1440
|
-
extractedText = await correctOcrText(extractedText);
|
|
1473
|
+
// Post-process: correct grammar/language via the backend the API resolved from the
|
|
1474
|
+
// user's settings (payload.correction = {backend,url,model}; default MLX = the agent
|
|
1475
|
+
// model server). Falls back to raw OCR text on any error so the job never fails here.
|
|
1476
|
+
extractedText = await correctOcrText(extractedText, payload.correction);
|
|
1441
1477
|
const totalTimeSeconds = (Date.now() - start) / 1000;
|
|
1442
1478
|
const doneRes = await workerFetch(`/api/worker/jobs/${jobId}`, {
|
|
1443
1479
|
method: "PATCH",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiens.nguyen/gonext-local-worker",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.219",
|
|
4
4
|
"description": "Polls GoNext cloud API for async local LLM jobs and runs them against Ollama/OpenAI-compatible servers on this Mac",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|