Skip to content

[biblio-ref] add new route (pps-search) - #472

Open
leogail wants to merge 3 commits into
mainfrom
services/biblio-ref/extract-detectors-pps
Open

[biblio-ref] add new route (pps-search)#472
leogail wants to merge 3 commits into
mainfrom
services/biblio-ref/extract-detectors-pps

Conversation

@leogail

@leogail leogail commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Je me pose plusieurs questions sur cette route :

  • Nom du champ
  • Format de la sortie
  • Autorisation des tableaux en entrée
  • Nom de la route

Toute suggestion est la bienvenue !

@parmentf

Copy link
Copy Markdown
Contributor

Pour le nom du champ, j'ai demandé conseil, et voilà ce que j'ai eu comme réponse:

Le terme Detectors apparaît dans 3 contextes :

  1. La description API (pps-search.ini:6) : « retourne sa ou ses Detectors » — c'est le nom officiel des catégories dans le système PPS SPIE
  2. Le nom du champ : {"classes": ["suspect", "tortured"]} — c'est un choix d'implémentation
  3. Les tests : jsonpath "$[*].value.classes" — vérifient le champ implémenté

Le développeur a fait un choix sémantiquement ambigu : classes ressemble à un mot-clé générique (classe d'un objet, classe de produits, etc.) alors que les valeurs réelles (suspect, tortured, annulled, mathgen, clayfeet, expression-of-concern) sont des labels de qualité attribués aux articles.

Voici mes recommandations, de la meilleure à la bonne :

Nom Verdict Pourquoi
tags ✅ Meilleur choix Générique, conventionnelle dans les APIs, court, sémantiquement clair : ce sont des labels/marques attribués à un DOI. {"tags": ["suspect", "tortured"]} se lit naturellement.
labels ✅ Très bon Similaire à tags mais implique une attribution un peu plus formelle. Un peu plus long.
detectors ⚠️ Techniquement juste mais ambigu C'est le nom SPIE, mais c'est aussi un mot anglais qui peut sembler technique ou incompréhensible pour un consommateur non-francophone. De plus, "detector" évoque un outil/entité, pas une propriété du DOI.
classes ❌ À éviter Trop générique. Ressemble à une classe OOP, une catégorie de produits, ou quelque chose de mathématique. Ne communique pas l'intention.
problem_types / flag_types ⚠️ Trop verbeux Exact mais lourd. Un consommateur API n'a pas besoin de cette précision dans le nom de champ.

Ma recommandation : tags

C'est le compromis idéal :

  • Sémantiquement juste : ce sont des tags/labels attachés à un DOI
  • Conventionnelle : tags est un pattern ubiquitaire dans les APIs modernes
  • Court : {"tags": ["annulled"]} vs {"detectors": ["annulled"]}
  • Autonome : un développeur qui découvre l'API comprend immédiatement, contrairement à detectors qui nécessite une lecture de la doc pour savoir que ce sont des labels SPIE

Si la cohérence avec le système SPIE est importante, labels est un excellent second choix — il garde la même sémantique mais avec un ton un peu plus formel.

Impact sur le code

Si le développeur choisit tags (ou labels), les modifications sont mineures et isolées :

  • pps-search.py : nom du champ dans les dicts de sortie
  • pps-search.ini : exemples dans la doc OpenAPI
  • tests.hurl : assertions jsonpath "$[*].value.tags"
  • examples.http : exemples de réponse

C'est un changement de nomenclature qui vaut vraiment le coup avant merge — c'est l'un des few noms de champ qui seront figés dans le contrat de l'API.

Comment thread services/biblio-ref/v1/pps-search.py Outdated
Comment on lines +11 to +13
def get_classes_for_doi(doi):
doi_lower = doi.lower()
return [classe for classe, dois in all_classes.items() if doi_lower in dois]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: 🟡 Performance : structure de données sous-optimale

La fonction get_classes_for_doi parcourt toutes les classes pour chaque DOI :

def get_classes_for_doi(doi):
    doi_lower = doi.lower()
    return [classe for classe, dois in all_classes.items() if doi_lower in dois]

C'est O(n × m) où n = nombre de classes et m = DOIs par classe. Une structure inversée doi → set(classes) donnerait des recherches O(1) :

# csv2pickle-all.py — après avoir construit classes_dict
doi_to_classes = {}
for classe, dois in classes_dict.items():
    for doi in dois:
        doi_to_classes.setdefault(doi, set()).add(classe)
pickle.dump(doi_to_classes, file)

Pour un dataset PPS de quelques milliers d'entrées, la différence est négligeable aujourd'hui, mais cela ne scale pas et le code est plus clair avec la structure inversée.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En fait l'objet all_class n'est pas un json. C'est un dictionnaire d'ensemble, qui ressemble à :

{"label_1" : {"doi_1", "doi_2", ...}, "label_2": { ... }}

L'objectif était d'éviter la conversion de list en set à chaque appel. Le fichier a donc été sauvegardé sous cette forme.

Donc la complexité était bien de O(n) où n = nombre de classes (19 ici).

Mais inverser le dictionnaire est encore meilleur ! Je modifie le code en condéquence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants