feat: add response logger for moderation/vision audit trail + cache model versioning
- Add responseLogger.ts with comprehensive logging: vision analysis, moderation analysis batches, cache hit/miss events, errors, retries, false positives, model version changes, cache invalidation - Integrate responseLogger calls into llmModerationClient.ts (cache events, moderation results, errors, retries) - Add model_version column to text_analysis_cache schema with composite index for efficient filtering - Add migration SQL for model_version column - Document CACHE_MODEL_VERSION in .env.example
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
-- Migration: Add model_version column to text_analysis_cache table
|
||||
-- Purpose: Track which vision/LLM model version produced each cache entry
|
||||
-- Reason: Invalidate old cache entries when model prompts change (e.g., terminal screenshot false positive fix)
|
||||
-- Date: 2026-06-02
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- Add model_version column with default value
|
||||
ALTER TABLE text_analysis_cache
|
||||
ADD COLUMN model_version VARCHAR(50) NOT NULL DEFAULT 'v1';
|
||||
|
||||
-- Create index for efficient filtering by model version
|
||||
CREATE INDEX idx_text_analysis_cache_model_version
|
||||
ON text_analysis_cache(model_version);
|
||||
|
||||
-- Create composite index for source + model_version queries (common pattern)
|
||||
CREATE INDEX idx_text_analysis_cache_source_model_version
|
||||
ON text_analysis_cache(source, model_version);
|
||||
|
||||
-- Optional: Clean up old vision_llm entries that may have stale/incorrect analysis
|
||||
-- Uncomment to remove all old vision analysis cache on deployment:
|
||||
-- DELETE FROM text_analysis_cache WHERE source = 'vision_llm' AND model_version = 'v1';
|
||||
|
||||
COMMIT;
|
||||
@@ -361,6 +361,9 @@ export const pgRetentionPoliciesTable = pgTable(
|
||||
*
|
||||
* Uses the FULL normalized text (not per-word) because context matters:
|
||||
* "kau" alone is clean, but "awas kau" can be a threat.
|
||||
*
|
||||
* model_version tracks the vision/LLM model version that produced this cache entry.
|
||||
* On model updates, bump the version to invalidate all old cache entries automatically.
|
||||
*/
|
||||
export const pgTextAnalysisCacheTable = pgTable(
|
||||
"text_analysis_cache",
|
||||
@@ -381,12 +384,20 @@ export const pgTextAnalysisCacheTable = pgTable(
|
||||
expires_at: pgBigint("expires_at", { mode: "number" }).notNull(),
|
||||
/** How many times this cached text has been reused. */
|
||||
hit_count: pgInteger("hit_count").notNull().default(0),
|
||||
/** Model version that produced this cache entry (e.g. "v1", "v2-2026-06-02"). Mismatched versions are ignored. */
|
||||
model_version: pgText("model_version").notNull().default("v1"),
|
||||
},
|
||||
(table) => ({
|
||||
expiresAtIdx: pgIndex("idx_text_analysis_cache_expires_at").on(
|
||||
table.expires_at,
|
||||
),
|
||||
sourceIdx: pgIndex("idx_text_analysis_cache_source").on(table.source),
|
||||
modelVersionIdx: pgIndex("idx_text_analysis_cache_model_version").on(
|
||||
table.model_version,
|
||||
),
|
||||
sourceModelVersionIdx: pgIndex(
|
||||
"idx_text_analysis_cache_source_model_version",
|
||||
).on(table.source, table.model_version),
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user