SPB Git forge

spb/trouve-ka

Public ★ Pinned

Trouve-KA — moteur de recherche web indépendant, Québec-first. Crawler distribué, index OpenSearch, ranking bilingue, galerie d'images. En prod : www.trouve-ka.com

40commits 1branches 0releases
9.2 MBsize
maindefault branch
23 days agolast push
Python 51.9% TypeScript 32.7% JavaScript 4.8% CSS 4.1% Shell 2.9% HTML 1.8% SQL 1.5%

docs: README v2 — galerie multi-pages, style du site, documentation, contact

Simon-Pierre Boucher committed 1 mo ago (Aug 24, 2026) parent 8880849

1 changed file +87 −16

modified README.md +87 −16
@@ -1,10 +1,16 @@
1 −# Trouve·Ka
1 +<p align="center">
2 + <a href="https://www.trouve-ka.com"><img src="https://www.trouve-ka.com/og.png" width="760" alt="Trouve·Ka — Le moteur de recherche du web québécois"></a>
3 +</p>
4 +<h1 align="center">Trouve·Ka</h1>
5 +<p align="center"><b>Le moteur de recherche du web québécois</b></p>
2 6
3 −**Cherche le Québec.** Moteur de recherche web indépendant, Québec-first — son propre crawler, son propre index, son propre ranking, son API et son application web publique.
7 +<div align="center">
4 8
5 −[![Site](https://img.shields.io/website?url=https%3A%2F%2Fwww.trouve-ka.com&style=flat-square&label=www.trouve-ka.com)](https://www.trouve-ka.com)
6 −![Nœud](https://img.shields.io/badge/n%C5%93ud-M2M32-1f6feb?style=flat-square)
7 −![Port](https://img.shields.io/badge/port-3000-141814?style=flat-square)
9 +[![Site](https://img.shields.io/website?url=https%3A%2F%2Fwww.trouve-ka.com&style=flat-square&label=www.trouve-ka.com&up_color=1c7ed6)](https://www.trouve-ka.com)
10 +[![Documentation](https://img.shields.io/badge/📖_documentation-%2Fdoc-1c7ed6?style=flat-square)](https://www.trouve-ka.com/doc/index.html)
11 +[![PDF](https://img.shields.io/badge/guide-PDF-1c7ed6?style=flat-square)](https://www.trouve-ka.com/doc/trouve-ka-documentation.pdf)
12 +![Nœud](https://img.shields.io/badge/n%C5%93ud-M2M32-1c7ed6?style=flat-square)
13 +![Port](https://img.shields.io/badge/port-3000-1c7ed6?style=flat-square)
8 14 ![PM2](https://img.shields.io/badge/process-PM2-2b037a?style=flat-square)
9 15 ![Docker](https://img.shields.io/badge/Docker-Postgres%20%2B%20Redis-2496ED?style=flat-square&logo=docker)
10 16 ![Next.js](https://img.shields.io/badge/Next.js-15-000000?style=flat-square&logo=nextdotjs)
@@ -12,7 +18,9 @@
12 18 ![OpenSearch](https://img.shields.io/badge/OpenSearch-2.17-005eb8?style=flat-square&logo=opensearch&logoColor=white)
13 19 ![Groupe KA](https://img.shields.io/badge/Groupe-KA-b7f000?style=flat-square)
14 20
15 −**Trouve·Ka** est un **vrai moteur de recherche québécois** — pas un métamoteur : **aucune dépendance à Google, Bing ou Brave** pour les résultats. Le crawler découvre le web québécois à partir de **64 seeds à forte autorité** (gouvernement, municipalités, universités, médias), suit les liens sortants, juge la **pertinence québécoise** de chaque page (`page_quebec_score` et `domain_quebec_score`) et indexe **immédiatement** : une page fetchée est **cherchable en ~2–4 secondes**, pendant que le frontier continue de grandir. L'enrichissement (autorité, entités, embeddings) arrive après, en asynchrone, sans jamais bloquer.
21 +</div>
22 +
23 +**Trouve·Ka** est un **vrai moteur de recherche québécois** — pas un métamoteur : **aucune dépendance à Google, Bing ou Brave** pour les résultats. Le crawler découvre le web québécois à partir de **64 seeds à forte autorité** (gouvernement, municipalités, universités, médias), suit les liens sortants, juge la **pertinence québécoise** de chaque page (`page_quebec_score` et `domain_quebec_score`) et indexe **immédiatement** : une page fetchée est **cherchable en ~2–4 secondes**, pendant que le frontier continue de grandir. L'enrichissement (autorité, entités, embeddings) arrive après, en asynchrone, sans jamais bloquer. C'est aussi **le moteur de recherche du Groupe KA** : les **14 sites de l'écosystème** (logements, propriétés, emplois, restos, événements, produits, véhicules, créateurs…) sont indexés en continu, avec **couverture sémantique de 100 %** de l'index.
16 24
17 25 > **Crawl en continu. Indexe immédiatement. Recherche immédiatement. Améliore en asynchrone.**
18 26
@@ -21,27 +29,78 @@ Crawler → Frontier → Fetcher → Parser → Classification Québec
21 29 → Déduplication → Indexer → Index → Ranking → API → Web App
22 30 ```
23 31
24 −En production : **https://www.trouve-ka.com** — détails techniques dans [docs/architecture.md](docs/architecture.md) (diagrammes Mermaid) et [docs/decisions.md](docs/decisions.md).
25 −
26 −## Captures d'écran
27 −
28 −<p align="center">
29 − <img src="docs/screenshots/trouve-ka-desktop.png" width="640" alt="Accueil — desktop">
30 − <img src="docs/screenshots/trouve-ka-mobile.png" width="200" alt="Accueil — mobile">
31 −</p>
32 +En production : **https://www.trouve-ka.com** — **177 000+ pages indexées** (181 369 constatées en direct sur [/status](https://www.trouve-ka.com/status) le 24 août 2026 — la croissance de l'index fait partie du produit). Détails techniques dans [docs/architecture.md](docs/architecture.md) (diagrammes Mermaid) et [docs/decisions.md](docs/decisions.md) ; guide utilisateur illustré sur [/doc](https://www.trouve-ka.com/doc/index.html).
33 +
34 +## Visite guidée
35 +
36 +Toutes les captures sont trackées dans le repo (`docs/screenshots/` et `apps/web/public/doc/img/` — ces dernières illustrent aussi le guide public [/doc](https://www.trouve-ka.com/doc/index.html)).
37 +
38 +<table>
39 + <tr>
40 + <td align="center"><img src="docs/screenshots/trouve-ka-desktop.png" width="420"><br><sub><b>Accueil — « Le moteur de recherche du Groupe KA », compteur live (174 906 pages indexées au moment de la capture)</b></sub></td>
41 + <td align="center"><img src="docs/screenshots/trouve-ka-mobile.png" width="240"><br><sub><b>Accueil mobile — même expérience, pastille live du compteur d'index</b></sub></td>
42 + </tr>
43 + <tr>
44 + <td align="center"><img src="apps/web/public/doc/img/etape2.png" width="420"><br><sub><b>Résultats « cabane à sucre » — 693 résultats en 269 ms, recherche sémantique active, filtres par univers KA / langue / fraîcheur</b></sub></td>
45 + <td align="center"><img src="apps/web/public/doc/img/etape3.png" width="420"><br><sub><b>Onglet Images — 692 résultats en 74 ms, galerie hotlink avec attribution du domaine source</b></sub></td>
46 + </tr>
47 + <tr>
48 + <td align="center"><img src="apps/web/public/doc/img/etape4.png" width="420"><br><sub><b>État du moteur (/status) — 177 301 pages indexées, couverture sémantique 100 %, 14 sites du Groupe KA, 4,58 M d'URL au frontier</b></sub></td>
49 + <td align="center"><img src="docs/screenshots/resultats.png" width="420"><br><sub><b>« plombier gatineau » — 4 278 résultats en 21 ms, badges Québec, filtres Tout / Images / Actualités / Gouvernement / FR / EN</b></sub></td>
50 + </tr>
51 + <tr>
52 + <td align="center"><img src="docs/screenshots/images.png" width="420"><br><sub><b>Onglet Images sur « montréal » — 1 554 résultats en 29 ms (phase crawl du web québécois ouvert)</b></sub></td>
53 + <td align="center"><img src="docs/screenshots/statut.png" width="420"><br><sub><b>État du moteur, vue antérieure — 58 801 pages, 7 898 domaines connus, files et erreurs en direct</b></sub></td>
54 + </tr>
55 + <tr>
56 + <td align="center" colspan="2"><img src="docs/screenshots/accueil.png" width="420"><br><sub><b>Accueil, première version « Cherche le Québec » — bandeau live « KA bot scrappe le site suivant » dans le pied de page</b></sub></td>
57 + </tr>
58 +</table>
32 59
33 60 ## Fonctionnalités
34 61
35 −- **Recherche Québec-first** : **59 000+ pages indexées**, **7 900+ domaines québécois** découverts à partir de 64 seeds, **latence de recherche 20–95 ms** (mesurée en prod).
62 +- **Recherche Québec-first** : **177 000+ pages indexées** (181 369 constatées live), **7 900+ domaines québécois** découverts à partir de 64 seeds, **14 sites du Groupe KA** indexés en continu, **latence de recherche 20–95 ms** en lexical (mesurée en prod ; jusqu'à ~270 ms quand la réécriture sémantique s'active).
36 63 - **Indexation incrémentale** : fetch → parse → score → index inline (`refresh_interval: 1s` côté OpenSearch) → cherchable en secondes. Détection de changement par hash de contenu + ETag/If-Modified-Since, recrawl adaptatif (inchangé → intervalle ×2, volatil → ÷2).
37 64 - **Détection Québec déterministe** : TLD (.qc.ca, .quebec), gazetteer de toponymes, codes postaux G/H/J, indicatifs (418/514/438/…), organisations connues (Hydro-Québec, RAMQ, UQAM…), JSON-LD, langue française — aucun LLM dans le chemin chaud.
38 65 - **Ranking bilingue** : `function_score` OpenSearch — BM25 FR/EN avec synonymes bilingues (thermopompe ↔ heat pump) + scores Québec + autorité de domaine (inlinks pondérés) + fraîcheur + boost de localité (« plombier Gatineau » → documents avec preuve géographique).
66 +- **Recherche sémantique** : embeddings sur 100 % de l'index — « heat pump » trouve « thermopompe », pas seulement par mots-clés ; la couverture progresse en arrière-plan sans bloquer le lexical.
39 67 - **Crawler poli et assumé** : UA identifié `TrouveKABot`, page publique [/trouveka-bot](https://www.trouve-ka.com/trouveka-bot), robots.txt respecté (Protego, cache 24 h), verrou de politesse Redis par hôte (défaut 2 s, `Crawl-delay` honoré), garde SSRF (IP privées/loopback/métadonnées cloud bloquées, revalidée à chaque redirection), détection de pièges de crawl (session IDs, calendriers infinis, facettes explosives).
40 68 - **Onglet Images** : galerie des pages avec image représentative (hotlink + attribution, jamais de crawl d'images).
41 −- **Métriques publiques réelles** : `/status` et `/stats` (tableau de bord + rapports PDF Groupe KA) — aucun compteur simulé, c'est une règle du projet.
69 +- **Métriques publiques réelles** : `/status` et `/stats` (tableau de bord + rapports PDF Groupe KA) — aucun compteur simulé, c'est une règle du projet. Les chiffres se rafraîchissent toutes les 10 secondes.
42 70 - **Crawl distribué multi-nœuds** : workers satellites sur M2M32b et M2M32c, coordonnés sans orchestrateur via le frontier Postgres (`FOR UPDATE SKIP LOCKED`) et les verrous Redis, communication par le LAN interne 192.168.2.x.
43 71 - **SSO KA ID** + favoris « Mon univers Ka », design Groupe KA et widget **KA Agent** (bulle de chat IA).
44 72
73 +## Pipeline complet
74 +
75 +Le chemin d'une page, de sa découverte à sa présence dans les résultats :
76 +
77 +1. **Découverte** — le frontier (Postgres) part de 64 seeds à forte autorité et grandit avec chaque lien sortant découvert (4,5 M+ d'URL en attente en prod). Les workers se servent sans orchestrateur via `FOR UPDATE SKIP LOCKED`.
78 +2. **Fetch poli** — `TrouveKABot` prend un verrou de politesse Redis par hôte (2 s par défaut, `Crawl-delay` honoré), vérifie robots.txt (Protego, cache 24 h) et la garde SSRF, puis télécharge avec ETag/If-Modified-Since.
79 +3. **Parsing** — extraction du contenu principal, du titre, des métadonnées, du JSON-LD, des liens sortants et d'une image représentative.
80 +4. **Classification Québec** — calcul déterministe de `page_quebec_score` et `domain_quebec_score` (TLD, toponymes, codes postaux, indicatifs, organisations, langue) — aucun LLM dans le chemin chaud.
81 +5. **Déduplication + indexation inline** — hash de contenu, puis indexation immédiate dans **OpenSearch 2.17** (`refresh_interval: 1s`) : la page est **cherchable en ~2–4 s**.
82 +6. **Enrichissement asynchrone** — via **Redis Streams** : autorité de domaine (inlinks pondérés), entités, embeddings sémantiques. Ne bloque jamais l'indexation ; en panne, le lexical continue.
83 +7. **Recrawl adaptatif** — le scheduler recale l'intervalle de revisite : contenu inchangé → intervalle ×2, contenu volatil → ÷2.
84 +8. **Ranking** — `function_score` : BM25 FR/EN + synonymes bilingues + scores Québec + autorité + fraîcheur + boost de localité, avec réécriture sémantique quand elle aide.
85 +
86 +## API
87 +
88 +L'API FastAPI (`trouveka.api`) est servie derrière le proxy Next.js (`/api/*`) — un seul port exposé (3000).
89 +
90 +| Endpoint | Méthode | Rôle |
91 +|---|---|---|
92 +| `/api/search` | GET | Recherche principale (requête, filtres univers/langue/fraîcheur, onglet images) |
93 +| `/api/suggest` | GET | Suggestions de saisie |
94 +| `/api/status` | GET | État du moteur en JSON : pages indexées, débits, frontier, erreurs, couverture sémantique |
95 +| `/api/live` | GET | Flux « en ce moment » (page en cours de crawl) |
96 +| `/api/submit` | POST | Soumission publique d'une URL au crawl ([/soumettre](https://www.trouve-ka.com/soumettre)) |
97 +| `/api/stats/dashboard` · `/catalog` · `/report` | GET/POST | Tableau de bord `/stats` + rapports PDF Groupe KA |
98 +| `/api/health` | GET | Sonde de santé |
99 +| `/api/admin/*` (overview, recent, frontier, zero-results, pause, resume, recrawl, seeds, domains/block) | GET/POST | Endpoints d'exploitation, protégés par `X-Admin-Token` |
100 +| `/embed` · `/rerank` | POST | Service d'embeddings interne (enrichissement sémantique) |
101 +
102 +**Latences observées en prod** : recherche lexicale **20–95 ms** (21 ms sur « plombier gatineau », 29 ms sur l'onglet Images), **~70–270 ms** quand la recherche sémantique s'active (269 ms sur « cabane à sucre »).
103 +
45 104 ## Architecture
46 105
47 106 En production sur **M2M32**, l'application tourne en processus natifs sous **PM2**, avec l'infrastructure de données en **Docker** :
@@ -59,6 +118,13 @@ En production sur **M2M32**, l'application tourne en processus natifs sous **PM2
59 118
60 119 La recherche s'appuie sur **OpenSearch 2.17** (BM25 FR/EN, synonymes bilingues, `function_score` Québec-first). Dégradation gracieuse partout : embeddings en panne → le lexical continue ; un worker crash → le frontier continue.
61 120
121 +## Documentation
122 +
123 +- **Guide utilisateur illustré** : [www.trouve-ka.com/doc](https://www.trouve-ka.com/doc/index.html) — la visite en 4 étapes (accueil, recherche, images, état du moteur + soumission de site).
124 +- **Guide PDF téléchargeable** : [trouve-ka-documentation.pdf](https://www.trouve-ka.com/doc/trouve-ka-documentation.pdf).
125 +- **Architecture** : [docs/architecture.md](docs/architecture.md) (diagrammes Mermaid) · **Décisions** : [docs/decisions.md](docs/decisions.md) · **Runbook** : [docs/RUNBOOK.md](docs/RUNBOOK.md).
126 +- **Le robot** : [/trouveka-bot](https://www.trouve-ka.com/trouveka-bot) — qui est `TrouveKABot`, comment le bloquer ou l'inviter.
127 +
62 128 ## Structure du repo
63 129
64 130 ```
@@ -139,6 +205,11 @@ Runbook et observabilité : [docs/RUNBOOK.md](docs/RUNBOOK.md), dashboard `/admi
139 205 | [trouve-ka.com](https://www.trouve-ka.com) | Petites annonces et recherche — **ce repo** |
140 206 | [api-ka.com](https://www.api-ka.com) | API de données |
141 207
208 +## Contact
209 +
210 +**Simon-Pierre Boucher** — fondateur, Groupe KA
211 +📧 [contact@spboucher.ai](mailto:contact@spboucher.ai)
212 +
142 213 ---
143 214
144 215 © Groupe KA — Simon-Pierre Boucher · contact@spboucher.ai
145 216