feat: log llm runtime responses
This commit is contained in:
+32
-3
@@ -1,12 +1,19 @@
|
||||
import OpenAI from "openai";
|
||||
import type { z } from "zod";
|
||||
|
||||
export type LlmTaskName =
|
||||
| "unknown"
|
||||
| "fact_extractor"
|
||||
| "article_optimizer"
|
||||
| "quality_inspector"
|
||||
| "targeted_rewriter";
|
||||
|
||||
export interface GenerateInput {
|
||||
system?: string;
|
||||
prompt: string;
|
||||
model?: string;
|
||||
temperature?: number;
|
||||
task?: string;
|
||||
task?: LlmTaskName;
|
||||
}
|
||||
|
||||
export interface GenerateValidatedJsonInput<T> extends GenerateInput {
|
||||
@@ -77,7 +84,16 @@ function getTask(input: GenerateInput) {
|
||||
return input.task?.trim() || "unknown";
|
||||
}
|
||||
|
||||
function truncateRaw(value: string, maxLength = 4000) {
|
||||
function getRawLogLimit() {
|
||||
const parsed = Number(process.env.LLM_LOG_RAW_LIMIT ?? "4000");
|
||||
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 4000;
|
||||
}
|
||||
|
||||
function stringifyForLog(value: unknown) {
|
||||
return typeof value === "string" ? value : JSON.stringify(value);
|
||||
}
|
||||
|
||||
function truncateRaw(value: string, maxLength = getRawLogLimit()) {
|
||||
return value.length > maxLength
|
||||
? `${value.slice(0, maxLength)}...[truncated ${value.length - maxLength} chars]`
|
||||
: value;
|
||||
@@ -195,8 +211,17 @@ export async function generateValidatedJson<T>({
|
||||
return null;
|
||||
}
|
||||
|
||||
const status = getLlmProviderStatus();
|
||||
const startedAt = Date.now();
|
||||
console.info(
|
||||
`[llm:start] provider=${status.provider} model=${input.model ?? status.model} task=${task}`,
|
||||
);
|
||||
|
||||
try {
|
||||
const generated = await generateJsonForValidation<unknown>(input);
|
||||
console.info(
|
||||
`[llm:response] task=${task} duration_ms=${Date.now() - startedAt} raw=${truncateRaw(stringifyForLog(generated))}`,
|
||||
);
|
||||
const parsed = schema.safeParse(generated);
|
||||
if (parsed.success) {
|
||||
console.info(`[llm:validated] task=${task} ok=true`);
|
||||
@@ -206,8 +231,12 @@ export async function generateValidatedJson<T>({
|
||||
`[llm:validated] task=${task} ok=false zod_error=${quoteLogValue(summarizeZodError(parsed.error))}`,
|
||||
);
|
||||
return null;
|
||||
} catch {
|
||||
} catch (error) {
|
||||
console.info(`[llm:validated] task=${task} ok=false reason=provider_error`);
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
console.warn(
|
||||
`[llm:error] task=${task} duration_ms=${Date.now() - startedAt} message=${quoteLogValue(message)}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user