Files

59 lines
2.6 KiB
SQL
Raw Permalink Normal View History

2026-08-23 22:03:57 +02:00
-- +goose Up
-- Full prompt/response capture for every LLM call, for the platform-admin AI
-- inspector (/admin/ai-calls).
--
-- Worker logs only ever carried a 500-rune head/tail preview and
-- processed_products.gpt_response keeps response metadata without the prompt, so
-- there was no way to answer "what exactly did we send for this job".
--
-- Rows are large (a category-formula prompt runs several KB) and high volume (one
-- per product per language), so they are strictly short-lived: CleanupExpiredAICalls
-- prunes them on the worker's retention tick. This table is a debugging buffer, not
-- an audit trail — never build billing or reporting on it.
CREATE TABLE IF NOT EXISTS ai_call_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Nullable: platform-level probes (admin AI role test) belong to no tenant.
company_id UUID REFERENCES companies(id) ON DELETE CASCADE,
-- Who triggered the work (job starter / campaign author). Kept on user delete
-- so a tenant's recent calls stay readable; the row expires on its own.
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
job_id UUID,
raw_product_id UUID,
-- aiprovider role: processing | categorize | seo_meta | campaign | support | probe.
role TEXT NOT NULL DEFAULT 'other',
provider_mode TEXT NOT NULL DEFAULT '',
model TEXT NOT NULL DEFAULT '',
system_prompt TEXT NOT NULL DEFAULT '',
user_prompt TEXT NOT NULL DEFAULT '',
response_text TEXT NOT NULL DEFAULT '',
error TEXT NOT NULL DEFAULT '',
finish_reason TEXT NOT NULL DEFAULT '',
prompt_tokens INTEGER NOT NULL DEFAULT 0,
completion_tokens INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
duration_ms INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- Primary browse: one company's most recent calls.
CREATE INDEX IF NOT EXISTS ai_call_logs_company_created_idx
ON ai_call_logs (company_id, created_at DESC);
-- Drill into a single job from the Processing page.
CREATE INDEX IF NOT EXISTS ai_call_logs_job_idx
ON ai_call_logs (job_id, created_at DESC)
WHERE job_id IS NOT NULL;
-- Retention sweep scans by age across all tenants.
CREATE INDEX IF NOT EXISTS ai_call_logs_created_idx
ON ai_call_logs (created_at);
-- Failures are the rare rows worth finding fast across a whole tenant.
CREATE INDEX IF NOT EXISTS ai_call_logs_failed_idx
ON ai_call_logs (company_id, created_at DESC)
WHERE error <> '';
-- +goose Down
DROP TABLE IF EXISTS ai_call_logs;