Accueil / Articles / 68e889b14c39 pour les systèmes de production — contrats et vérifications

68e889b14c39 pour les systèmes de production — contrats et vérifications

Guide opérationnel pour 68e889b14c39 destiné aux systèmes de production — contrats et vérifications : contrats, vérifications, ainsi que des emplacements pour du code à insérer destinés aux équipes qui implémentent ce modèle.

1374 mots

Les notes suivantes reconstituent une approche pratique pour travailler avec “”. L’accent est mis sur les contrats, les vérifications et les placeholders de code plutôt que sur une présentation motivante. Lors de la phase d’aperçu, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce du coût évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés.

1. Les embeddings transforment le sens en géométrie

La phase de transformation des significations par les 1 embeddings fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Séparez la politique de segmentation des données de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité évoluent.

# pip install openai
# export OPENAI_API_KEY=sk-...
import math

from openai import OpenAI

client = OpenAI()


def embed(texts):
    resp = client.embeddings.create(
        model="text-embedding-3-small",
        input=texts,
    )
    return [d.embedding for d in resp.data]


def cosine(a, b):
    dot = sum(x * y for x, y in zip(a, b))
    na = math.sqrt(sum(x * x for x in a))
    nb = math.sqrt(sum(y * y for y in b))
    return dot / (na * nb)


q, hit, miss = embed([
    "How do I get my money back?",
    "Refunds are possible within 14 days "
    "of purchase.",
    "Data is stored in Frankfurt and "
    "encrypted at rest.",
])

print(f"refund doc:  {cosine(q, hit):.3f}")
print(f"storage doc: {cosine(q, miss):.3f}")

2. Un stockage vectoriel est une liste que l’on peut classer

La phase de stockage vectoriel 2A fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple réussi, un cas d’échec ainsi que la note de réversion avant d’élargir le périmètre. Documentez en même temps le parcours optimal et celui de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Fixez les versions des dépendances et enregistrez le digest de l’image ayant servi à la démonstration. La reproductibilité vaut mieux que les connaissances propres à un groupe.

class VectorStore:
    def __init__(self):
        self.texts = []
        self.vectors = []

    def add(self, texts):
        self.texts.extend(texts)
        self.vectors.extend(embed(texts))

    def top_k(self, query, k=3):
        q = embed([query])[0]
        scored = [
            (cosine(q, v), t)
            for v, t in zip(
                self.vectors, self.texts
            )
        ]
        scored.sort(
            key=lambda s: s[0], reverse=True
        )
        return scored[:k]


store = VectorStore()
store.add([
    "Refunds are possible within 14 days.",
    "The Pro plan costs 12 EUR per month.",
    "Data is stored in Frankfurt.",
])

for score, text in store.top_k(
    "can I cancel and get a refund?", k=2
):
    print(f"{score:.3f}  {text}")

3. Le pipeline complet : récupérer, enrichir, générer

La phase complète du pipeline fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemplaire idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’erreur doit pointer vers une seule responsabilité plutôt que vers un pipeline embrouillé. Séparez la politique de segmentation de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité évoluent. La phase complète du pipeline fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemplaire idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés.

# examples/part07_rag.py
# Mini RAG in ~90 lines: embed -> store -> top-k
# -> stitch into messages -> generate.
#
# Setup:
#   pip install openai
#   export OPENAI_API_KEY=sk-...
#
# Run:
#   python part07_rag.py

import math

from openai import OpenAI

client = OpenAI()

EMBED_MODEL = "text-embedding-3-small"
CHAT_MODEL = "gpt-4o-mini"

# A tiny corpus. In real life these are chunks
# of your docs, not whole documents.
DOCS = [
    "Support hours are 9am to 6pm CET, "
    "Monday to Friday.",
    "Refunds are possible within 14 days "
    "of purchase, no questions asked.",
    "The Pro plan costs 12 EUR per month "
    "and includes API access.",
    "The Free plan allows 3 projects and "
    "community support only.",
    "Data is stored in Frankfurt and "
    "encrypted at rest with AES-256.",
    "You can export all your data as "
    "JSON from the settings page.",
]


def embed(texts):
    resp = client.embeddings.create(
        model=EMBED_MODEL,
        input=texts,
    )
    return [d.embedding for d in resp.data]


def cosine(a, b):
    dot = sum(x * y for x, y in zip(a, b))
    na = math.sqrt(sum(x * x for x in a))
    nb = math.sqrt(sum(y * y for y in b))
    return dot / (na * nb)


class VectorStore:
    """A list of (vector, text) pairs. That is
    all a vector store is, before you need
    scale."""

    def __init__(self):
        self.texts = []
        self.vectors = []

    def add(self, texts):
        self.texts.extend(texts)
        self.vectors.extend(embed(texts))

    def top_k(self, query, k=3):
        q = embed([query])[0]
        scored = [
            (cosine(q, v), t)
            for v, t in zip(
                self.vectors, self.texts
            )
        ]
        scored.sort(key=lambda s: s[0], reverse=True)
        return scored[:k]



def build_messages(question, hits):
    context = "\n\n".join(
        f"[{i + 1}] {text}"
        for i, (_, text) in enumerate(hits)
    )
    system = (
        "Answer using only the context below. "
        "If the answer is not in the context, "
        "say you do not know.\n\n"
        "Context:\n" + context
    )
    return [
        {"role": "system", "content": system},
        {"role": "user", "content": question},
    ]


def ask(store, question):
    hits = store.top_k(question, k=3)
    print(f"Q: {question}")
    for score, text in hits:
        print(f"  {score:.3f}  {text[:44]}...")
    messages = build_messages(question, hits)
    resp = client.chat.completions.create(
        model=CHAT_MODEL,
        messages=messages,
    )
    return resp.choices[0].message.content


if __name__ == "__main__":
    store = VectorStore()
    store.add(DOCS)

    answer = ask(
        store,
        "Where is my data stored, and can "
        "I get it out?",
    )
    print(f"A: {answer}")

Où la version simplifiée échoue

Pour l’étape « Where the toy version », définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les flags fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système. Ajoutez un test de fumée qui exerce le chemin critique dans l’CI en utilisant des fixtures, et non des API payantes en temps réel, chaque fois que le budget le permet.

Liste de contrôle opérationnelle

Pour l’étape « Liste de contrôle opérationnelle », définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché.

Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès, et refusez les terminaisons partielles silencieuses.

Ajoutez un test de base qui met à l’épreuve le chemin critique dans le CI en utilisant des fixtures, et non des API payantes en ligne, chaque fois que le budget le permet.

Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un pipeline embrouillé.

Fixez les versions des dépendances et enregistrez le digest de l’image ayant exécuté la démonstration. La reproductibilité vaut mieux que les connaissances internes au groupe.

Dokumentez à la fois le parcours normal et le parcours de récupération. Les tentatives de réessai, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’une mise en forme ultérieure.

Au préalable de promouvoir l’ensemble technique, figez les versions, conservez une transcription exemplaire pour le chemin critique, et confirmez les étapes de réversion. Les environnements partagés nécessitent des limites de débit, des vérifications d’attribution, ainsi qu’un responsable clair pour la rotation des secrets. Préférez une fiabilité sans faille à des démonstrations brillantes mais ponctuelles.

Note de batch pour 68e889b14c39 : gardez les clés du fournisseur hors du répertoire, fixez un plafond pour les tokens par session, et stockez les transcriptions à côté des fichiers de configuration d’évaluation afin que les remplacements ultérieurs de modèles restent comparables.