#!/usr/bin/env python3 # ============================================================================= # Job·Ka — Groupe KA # Auteur : Simon-Pierre Boucher # Contact : contact@spboucher.ai # Fichier : scripts/classify_sectors.py # Rôle : Remplit `sectors` (1-2 étiquettes FR du vocabulaire existant) des # entrées d'un feeds-*.json qui n'en ont pas — lots de 40 via l'API # Anthropic (claude-haiku), écrit le fichier en place # Créé : 2026-08-23 Modifié : 2026-08-23 # ============================================================================= """Usage : ANTHROPIC_API_KEY=… python3 scripts/classify_sectors.py FEEDS.json""" from __future__ import annotations import json import os import sys from pathlib import Path import requests VOCAB = ["TI", "Santé", "Commerce de détail", "Secteur public", "Finance", "Ingénierie", "Fabrication", "Immobilier", "Assurance", "Agroalimentaire", "Jeux vidéo", "Énergie", "Création", "Aéronautique", "Placement", "Conseil", "Éducation", "Logistique", "Services", "Transport", "Construction", "Pharmaceutique", "Divertissement", "Recherche", "Automobile", "SaaS", "Marketing", "Distribution", "Médias", "Animation", "Restauration", "IA", "Pâtes et papiers", "Services sociaux", "Mode", "Web", "Effets visuels", "Administration", "Publicité", "Hôtellerie", "Mines", "Ventes", "Gestion immobilière", "Sport", "Juridique", "Télécommunications", "Fintech", "Voyage", "Données", "Biotechnologie", "Environnement", "Sécurité", "Ressources humaines", "Tourisme", "Arts", "Musique", "Camionnage", "Foresterie", "Métallurgie"] API = "https://api.anthropic.com/v1/messages" MODEL = "claude-haiku-4-5-20251001" def classify(names: list[str], key: str) -> dict[str, list[str]]: prompt = ( "Voici des employeurs (surtout québécois/canadiens). Pour chacun, " "donne 1 ou 2 secteurs d'activité, choisis STRICTEMENT dans ce " "vocabulaire :\n" + ", ".join(VOCAB) + "\n\nRéponds UNIQUEMENT avec un objet JSON " '{"Nom employeur": ["Secteur", ...], ...} — aucun autre texte.\n\n' + "\n".join(f"- {n}" for n in names)) r = requests.post(API, timeout=120, headers={ "x-api-key": key, "anthropic-version": "2023-06-01", "content-type": "application/json"}, json={"model": MODEL, "max_tokens": 4000, "messages": [{"role": "user", "content": prompt}]}) r.raise_for_status() txt = r.json()["content"][0]["text"].strip() if txt.startswith("```"): txt = txt.strip("`").lstrip("json").strip() return json.loads(txt) def main() -> None: key = os.environ.get("ANTHROPIC_API_KEY") if not key: sys.exit("ANTHROPIC_API_KEY manquant") path = Path(sys.argv[1]) feeds = json.loads(path.read_text(encoding="utf-8")) todo = [f for f in feeds if not f.get("sectors")] print(f"[secteurs] {len(todo)} employeurs à classifier") for i in range(0, len(todo), 40): batch = todo[i:i + 40] try: got = classify([f["employer"] for f in batch], key) except Exception as exc: print(f" ! lot {i}: {exc}") continue for f in batch: secs = got.get(f["employer"]) or [] f["sectors"] = [s for s in secs if s in VOCAB][:2] print(f" lot {i // 40 + 1}: {len(got)} classés") path.write_text(json.dumps(feeds, ensure_ascii=False, indent=1) + "\n", encoding="utf-8") missing = sum(1 for f in feeds if not f.get("sectors")) print(f"[secteurs] terminé — {missing} sans secteur") if __name__ == "__main__": main()