YaCy improved-search

Un fork expérimental de YaCy : meilleur classement, résultats signés, pairs derrière un NAT

Un fork de YaCy qui corrige des faiblesses mesurées sur le réseau public, ajoute une couche de confiance permettant de filtrer les résultats falsifiés et le spam, et permet aux pairs situés derrière un NAT de participer via un relais. Chaque affirmation de cette page est mesurée dans des réseaux pair-à-pair fermés que chacun peut reconstruire avec docker compose.

Statut : expérience. Ce fork n’est pas une version publiée par le projet YaCy et n’y est pas affilié. Il rompt délibérément la compatibilité avec le réseau YaCy public (identifiants de pairs, seeds, hachages de mots CJK). Il est partagé pour montrer, données à l’appui, ce que font les changements, afin que les idées puissent être discutées et, là où elles conviennent, proposées en amont par petits morceaux.

Pourquoi

Mesuré sur le réseau YaCy public (freeworld) avec 16 requêtes, seuls 11% des 10 premiers résultats contenaient tous les termes de la requête. En examinant les causes :

Ce qui a changé

Classement

Un minimum match plus strict, une pondération par couverture des termes après la normalisation par pair, une pondération contre les pages pauvres et la recherche sur tous les pairs des petits réseaux.

CJK

Le texte chinois, japonais et coréen est indexé et recherché sous forme de bigrammes chevauchants, dans Solr et dans l’index de mots.

Confiance

Des clés de pair Ed25519, des seeds signés, des listes de confiance signées par des coordinateurs avec des tags déclarés, et une signature d’auteur sur chaque document que le pair crawle.

Traversée de NAT

Un petit sidecar go-libp2p réserve un emplacement sur un circuit relay, pour que les pairs derrière un NAT répondent aux recherches.

Qualité de recherche

SymptômeCauseChangement
Les pages qui correspondent à un seul terme (bourrage de mots-clés) sont classées en têteSolr mm=1 pour les requêtes à plusieurs termesMinimum match 2<-1 5<80% : avec deux termes, les deux doivent correspondre ; avec 3 à 5 termes, un peut manquer (search.ranking.solr.mm, .mm.cjk)
La meilleure correspondance partielle d’un pair est classée comme les correspondances exactes des autres pairsNormalisation des scores par pairMultiplier le score normalisé par (termes trouvés / termes de la requête)², au moins 0.05, et jamais en dessous de ce que garantit le minimum match (search.ranking.coverage.exponent)
Japonais / chinois introuvables dans l’index de motsPas de segmentation en mots pour le CJKBigrammes chevauchants dans l’index de mots et dans la requête ; CJKWidthFilter + CJKBigramFilter dans le schéma Solr
Les pages pauvres contenant toute la requête dans leur titre (listes de tags) sont classées en têteLe qf par défaut pondère title^5 et h1^5 (et host ^6, nom de fichier de l’URL ^4, chemin ^3) face à text^1Les résultats de moins de 100 mots sont pondérés par mots / 100, au moins 0.1 (search.ranking.thin.words) ; comptage des mots CJK corrigé (il comptait les espaces)
Un réseau de nouveaux pairs ne cherche jamais dans les index de mots des autres pairsLa recherche DHT exige des pairs âgés de plus de 3 joursConfigurable (remotesearch.dht.minage, 3 par défaut)
Les petits réseaux n’envoient les requêtes Solr distantes à personne, ou ignorent les cibles DHTLa formule du nombre de cibles donne 0 ; les cibles DHT étaient exclues de SolrLes réseaux jusqu’à 32 pairs interrogent chaque pair de confiance connecté (chaque pair en mode ouvert), cibles DHT comprises

Couche de confiance

Traversée de NAT

Un processus sidecar (Go, go-libp2p) tourne à côté de YaCy avec la même clé. Derrière un NAT, il réserve un emplacement sur un circuit relay v2 et annonce l’adresse du circuit dans le seed signé (Reach=relay). Les autres pairs ouvrent vers lui un port de tunnel local et utilisent du HTTP ordinaire, si bien que les clients existants de YaCy fonctionnent sans modification. Par défaut, ces pairs ne font que répondre aux recherches. Ils ne stockent pas de données DHT, sauf s’ils l’activent.

Voir la conception confiance et NAT (en anglais) pour les détails.

