@runnerpro/backend 1.22.2 → 1.22.4
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/lib/cjs/prompt/ai.js
CHANGED
|
@@ -260,6 +260,64 @@ function generateObject(options) {
|
|
|
260
260
|
});
|
|
261
261
|
}
|
|
262
262
|
exports.generateObject = generateObject;
|
|
263
|
+
// Tope por cadena al derivar la firma de unos `messages`. Existe por las llamadas multimodales
|
|
264
|
+
// (analizar-foto manda una imagen en base64 de hasta 10 MB): sin él, cada foto metería megas en la
|
|
265
|
+
// clave y en la columna INPUT PROMPT. Dos payloads enormes que compartan los primeros 4000
|
|
266
|
+
// caracteres caerían en la misma fila, pero el ON CONFLICT acumula, así que el coste total sigue
|
|
267
|
+
// siendo correcto: solo se pierde granularidad.
|
|
268
|
+
const TEXT_SIG_MAX_CHARS = 4000;
|
|
269
|
+
/**
|
|
270
|
+
* Deriva el texto que identifica una llamada de `generateText`.
|
|
271
|
+
*
|
|
272
|
+
* El SDK admite `prompt` (string) o `messages` (array). Sin cubrir el segundo caso, todas las
|
|
273
|
+
* llamadas con `messages` compartirían system+prompt indefinidos y colapsarían en UNA sola fila.
|
|
274
|
+
*/
|
|
275
|
+
function textPromptSignature(options) {
|
|
276
|
+
if (typeof (options === null || options === void 0 ? void 0 : options.prompt) === 'string')
|
|
277
|
+
return options.prompt;
|
|
278
|
+
if (!Array.isArray(options === null || options === void 0 ? void 0 : options.messages))
|
|
279
|
+
return undefined;
|
|
280
|
+
try {
|
|
281
|
+
return JSON.stringify(options.messages, (_k, v) => typeof v === 'string' && v.length > TEXT_SIG_MAX_CHARS ? `${v.slice(0, TEXT_SIG_MAX_CHARS)}…(${v.length})` : v);
|
|
282
|
+
}
|
|
283
|
+
catch (_a) {
|
|
284
|
+
return undefined;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Registra en "LLM CACHE" el coste de una llamada de `generateText`.
|
|
289
|
+
*
|
|
290
|
+
* REGISTRO, NO CACHÉ: no hay `lookup` previo y nunca se reutiliza el texto guardado. Cachear
|
|
291
|
+
* `generateText` daría a dos clientes con el mismo contexto la misma respuesta literal, que en el
|
|
292
|
+
* chat del entrenador es inaceptable. La fila existe solo para saber qué modelo respondió y cuánto
|
|
293
|
+
* costó; usa TEXT_CALL_SIG para no compartir espacio de claves con `generateObject`.
|
|
294
|
+
*
|
|
295
|
+
* Se anota el coste YA saneado, que incluye el retry anti-CoT y el sanitizer LITE si llegaron a
|
|
296
|
+
* correr. Ojo con la atribución: el gasto es el total real de la llamada lógica, pero la columna
|
|
297
|
+
* MODEL guarda el modelo principal, así que si intervino el sanitizer parte de ese coste es de LITE.
|
|
298
|
+
*
|
|
299
|
+
* Opt-out con `options.log === false`. Fire-and-forget: nunca bloquea ni rompe la llamada.
|
|
300
|
+
*/
|
|
301
|
+
function logTextCost(options, modelName, result) {
|
|
302
|
+
if ((options === null || options === void 0 ? void 0 : options.log) === false)
|
|
303
|
+
return;
|
|
304
|
+
try {
|
|
305
|
+
const prompt = textPromptSignature(options);
|
|
306
|
+
const key = (0, llmCacheStore_1.llmCacheKey)({ system: options === null || options === void 0 ? void 0 : options.system, prompt, schemaSig: llmCacheStore_1.TEXT_CALL_SIG, temperature: options === null || options === void 0 ? void 0 : options.temperature });
|
|
307
|
+
(0, llmCacheStore_1.store)(key, {
|
|
308
|
+
modelName,
|
|
309
|
+
system: options === null || options === void 0 ? void 0 : options.system,
|
|
310
|
+
prompt,
|
|
311
|
+
schemaSig: llmCacheStore_1.TEXT_CALL_SIG,
|
|
312
|
+
temperature: options === null || options === void 0 ? void 0 : options.temperature,
|
|
313
|
+
output: result.text,
|
|
314
|
+
cost: result.cost,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
catch (_a) {
|
|
318
|
+
// best-effort: registrar el coste jamás debe tumbar una generación válida
|
|
319
|
+
}
|
|
320
|
+
}
|
|
263
321
|
/**
|
|
264
322
|
* Wrapper de generateText con retry automático, cadena de fallbacks y saneamiento
|
|
265
323
|
* de chain-of-thought.
|
|
@@ -304,6 +362,7 @@ function generateText(options) {
|
|
|
304
362
|
const tracker = costTrackingStorage.getStore();
|
|
305
363
|
if (tracker)
|
|
306
364
|
tracker.push(cleanResult.cost);
|
|
365
|
+
logTextCost(currentOptions, modelName, cleanResult);
|
|
307
366
|
return cleanResult;
|
|
308
367
|
}
|
|
309
368
|
catch (error) {
|
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.store = exports.lookup = exports.llmCacheKey = exports.schemaSignature = void 0;
|
|
12
|
+
exports.TEXT_CALL_SIG = exports.store = exports.lookup = exports.llmCacheKey = exports.schemaSignature = void 0;
|
|
13
13
|
/**
|
|
14
14
|
* Caché LLM (cache-aside) para `generateObject`.
|
|
15
15
|
*
|
|
@@ -39,6 +39,13 @@ function ensureReady() {
|
|
|
39
39
|
return _ready;
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Firma reservada para las llamadas de `generateText`, que se registran por su coste pero NUNCA
|
|
44
|
+
* se cachean. Al ocupar su propio espacio de claves, una fila de texto no puede ser devuelta por
|
|
45
|
+
* el `lookup` de `generateObject` aunque coincidan system, prompt y temperatura.
|
|
46
|
+
*/
|
|
47
|
+
const TEXT_CALL_SIG = '__text__';
|
|
48
|
+
exports.TEXT_CALL_SIG = TEXT_CALL_SIG;
|
|
42
49
|
/** Firma ligera del schema (zod) para distinguir llamadas con el mismo prompt pero distinta forma. */
|
|
43
50
|
function schemaSignature(schema) {
|
|
44
51
|
var _a, _b;
|
|
@@ -73,13 +80,19 @@ function llmCacheKey(opts) {
|
|
|
73
80
|
return (0, node_crypto_1.createHash)('sha256').update(payload).digest('hex');
|
|
74
81
|
}
|
|
75
82
|
exports.llmCacheKey = llmCacheKey;
|
|
76
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* HIT: incrementa USE COUNT + LAST USED y devuelve OUTPUT (atómico). null en MISS o ante error.
|
|
85
|
+
*
|
|
86
|
+
* El filtro `"OUTPUT" IS NOT NULL` excluye las filas podadas (la poda vacía los textos pero
|
|
87
|
+
* conserva la fila por su coste). Sin él, una fila podada contaría como uso e inflaría USE COUNT,
|
|
88
|
+
* blindándola contra futuras podas pese a no servir ya de caché.
|
|
89
|
+
*/
|
|
77
90
|
function lookup(key) {
|
|
78
91
|
return __awaiter(this, void 0, void 0, function* () {
|
|
79
92
|
if (!(yield ensureReady()))
|
|
80
93
|
return null;
|
|
81
94
|
try {
|
|
82
|
-
const rows = yield (0, db_1.query)('UPDATE "LLM CACHE" SET "USE COUNT" = "USE COUNT" + 1, "LAST USED AT" = now() WHERE "KEY" = ? RETURNING "OUTPUT"', [key]);
|
|
95
|
+
const rows = yield (0, db_1.query)('UPDATE "LLM CACHE" SET "USE COUNT" = "USE COUNT" + 1, "LAST USED AT" = now() WHERE "KEY" = ? AND "OUTPUT" IS NOT NULL RETURNING "OUTPUT"', [key]);
|
|
83
96
|
return rows && rows[0] ? rows[0].output : null;
|
|
84
97
|
}
|
|
85
98
|
catch (_a) {
|
|
@@ -89,11 +102,13 @@ function lookup(key) {
|
|
|
89
102
|
}
|
|
90
103
|
exports.lookup = lookup;
|
|
91
104
|
/**
|
|
92
|
-
* MISS: inserta (ON CONFLICT cubre la carrera
|
|
105
|
+
* MISS: inserta (ON CONFLICT cubre la carrera y la regeneración de una fila podada).
|
|
106
|
+
* Fire-and-forget, nunca lanza.
|
|
93
107
|
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
108
|
+
* Solo se llama tras una generación REAL (un HIT no cuesta nada y no pasa por aquí), así que el
|
|
109
|
+
* ON CONFLICT ACUMULA tokens y coste en vez de descartarlos: si el mismo prompt se regenera —por
|
|
110
|
+
* una carrera, o porque la poda vació sus textos— ese gasto es real y debe sumarse. Restaura
|
|
111
|
+
* además los textos, devolviendo a la fila podada su capacidad de servir como caché.
|
|
97
112
|
*/
|
|
98
113
|
function store(key, data) {
|
|
99
114
|
void ensureReady()
|
|
@@ -101,7 +116,19 @@ function store(key, data) {
|
|
|
101
116
|
var _a, _b, _c, _d, _e, _f;
|
|
102
117
|
if (!ok)
|
|
103
118
|
return undefined;
|
|
104
|
-
return (0, db_1.query)(
|
|
119
|
+
return (0, db_1.query)(`INSERT INTO "LLM CACHE" ("KEY","MODEL","SYSTEM PROMPT","INPUT PROMPT","SCHEMA SIG","TEMPERATURE","OUTPUT","INPUT TOKENS","OUTPUT TOKENS","INPUT COST","OUTPUT COST")
|
|
120
|
+
VALUES (?,?,?,?,?,?,?::jsonb,?,?,?,?)
|
|
121
|
+
ON CONFLICT ("KEY") DO UPDATE SET
|
|
122
|
+
"USE COUNT" = "LLM CACHE"."USE COUNT" + 1,
|
|
123
|
+
"LAST USED AT" = now(),
|
|
124
|
+
"MODEL" = EXCLUDED."MODEL",
|
|
125
|
+
"SYSTEM PROMPT" = EXCLUDED."SYSTEM PROMPT",
|
|
126
|
+
"INPUT PROMPT" = EXCLUDED."INPUT PROMPT",
|
|
127
|
+
"OUTPUT" = EXCLUDED."OUTPUT",
|
|
128
|
+
"INPUT TOKENS" = "LLM CACHE"."INPUT TOKENS" + EXCLUDED."INPUT TOKENS",
|
|
129
|
+
"OUTPUT TOKENS" = "LLM CACHE"."OUTPUT TOKENS" + EXCLUDED."OUTPUT TOKENS",
|
|
130
|
+
"INPUT COST" = "LLM CACHE"."INPUT COST" + EXCLUDED."INPUT COST",
|
|
131
|
+
"OUTPUT COST" = "LLM CACHE"."OUTPUT COST" + EXCLUDED."OUTPUT COST"`, [
|
|
105
132
|
key,
|
|
106
133
|
data.modelName || null,
|
|
107
134
|
data.system || null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../src/prompt/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,IAAI,sBAAsB,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,IAAI,CAAC;AAEpG,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAwKhE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,iBAAe,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAoD/H;
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../../src/prompt/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,IAAI,sBAAsB,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,IAAI,CAAC;AAEpG,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAwKhE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,iBAAe,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAoD/H;AA4DD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,iBAAe,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CA4C5H;AA+ED;;;;;;;;;;;;;;;;;GAiBG;AACH,iBAAe,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,SAAS,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgB5H;AAED,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { CostResult } from './modelPricing';
|
|
2
|
+
/**
|
|
3
|
+
* Firma reservada para las llamadas de `generateText`, que se registran por su coste pero NUNCA
|
|
4
|
+
* se cachean. Al ocupar su propio espacio de claves, una fila de texto no puede ser devuelta por
|
|
5
|
+
* el `lookup` de `generateObject` aunque coincidan system, prompt y temperatura.
|
|
6
|
+
*/
|
|
7
|
+
declare const TEXT_CALL_SIG = "__text__";
|
|
2
8
|
/** Firma ligera del schema (zod) para distinguir llamadas con el mismo prompt pero distinta forma. */
|
|
3
9
|
declare function schemaSignature(schema: any): string;
|
|
4
10
|
/**
|
|
@@ -12,14 +18,22 @@ declare function llmCacheKey(opts: {
|
|
|
12
18
|
schemaSig?: string | null;
|
|
13
19
|
temperature?: number | null;
|
|
14
20
|
}): string;
|
|
15
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* HIT: incrementa USE COUNT + LAST USED y devuelve OUTPUT (atómico). null en MISS o ante error.
|
|
23
|
+
*
|
|
24
|
+
* El filtro `"OUTPUT" IS NOT NULL` excluye las filas podadas (la poda vacía los textos pero
|
|
25
|
+
* conserva la fila por su coste). Sin él, una fila podada contaría como uso e inflaría USE COUNT,
|
|
26
|
+
* blindándola contra futuras podas pese a no servir ya de caché.
|
|
27
|
+
*/
|
|
16
28
|
declare function lookup(key: string): Promise<any | null>;
|
|
17
29
|
/**
|
|
18
|
-
* MISS: inserta (ON CONFLICT cubre la carrera
|
|
30
|
+
* MISS: inserta (ON CONFLICT cubre la carrera y la regeneración de una fila podada).
|
|
31
|
+
* Fire-and-forget, nunca lanza.
|
|
19
32
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
33
|
+
* Solo se llama tras una generación REAL (un HIT no cuesta nada y no pasa por aquí), así que el
|
|
34
|
+
* ON CONFLICT ACUMULA tokens y coste en vez de descartarlos: si el mismo prompt se regenera —por
|
|
35
|
+
* una carrera, o porque la poda vació sus textos— ese gasto es real y debe sumarse. Restaura
|
|
36
|
+
* además los textos, devolviendo a la fila podada su capacidad de servir como caché.
|
|
23
37
|
*/
|
|
24
38
|
declare function store(key: string, data: {
|
|
25
39
|
modelName?: string;
|
|
@@ -30,5 +44,5 @@ declare function store(key: string, data: {
|
|
|
30
44
|
output: any;
|
|
31
45
|
cost?: CostResult;
|
|
32
46
|
}): void;
|
|
33
|
-
export { schemaSignature, llmCacheKey, lookup, store };
|
|
47
|
+
export { schemaSignature, llmCacheKey, lookup, store, TEXT_CALL_SIG };
|
|
34
48
|
//# sourceMappingURL=llmCacheStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llmCacheStore.d.ts","sourceRoot":"","sources":["../../../../src/prompt/llmCacheStore.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAejD,sGAAsG;AACtG,iBAAS,eAAe,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,CAW5C;AAED;;;;GAIG;AACH,iBAAS,WAAW,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,MAAM,CAQ/H;AAED
|
|
1
|
+
{"version":3,"file":"llmCacheStore.d.ts","sourceRoot":"","sources":["../../../../src/prompt/llmCacheStore.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAejD;;;;GAIG;AACH,QAAA,MAAM,aAAa,aAAa,CAAC;AAEjC,sGAAsG;AACtG,iBAAS,eAAe,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,CAW5C;AAED;;;;GAIG;AACH,iBAAS,WAAW,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,MAAM,CAQ/H;AAED;;;;;;GAMG;AACH,iBAAe,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAWtD;AAED;;;;;;;;GAQG;AACH,iBAAS,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC;IAAC,IAAI,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,CAkCxL;AAED,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC"}
|