Skip to main content

tagsearch — Python Engine

Réalisé par Gillesto66 & Kiro | Moteur de référence du projet TagSearch

Le moteur Python est la source de vérité du projet. C'est ici que les algorithmes sont définis, documentés et validés avant d'être portés en TypeScript et PHP. Toute modification de la formule de scoring doit partir de ce module.


Objectif du module

Fournir un moteur de recherche par tags entièrement in-memory, sans dépendance externe, capable de :

  • Indexer des produits e-commerce avec leurs métadonnées (type, niche, prix, localisation, avis)
  • Répondre à des requêtes textuelles avec autocomplétion (O(L)) et recherche floue (Levenshtein + pruning)
  • Classer les résultats selon 5 dimensions : pertinence BM25, qualité des avis, type de produit, niche, proximité géographique, budget

Architecture des modules

tagsearch/
├── models.py       ProductMeta, ProductType, SearchPreferences
├── structures.py   Trie, DAWG, VarInt, CompressedPostingsList, LRUCache
├── scoring.py      BM25Index, calculate_final_score + constantes canoniques
└── engine.py       SearchEngine — point d'entrée public

structures.py — Phase 1 (mémoire)

  • TrieNode avec __slots__ + tableau fixe de 38 slots : 83% moins de RAM qu'un objet standard
  • DAWG via algorithme de Daciuk : partage réel des suffixes (le mot est reconstruit par le chemin, jamais stocké dans le nœud). Gain mesuré sur le nombre de nœuds : 85 % sur un vocabulaire synthétique à suffixes répétés, 50 % en pire cas ; non mesuré sur un vrai catalogue (benchmarks/dawg_vs_trie.py)
  • CompressedPostingsList : delta-encoding + VarInt, −97,5 % de RAM vs set Python sur 500 identifiants (mesuré)

Indexation paresseuse : add_product() / add_products() / load_catalog() n'enregistrent que les données ; le DAWG est reconstruit une seule fois, au premier search() suivant ou via commit(). Charger N produits coûte O(N). load_catalog() est atomique (un produit invalide n'ajoute rien).

Erreurs : seules les ValueError de validation d'entrée (requête vide, max_dist < 0, top_k < 1) sont levées volontairement ; toute autre exception est un vrai bug et remonte telle quelle (elle n'est plus convertie en « aucun résultat »).

scoring.py — Phase 2 (intelligence)

  • BM25Index : Okapi BM25 in-memory, paramètres k1=1.5, b=0.75
  • calculate_final_score : formule multiplicative 5 dimensions avec Bayesian rating

Installation

# Développement (pas d'installation nécessaire)
cd python-engine
python -m pytest tests/ -v

# Installation dans un autre projet
pip install -e .

Pas besoin de pip install -e . pour développer — pytest trouve le package via pythonpath = ["."] dans pyproject.toml.


Quick Start

from tagsearch import SearchEngine, ProductMeta, ProductType, SearchPreferences

# Chargement depuis le dataset partagé
engine = SearchEngine(cache_size=200)
engine.load_catalog("../shared-assets/catalog.json")

# Recherche simple
results, status = engine.search("gaming")
# status = "CALCULÉ" | "CACHÉ" | "MISS"

# Recherche avec préférences utilisateur
prefs = SearchPreferences(
    preferred_type=ProductType.DIGITAL,   # Filtre doux : relègue les Physical
    max_price=50.0,                        # Filtre dur : exclut > 50€
    min_rating=4.0,                        # Filtre dur : exclut < 4★
    user_location="France",                # Bonus +15% si même zone
)
results, status = engine.search("cuisine", prefs=prefs, fuzzy=True, max_dist=1)

# Ajout manuel d'un produit
from tagsearch.models import ProductMeta, ProductType
meta = ProductMeta(
    name="Casque VR Pro",
    product_type=ProductType.PHYSICAL,
    niche="gaming",
    price=299.0,
    location="France",
    avg_rating=4.7,
    review_count=89,
    tags=["casque", "vr", "gaming", "tech"],
)
engine.add_product(11, meta)

API

SearchEngine.search(query, prefs, fuzzy, max_dist, top_k)

Paramètre Type Défaut Description
query str — Requête (normalisée en interne)
prefs SearchPreferences None Préférences de re-ranking
fuzzy bool True Recherche floue (Levenshtein + pruning)
max_dist int 1 Distance de Levenshtein max
top_k int 10 Nombre de résultats

Retourne (list[dict], status) où chaque dict contient : id, name, type, niche, price, rating, reviews, score.

SearchPreferences

Champ Type Effet
preferred_type ProductType | None Filtre doux : ×0.1 si mismatch
preferred_niche str | None Boost ×1.2 si match
max_price float | None Filtre dur : exclusion
min_price float | None Filtre dur : exclusion
user_location str | None Bonus ×1.15 si match
min_rating float Filtre dur : exclusion (défaut 0.0)

Formule de scoring

score = bm25_norm × quality_mult × type_factor × niche_boost × proximity × price_factor
  • bm25_norm = max(min(bm25_raw / 10.0, 1.0), 0.05)
  • quality_mult = (bayesian_rating / 5.0) ** 1.5
  • bayesian_rating = (count × rating + 3.5 × 10) / (count + 10)

Tests

python -m pytest tests/ -v
python -m pytest tests/ -v --tb=short   # affichage compact

19 tests, organisés en 4 sections :

  • TestBM25Components — composants IDF/TF isolés
  • TestScoringDimensions — TC01 à TC05 cross-langage
  • TestCrossLanguageFixtures — scores de référence stables
  • TestRobustness — gestion d'erreurs exhaustive

Benchmark

Opération Complexité Temps typique (10k tags)
Autocomplete O(L) < 0.1 ms
Fuzzy search (max_dist=1) O(L × ~5% nœuds) < 1 ms
Scoring 100 candidats O(n) < 0.5 ms
Cache HIT O(1) < 0.01 ms

L = longueur du préfixe/requête

Metadata

Release files for tagsearch 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tagsearch 1.0.1
File Size Uploaded Provenance
tagsearch-1.0.1.tar.gz 24.3 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for tagsearch 1.0.1
File Interpreter ABI Platform
tagsearch-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 42.5 kB

Release files / tagsearch-1.0.1.tar.gz

Download URL tagsearch-1.0.1.tar.gz
Size 24.3 kB
Tags Source
SHA-256 checksum
How to use checksums
6c3b0a4a0eae9b42474a919697e784d10add4d4f559003be90dc4ff25d86b732
BLAKE2b-256 checksum
How to use checksums
fc19504bfa4f14c014fe6072cddc53ab6f2984f2db8ac83d842074a6bae3bdca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / tagsearch-1.0.1-py3-none-any.whl

Download URL tagsearch-1.0.1-py3-none-any.whl
Size 18.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
910c858cb4e047be13e4626351e5e8f4a2a227300e6eba55da501220b17ed5db
BLAKE2b-256 checksum
How to use checksums
5c47dd92d83af506914a003aa8bef85438bf44132add68786347584d758a7466
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Security for tagsearch 1.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for tagsearch-1.0.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page