Architecture
Le déroulement d'une campagne de recherche, et ce qui sort de votre machine par quelle porte, avec le fichier du code derrière chaque ligne.
Le déroulement d’une campagne de recherche
manifeste.json
│ campagne.py
▼
SearXNG ── requêtes
▼
collecte HTTP légère ──► navigateur réel (seulement si la page ne suffit pas)
▼
collecte.jsonl + operations.jsonl
▼
OpenCode ── classement, puis le rapport
▼
rapport_<horodatage>.md
- Le manifeste est un fichier JSON de cibles : une
querypour SearXNG, uneurlfixe, unproduit(trouver la page qui est vraiment celle du produit) ou unetable_reference(une liste de domaines de confiance pour un sujet). Seuls l’identifiant de la campagne et les cibles sont obligatoires. - La découverte. Une cible
querypart vers l’instance SearXNG que vous avez configurée, qui interroge à son tour d’autres moteurs, sur lesquels Dinoer n’a pas la main. - La collecte. Chaque page est récupérée par une simple requête HTTP,
après lecture de son
robots.txt. Seule une page dont le texte ne se lit pas ainsi passe à un vrai navigateur, un processus Playwright par page. Une cible qui échoue n’arrête pas les autres. - Le corpus. Un
collecte.jsonlpar campagne, une ligne par page retenue, etoperations.jsonl, qui consigne chaque tentative, réussie ou non. - Le rapport. Les pages sont réordonnées (par période et par
embeddings locaux, si le manifeste le demande), coupées à un budget de
taille, puis confiées à OpenCode, qui rédige le corps de
rapport_<horodatage>.md. Dinoer ajoute lui-même la liste des sources ; le modèle ne l’écrit jamais.
shot.py et rpa.py fonctionnent autrement : chaque appel est un processus à
part, qui se termine dès qu’il a répondu. Pourquoi →
Ce qui sort de votre machine, et par quelle porte
| Quoi | Où cela part | Qui décide | Dans le code |
|---|---|---|---|
| Les requêtes de découverte | l’instance SearXNG que vous avez configurée, qui interroge à son tour d’autres moteurs | vous, avec DINOER_SEARXNG_URL | lib/searxng.py |
| Les requêtes de pages | chaque site directement, son robots.txt lu d’abord | les cibles de votre manifeste | lib/fetch_leger.py, rpa.py |
| Le texte collecté | le modèle OpenCode que vous désignez, pour le rapport, pour l’extraction ciblée et pour choisir une page produit (les 1 500 premiers caractères de chaque candidate) | vous, avec DINOER_OPENCODE_MODEL | lib/modeles.py, lib/synthese.py, lib/extraction.py, lib/selection_candidats.py |
| Un sujet, pour une table de référence | le même modèle OpenCode, le sujet seul, quand aucune table n’existe encore pour lui | la cible table_reference | lib/tables_reference.py |
| Les embeddings | votre Ollama local, http://localhost:11434 : le texte reste sur la machine, sauf si vous dirigez DINOER_OLLAMA_URL ailleurs | vous | lib/vector.py |
| Une notification | un serveur ntfy, https://ntfy.sh sauf si vous en indiquez un autre : l’identifiant de la campagne et le nombre de sources. Seulement si un topic ntfy est défini | vous, avec ntfy_topic, DINOER_NTFY_TOPIC, DINOER_NTFY_URL | campagne.py, lib/ntfy.py |
| Vos identifiants | nulle part : résolus dans le processus Playwright, depuis le répertoire chiffré | — | lib/repertoire_chiffre.py |
Source : le code de la version 1.0.1, lu le 27 septembre 2026. Les modèles
rangés sous opencode/ sont hébergés par leur fournisseur (opencode.ai/zen,
d’après opencode models --verbose, OpenCode 1.18.32). Ce que le modèle a le
droit de faire sur le web figure sur la page consacrée à la confiance.