Record token usage per turn and show daily, weekly and all-time totals by host
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
// are.
|
||||
// ═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
const fs = require('fs');
|
||||
const { buildIndex } = require('./index.js');
|
||||
const { search } = require('./search.js');
|
||||
|
||||
@@ -24,6 +25,27 @@ function flag(name) {
|
||||
return process.argv.includes(`--${name}`);
|
||||
}
|
||||
|
||||
// Token accounting. Writes the same row shape as the WebGUI worker into the same file — one
|
||||
// ledger for both paths, or the totals quietly come to mean "whatever the tab happened to do".
|
||||
// Skipped silently when the caller passes neither flag, because cli.js has to stay runnable by
|
||||
// hand. Best-effort: a failed append must never cost a caller an answer it already has.
|
||||
//
|
||||
// Trimming is deliberately not done here. The PHP side prunes on write, and duplicating a
|
||||
// read-modify-write of the whole file in a second language is how the two drift apart.
|
||||
function recordTokens(profile, prompt, completion, tokS) {
|
||||
const db = arg('token-db', ''), host = arg('token-host', '');
|
||||
if (!db || !host || (prompt <= 0 && completion <= 0)) return;
|
||||
const d = new Date();
|
||||
const p2 = n => String(n).padStart(2, '0');
|
||||
const row = [
|
||||
`${d.getFullYear()}-${p2(d.getMonth() + 1)}-${p2(d.getDate())}`,
|
||||
`${p2(d.getHours())}:${p2(d.getMinutes())}:${p2(d.getSeconds())}`,
|
||||
host, profile, 'cli', prompt, completion,
|
||||
tokS === null ? '' : tokS.toFixed(1),
|
||||
].join('|') + '\n';
|
||||
try { fs.appendFileSync(db, row); } catch { /* accounting is not the answer */ }
|
||||
}
|
||||
|
||||
function fail(msg, code = 1) {
|
||||
console.error(msg);
|
||||
process.exit(code);
|
||||
@@ -165,6 +187,11 @@ ANSWER`;
|
||||
if (!res.ok) fail(`generation HTTP ${res.status}`, 2);
|
||||
const j = await res.json();
|
||||
|
||||
// 'varaverk' rather than a CLI-specific name: this path retrieves and cites, so it is the
|
||||
// same kind of turn the tab's default profile runs, and the two should aggregate together.
|
||||
recordTokens('varaverk', j.prompt_eval_count || 0, j.eval_count || 0,
|
||||
j.eval_duration > 0 ? (j.eval_count / (j.eval_duration / 1e9)) : null);
|
||||
|
||||
if (flag('json')) {
|
||||
console.log(JSON.stringify({ answer: j.response, sources: r.results.map(x => ({ path: x.path, section: x.section, heading: x.heading, score: x.score })) }));
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user