partial googleai fixes; adds jsonl file backend for promptlogger stolen from fiz
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
// stolen from https://gitgud.io/fiz1/oai-reverse-proxy
|
||||
|
||||
import { promises as fs } from "fs";
|
||||
import * as path from "path";
|
||||
import { USER_ASSETS_DIR, config } from "../../../config";
|
||||
import { logger } from "../../../logger";
|
||||
import { LogBackend, PromptLogEntry } from "../index";
|
||||
import { glob } from "glob";
|
||||
|
||||
const MAX_FILE_SIZE = 25 * 1024 * 1024;
|
||||
|
||||
let currentFileNumber = 0;
|
||||
let currentFilePath = "";
|
||||
let currentFileSize = 0;
|
||||
|
||||
export { currentFileNumber };
|
||||
|
||||
export const fileBackend: LogBackend = {
|
||||
init: async (_onStop: () => void) => {
|
||||
try {
|
||||
await createNewLogFile();
|
||||
} catch (error) {
|
||||
logger.error("Error initializing file backend", error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const files = glob.sync(
|
||||
path.join(USER_ASSETS_DIR, `${config.promptLoggingFilePrefix}*.jsonl`),
|
||||
{ windowsPathsNoEscape: true }
|
||||
);
|
||||
const sorted = files.sort((a, b) => {
|
||||
const aNum = parseInt(path.basename(a).replace(/[^0-9]/g, ""), 10);
|
||||
const bNum = parseInt(path.basename(b).replace(/[^0-9]/g, ""), 10);
|
||||
return aNum - bNum;
|
||||
});
|
||||
|
||||
if (sorted.length > 0) {
|
||||
const latestFile = sorted[sorted.length - 1];
|
||||
const stats = await fs.stat(latestFile);
|
||||
currentFileNumber = parseInt(
|
||||
path.basename(latestFile).replace(/[^0-9]/g, ""),
|
||||
10
|
||||
);
|
||||
currentFilePath = latestFile;
|
||||
currentFileSize = stats.size;
|
||||
}
|
||||
|
||||
logger.info(
|
||||
{ currentFileNumber, currentFilePath, currentFileSize },
|
||||
"File backend initialized"
|
||||
);
|
||||
},
|
||||
appendBatch: async (batch: PromptLogEntry[]) => {
|
||||
try {
|
||||
if (currentFileSize > MAX_FILE_SIZE) {
|
||||
await createNewLogFile();
|
||||
}
|
||||
|
||||
const batchString =
|
||||
batch.map((entry) => JSON.stringify(entry)).join("\n") + "\n";
|
||||
const batchSizeBytes = Buffer.byteLength(batchString);
|
||||
const batchLines = batch.length;
|
||||
logger.debug(
|
||||
{ batchLines, batchSizeBytes, currentFileSize, file: currentFilePath },
|
||||
"Appending batch to file"
|
||||
);
|
||||
await fs.appendFile(currentFilePath, batchString);
|
||||
currentFileSize += Buffer.byteLength(batchString);
|
||||
} catch (error) {
|
||||
logger.error("Error appending batch to file", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
async function createNewLogFile() {
|
||||
currentFileNumber++;
|
||||
currentFilePath = path.join(
|
||||
USER_ASSETS_DIR,
|
||||
`${config.promptLoggingFilePrefix}${currentFileNumber}.jsonl`
|
||||
);
|
||||
currentFileSize = 0;
|
||||
|
||||
await fs.writeFile(currentFilePath, "");
|
||||
logger.info(`Created new log file: ${currentFilePath}`);
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
export * as sheets from "./sheets";
|
||||
export { fileBackend as file } from "./file";
|
||||
|
||||
@@ -17,4 +17,9 @@ export interface PromptLogEntry {
|
||||
// TODO: temperature, top_p, top_k, etc.
|
||||
}
|
||||
|
||||
export interface LogBackend {
|
||||
init: (onStop: () => void) => Promise<void>;
|
||||
appendBatch: (batch: PromptLogEntry[]) => Promise<void>;
|
||||
}
|
||||
|
||||
export * as logQueue from "./log-queue";
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
* logging backend. */
|
||||
|
||||
import { logger } from "../../logger";
|
||||
import { PromptLogEntry } from ".";
|
||||
import { sheets } from "./backends";
|
||||
import { LogBackend, PromptLogEntry } from ".";
|
||||
import { sheets, file } from "./backends";
|
||||
import { config } from "../../config";
|
||||
import { assertNever } from "../utils";
|
||||
|
||||
const FLUSH_INTERVAL = 1000 * 10;
|
||||
const MAX_BATCH_SIZE = 25;
|
||||
@@ -15,6 +17,7 @@ let started = false;
|
||||
let timeoutId: NodeJS.Timeout | null = null;
|
||||
let retrying = false;
|
||||
let consecutiveFailedBatches = 0;
|
||||
let backend: LogBackend;
|
||||
|
||||
export const enqueue = (payload: PromptLogEntry) => {
|
||||
if (!started) {
|
||||
@@ -34,7 +37,7 @@ export const flush = async () => {
|
||||
const nextBatch = queue.splice(0, batchSize);
|
||||
log.info({ size: nextBatch.length }, "Submitting new batch.");
|
||||
try {
|
||||
await sheets.appendBatch(nextBatch);
|
||||
await backend.appendBatch(nextBatch);
|
||||
retrying = false;
|
||||
consecutiveFailedBatches = 0;
|
||||
} catch (e: any) {
|
||||
@@ -64,8 +67,20 @@ export const flush = async () => {
|
||||
};
|
||||
|
||||
export const start = async () => {
|
||||
const type = config.promptLoggingBackend!;
|
||||
try {
|
||||
await sheets.init(() => stop());
|
||||
switch (type) {
|
||||
case "google_sheets":
|
||||
backend = sheets;
|
||||
await sheets.init(() => stop());
|
||||
break;
|
||||
case "file":
|
||||
backend = file;
|
||||
await file.init(() => stop());
|
||||
break;
|
||||
default:
|
||||
assertNever(type)
|
||||
}
|
||||
log.info("Logging backend initialized.");
|
||||
started = true;
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user