- 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>
54 lines
2 KiB
SQL
54 lines
2 KiB
SQL
-- 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()
|
||
);
|