Résultats

Deux expériences dans yacy-lab. Toutes deux exécutent des réseaux fermés dans docker compose, avec un corpus et un jeu de requêtes déterministes.

Qualité de recherche : upstream contre fork, 3 pairs chacun

Chaque pair crawle un site. Les requêtes sont envoyées au pair 1 avec resource=global, et la plupart des pages pertinentes se trouvent sur les autres pairs. Le corpus contient deux sortes de leurres : des pages bourrées d’un seul terme de la requête, et des pages pauvres d’« archive de tags » contenant toute la requête dans leur titre. Moyenne sur 11 requêtes (6 en anglais, 4 en japonais, 1 en chinois), 2 exécutions au résultat identique sauf mention contraire.

Cluster / cheminR-précision ↑Recall@10 ↑Leurres dans le top R ↓Tous les termes dans le top 10 ↑
upstream, par défaut0.520.960.480.42
fork, par défaut0.79–0.861.000.14–0.210.75
upstream, index de mots seul0.020.020.000.09
fork, index de mots seul0.930.950.070.77

Confiance et NAT : 6 pairs du fork, un relais et un NAT

Trois pairs de confiance, un pair de confiance qui déclare ads, un pair signé mais non fiable qui crawle du spam et implante des documents avec une signature empruntée, et un pair derrière un routeur MASQUERADE. Les 26 vérifications passent toutes, entre autres :

Essayer

Sans Docker : ouvrez la démo dans votre navigateur. Elle fonctionne en mode simulé et rejoue des réponses enregistrées sur la vraie démo (la page est en japonais).

La démo démarre les deux réseaux (3 pairs upstream, et la configuration confiance et NAT du fork) sur une seule machine et place une page de recherche devant eux. Il vous faut Docker avec environ 7 Go de mémoire.

git clone https://github.com/pad01g/yacy_search_server.git yacy
git clone https://github.com/pad01g/yacy-lab.git
cd yacy
git checkout baseline        && docker build -t yacy-lab/upstream:baseline -f docker/Dockerfile .
git checkout improved-search && docker build -t yacy-lab/fork:latest -f docker/Dockerfile .
docker build -t yacy-lab/sidecar:latest sidecar/
cd ../yacy-lab
docker compose -f compose.demo.yaml -p yacydemo up -d
# ouvrir http://localhost:8800 (la mise en place prend environ 10 minutes et affiche sa progression)
La page de démo : la même requête envoyée au réseau upstream (à gauche) et au fork (à droite). L’upstream affiche d’abord des pages de spam ; le fork affiche d’abord des pages pertinentes vérifiées et, en mode ouvert, le spam en dessous, marqué non vérifié.
« bitcoin lightning channel » en mode ouvert. À gauche : l’upstream affiche d’abord le spam. À droite : le fork affiche d’abord les résultats vérifiés, et le spam, marqué non vérifié, en dessous.

La page permet aussi de modifier la confiance : choisir à quels coordinateurs le pair qui cherche fait confiance (un second coordinateur ne liste que le pair de spam, donc lui faire confiance rend le spam « vérifié »), modifier et re-signer la liste de confiance, remettre la nouvelle version à un pair et la regarder se propager, et révoquer ou rétablir la délégation de l’opérateur.

Les expériences elles-mêmes : docker compose -p yacylab up -d && docker compose -p yacylab run --rm runner (qualité de recherche) et docker compose -f compose.trust.yaml -p yacytrust up -d && docker compose -f compose.trust.yaml -p yacytrust run --rm runner (confiance et NAT). Voir le README du labo.

Rejoindre : aucune autorisation nécessaire

N’importe qui, personne ou agent, peut faire tourner un pair, le connecter avec l’URL d’un membre (p2p.bootstrap.peers, y compris à travers un réseau Tailscale), indexer et signer ses propres pages et services, et gérer son propre coordinateur ou opérateur : un coordinateur n’est qu’une clé et un fichier signé à n’importe quelle URL, sans serveur. Les publicités déclarées (tag ads) sont autorisées ; les utilisateurs choisissent à quelles listes ils font confiance. Comment rejoindre · pull requests bienvenues.

Pour les agents IA

Un agent peut faire tourner son propre pair et l’utiliser comme outil de recherche, sans API de recherche ni clé d’API :

Limites