Aller au contenu
English

Propriété et source de vérité

  • Leçon 4
  • 50 min
  • Module 1 : Choisir le stockage selon la charge de travail

Ce que vous saurez faire

Décidez où conserver l’original de chaque donnée et où garder les copies. Ainsi, perdre une copie coûte du temps, jamais des données. Recréez ensuite une copie depuis son original.

Avant de commencerCe qu’il faut savoir et avoir sous la mainEnviron 50 minutes

Ce que vous devez savoir

Ce qu’il vous faut sur votre ordinateur

  • Le projet ~/projects/ticket-api avec les petites données chargées. python -m pytest affiche 34 passed (34 tests réussis).
  • Le dépôt des exercices ou son fichier ZIP dans ~/projects, provenant de De SQLite à PostgreSQL. Si vous l’avez cloné il y a un moment, exécutez d’abord git -C ../nextia-learning-labs pull dans le dossier du projet. Avec le fichier ZIP, téléchargez-le et décompressez-le à nouveau.
  • Facultatif : environ 2 Go d’espace disque libre pour un modèle de plongement (embedding). Sans lui, vous pouvez tout faire sauf la reconstruction. La leçon montre sa sortie.

Cette leçon ajoute trois fichiers à votre projet. À la fin, votre projet correspond à l’instantané end-of-m01.

La fiche de recette de votre grand-mère est dans un tiroir. Le dimanche, vous faites son gâteau avec cette recette.

Si le chien mange le gâteau, vous êtes contrarié, mais vous en faites un autre. Cela coûte de la farine, des œufs et une heure. Rien n’est perdu pour toujours, car la recette est encore dans le tiroir.

Imaginez maintenant l’inverse. La fiche a disparu, et il ne reste que le gâteau. Vous pouvez le goûter et deviner, mais vous ne pouvez pas retrouver la recette exacte à partir du gâteau.

La fiche est l’original. Le gâteau est une copie, faite depuis l’original avec une méthode : le four, le temps, l’ordre des étapes. Perdre une copie est sans danger seulement si son original et sa méthode existent encore.

Le problème : « tout garder dans la base de données vectorielle »

Section intitulée « Le problème : « tout garder dans la base de données vectorielle » »

Tomás a un plan pour la fonction de recherche de billets semblables. « Les bases de données vectorielles stockent aussi des métadonnées, dit-il. Mettons le texte, le statut et le client de chaque billet à côté de son vecteur. Comme ça, tout est au même endroit, et la recherche peut tout renvoyer. »

Mei pose une question : « Qu’arrive-t-il aux billets si on perd les vecteurs? »

Les vecteurs se perdent plus souvent que vous pourriez le penser. Un nouveau modèle de plongement rend tous les anciens vecteurs inutiles. Deux modèles placent le même texte à des endroits différents. Le module 5 le mesure. Un vecteur de requête issu d’un modèle a trouvé 0,4 % des bons voisins parmi les vecteurs d’un autre modèle. Il n’y avait aucune erreur. On supprime donc régulièrement les vecteurs pour les recréer. On supprime un index et on le reconstruit. Une migration se passe mal.

Essayez une perte dans votre propre projet. Ce cas est construit : vous supprimez volontairement tous les vecteurs. Ouvrez psql (docker compose exec db psql -U tickets -d tickets) et exécutez :

TRUNCATE ticket_embeddings;
SELECT count(*) AS tickets FROM tickets;
SELECT count(*) AS vectors FROM ticket_embeddings;

Les réponses sont 200 billets et 0 vecteur. TRUNCATE a supprimé toutes les lignes de ticket_embeddings et rien d’autre. Exécutez maintenant à nouveau la requête de billets semblables de la leçon de configuration :

SELECT ticket_id, subject FROM tickets ORDER BY (SELECT embedding FROM ticket_embeddings WHERE ticket_id = 'T-30002') <=> (SELECT embedding FROM ticket_embeddings e WHERE e.ticket_id = tickets.ticket_id) LIMIT 4;
ticket_id | subject
-----------+-----------------------------------
T-30002 | Charged twice for order LK-182074
T-30003 | Merge two accounts
T-30004 | robot vacuum not delivered
T-30001 | Tracking number does not work
(4 rows)

Il n’y a aucune erreur. Sans vecteurs, toutes les distances sont vides, donc PostgreSQL renvoie les billets dans un ordre quelconque. Vos lignes peuvent être différentes. La fonction ne marche plus, mais le service de soutien n’a perdu aucune donnée. Les 200 billets, leurs messages et leurs fichiers sont toujours là.

Dans la conception de Tomás, le même TRUNCATE aurait supprimé l’unique copie de 200 billets. Personne ne pourrait les recréer, car on ne peut pas reconvertir un vecteur en son texte. C’est le gâteau sans la fiche de recette.

Quittez psql avec \q. Vous recréerez les vecteurs plus loin dans cette leçon.

Pour chaque fait, un stockage est la source de vérité : celui qui garde l’original. Si deux stockages se contredisent, la source de vérité l’emporte. Ses données font autorité. Le terme système de référence désigne la même idée.

Tous les autres stockages gardent des données dérivées : une copie faite depuis un original par une méthode connue. On peut toujours recréer une copie dérivée. La perdre coûte donc du temps, pas des données. Une copie jetable est une copie dérivée que personne ne reconstruit. La requête suivante remplit à nouveau une entrée de cache.

Trois règles en découlent :

  1. Chaque fait a exactement un original, dans un seul stockage, avec une sauvegarde.
  2. Chaque copie indique ce qui a servi à la créer : quel original, quelle méthode et quelle version.
  3. Une copie n’est jamais le seul endroit qui conserve un fait. Sinon, ce n’est pas une copie : c’est un original dans le mauvais stockage.

La propriété va avec ces règles. Le stockage qui garde l’original possède le fait. Une modification va d’abord au propriétaire; les copies suivent.

Un petit exemple détaillé : la recette d’un vecteur

Section intitulée « Un petit exemple détaillé : la recette d’un vecteur »

Le vecteur de T-30002 est dérivé. Voici tout ce qui a servi à le créer. L’original est le texte du billet dans PostgreSQL : son sujet et son corps, séparés par un saut de ligne.

Charged twice for order LK-182074
My card was charged two times for order LK-182074, 449.00 dollars each time. Please refund one of the payments.

La méthode se trouve dans scripts/embed.py, que vous ajouterez au projet ci-dessous :

scripts/embed.py (part)
MODELS = { # embedding version: (model, revision, prefix, licence)
"e5-small-v1": (
"intfloat/multilingual-e5-small",
"614241f622f53c4eeff9890bdc4f31cfecc418b3",
"query: ",
"MIT",
),
...
}

Le modèle est intfloat/multilingual-e5-small, celui du cours RAG : créer une IA qui utilise vos données. La révision fixe une version exacte de ses fichiers : une autre révision pourrait donner d’autres nombres. Le texte reçoit le préfixe "query: ", et le résultat est normalisé à une longueur de 1. Le résultat contient 384 nombres.

Même original, même modèle, même révision, même préfixe : même vecteur. C’est toute la promesse d’une copie dérivée.

Un flux de gauche à droite. L'original : tickets.subject et body, dans PostgreSQL. Il passe par la recette : intfloat/multilingual-e5-small, révision 614241f, préfixe 'query : ', normalisation. Le résultat est la copie : ticket_embeddings, 200 vecteurs. De cette copie vient une copie de copie : l'index HNSW, dans le module 5. Une flèche pointillée part de la copie : perdue ou douteuse? Alors python -m scripts.embed --rebuild --all recrée la copie depuis le même original avec la même recette.
Comment les vecteurs de billets sont dérivés et recréés : le même original passe par la même recette.
Description textuelle du diagramme

L’original est le texte du billet dans PostgreSQL. La recette comprend le modèle, sa révision, le préfixe et la normalisation. La copie est constituée des 200 lignes de ticket_embeddings. L’index HNSW du module 5 est une copie de cette copie. Si la copie est perdue ou que personne ne lui fait confiance, python -m scripts.embed --rebuild --all la recrée. La commande utilise le même original et la même recette.

Mei écrit qui possède les données du service de soutien, pour que cette information ne reste pas seulement dans sa tête. Ajoutez sa carte et le script de reconstruction à votre projet.

  1. Dans le dossier du projet, copiez les trois fichiers de cette leçon depuis l’instantané end-of-m01. Si votre dossier d’exercices s’appelle nextia-learning-labs-main, utilisez ce nom.

    Fenêtre de terminal
    cp ../nextia-learning-labs/C20/snapshots/end-of-m01/docs/storage-map.md docs/
    cp ../nextia-learning-labs/C20/snapshots/end-of-m01/scripts/embed.py scripts/
    cp ../nextia-learning-labs/C20/snapshots/end-of-m01/requirements-embed.txt .
  2. Ouvrez docs/storage-map.md dans VS Code. Lisez le tableau de gauche à droite. Chaque ligne indique les données, le stockage de leur original et les stockages de leurs copies. La dernière colonne indique quoi faire lorsqu’une copie est perdue.

    docs/storage-map.md
    | Data | Original in | Copies in | If a copy is lost |
    |---|---|---|---|
    | Customers | PostgreSQL `customers` | none | not a copy: restore it from a backup |
    | Tickets and messages | PostgreSQL `tickets`, `messages` | ticket vectors (made from the text) | not a copy: restore it from a backup |
    | Files that customers attach | object storage (Azurite on your computer), one object per file | none | not a copy: back up the object storage separately |
    | File details (name, size, checksum, owner) | PostgreSQL `attachments` | none | restore it from a backup; check that every file still exists |
    | Policy documents | PostgreSQL `documents` (each version) | none | restore it from a backup |
    | AI runs (model, prompt version, tokens, cost) | PostgreSQL `ai_runs` | none | restore it from a backup |
    | Ticket vectors | none: they are a copy | PostgreSQL `ticket_embeddings` (pgvector) | make them again from the ticket text with the same model and version: `python -m scripts.embed --rebuild` |
    | Similar-ticket index (HNSW) | none: it is a copy | PostgreSQL index on `ticket_embeddings` | build it again: `REINDEX INDEX ...` or drop and create it |
    | Cached answers (if you add a cache) | none: they are a copy | the cache | nothing to do: the next request fills it again |

    Seul le tableau est affiché. Le fichier commence par une phrase qui décrit son rôle. Il se termine par deux règles. Chaque copie indique ce qui a servi à la créer. Une copie n’est jamais le seul endroit qui conserve un fait.

  3. Exécutez les tests :

    Fenêtre de terminal
    python -m pytest

    La dernière ligne est toujours 34 passed. Les nouveaux fichiers n’ajoutent aucun test : la carte est un document, et le script est facultatif.

Votre projet correspond maintenant à l’instantané end-of-m01. Deux lignes de la carte décrivent des éléments qui n’existent pas encore. L’index HNSW arrive au module 5, et le projet n’a pas de cache. Une carte peut montrer le plan et la situation actuelle, tant qu’elle les distingue.

La carte répond rapidement à une question difficile : que coûte chaque perte? Essayez chaque stockage.

Explorer

Perdre un stockage : qu'est-ce qui est perdu pour toujours?

Perdu pour de bon ou brisé
0 sur 8
Refait ou rempli de nouveau
2
Pas touché
6

Stockage perdu : la table des vecteurs et son index. Rien n’est perdu pour de bon : 2 données sont des copies, refaites ou remplies de nouveau à partir des originaux.

Stockage perdu : la table des vecteurs et son index
DonnéeRésultatCe qui arriveSon original
Un billetPas touchéPas dans ce stockage.PostgreSQL tickets, messages
Un messagePas touchéPas dans ce stockage.PostgreSQL tickets, messages
Une photo jointe par un clientPas touchéPas dans ce stockage.stockage objet (Azurite sur votre ordinateur), un objet par fichier
Un document de politiquePas touchéPas dans ce stockage.PostgreSQL documents (chaque version)
Une exécution d’IAPas touchéPas dans ce stockage.PostgreSQL ai_runs
Un vecteur de billetRefaitRefait à partir du texte des billets : python -m scripts.embed --rebuildcopie, faite à partir de l’objet et le corps du billet, avec le même modèle et la même version
L’index des billets semblables (HNSW)RefaitReconstruit à partir des vecteurs, une fois ceux-ci refaits.copie, faite à partir de les vecteurs des billets
Une réponse en cachePas touchéPas dans ce stockage.copie, faite à partir de la réponse de la base de données
Ce qui arrive à chaque donnée du service de soutien lorsqu'un stockage est perdu, selon les règles de docs/storage-map.md du projet. « Perdu pour toujours » signifie que seule une sauvegarde permet de récupérer la donnée.
Description textuelle de l’explorateur

L’explorateur a une seule commande : le stockage perdu. Les choix sont la table des vecteurs et son index, le stockage objet, le cache et toute la base de données PostgreSQL. Un tableau montre chacune des huit données, son résultat, ce qui arrive et l’emplacement de son original. Au-dessus du tableau, trois nombres comptent les données perdues pour toujours ou inutilisables, recréées ou remplies à nouveau, et intactes.

La table des vecteurs et son index : rien n’est perdu pour toujours. Les vecteurs de billets sont recréés depuis le texte des billets, et l’index HNSW est reconstruit depuis les vecteurs. Les six autres données restent intactes.

Le stockage objet : les photos sont perdues pour toujours, et les lignes de attachments pointent vers des fichiers manquants. Seule une sauvegarde du stockage objet permet de les récupérer.

Le cache : rien n’est perdu. La requête suivante le remplit à nouveau.

Toute la base de données PostgreSQL : cinq données sont perdues pour toujours ou inutilisables. Les billets, les messages, les documents de politiques et les exécutions d’IA ont disparu. Les photos restent dans le stockage objet, mais les lignes contenant leurs détails ont disparu. Personne ne sait donc à qui appartiennent ces fichiers : ce sont des fichiers orphelins. Les vecteurs et l’index ont aussi disparu, car ils résident dans PostgreSQL. On peut les recréer seulement après avoir récupéré les billets depuis une sauvegarde.

Perdre les vecteurs ne fait rien perdre pour toujours. Perdre PostgreSQL fait perdre presque tout, et rend même inutilisables les fichiers d’un autre stockage. Les originaux méritent des sauvegardes, et le module 5 les teste.

Cette partie nécessite un modèle de plongement, qui est volumineux. Il faut environ 1 Go de paquets (sentence-transformers 6.1.0 et torch 2.14.1) et un modèle de 470 Mo, téléchargé une fois. Le modèle utilise le processeur de votre ordinateur. Aucun compte ni aucune clé ne sont nécessaires. Si vous sautez cette partie, lisez les sorties. Puis remettez les vecteurs depuis les fichiers de données avec python -m scripts.load --reset.

  1. Installez les paquets facultatifs dans l’environnement virtuel du projet. Sous Linux, installez d’abord la version de torch pour processeur, avec la commande dans requirements-embed.txt.

    Fenêtre de terminal
    python -m pip install -r requirements-embed.txt
  2. Vos vecteurs sont toujours supprimés. Vérifiez d’abord que l’original est complet : python -m scripts.load --reset recharge les petites données avec les vecteurs qui les accompagnaient. Comparez ensuite ces vecteurs stockés à de nouveaux vecteurs, créés maintenant depuis le texte des billets :

    Fenêtre de terminal
    python -m scripts.embed --check
    Embedded 200 tickets with intfloat/multilingual-e5-small in 5.3 s.
    Largest difference from the stored vectors: 4.99e-08 (the same, apart from rounding).

    La première exécution télécharge aussi le modèle, donc elle prend plus de temps. Un avertissement sur HF_TOKEN et « unauthenticated requests » (requêtes non authentifiées) est sans danger. Le modèle est public et ne nécessite aucun jeton.

  3. Lisez le résultat. Pour chacun des 200 billets, le script a recréé les 384 nombres et les a comparés aux nombres stockés. Le plus grand écart parmi les 76 800 nombres est de 0,0000000499. Les vecteurs stockés ont été arrondis à 7 chiffres significatifs lors de l’enregistrement. C’est donc un arrondi, pas un changement. La copie correspond à son original.

  4. Provoquez maintenant la perte et la reconstruction. Dans psql, exécutez à nouveau TRUNCATE ticket_embeddings;, puis quittez. Reconstruisez ensuite depuis l’original :

    Fenêtre de terminal
    python -m scripts.embed --rebuild --all
    Embedded 200 tickets with intfloat/multilingual-e5-small in 5.1 s.
    Stored 200 vectors of version e5-small-v1.
  5. Vérifiez la copie reconstruite et exécutez à nouveau la requête de billets semblables de la leçon de configuration dans psql :

    Fenêtre de terminal
    python -m scripts.embed --check
    Embedded 200 tickets with intfloat/multilingual-e5-small in 4.9 s.
    Largest difference from the stored vectors: 4.99e-08 (the same, apart from rounding).

    La requête renvoie encore T-30002, T-30050, T-30168 et T-30064. Ce sont les mêmes quatre billets « Charged twice » (facturé deux fois) qu’avant la perte.

Vos temps seront différents. Sur l’ordinateur du cours, --check a pris 5,3 secondes pour 200 billets. Les 10 000 vecteurs des grandes données ont pris 24,8 secondes. Dans le module 5, construire leur index HNSW prend 0,36 seconde. Une reconstruction coûte des secondes ou des minutes, jamais des données.

Sans le modèle, python -m scripts.load --reset récupère aussi les vecteurs. C’est une opération différente : elle restaure une copie sauvegardée des vecteurs, fournie avec les données. Une reconstruction les crée depuis l’original. Les deux fonctionnent ici. Seule la reconstruction fonctionne encore après un changement de modèle, de texte ou de version.

Erreur courante

La reconstruction stocke 0 vecteur

Symptôme : après la perte de tous les vecteurs, python -m scripts.embed --rebuild affiche ceci. La requête de billets semblables renvoie encore des billets sans rapport :

Embedded 0 tickets with intfloat/multilingual-e5-small in 4.3 s.
Stored 0 vectors of version e5-small-v1.

Cause : --rebuild recrée les vecteurs qui existent : la commande calcule les plongements des billets qui ont déjà un vecteur. Cette règle limite les grandes données aux 10 000 billets les plus récents. Après une perte totale, aucun billet n’a de vecteur, donc la liste est vide. La copie était le seul relevé des billets qu’elle couvrait.

Diagnostic : SELECT count(*) FROM ticket_embeddings; donne 0 avant et après la reconstruction.

Correction : exécutez python -m scripts.embed --rebuild --all. La commande calcule un plongement pour chaque billet dans l’original. Dans les petites données, chaque billet a un vecteur, donc --all recrée exactement les 200 vecteurs. Dans les grandes données, --all créerait 300 000 vecteurs, pas seulement les 10 000 plus récents. La règle « quels billets reçoivent un vecteur » doit s’appuyer sur l’original, pas seulement sur la copie.

Gardez une copie dérivée lorsqu’elle répond à une question à laquelle l’original ne peut pas répondre rapidement, ou pas du tout. Les vecteurs répondent à la question « billets semblables ». L’index HNSW rend cette recherche rapide. Un cache conserve une réponse lente à produire et souvent demandée.

Chaque copie a un prix :

  • Une recette à conserver. Le nom du modèle, sa révision, le préfixe et la version doivent être enregistrés avec la copie. Le module 5 ajoute une version de plongement et une somme de contrôle du texte à chaque vecteur.
  • Du temps pour reconstruire. Des secondes pour 200 billets, des minutes pour plusieurs milliers. Prévoyez où la recherche trouvera ses réponses pendant la reconstruction d’une copie.
  • Les copies peuvent devenir périmées. Quand le texte d’un billet change, son vecteur est périmé jusqu’à ce que quelqu’un le recrée. Le module 5 repère ces « vecteurs périmés ».
  • La suppression doit atteindre chaque copie. Grace demande : « Si un client nous demande de supprimer ses données, est-ce qu’on peut? » Oui, mais seulement si vous supprimez l’original et chaque copie. La carte les répertorie toutes. Le module 5 le fait.

Le prochain projet de Larkfield est un assistant documentaire. Le personnel téléverse des politiques en PDF, et l’assistant répond aux questions à partir de ces documents, avec des citations. C’est le principe présenté dans RAG : créer une IA qui utilise vos données. Pour chaque donnée, choisissez un stockage et indiquez s’il s’agit d’un original ou d’une copie. Pour une copie, indiquez ce qui sert à la créer.

  1. Les fichiers PDF téléversés.
  2. Les détails de chaque document : titre, propriétaire, version, personnes autorisées à le lire.
  3. Le texte extrait de chaque page.
  4. Les segments : des morceaux du texte d’environ 300 mots chacun.
  5. Un vecteur pour chaque segment.
  6. L’index vectoriel des vecteurs de segments.
  7. Les conversations : chaque question, la réponse et les segments cités.
  8. Chaque appel au modèle : modèle, jetons, coût, temps.
  9. Les réponses en cache aux dix questions les plus fréquentes.
Afficher un exemple de réponse
Données Stockage Original ou copie
Fichiers PDF stockage objet original
Détails et autorisations des documents base de données relationnelle original
Texte des pages base de données relationnelle copie, créée depuis le PDF par un extracteur de texte (conservez sa version)
Segments base de données relationnelle copie, créée depuis le texte des pages par une règle de découpage (taille et chevauchement)
Vecteurs de segments index vectoriel (par exemple pgvector) copie, créée depuis les segments par un modèle de plongement et une révision
Index vectoriel index vectoriel copie d’une copie, construite depuis les vecteurs de segments
Conversations base de données relationnelle original : une réponse qui a été donnée ne peut pas être recréée
Appels au modèle base de données relationnelle original : les jetons et le coût correspondent à un événement unique
Réponses en cache cache copie jetable; elle doit expirer lorsqu’un document change

Vérifiez trois choses dans votre propre réponse. Premièrement, la chaîne de copies commence par un original qui a une sauvegarde : les PDF et leurs détails. Deuxièmement, les conversations sont des originaux, même si un modèle a écrit les réponses. La même question posée à nouveau peut recevoir une réponse différente. Troisièmement, une nouvelle version de document doit atteindre chaque copie qui en découle : texte des pages, segments, vecteurs, index et cache.

Vous avez terminé le module 1 quand vous pouvez montrer ces éléments dans votre propre projet :

  • python -m scripts.load --reset affiche les petits nombres, et python -m pytest affiche 34 passed (34 tests réussis).
  • docs/storage-map.md est dans votre projet, et vous pouvez nommer l’original de chaque ligne.
  • Vérification de fin de module : vous pouvez expliquer comment reconstruire un index dérivé à partir des données faisant autorité. Utilisez les vecteurs des billets de soutien : l’original, la recette, la commande et la vérification du résultat. Avec le modèle facultatif, montrez-le : python -m scripts.embed --check affiche une différence maximale d’environ 4.99e-08.

Réinitialisation. Si votre projet ne fonctionne plus, renommez-le et copiez l’instantané end-of-m01. Gardez votre .env. Dans ~/projects :

Fenêtre de terminal
mv ticket-api ticket-api-old
cp -R nextia-learning-labs/C20/snapshots/end-of-m01 ticket-api
cp ticket-api-old/.env ticket-api/

Sur Windows, dans PowerShell, dans ~/projects : Rename-Item ticket-api ticket-api-old, puis Copy-Item -Recurse nextia-learning-labs\C20\snapshots\end-of-m01 ticket-api, puis Copy-Item ticket-api-old\.env ticket-api\. Recréez l’environnement virtuel, comme dans la leçon de configuration, et exécutez python -m scripts.load --reset.

Vérifiez votre compréhension

Dans vos mots : qu'est-ce qu'une source de vérité, et quand peut-on perdre une copie sans risque? Prenez les vecteurs des billets comme exemple.

Afficher la réponse

La source de vérité est le seul stockage qui conserve l’original d’un fait. Si les stockages se contredisent, elle fait autorité. Pour un billet, c’est la table tickets dans PostgreSQL. On peut perdre une copie sans risque seulement si son original et sa recette existent encore. Les vecteurs des billets sont produits à partir du texte des billets par intfloat/multilingual-e5-small, à une révision fixe, avec le préfixe "query: ". Si vous les perdez, python -m scripts.embed --rebuild --all les recrée avec le même texte et la même recette.

Vérifiez votre compréhension

Vérification de fin de module : expliquez comment reconstruire l'index des billets similaires (HNSW, du module 5) après la perte complète de la table des vecteurs. Partez des données faisant autorité. Nommez chaque étape et sa vérification.

Afficher la réponse

Les données faisant autorité sont le texte des billets dans tickets. Les vecteurs et l’index sont tous deux dérivés. Recréez d’abord les vecteurs à partir du texte, avec le modèle, la révision et le préfixe consignés : python -m scripts.embed --rebuild --all. Utilisez --all (tous), car après une perte totale, aucun billet n’a de vecteur à reconstruire. Ensuite, reconstruisez l’index à partir des vecteurs : supprimez-le et créez-le, ou utilisez REINDEX (réindexer). Vérifiez avec python -m scripts.embed --check : la différence maximale est d’environ 4.99e-08. Vérifiez ensuite une recherche connue : les billets les plus proches de T-30002 sont T-30050, T-30168 et T-30064.

Vérifiez votre compréhension

Prédisez : Tomás conserve le texte de chaque billet uniquement comme métadonnées dans une base de données vectorielle. L'équipe change de modèle de plongement. Que doit-il arriver aux vecteurs, et d'où vient le texte?

Afficher la réponse

Il faut recréer chaque vecteur. Les vecteurs de deux modèles ne se mélangent pas : le module 5 n’a mesuré que 0,4 % de voisins corrects après leur mélange. Pour recréer les plongements, il faut le texte. Dans la conception de Tomás, le texte existe seulement à côté des anciens vecteurs. La base de données vectorielle est donc maintenant l’original, dans un stockage régulièrement supprimé et reconstruit. Une seule mauvaise reconstruction fait perdre les billets pour de bon. Gardez le texte dans PostgreSQL et traitez les vecteurs comme une copie.

Récapitulatif

  • La source de vérité conserve l’original d’un fait (les données faisant autorité). Les données dérivées sont une copie produite selon une recette connue. Une copie jetable, comme une entrée de cache, n’est même pas reconstruite.
  • Trois règles. Chaque fait a un seul original, avec une sauvegarde. Chaque copie consigne ce qui a servi à la produire. Une copie n’est jamais le seul endroit où un fait est conservé.
  • Une perte provoquée de tous les vecteurs a brisé la recherche de billets similaires, sans erreur et sans perte de données : 200 billets restaient.
  • python -m scripts.embed --check a prouvé que les vecteurs stockés correspondent à leur original : une différence maximale de 4.99e-08. --rebuild --all les a recréés à partir du texte des billets.
  • docs/storage-map.md, scripts/embed.py et requirements-embed.txt sont dans le projet, qui correspond maintenant à end-of-m01. python -m pytest affiche 34 passed.

Vous avez terminé le module 1. Dans le module 2, les originaux reçoivent des règles : clés, contraintes et transactions qui gardent les données correctes dans PostgreSQL.

Leçon suivante : Entités et relations