SPB Git forge

spb/ka-ui

Public
30commits 1branches 0releases
145.7 MBsize
maindefault branch
27 days agolast push
Python 33.5% JavaScript 30.1% TypeScript 25% CSS 10% Shell 1.4%
3.6 KB · 83 lines markdown
Rendered Raw Blame History
1# KA ID v2 — personnalisation Groupe KA (module satellite)23Standard 2026-08-26. Le hub **groupe-ka.com** est le feature store du groupe :4journal d'interactions, favoris, recherches sauvegardées + alertes, éléments5masqués, **profil de préférences appris** (décroissance 30 j, signaux6négatifs, corrections utilisateur sur `/mon-ka`). Chaque satellite le7consomme par le canal s2s HMAC existant (`KA_SSO_SECRET`).89## Fichiers canoniques1011- `kaid.py` — client backend (FastAPI) : `track()`, `fetch_prefs()`,12  `rerank()`, `build_router()`. Copié dans le paquet de l'app par13  `./sync-kaid.sh`.14- `ka-id.js` — SDK navigateur : clics positionnés, dwell de fiche,15  visites de retour, `KAID.hide()`, `KAID.saveSearch()`. Copié dans16  `frontend/public/` (+ `dist/`).1718## Endpoints hub (s2s, sig = HMAC(secret, "client.ka_id.ts"))1920- `POST /api/sso/events` — lot d'événements `{type, entity_id?, query?,21  filters?, features?, dwell_ms?, position?}` (max 50)22- `GET  /api/sso/prefs` — `{personalization, profile: {app, global}, hidden}`23- `GET/POST /api/sso/saved-searches`, `POST /api/sso/hide`2425## Intégration type (app FastAPI)2627```python28# web.py29from . import kaid30kaid.init("job-ka")31app.include_router(kaid.build_router(lambda req: current_user(req)))3233# endpoint listing — APRÈS le tri de base, seulement pour le tri par défaut :34user = current_user(request)35kaid.track(user, "search", query=q, filters={"city": city, ...})36if sort == "recent":                     # jamais sur un tri explicite37    items, personalized = kaid.rerank(38        items, user,39        features_of=lambda it: {"city": it.get("city"), "price": it.get("price"), ...},40        active_dims={d for d in ("city",) if city},   # intention de session41    )4243# endpoint fiche :44kaid.track(user, "detail_view", entity_type="job", entity_id=uid,45           features=_features_of(row))4647# favoris (accounts.py) :48kaid.track(user, "favorite", entity_id=uid, features=_features_of(row))49```5051```html52<!-- index.html, avant le bundle -->53<script>window.KAID_CONF={card:"a[href^='/emploi/']",detail:"^/emploi/(.+)$",entity:"job"};</script>54<script src="/ka-id.js" defer></script>55```5657## Règles58591. **Jamais obligatoire** : sans session KA ID, zéro appel, zéro changement.602. **Fail-open** : hub injoignable ou profil vide → classement de base.613. **Pertinence d'abord** : `rerank()` reclasse APRÈS le tri de base62   (blend 0,35) et uniquement le tri par défaut — un tri explicite63   (prix, salaire…) n'est jamais altéré.644. **Session > long terme** : passer les dimensions filtrées par la requête65   dans `active_dims` — elles sont exclues du score personnel.665. **Badge parcimonieux** : `item["ka_reco"]` n'apparaît que si le score67   personnel ≥ 0,62, plafonné à ~1 carte sur 8. Frontend : petite68   étiquette « Recommandé pour vous » + raisons (`MATCH_LOCATION`,69   `MATCH_PRICE_RANGE`, `MATCH_<DIM>`…).706. **features riches** : envoyer les mêmes clés dans `track(features=…)` et71   `features_of()` — c'est le vocabulaire du profil (city, price, brand,72   category…). Valeurs texte OU nombres (les nombres apprennent des plages).737. Le masquage (« Pas pour moi ») retire l'annonce des résultats de TOUTES74   les sessions futures et compte comme signal négatif fort.7576## Confidentialité7778Réglages sur groupe-ka.com/mon-ka : Personnalisation / Historique /79Recommandations (ON par défaut, opt-out), effacement de l'historique,80réinitialisation des recommandations, export JSON (Loi 25).81`prefs.personalization=false` ⇒ `rerank()` ne fait que l'exclusion des82masqués ; Historique OFF ⇒ le hub jette les événements reçus.83