metalfrom.eu/apps/api/migrations/008_band_locations.sql
Nicolas Fryder c39a8513f8 feat(geocoding): pipeline multi-étapes avec LLM Groq free tier
- Migration 008 : tables band_locations (N steps × M villes par band)
  et llm_cache (évite les double-appels LLM par sha256)
- parser.py : parse location_text en steps structurés, gère N/A/Unknown,
  villes multiples (Bergen / Oslo), hiérarchies admin, codes pays
- enqueue.py rewrite : peuple band_locations depuis bands, résout les
  is_country_only avec centroïdes hardcodés (confidence=0.1)
- worker.py rewrite : fallbacks progressifs Geoapify (plus spécifique
  → plus vague), sync bands.lat/lon depuis le step le plus récent,
  bascule en llm_needed après 3 échecs
- groq_worker.py (nouveau) : Groq free tier JSON mode, llm_cache,
  rate-limit par modèle, backoff exponentiel, fallback 8B si 70B saturé
- docker-compose : geocoder-enqueue (one-shot), groq-worker (continu),
  geocoder-worker devient unless-stopped
- Admin API : /geocoding retourne stats band_locations + llm_cache ;
  nouvelles routes /locations/reset-errors /reset-llm /requeue-all
- Admin UI : page Géocodage affiche les deux pipelines en parallèle

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 21:49:22 +02:00

54 lines
2 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 008_band_locations.sql
-- Table relationnelle N steps × M villes par band pour le géocodage multi-périodes.
-- Remplace la logique mono-entrée de geocode_queue pour les nouveaux traitements.
CREATE TABLE IF NOT EXISTS band_locations (
id BIGSERIAL PRIMARY KEY,
ma_id INTEGER NOT NULL REFERENCES bands(ma_id) ON DELETE CASCADE,
step_order SMALLINT NOT NULL DEFAULT 0,
step_label TEXT,
location_raw TEXT NOT NULL,
is_country_only BOOLEAN NOT NULL DEFAULT FALSE,
lat DOUBLE PRECISION,
lon DOUBLE PRECISION,
geocode_status TEXT NOT NULL DEFAULT 'queued',
geocode_query TEXT,
geocode_provider TEXT,
geocode_confidence REAL,
geocode_error TEXT,
geocode_tries_geo SMALLINT NOT NULL DEFAULT 0,
geocode_tries_llm SMALLINT NOT NULL DEFAULT 0,
geocode_next_at TIMESTAMPTZ NOT NULL DEFAULT now(),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE (ma_id, step_order, location_raw)
);
-- Index pour la boucle de travail du geocoder
CREATE INDEX IF NOT EXISTS idx_bl_geo_work
ON band_locations (geocode_next_at ASC, id ASC)
WHERE geocode_status = 'queued';
-- Index pour la boucle du groq-worker
CREATE INDEX IF NOT EXISTS idx_bl_llm_work
ON band_locations (geocode_tries_llm ASC, id ASC)
WHERE geocode_status = 'llm_needed';
-- Index de navigation par band
CREATE INDEX IF NOT EXISTS idx_bl_ma_id ON band_locations (ma_id);
-- Cache pour éviter de rappeler le LLM pour la même entrée
CREATE TABLE IF NOT EXISTS llm_cache (
id BIGSERIAL PRIMARY KEY,
input_hash TEXT NOT NULL UNIQUE,
model TEXT NOT NULL,
prompt TEXT NOT NULL,
response TEXT NOT NULL,
parsed_city TEXT,
parsed_country TEXT,
is_null BOOLEAN NOT NULL DEFAULT FALSE,
tokens_in INTEGER,
tokens_out INTEGER,
cost_usd NUMERIC(10, 8),
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);