---
title: "Comment alimenter Amazon Bedrock Knowledge Bases avec des données web en direct grâce à Bright Data"
slug: amazon-bedrock-knowledge-bases-with-bright-data
date: 2026-10-15T18:45:42+00:00
modified: 2026-10-15T18:45:45+00:00
permalink: https://brightdata.fr/blog/savoir-faire/amazon-bedrock-knowledge-bases-with-bright-data
type: blog
---

[ Blog ](https://brightdata.fr/blog "Blog") / [How Tos](https://brightdata.fr/blog/savoir-faire)







 [How Tos](https://brightdata.fr/blog/savoir-faire)

# Comment alimenter Amazon Bedrock Knowledge Bases avec des données web en direct grâce à Bright Data

Bright Data permet à Amazon Bedrock Knowledge Bases d’accéder aux données web bloquées par le rendu JavaScript, la protection anti-bot, ou les restrictions géographiques.

 56 min de lecture





 [ ![Satyam Tripathi](https://media.brightdata.fr/2024/09/Satyam-Tripathi-50x50.png) ](https://brightdata.com/blog/authors/satyam-tripathi)

 [Satyam Tripathi

Technical Writer

 ](https://brightdata.com/blog/authors/satyam-tripathi)





 ![Amazon Bedrock Knowledge Bases with Bright Data](https://media.brightdata.fr/2026/08/Amazon-Bedrock-Knowledge-Bases-with-Bright-Data.png)





Amazon Bedrock Knowledge Bases est un service géré pour la génération augmentée par récupération (RAG). Pointez-le vers une source de données, et il découpe, vectorise et indexe vos documents, puis répond aux requêtes avec des citations. Ses connecteurs incluent Amazon S3, SharePoint, et un Web Crawler natif pour les pages publiques.

Ce crawler couvre le web coopératif. De nombreux catalogues produits, marketplaces et sites d’actualités se rendent avec JavaScript, se trouvent derrière une protection anti-bot, ou servent un contenu différent selon le pays. Le crawler renvoie une coquille vide, un blocage, ou le contenu du mauvais pays. Ce guide alimente ces pages dans une base de connaissances via Bright Data et S3.

## En résumé

- Web Unlocker renvoie une page publique en Markdown en une seule requête, sauf si la page nécessite une interaction. Écrivez chaque page sur S3 sous forme de `.md` plus un fichier annexe `.metadata.json`.
- Hachez le contenu avant l’écriture, pour qu’un rafraîchissement ré-intègre les pages que vous avez réécrites au lieu de tout le corpus.
- Mesurez la récupération par rapport à un ensemble de référence avant de passer à l’échelle, car votre découpage est défini sur la source de données et les clés de métadonnées non filtrables sont définies sur un index S3 Vectors. Vous ne pouvez modifier ni l’un ni l’autre par la suite.
- Routez par requête. Basculez vers une recherche en direct lorsque le score le plus élevé est en dessous d’un seuil de pertinence.

## Pourquoi le Web Crawler natif laisse un vide

La [source de données Web Crawler](https://docs.aws.amazon.com/bedrock/latest/userguide/webcrawl-data-source-connector.html) est un connecteur propriétaire, et pour vos propres pages statiques, c’est un bon choix. Aujourd’hui, ses contraintes laissent les données web publiques à grande échelle à Bright Data.

- **Il prend en charge les sites web statiques.** La documentation le dit directement, et le crawler ne récupère pas les pages qui se rendent côté client. De nombreux catalogues, tableaux de bord et pages de listing se rendent ainsi, donc le crawler voit une coquille vide là où les données devraient être.
- **Il est conçu pour le web coopératif.** Le crawler respecte le `robots.txt` selon la [RFC 9309](https://www.rfc-editor.org/rfc/rfc9309.html), et considère le site comme interdit quand il n’en trouve aucun. Il s’identifie comme `bedrockbot`, et s’arrête devant la protection anti-bot par conception.
- **Il plafonne à 25 000 pages par synchronisation, et prend en charge un seul magasin vectoriel.** Si vous dépassez cette limite, la synchronisation échoue et n’ingère rien. Ce magasin est actuellement Amazon OpenSearch Serverless, donc S3 Vectors n’est pas une option avec le crawler.
- **Il renvoie des pages, pas des enregistrements propres.** Le crawler ingère du HTML. La navigation, les bannières de cookies et le texte générique arrivent avec le contenu, et il n’y a aucune étape d’extraction structurée. Vos chunks transportent le bruit jusque dans les vecteurs.

La console étiquette le Web Crawler comme « Preview » sur l’écran où vous le sélectionnez :

![Assistant Amazon Bedrock create-knowledge-base, Choisir le type de source de données. Amazon S3 est sélectionné et sa carte note que vous pouvez ajouter jusqu'à 5 buckets comme sources de données. Confluence, Salesforce, SharePoint et Web Crawler sont tous étiquetés Preview, et Custom ne l'est pas. Un encadré rouge marque la carte Web Crawler.](https://media.brightdata.com/2026/08/Sy9Mv2Zvze.png)Rien de tout cela ne fait du crawler un mauvais choix pour les pages statiques et coopératives pour lesquelles il a été conçu. Dans le [rapport *Données pour l’IA* 2026](/ai/data-for-ai-report) de Bright Data, 90 % des organisations IA ont déclaré que les restrictions d’accès limitent leurs initiatives. [Cloudflare a reclassifié les crawlers IA](https://techcrunch.com/2026/07/01/cloudflares-new-policy-pushes-ai-companies-to-pay-for-publishers-content/) en juillet 2026. Elle a annoncé qu’elle bloquerait par défaut les crawlers à usage mixte à partir du 15 septembre 2026, sur les pages financées par la publicité pour les nouveaux clients, les nouveaux sites, et les comptes gratuits inchangés. Maintenir l’accès fonctionnel demande un effort continu, et Bright Data le fait pour vous.

## L’architecture

Le pipeline transforme une liste d’URL publiques en une base de connaissances consultable et citée, et la maintient à jour. Bright Data gère l’accès et la conversion en Markdown. S3 est le point de passage. Bedrock gère l’indexation et la récupération.

![Diagramme de flux. Les URL publiques vont vers Bright Data Web Unlocker, qui renvoie du Markdown. Une Loader Lambda écrit des fichiers .md plus des fichiers annexes .metadata.json sur Amazon S3. Une Bedrock Knowledge Base synchronise ce bucket, vectorise vers un magasin vectoriel, et renvoie des réponses citées à une Application.](https://media.brightdata.com/2026/08/SkyEDnZwfg.png)Le diagramme montre le chemin principal :

1. Le loader appelle le Web Unlocker de Bright Data pour la protection anti-bot, le routage géographique et le rendu JavaScript, et récupère la page sous forme de Markdown.
2. Le loader écrit ensuite chaque page sur Amazon S3 sous forme d’un document `<slug>.md` plus un fichier annexe `<slug>.md.metadata.json`.
3. La base de connaissances synchronise la source de données S3 avec `StartIngestionJob`, et les exécutions ultérieures sont incrémentielles.
4. Bedrock découpe chaque document, le vectorise avec Titan Text Embeddings V2, et écrit les vecteurs dans un magasin tel qu’Amazon S3 Vectors ou OpenSearch Serverless.
5. Une application appelle `Retrieve` pour des chunks bruts ou `RetrieveAndGenerate` pour une réponse ancrée et citée.

Trois éléments de l’enveloppe de production se trouvent en dehors de ce chemin principal, et le diagramme ne les montre pas. Une planification Amazon EventBridge déclenche le loader aussi souvent que vous le choisissez, AWS Secrets Manager contient le jeton Bright Data, et la base de connaissances assume un rôle IAM à privilège minimal. Le diagramme représente le loader comme une Lambda, qui est là où il s’exécute une fois planifié. Ci-dessous, vous exécutez le loader depuis votre propre machine, pour pouvoir observer chaque étape d’abord.

Écrire sur S3 est un choix plutôt qu’un défaut, car vous pouvez aussi envoyer des documents directement via une source de données personnalisée et l’API `IngestKnowledgeBaseDocuments`. Le bucket est la meilleure option pour un corpus scrapé. Les objets restent rejouables, les fichiers annexes vous permettent d’inspecter le contrat de métadonnées, et une exécution échouée laisse le corpus précédent intact. L’API Crawl de Bright Data livre aussi nativement dans le même bucket.

## Prérequis

- Un compte AWS avec accès à Amazon Bedrock dans une Région prise en charge, et Amazon Titan Text Embeddings V2 (`amazon.titan-embed-text-v2:0`) activé là-bas. Plus un modèle de génération dans la même Région, si vous voulez des réponses rédigées à l’Étape 5 plutôt que des chunks bruts.
- Un principal IAM capable de créer des buckets S3, des bases de connaissances et sources de données Bedrock, un magasin vectoriel, et le rôle de service IAM que la base de connaissances assume. Le [dépôt compagnon](https://github.com/luminati-io/bedrock-web-kb-brightdata) liste les énoncés de politique exacts.
- Un compte Bright Data avec un jeton API et une zone **Web Unlocker**. Chaque requête référence la zone par son nom. Un niveau gratuit couvre les 5 000 premiers crédits chaque mois, ce qui suffit pour parcourir chaque étape ci-dessous. Vérifiez l’allocation et le tarif actuels sur la [tarification Web Unlocker](/pricing/web-unlocker), puis définissez une limite de dépense sur la zone.
- Python 3.10 ou ultérieur avec `boto3` et `requests`.
- Une connaissance pratique d’Amazon S3 et IAM.

Le modèle de vectorisation définit votre dimension vectorielle, et l’index de votre magasin vectoriel doit y correspondre. Si vous créez le magasin manuellement et que les deux sont en désaccord, l’ingestion échoue au moment de l’écriture. Titan Text Embeddings V2 prend en charge 256, 512, ou 1024 dimensions.

Vérifiez votre quota de vectorisation avant de construire quoi que ce soit, car il peut être nul et rien dans le flux de création ne vous avertit. Un nouveau compte peut avoir un quota à la demande de 0 requête par minute pour le modèle de vectorisation. Ce quota vous laisse créer la base de connaissances et la source de données normalement, puis échoue à chaque tâche d’ingestion. Confirmez-le en un appel, et demandez une augmentation dans Service Quotas s’il indique zéro :

```none
aws service-quotas list-service-quotas --service-code bedrock --region YOUR_REGION \
  --query "Quotas[?contains(QuotaName,'Titan Text Embeddings V2')].[QuotaName,Value]" --output text
```

Exécutez-le contre la Région que vous avez réellement l’intention d’utiliser, car AWS définit le quota par Région, et la différence peut être totale. Dans un compte, le même jour, Titan Text Embeddings V2 avait un quota à la demande appliqué de 0 requête par minute et 0 jeton par minute dans US East (Virginie du Nord) :

![AWS Service Quotas pour Amazon Bedrock dans US East (Virginie du Nord), filtré sur Titan Text Embeddings V2. Les requêtes par minute et jetons par minute appliqués indiquent tous deux 0, contre des valeurs par défaut de 6 000 et 300 000. Un encadré rouge marque ces lignes.](https://media.brightdata.com/2026/08/Sk6Nw2WvGe.png)Dans US East (Ohio), le même modèle avait 60 requêtes par minute et 300 000 jetons par minute :

![Le même filtre identique dans US East (Ohio) pour le même compte, où le quota appliqué indique 60 requêtes par minute et 300 000 jetons par minute. Un encadré rouge marque les deux lignes fonctionnelles.](https://media.brightdata.com/2026/08/BkFBv2bDMl.png)Comparez la valeur appliquée avec le défaut AWS dans la console Service Quotas. Un quota de 60 contre un défaut de 6 000 signifie que la Région qui fonctionne tourne encore à un centième du taux de requête standard. Le quota de jetons juste à côté est au défaut complet, donc les requêtes par minute sont la limite qui compte. À environ 300 jetons par chunk, 60 requêtes par minute font environ 18 000 jetons par minute contre un plafond de 300 000. C’est suffisant pour un petit corpus. C’est un goulot d’étranglement pour un grand.

Deux messages d’erreur dans ce pipeline désignent la mauvaise cause.

- **`AccessDeniedException` sur `CreateKnowledgeBase`, nommant votre utilisateur et l’action.** Cela signifie généralement un `roleArn` mal formé plutôt qu’un problème de permissions, donc vérifiez la chaîne ARN avant d’auditer IAM.
- **`not able to call specified bedrock embedding model` pendant l’ingestion.** Cela ressemble à une erreur de permissions, et un quota de vectorisation nul la produit aussi. Invoquez le modèle de vectorisation directement vous-même, et si cela est aussi limité, vous avez un problème de quota.

Les deux sont des problèmes de configuration plutôt que des problèmes de pipeline, et aucun ne revient une fois le compte correctement configuré.

## Étape 1 – Scraper les pages avec Bright Data

Le [Web Unlocker](/products/web-unlocker) de Bright Data prend une seule URL et renvoie la page. Les vérifications anti-bot et le routage proxy se font de son côté, et il rend le JavaScript quand vous activez cette option. Définissez `data_format` sur `markdown`, et au lieu du HTML brut vous obtenez la page en Markdown, le format que vous voulez pour le RAG.

Vous créez la zone Web Unlocker une fois dans le panneau de contrôle Bright Data, et chaque requête la référence par son nom. La zone porte aussi le paramètre de géolocalisation. Pour un site qui sert un contenu différent selon le pays, Web Unlocker récupère depuis le pays que vous configurez là, pas depuis l’endroit où votre loader s’exécute. Le code ci-dessous a besoin de deux choses depuis l’onglet Overview de la zone : le nom de la zone (`web_unlocker` ici) et le jeton API.

![Panneau de contrôle Bright Data, onglet Overview de la zone web_unlocker, marquée Active. Les détails d'accès montrent la clé API, une liste blanche IP, et un exemple cURL prêt à l'emploi contre api.brightdata.com/request. Une note indique que la limite de débit a été fixée à 1 000 requêtes par minute jusqu'à ce que des fonds soient ajoutés. Des encadrés rouges marquent le nom de la zone et le tarif à l'utilisation de 1,50 $ pour 1 000 requêtes, avec un tarif premium de 2,50 $ listé en dessous.](https://media.brightdata.com/2026/08/SJKUw2Wwfg.png)En Python, cet appel est un seul POST portant la zone, l’URL cible, et le format de sortie voulu :

```none
import requests

BRIGHTDATA_TOKEN = "..."   # from your Bright Data account
UNLOCKER_ZONE = "web_unlocker"

def scrape_markdown(url: str) -> str:
    """Fetch a public URL as Markdown via Bright Data Web Unlocker."""
    resp = requests.post(
        "https://api.brightdata.com/request",
        headers={"Authorization": f"Bearer {BRIGHTDATA_TOKEN}"},
        json={
            "zone": UNLOCKER_ZONE,
            "url": url,
            "format": "raw",            # return the response body directly
            "data_format": "markdown",  # convert the page to Markdown
            # add "render": "true" when content exists only after client-side JS
        },
        timeout=120,
    )
    resp.raise_for_status()
    return resp.text
```

Il n’y a aucune session de navigateur à gérer, aucune étape de CAPTCHA, et aucune analyse HTML.

Un échec ici ne ressemble pas à un échec. Trois choses renvoient un 200 vide plutôt qu’une erreur : un nom de zone incorrect, un jeton révoqué, ou une liste blanche IP qui ne correspond plus à votre adresse actuelle. Donc `raise_for_status` l’accepte, et votre loader stocke la page comme un document vide. Vérifiez la longueur de la réponse, pas seulement le code de statut. Pour un pipeline planifié, ignorez la liste blanche et laissez le jeton être l’identifiant.

Un navigateur headless rendrait aussi le JavaScript pour vous, et cette partie reste identique. Le reste n’est pas un paramètre que vous configurez une fois. C’est un flux en perpétuel changement : trouver une IP de sortie qui fonctionne pour cette cible, personnaliser les en-têtes, et faire tourner les empreintes quand la détection évolue. La tarification fait porter ce risque à Bright Data, puisqu’elle ne facture pas les requêtes échouées.

Une fois que vous avez la page, elle a encore besoin de structuration, d’analyse et de nettoyage, puisque le HTML est désordonné. Le format `markdown` déplace ce travail du côté de Bright Data.

### Activer le rendu seulement quand la page en a besoin

Web Unlocker ne démarre pas un navigateur à chaque requête. Il utilise le chemin rapide pour une page qu’il peut récupérer sans exécuter de JavaScript. Pour un contenu qui n’existe qu’après le rendu côté client, définissez `render` sur `"true"`.

La page d’entraînement quotes.toscrape.com/js injecte son contenu avec JavaScript. Un GET simple a produit 96 caractères de texte indexable et aucune des citations, le chemin rapide a renvoyé une coquille de 191 caractères, et seule la requête rendue a renvoyé les 1 583 caractères complets. Sur cette page, la requête rendue s’est terminée en 7,7 secondes, contre 17,1 secondes sur le chemin rapide. C’est un échantillon d’un sur chaque chemin, donc traitez le rendu comme un commutateur de justesse plutôt qu’une pénalité de latence, et mesurez vos propres cibles.

Le `8_render_check.py` du dépôt exécute ce contrôle à trois voies contre n’importe quelle URL, donc c’est la première chose à essayer quand un scrape paraît suspicieusement fin. Il a besoin d’un jeton Bright Data et de rien d’autre. Vous pouvez le pointer vers vos propres URL et voir ce que chaque chemin renvoie avant de créer une seule ressource AWS. Si le contenu est toujours absent avec le rendu activé, la page a probablement besoin d’interaction, ce que couvre l’API Browser mais pas Web Unlocker. Le script sort avec un code non nul sur cette page quand vous passez `--probe` :

![Sortie terminal de 8_render_check.py contre quotes.toscrape.com/js. Un encadré rouge marque trois lignes de résultat. Le GET simple renvoie 96 caractères, le chemin rapide 191, et la requête rendue 1 583 avec le probe FOUND.](https://media.brightdata.com/2026/08/Sygg_w2WwMe.png)Les pages scrapées ci-dessous sont rendues côté serveur, donc l’exécution par défaut laisse `render` désactivé.

### Scraper une liste, pas une page

Web Unlocker est une requête par URL, donc un petit pool de threads maintient un débit élevé sans un framework lourd :

```none
from concurrent.futures import ThreadPoolExecutor

def scrape_many(urls: list[str], workers: int = 8) -> dict[str, str]:
    """Scrape a batch of URLs. Return {url: markdown} for the ones that succeed."""
    out: dict[str, str] = {}
    with ThreadPoolExecutor(max_workers=workers) as pool:
        for url, md in zip(urls, pool.map(_safe_scrape, urls)):
            if md:
                out[url] = md
    return out

def _safe_scrape(url: str) -> str | None:
    try:
        return scrape_markdown(url)
    except requests.RequestException:
        return None   # a page that fails is skipped, not fatal
```

Une page échouée renvoie `None` et quitte le lot au lieu d’arrêter l’exécution. Le loader du dépôt est plus strict que cet extrait. Il réessaie deux fois avec un délai progressif de 1 seconde puis 2 secondes. Il traite aussi un corps vide ou HTML comme un échec, pas comme du contenu. Cela signifie qu’une page qui a échoué à récupérer garde sa version précédente dans le corpus, et rien dans une réponse ultérieure ne la marque comme périmée. Traitez les échecs de récupération comme un signal sur lequel agir plutôt qu’une ligne dans un journal.

Web Unlocker a récupéré 6 pages de documentation. Chaque requête a pris entre 24,6 et 36,7 secondes, avec une médiane de 30,6 secondes. Chaque étape numérotée ici a été exécutée en direct contre ce même corpus de 6 pages en une seule journée. Ces pages sont coopératives, donc les chronométrages mesurent le pipeline lui-même plutôt que les défenses d’une cible. Débloquer une page n’est pas une récupération statique, ce qui explique le temps, et la concurrence rend cela viable. Les mêmes 6 pages ont pris 43,1 secondes de temps réel avec 6 workers, contre environ 3 minutes que prendrait une exécution en série.

Gardez quand même le nombre de workers bas, puisque le pool cible un seul site. Bright Data a plafonné la zone ci-dessus à 1 000 requêtes par minute jusqu’à ce que vous ajoutiez des fonds. À une médiane de 30 secondes, c’est bien plus de marge que ce qu’une poignée de workers utilisera. Vérifiez le plafond de votre zone, et confirmez la latence sur vos propres cibles avant de faire évoluer la liste.

### Préférer le jumeau Markdown natif du site

Avant de scraper un site, vérifiez s’il publie déjà ce que vous êtes sur le point de reconstituer. De nombreuses plateformes de documentation servent un jumeau Markdown prêt pour les LLM de chaque page, généralement sous la forme `<page-url>.md`, et listent les jumeaux dans un index `/llms.txt`. La documentation de Bright Data elle-même publie des jumeaux et les indexe sur [docs.brightdata.com/llms.txt](https://docs.brightdata.com/llms.txt), donc les 6 pages ci-dessus avaient toutes un jumeau. Ces jumeaux sont gratuits, et un simple GET les renvoie au lieu d’un scrape de 30,6 secondes. Ils ne portent aucune des navigation que le scrape ramasse.

Ils ne sont pas de la prose simple. Le jumeau ci-dessous porte encore les propres balises de composants de la plateforme et des URL d’images complètes, donc vous échangez le chrome du site contre du balisage qu’un nettoyage par ligne ne saisira pas :

![Navigateur en navigation privée sur docs.brightdata.com/scraping-automation/web-unlocker/quickstart.md montrant un Markdown non stylisé sans navigation, logo, ou boîte de recherche, mais portant encore des balises de composants Callout, Steps et Frame, et des URL d'images mintcdn.com complètes. Des encadrés rouges marquent l'URL .md et les premières lignes pointant vers docs.brightdata.com/llms.txt.](https://media.brightdata.com/2026/08/ryEYPhWwzx.png)En dehors des plateformes de documentation développeur, un jumeau Markdown est rare, et Web Unlocker fait le travail là-bas. Cela fait de la récupération une décision en deux temps :

```none
def fetch_page(url: str) -> str:
    """Prefer the site's own Markdown twin. Scrape only when there isn't one."""
    return native_markdown(url) or scrape_markdown(url)
```

`native_markdown` est l’assistant `src/web_kb/clean.py` du dépôt, un `GET` de `<page-url>.md` qui renvoie `None` quand la page n’a pas de jumeau. Il ne retire pas le balisage de composants, et le nettoyage du chrome de l’Étape 2 non plus. Un corpus riche en jumeaux a besoin de son propre passage conscient des balises.

Quand vous devez scraper, Web Unlocker renvoie la page sans décider quelles parties en sont le contenu principal. Sur 6 pages d’un site de documentation en direct, le Markdown portait encore le chrome du site : la bande de logo, un lien « Skip to main content », la boîte de recherche, l’arbre complet de navigation latérale, et un pied de page « Was this page helpful ». Ce chrome représentait environ 43 % des caractères. L’Étape 2 couvre le nettoyage de ce qui se répète.

## Étape 2 – Écrire des documents et métadonnées propres sur S3

Bedrock lit chaque fichier pris en charge sous le préfixe que vous lui donnez. Chacun devient un document pouvant aller jusqu’à 50 Mo, avec un fichier annexe optionnel à côté pour les métadonnées. Vous écrivez les deux.

### Nettoyer le chrome en premier

Un bloc de navigation est presque identique sur chaque page d’un site, donc un corpus de 50 pages vectorise ce même bloc 50 fois. Vous payez pour le vectoriser, vous payez pour le stocker, et au moment de la requête, ces 50 chunks quasi-identiques entrent en concurrence avec le contenu demandé. La déduplication plus loin dans cette étape ne peut pas l’attraper, car les pages ne sont pas des doublons. Seul leur chrome se répète.

Vous n’avez pas besoin de règles spécifiques au site pour le retirer, car la plupart du chrome est du texte qui se répète. Comptez combien de fois chaque ligne apparaît dans le lot et supprimez celles qui apparaissent sur la majorité des pages :

```none
from collections import Counter

KEEP = {"", "-" * 3, "`" * 3}          # blanks, bare rules, and bare fences are never chrome

def strip_repeated(pages: dict[str, str], threshold: float = 0.6) -> dict[str, str]:
    """Drop lines that repeat on most pages of the batch. Those are the chrome."""
    counts = Counter()
    for markdown in pages.values():
        for line in {ln.strip() for ln in markdown.splitlines()}:
            if line not in KEEP and len(line) >= 2:   # >= 2 so the ⌘K hint counts
                counts[line] += 1

    cutoff = max(2, int(len(pages) * threshold))
    boilerplate = {line for line, n in counts.items() if n >= cutoff}
    return {url: "\n".join(ln for ln in md.splitlines() if ln.strip() not in boilerplate)
            for url, md in pages.items()}
```

Sur l’échantillon de 6 pages, cela a fait passer le lot de 76 722 à 60 846 caractères, une réduction de 21 %. C’est environ la moitié du chrome mesuré à l’Étape 1. La règle ne se déclenche que sur les lignes identiques entre les pages, mais certains sites formulent leur navigation un peu différemment sur chaque page. Les lignes qui se répétaient sur la majorité du lot sont passées de 63 à 0. Chacune de ces lignes aurait pu devenir un chunk dupliqué. Les 6 pages montraient toutes la boîte de recherche, l’indice de raccourci `⌘K`, le sélecteur de langue, et chaque lien de navigation latérale.

Les économies sont inégales, car le chrome est un coût fixe par page. Dans cette exécution, il a retiré 41 % de la page la plus courte et 12 % de la plus longue. Un corpus de nombreuses pages courtes paierait autrement le plus pour vectoriser la navigation.

La technique est une heuristique, pas un analyseur, donc auditez-la avant de lui faire confiance sur un nouveau site. Sur un corpus riche en code, ajoutez aussi les blocs de code balisés par langage à `KEEP`, puisque `KEEP` ne protège que les blocs nus, et retirer un bloc d’ouverture partagé laisse son bloc de fermeture orphelin.

Le `6_inspect_cleaning.py` du dépôt liste chaque ligne qu’il supprimerait, et `--verify` note ce qui a survécu par rapport au propre jumeau Markdown d’une page. Sur ce corpus, le nettoyage n’a perdu aucun contenu unique à une page. Selon cette comparaison, la seule ligne manquante sur chaque page était le même texte générique llms.txt. Pour du HTML brut plutôt que du Markdown, utilisez un extracteur dédié tel que [Trafilatura](https://trafilatura.readthedocs.io/).

Ces 6 pages publient toutes un jumeau Markdown, donc l’exécution par défaut les utilise à chaque fois. Les chiffres de scrape et de chrome ci-dessus proviennent de forcer le chemin Web Unlocker avec `--no-native`.

![Sortie terminal de 6_inspect_cleaning.py sur 6 pages de documentation avec le chemin jumeau natif désactivé. Il rapporte 63 lignes répétitives, puis un tableau par page. Des encadrés rouges marquent le nombre de lignes et le total du lot, 76 722 à 60 846 caractères.](https://media.brightdata.com/2026/08/HkB9vnZvMl.png)### Écrire le document et son fichier annexe

Bedrock associe un document à ses métadonnées uniquement par le nom de fichier. Pour un document `quickstart-3f9a2c1b04.md`, le fichier de métadonnées est `quickstart-3f9a2c1b04.md.metadata.json`. À l’intérieur, chaque attribut a une valeur typée et un indicateur `includeForEmbedding`. Cet indicateur contrôle si Bedrock ajoute la valeur au texte vectorisé. Le loader écrit le fichier annexe, puis le document, estampillé avec le hachage de contenu qui permet à l’exécution suivante de sauter les deux :

```none
import boto3, json, hashlib, re
from datetime import datetime, timezone

REGION = "us-east-2"                    # a Region with non-zero embedding quota
s3 = boto3.client("s3", region_name=REGION)
BUCKET = "web-kb-corpus-111122223333"   # your bucket
PREFIX = "docs"

def slugify(url: str) -> str:
    """Stable, safe object key derived from the URL."""
    digest = hashlib.sha1(url.encode()).hexdigest()[:10]
    tail = url.rstrip("/").split("/")[-1][:40] or "page"
    safe = "".join(c if c.isalnum() or c in "-_" else "-" for c in tail)
    return f"{safe}-{digest}"

def content_hash(markdown: str) -> str:
    """Hash the meaningful text. Normalizing whitespace stops different
    line breaks from looking like a content change."""
    return hashlib.sha256(re.sub(r"\s+", " ", markdown).strip().encode()).hexdigest()

def stored_hash(key: str) -> str | None:
    """The hash saved on the object last run, or None if the object is not there.

    Only a missing object counts as absent. Catching every ClientError would report
    AccessDenied or throttling as a new page, rewrite it, and re-embed the corpus."""
    try:
        return s3.head_object(Bucket=BUCKET, Key=key)["Metadata"].get("content-hash")
    except s3.exceptions.ClientError as exc:
        if exc.response["Error"]["Code"] in ("404", "NoSuchKey", "NotFound"):
            return None
        raise

def put_document(url: str, markdown: str, title: str, section: str,
                 raw: str | None = None) -> str:
    key = f"{PREFIX}/{slugify(url)}.md"
    chash = content_hash(raw or markdown)   # hash the RAW scrape, not the stripped body

    if stored_hash(key) == chash:
        return "unchanged"          # leave the object alone, so the next sync skips it

    metadata = {
        "metadataAttributes": {
            "source_url":  {"value": {"type": "STRING", "stringValue": url},
                            "includeForEmbedding": False},
            "title":       {"value": {"type": "STRING", "stringValue": title},
                            "includeForEmbedding": True},
            "section":     {"value": {"type": "STRING", "stringValue": section},
                            "includeForEmbedding": True},
            "scraped_date":{"value": {"type": "NUMBER",
                                      "numberValue": int(datetime.now(timezone.utc).strftime("%Y%m%d"))},
                            "includeForEmbedding": False},
        }
    }
    # Sidecar first. The document carries the hash the next run compares against, so it is
    # the commit point. The reverse order can leave a new document beside a stale sidecar
    # that never self-heals, because the hash already matches.
    s3.put_object(Bucket=BUCKET, Key=f"{key}.metadata.json",
                  Body=json.dumps(metadata).encode("utf-8"),
                  ContentType="application/json")
    s3.put_object(Bucket=BUCKET, Key=key, Body=markdown.encode("utf-8"),
                  ContentType="text/markdown", Metadata={"content-hash": chash})
    return "written"
```

### N’écrire que quand le hachage de contenu change

Le verrou de hachage en haut de `put_document` garde un rafraîchissement bon marché. Lors d’une synchronisation incrémentielle, Bedrock utilise le propre suivi des changements de la source de données pour décider quoi ré-vectoriser. La documentation AWS n’indique pas actuellement quel signal Bedrock lit pour S3. Un loader qui réécrit chaque objet à chaque exécution met à jour ce signal, que le contenu ait changé ou non. L’hypothèse prudente est qu’une synchronisation censée toucher trois pages ré-vectorise tout le corpus, et vous payez pour tout. Comparer le hachage de contenu avant d’écrire signifie que vous laissez une page inchangée tranquille, et cela ne coûte rien en aval.

Les [données de Cloudflare suggèrent](https://www.cloudflare.com/press/press-releases/2026/cloudflare-allows-the-agentic-internet-to-flourish-with-a-simple-philosophy-your-content-your-rules/) que plus de la moitié du trafic des crawlers IA va à récupérer de nouveau des pages qui n’ont pas changé. Ce verrou ne résout pas cela, car vous récupérez la page dans tous les cas, et il n’économise que la vectorisation. Le calendrier de re-synchronisation de l’Étape 4 contrôle la récupération elle-même.

Hachez le scrape brut plutôt que le corps nettoyé du chrome. Ce nettoyage plus tôt dans cette étape est relatif au lot, donc une page inchangée dans un lot différent serait autrement hachée différemment et ré-vectorisée pour rien. L’extrait prend un argument `raw` séparé exactement pour cette raison, donc passez le texte non nettoyé quand vous l’appelez.

Le loader du dépôt garde les hachages qu’il a vus dans une exécution, donc il élimine aussi les doublons exacts, où deux URL renvoient un texte identique octet pour octet. En pratique, cela couvre les alias `?utm_source=` et `?print=1`. Une copie syndiquée ou une variante paginée diffère de quelques octets et échappe à cette vérification.

Attraper ceux-ci nécessite une détection de quasi-doublons, et le dépôt la livre en MinHash derrière un indicateur optionnel `--near-dup` sur le loader. Il est par défaut à un seuil de similarité de 0,85. Sur ce corpus, les pages distinctes ont obtenu au maximum 0,02, et une page contre son propre jumeau Markdown a obtenu 0,75, donc le défaut garde les deux. L’implémentation en Python pur convient aux corpus allant jusqu’à quelques milliers de pages. À la latence mesurée précédemment, c’est plus qu’une seule exécution par lot ne couvrira habituellement.

### Choisir ce que portent les métadonnées

Le fichier annexe contient les deux choses qu’un corpus scrapé perd en entrant dans un magasin vectoriel. `source_url` donne à chaque chunk récupéré une citation vers la page dont il provient, donc une réponse peut montrer sa source. `section` et `scraped_date` deviennent des clés de filtrage au moment de la requête. Vous pouvez limiter une recherche à une partie du corpus, ou à du contenu modifié après une date limite.

Le fichier annexe porte aussi le `title` de la page. Définir `includeForEmbedding` sur `True` pour `title` et `section` les ajoute au texte vectorisé, donc une requête nommant l’un ou l’autre a plus de matière à correspondre. Le définir sur `False` pour `source_url` garde une URL longue hors des vecteurs, où elle ajouterait plus de bruit que de signal.

Bedrock prend en charge les types de métadonnées `STRING`, `NUMBER`, `BOOLEAN`, et `STRING_LIST`. Stocker `scraped_date` comme un `NUMBER` au format `YYYYMMDD` vous permet de filtrer avec `greaterThan` et `lessThan` plus tard. Vous ne réécrivez pas une page inchangée, donc elle garde sa date antérieure. Cela fait de `scraped_date` un filtre d’ancienneté de contenu, pas un signal qu’une page se rafraîchit encore. Ce signal a besoin d’un horodatage de dernière observation séparé, et le dépôt en écrit un à chaque récupération réussie.

Exécutez le loader sur votre liste d’URL, et le bucket contient alors un document et un fichier annexe par page. Confirmez les paires dans la console avant de pointer une base de connaissances vers le préfixe :

![Console Amazon S3 montrant le préfixe docs/ listant 12 objets en 6 paires, chaque document Markdown suivi de son fichier annexe .metadata.json portant le même nom. Les documents vont de 4,0 à 21,6 Ko, les fichiers annexes de 590 à 619 octets. Un encadré rouge marque la première paire.](https://media.brightdata.com/2026/08/rJ_ow2bvGg.png)## Étape 3 – Créer la base de connaissances

Vous créez la base de connaissances une fois. Après cela, le pipeline écrit des fichiers et déclenche des synchronisations. La console est le chemin le plus clair pour cette configuration, et le [flux create-knowledge-base](https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-create.html) couvre chaque écran.

### Choisir géré ou géré par le client

La documentation AWS recommande la base de connaissances entièrement gérée par défaut. Selon votre Région, la console l’offre aussi. Les bases de connaissances gérées font tourner leur propre magasin de données, analyse, et reclassement. Elles ajoutent aussi la récupération agentique et incluent des connecteurs natifs tels que Google Drive.

Cette construction prend le chemin géré par le client. Choisir votre propre magasin vectoriel vous donne la tarification S3 Vectors ci-dessous, et laisse l’index dans votre compte. Une base de connaissances gérée peut ingérer les documents que ce pipeline écrit sur S3, via la même source de données S3. Le vide du crawler reste le même sur chaque chemin.

### Définir les choix que vous ne pouvez pas changer plus tard

Quatre choix façonnent la récupération. Trois des quatre se verrouillent dès que la base de connaissances et sa source de données existent.

- **Source de données.** Choisissez **Amazon S3** et pointez-la vers votre bucket et le préfixe `docs/`. Bedrock lit ensuite les documents et leurs fichiers annexes depuis là à chaque synchronisation. Une base de connaissances prend jusqu’à 5 buckets comme sources de données.
- **Modèle de vectorisation.** Amazon Titan Text Embeddings V2 (`amazon.titan-embed-text-v2:0`) est le défaut pour le texte, et c’est le modèle derrière chaque chiffre de récupération ci-dessous. À 1024 dimensions, vous obtenez une meilleure qualité de récupération, et à 256, un coût de stockage plus bas. Les [modèles de vectorisation pris en charge](https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-supported.html) incluent Amazon Nova Multimodal Embeddings, à considérer quand un corpus mélange texte et images. Choisissez une fois, car vous ne pouvez pas changer le modèle de vectorisation sur une base de connaissances existante.
- **Magasin vectoriel.** Amazon S3 Vectors a atteint la disponibilité générale en décembre 2025. Il stocke et interroge les vecteurs à l’utilisation sans cluster à faire tourner, et vous ne pouvez pas l’échanger après que la base de connaissances existe. Créez son bucket et son index avant d’ouvrir l’assistant. Puis pointez l’assistant vers ce magasin existant, au lieu de laisser Amazon en créer un pour vous. La section suivante explique pourquoi. AWS dit que S3 Vectors réduit le coût de téléversement, de stockage et d’interrogation des vecteurs jusqu’à 90 % par rapport à des solutions alternatives non nommées. Amazon OpenSearch Serverless reste l’option quand vous avez besoin de ses fonctionnalités de requête ou d’un débit plus élevé, bien que cette construction ait tourné uniquement sur S3 Vectors. Pour un corpus que vous rafraîchissez selon un calendrier plutôt que de servir à un volume de requêtes élevé, ce compromis vaut généralement le coup. La console offre aussi Amazon Aurora PostgreSQL Serverless. Confirmez le statut actuel et la tarification sur la [documentation S3 Vectors](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors-bedrock-kb.html) au moment de construire.
- **Découpage.** Les articles scrapés ont une structure de phrases et de paragraphes, donc le découpage par défaut d’environ 300 jetons sur des limites de phrases est un point de départ raisonnable. Si vous scrapez de longues pages de référence, le découpage hiérarchique récupère des chunks enfants précis et renvoie leurs parents plus larges pour le contexte, bien que Bedrock le déconseille sur un magasin S3 Vectors. Bedrock offre aussi d’autres stratégies. Le découpage à taille fixe utilise un nombre de jetons que vous définissez. Le découpage sémantique groupe par sens plutôt que par longueur. Une option sans découpage traite chaque document comme un seul chunk. Vous ne pouvez pas changer la stratégie de découpage après avoir créé la source de données.

L’assistant vous avertit de cela pour le modèle de vectorisation et le magasin vectoriel, sur l’écran où vous les définissez :

![Assistant Bedrock, Configurer le stockage et le traitement des données. Une ligne au-dessus des panneaux indique «Le modèle de vectorisation et le magasin vectoriel ne peuvent pas être modifiés après la création de la Knowledge Base.» Le menu déroulant du magasin vectoriel liste OpenSearch Serverless, S3 Vectors étiqueté new, et Aurora PostgreSQL Serverless. Des encadrés rouges marquent S3 Vectors et l'avertissement de non-modification après création.](https://media.brightdata.com/2026/08/ryepwhbvGx.png)### Nommer les clés de métadonnées non filtrables

Si vous choisissez S3 Vectors, marquez le texte du chunk et les propres métadonnées de Bedrock comme non filtrables lors de la création de l’index. Sinon, Bedrock échoue à ingérer la plupart de votre corpus. S3 Vectors permet au maximum 2048 octets de métadonnées *filtrables* par vecteur, et Bedrock en utilise une partie pour le texte du chunk et sa propre comptabilité. Tout sauf un chunk très court dépasse le budget. Après ce surcoût, la [documentation de la base de connaissances S3 Vectors](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors-bedrock-kb.html) fixe l’allocation pratique pour vos attributs à 1 Ko et 35 clés par vecteur. Gardez les fichiers annexes petits.

Lors de la première exécution, 5 documents sur 6 ont échoué avec `Filterable metadata must have at most 2048 bytes`, et le seul qui a survécu avait un chunk de 499 octets. Nommer les deux propres clés de Bedrock lors de la création de l’index corrige cela, et vous ne pouvez pas changer ce choix après coup :

```none
aws s3vectors create-vector-bucket --vector-bucket-name YOUR_VECTOR_BUCKET --region YOUR_REGION

aws s3vectors create-index --vector-bucket-name YOUR_VECTOR_BUCKET --region YOUR_REGION \
  --index-name web-kb-index --data-type float32 --dimension 1024 --distance-metric cosine \
  --metadata-configuration '{"nonFilterableMetadataKeys":["AMAZON_BEDROCK_TEXT","AMAZON_BEDROCK_METADATA"]}'
```

Le nom que les gens confondent est `AMAZON_BEDROCK_TEXT`. `AMAZON_BEDROCK_TEXT_CHUNK` est le nom de champ OpenSearch, et nommer celui-là à la place laisse l’échec exactement tel quel. Le `2_create_kb.py` du dépôt compagnon crée l’index de cette façon pour vous. Il refuse aussi de continuer contre un index existant qui manque ces clés. L’alternative est de découvrir le problème lors d’une synchronisation qui rapporte un succès.

L’assistant répète l’avertissement pour les stratégies d’analyse et de découpage un écran plus loin.

![Assistant Bedrock create-knowledge-base, Configurer la source de données. L'analyseur par défaut Amazon Bedrock est sélectionné sous une note indiquant que l'option d'analyse ne peut pas être modifiée après la création de la base de connaissances. Des encadrés rouges marquent l'avertissement que la stratégie de découpage ne peut pas être modifiée après la création de la source de données et l'option de découpage par défaut d'environ 300 jetons.](https://media.brightdata.com/2026/08/rJTpPnWDMe.png)Ce même écran porte une fonction de transformation optionnelle. La [récupération contextuelle](https://www.anthropic.com/engineering/contextual-retrieval) ajoute avant la vectorisation une note rédigée par un modèle sur la place de chaque chunk dans le document. Anthropic a mesuré une baisse de 35 % des échecs de récupération dans le top-20. Bedrock exécute cette fonction à l’ingestion, au coût d’un appel de modèle par chunk. Cette construction la laisse désactivée, donc les chiffres de récupération ci-dessous proviennent du découpage par défaut seul.

Si vous préférez créer la base de connaissances en code, ce même `2_create_kb.py` appelle `create_knowledge_base` et `create_data_source` du client `bedrock-agent`. Il définit la configuration S3 et le rôle de service IAM pour vous. Le dépôt livre aussi Terraform pour tout le côté AWS. C’est le chemin le plus court si vous préférez ne cliquer sur rien de tout cela, et il définit les clés de métadonnées non filtrables ci-dessus, donc vous ne pouvez pas les oublier.

Quand le flux de création se termine, la page de détail de la base de connaissances montre ce que vous avez construit :

![Console Amazon Bedrock, vue d'ensemble de la base de connaissances web-kb. Le statut est Available et le type RAG est Vector store. La section Data source liste une source S3 nommée web-corpus, aussi Available. Des encadrés rouges marquent le statut et la ligne de source de données.](https://media.brightdata.com/2026/08/B1CRvn-DMx.png)## Étape 4 – Ingérer et maintenir les données à jour

Créer la base de connaissances ne lit pas vos données. L’ingestion le fait. Une synchronisation, appelée tâche d’ingestion, lit le bucket, découpe et vectorise les documents, et écrit les vecteurs. Vous en démarrez une après le premier chargement et à nouveau après chaque rafraîchissement :

```none
bedrock_agent = boto3.client("bedrock-agent", region_name=REGION)

def sync(knowledge_base_id: str, data_source_id: str) -> str:
    job = bedrock_agent.start_ingestion_job(
        knowledgeBaseId=knowledge_base_id,
        dataSourceId=data_source_id,
    )
    return job["ingestionJob"]["ingestionJobId"]
```

Après la première synchronisation complète, les synchronisations ultérieures sont incrémentielles. Bedrock ingère les fichiers nouveaux et modifiés et retire les vecteurs de ceux qui ont quitté le bucket, donc un rafraîchissement ré-vectorise seulement les pages que votre loader a réécrites. Ce comportement rend le verrou de hachage de l’Étape 2 essentiel, puisqu’un objet que vous réécrivez avec des octets identiques peut quand même compter comme modifié. La clé `slugify` est déterministe, donc un re-scrape de la même URL écrase le même objet plutôt que de créer un doublon.

Cela gère les pages nouvelles et modifiées, mais rien ne retire celles que vous retirez. Le loader ne fait qu’écrire, donc supprimer une URL de votre liste ne supprime pas son objet. Ce contenu périmé reste dans le corpus, où il peut apparaître dans n’importe quelle réponse ultérieure. Retirer une page est une étape de réconciliation séparée qui liste le bucket, trouve les objets dont l’URL a disparu, et les supprime pour que la synchronisation suivante efface leurs vecteurs. Le dépôt compagnon livre cela sous le nom `7_reconcile.py`, un script en mode simulation par défaut. Il compare à la liste complète des URL, donc il ne confond jamais une page qui a simplement échoué à scraper avec une page que vous avez retirée.

Faites correspondre le calendrier de re-synchronisation au contenu qui change le plus vite dans votre corpus. Les publications sociales peuvent être périmées en quelques heures, les actualités en quelques jours, les pages de tarifs et finances en quelques semaines, tandis que la documentation de référence peut rester à jour pendant des mois. Ce sont des points de départ, pas des mesures. Une base de connaissances de pages d’actualités pourrait se re-synchroniser quotidiennement, et une construite à partir de documentation produit, hebdomadairement. Une planification Amazon EventBridge peut déclencher le scrape-et-synchronisation à l’intervalle que vous choisissez, donc le rafraîchissement s’exécute sans qu’un humain ne le démarre.

Lisez les statistiques, pas le statut. Une tâche d’ingestion rapporte `COMPLETE` même quand la plupart de ses documents ont échoué. Une exécution qui a indexé 1 page sur 6 ressemble quand même à un succès à partir du seul champ de statut. Le `3_sync.py` du dépôt imprime ces comptages et sort avec un code non nul en cas d’échecs :

```none
{"status": "COMPLETE",
 "statistics": {"numberOfDocumentsScanned": 6, "numberOfNewDocumentsIndexed": 6,
                "numberOfModifiedDocumentsIndexed": 0, "numberOfDocumentsDeleted": 0,
                "numberOfDocumentsFailed": 0}}
```

C’est un résultat mesuré du corpus de 6 pages, et il a fallu deux tentatives pour y arriver. La première exécution a rapporté `COMPLETE` avec `numberOfDocumentsFailed: 5`, tous touchés par la limite de métadonnées S3 Vectors décrite à l’Étape 3. Quand des documents échouent, `failureReasons` sur la tâche porte l’erreur réelle et est la première chose à lire. Un quota de vectorisation nul apparaît aussi ici, et ressemble à un problème de permissions. L’ingestion de 6 pages a pris environ 25 secondes. Le temps et les comptages de chunks évoluent avec votre corpus et comment vous le découpez, donc mesurez-les sur vos propres données.

La page de la source de données liste chaque tâche dans son historique de synchronisation avec les statistiques par document :

![Page console Amazon Bedrock de la source de données web-corpus. L'historique de synchronisation montre une tâche terminée avec Scanned 6, Added 6, Failed 0, Modified 0, Deleted 0. La section Documents rapporte 6, et chaque ligne visible indique INDEXED. Des encadrés rouges marquent les colonnes de comptage et la colonne de statut.](https://media.brightdata.com/2026/08/H1_bd2bPzl.png)## Étape 5 – Interroger la base de connaissances

Bedrock offre un appel de récupération et un appel de génération. Celui que vous choisissez dépend de si vous voulez la preuve brute ou une réponse rédigée. Les deux sont sur le client `bedrock-agent-runtime`.

`Retrieve` renvoie les chunks source et rien d’autre. C’est le bon choix quand votre propre modèle ou application fait la rédaction et que vous avez seulement besoin de contexte ancré et de citations :

```none
runtime = boto3.client("bedrock-agent-runtime", region_name=REGION)

def retrieve(kb_id: str, query: str, section: str | None = None,
             num_results: int = 5) -> list[dict]:
    config = {"vectorSearchConfiguration": {"numberOfResults": num_results}}
    if section:
        config["vectorSearchConfiguration"]["filter"] = {
            "equals": {"key": "section", "value": section}
        }
    resp = runtime.retrieve(
        knowledgeBaseId=kb_id,
        retrievalQuery={"text": query},
        retrievalConfiguration=config,
    )
    return resp["retrievalResults"]
```

Chaque résultat porte le texte du chunk, un `score` de pertinence, la `location` de l’objet source, et les `metadata` que vous avez écrites à l’Étape 2. Sur ce corpus, un bon résultat principal a obtenu 0,67, un chiffre que vous utilisez pour définir le seuil de pertinence plus tard. Ces métadonnées font fonctionner le `filter` optionnel, limitant la recherche à une `section` ou à une plage de dates :

![Panneau de Test de la console Amazon Bedrock pour web-kb. La requête sur le ciblage pays renvoie 5 chunks. Le Chunk 1 obtient un score de 0,67 et ses métadonnées listent le titre Web Unlocker API features et un source_url. Des encadrés rouges marquent le score de pertinence et la ligne source_url.](https://media.brightdata.com/2026/08/rkDLdh-Dfl.png)Le crawler natif ingère du HTML sans étape de fichier annexe, donc ces attributs n’ont nulle part d’où venir.

`RetrieveAndGenerate` fait ce que fait `Retrieve`, puis rédige la réponse. Il ancre cette réponse dans les chunks récupérés et renvoie des citations avec elle :

```none
def answer(kb_id: str, query: str, model_arn: str) -> dict:
    resp = runtime.retrieve_and_generate(
        input={"text": query},
        retrieveAndGenerateConfiguration={
            "type": "KNOWLEDGE_BASE",
            "knowledgeBaseConfiguration": {
                "knowledgeBaseId": kb_id,
                "modelArn": model_arn,
            },
        },
    )
    return resp   # resp["output"]["text"] plus resp["citations"]
```

La réponse contient le texte généré et un tableau `citations` qui associe des portions de la réponse aux chunks dont elles proviennent. Parce que vous avez défini `source_url` dans le fichier annexe, chaque citation se résout vers la page que vous avez scrapée. Une réponse sur la tarification d’un produit cite alors la page de tarification que Bright Data a récupérée.

Si vous construisez une base de connaissances entièrement gérée, utilisez `managedSearchConfiguration` à la place de `vectorSearchConfiguration`, puisque les bases de connaissances gérées font tourner la recherche hybride avec reclassement activé par défaut. Le `retrieve()` du dépôt compagnon marque où l’échanger.

## Étape 6 – Mesurer si la récupération fonctionne

Rien dans le pipeline jusqu’ici ne vous dit si la base de connaissances renvoie la bonne page pour les questions que vos utilisateurs posent. Corriger une mauvaise taille de chunk signifie recréer la source de données, donc découvrez-le sur 20 pages plutôt que 20 000.

L’outil pour cela est un ensemble de référence, une liste de questions, chacune avec les pages qui devraient y répondre. L’ensemble de ce pipeline contient 6 questions, et il est dans le dépôt sous `eval/golden.json`, à côté de `eval/golden-v1-mislabeled.json`, la première version dont cette section explique le mauvais étiquetage :

```none
[
  {"question": "How do I get the page back as markdown instead of HTML?",
   "expect": ["https://docs.brightdata.com/scraping-automation/web-unlocker/features"]},
  {"question": "How do I target a specific country for my request?",
   "expect": ["https://docs.brightdata.com/scraping-automation/web-unlocker/features",
              "https://docs.brightdata.com/scraping-automation/web-unlocker/configuration"]}
]
```

Vous faites ensuite passer chaque question par `Retrieve` et enregistrez où la page attendue apparaît dans les résultats :

```none
def evaluate(kb_id: str, golden: list[dict], k: int = 5):
    ranks = []
    for item in golden:
        chunks = retrieve(kb_id, item["question"], num_results=k)
        got = [c.get("metadata", {}).get("source_url", "") for c in chunks]
        # 1-based rank of the first expected page, or None if it never appeared
        ranks.append(next((i + 1 for i, u in enumerate(got) if u in item["expect"]), None))

    hit_rate = sum(r is not None for r in ranks) / len(ranks)
    mrr = sum(1 / r if r else 0 for r in ranks) / len(ranks)
    missed = [g["question"] for g, r in zip(golden, ranks) if r is None]
    return hit_rate, mrr, missed
```

Le taux de réussite est la proportion de questions où la page attendue est apparue, tout court. Il vous dit si le corpus peut ancrer une réponse en premier lieu. Le rang réciproque moyen fait la moyenne de 1 divisé par le rang de cette page. Il chute quand la bonne page apparaît mais se trouve au rang 5, et un taux de réussite seul masque cela.

La liste des échecs est la partie sur laquelle agir. Un échec signifie généralement une des quatre choses. La page n’a jamais atteint le corpus, donc vérifiez la sortie du loader pour une récupération échouée. Les chunks sont trop grands, donc le texte environnant dilue le passage pertinent. Les chunks sont trop petits, donc le passage a perdu le contexte qui le faisait correspondre. Ou votre ensemble de référence est incorrect.

La première exécution d’évaluation a obtenu 83 % de hit@5, avec un échec sur « How do I target a specific country for my request? » L’ensemble de référence attendait la page de configuration. Lire le chunk que la récupération a renvoyé à la place a tranché la question. Le passage de la page de fonctionnalités contenait la documentation de ciblage pays mot pour mot. La récupération avait eu raison et l’étiquette avait tort. La corriger a donné 100 % de hit@5 avec un MRR de 0,88, et 83 % de hit@3 avec un MRR de 0,83. Ce sont 6 questions contre 6 pages, donc lisez-les comme un seul point de données mesuré plutôt qu’un benchmark.

![Sortie terminal du script d'évaluation, exécutant scripts/5_evaluate.py contre l'ensemble de référence à k égal 5. Il rapporte 6 questions, un hit@5 de 100 %, et un rang réciproque moyen de 0,88. Un encadré rouge marque les deux lignes de résultat.](https://media.brightdata.com/2026/08/S16Gun-wzl.png)Lisez toujours ce que la récupération a renvoyé lors d’un échec avant de changer quoi que ce soit au pipeline. Seul le texte récupéré vous dit si la récupération ou l’étiquette est fausse. Un problème de pipeline vous renvoie au loader, un problème de découpage vous renvoie à la source de données, et une question mal étiquetée a juste besoin d’un meilleur ensemble de référence.

Exécutez ceci avant de faire évoluer le corpus, et continuez à l’exécuter. Une fois que vous avez un taux de réussite qui vous satisfait, traitez-le comme une porte de publication. Le script d’évaluation du dépôt compagnon prend un indicateur `--min-hit-rate` exactement pour cela. Un rafraîchissement planifié qui dégrade silencieusement la récupération échoue alors bruyamment au lieu de livrer de moins bonnes réponses.

Bedrock livre aussi une évaluation gérée qui note la récupération et la génération avec un modèle juge. Utilisez-la pour étudier la qualité, et gardez l’ensemble de référence comme porte de publication. L’ensemble est déterministe, ne coûte que les appels de récupération, et s’exécute en quelques secondes à cette échelle.

## Quand aller au-delà de la base de connaissances

Une base de connaissances est un instantané des pages que vous avez choisies. Vous les vectorisez une fois et les interrogez plusieurs fois. Cet instantané rend chaque requête bon marché, et il place aussi deux types de questions hors de portée. Les questions sur des faits qui changent plus vite que votre calendrier de synchronisation obtiennent des réponses périmées. Les questions sur des pages qui n’ont jamais été dans le corpus n’ont rien avec quoi correspondre.

Routez par requête au lieu de choisir une fois entre une base de connaissances persistante et une récupération en direct. Interrogez d’abord la base de connaissances, et quand elle ne peut pas ancrer la question, basculez vers une recherche Bright Data en direct :

```none
def route_answer(kb_id: str, query: str, min_score: float = 0.4):
    chunks = retrieve(kb_id, query, num_results=5)
    top = max((c.get("score", 0.0) for c in chunks), default=0.0)

    if chunks and top >= min_score:
        return "knowledge_base", chunks

    # nothing in the corpus covers this, so search and fetch it live
    return "live_web", live_context(query)      # Bright Data SERP + Web Unlocker
```

`live_context` est l’assistant de recherche-puis-récupération du dépôt dans `src/web_kb/live_tool.py`, et il a besoin d’une zone SERP Bright Data à côté de la zone Web Unlocker de l’Étape 1. Vous créez la zone SERP de la même façon et l’appelez via le même point de terminaison `api.brightdata.com/request`. Elle renvoie la page de résultats en JSON, pour que le repli puisse choisir des URL à récupérer.

Le seuil de pertinence est le signal de routage. Bedrock renvoie un score avec chaque chunk, et quand le meilleur tombe en dessous du seuil, le corpus ne couvre probablement pas la question. Répondre à partir du corpus quand même est le mode d’échec à éviter, car le résultat est une réponse assurée citant une page qui ne la soutient pas.

Le 0,4 ci-dessus est un point de départ, pas une valeur mesurée. Il se situe en dessous du 0,67 qu’un bon résultat principal a obtenu à l’Étape 5. Ajustez-le par rapport à l’ensemble de référence de l’Étape 6, à côté de quelques questions dont vous savez que le corpus ne les couvre pas. `5_evaluate.py` imprime la plage qu’il a observée, le score le plus bas sur un succès et le plus haut sur un échec. Le seuil se situe entre les deux. Gardez ces questions supplémentaires dans un fichier séparé, puisqu’une question sans page attendue compte comme un échec contre la porte de publication.

Les bases de connaissances gérées prennent une version de cette décision en interne, appelée récupération agentique. Garder cette décision dans votre propre code signifie que vous pouvez inspecter le signal, le seuil, et le repli, et le chemin en direct peut atteindre en dehors d’AWS. Connectez-le comme un groupe d’actions d’agent Bedrock, comme un outil dans un framework comme [Strands Agents](https://strandsagents.com/), ou comme le [serveur MCP](/ai/mcp-server) de Bright Data.

Ce serveur donne à tout agent compatible MCP la même recherche, déblocage, et crawl en direct. Dans une AgentCore Gateway, il se trouve à côté d’un outil qui appelle `Retrieve`. La règle de routage ne change pas, seulement l’endroit où le repli s’exécute.

Une base de connaissances est le bon choix quand vous interrogez les mêmes pages de façon répétée, quand vous avez besoin de citations, de filtres, et de contrôle d’accès, et quand le corpus change plus lentement que vous l’interrogez. La récupération en direct gagne quand un fait bouge plus vite que votre synchronisation, quand l’espace des questions est ouvert, ou quand vous vectoriseriez bien plus que ce que vous récupérerez jamais. Le signe le plus clair que l’équilibre est faux est de synchroniser si souvent que vous ré-vectorisez la plupart des pages avant que quiconque les interroge. Alors vous payez pour maintenir un index au lieu de l’utiliser.

La mise en cache des invites a changé une partie de cette règle. Avec un corpus assez petit et stable pour tenir dans la fenêtre de contexte d’un modèle, vous pouvez sauter entièrement la récupération. Ce pipeline vaut la peine d’être construit une fois que le corpus dépasse le cache, ou quand les réponses doivent citer des pages exactes, que les filtres doivent limiter les requêtes, ou que les pages se rafraîchissent selon des calendriers différents. Sans aucun de ces éléments, mettre en cache le corpus entier est plus simple.

## Couverture d’un site entier avec l’API Crawl et la livraison S3 native

Le pipeline jusqu’ici prend une liste connue d’URL. Quand le corpus grandit, vous ne connaissez peut-être pas chaque URL à l’avance, et vous préférez ne pas exécuter la boucle de récupération vous-même. L’[API Crawl](/products/crawl-api) de Bright Data gère les deux. Elle découvre et crawle les pages internes d’un site à partir d’une URL de départ, renvoyant chaque page en Markdown. Elle peut aussi livrer la sortie directement vers votre bucket S3.

Ce chemin a été assemblé à partir de la documentation plutôt qu’exécuté. La séquence d’appels et les noms de champs ci-dessous suivent la référence API de Bright Data, donc vérifiez-les contre la [documentation de l’API Crawl](https://docs.brightdata.com/scraping-automation/crawl-api/overview) avant de dépendre de ce chemin.

Cet extrait continue des étapes précédentes : il réutilise `BRIGHTDATA_TOKEN` de l’Étape 1 et `REGION` de l’Étape 2. Les tâches de crawl sont asynchrones, et la livraison est son propre appel plutôt qu’une option sur le déclencheur. Vous déclenchez un crawl et recevez un ID d’instantané, interrogez jusqu’à ce que cet instantané soit `ready`, puis le remettez au point de terminaison de livraison avec une cible `s3`. L’appel de livraison écrit la sortie dans votre bucket sans étape de téléchargement dans votre code :

```none
import requests, time

BD = "https://api.brightdata.com"
HEADERS = {"Authorization": f"Bearer {BRIGHTDATA_TOKEN}"}
CRAWL_DATASET_ID = "..."   # the Crawl API dataset ID from your Bright Data control panel
AWS_KEY, AWS_SECRET = "...", "..."   # delivery credentials. Prefer an IAM role ARN with an external ID

def _call(method: str, path: str, **kw):
    resp = requests.request(method, f"{BD}{path}", headers=HEADERS, timeout=60, **kw)
    resp.raise_for_status()
    return resp.json()

def crawl_to_s3(seed_url: str, bucket: str, directory: str) -> str:
    # 1. Trigger. The body is a bare array of input objects, not a wrapper object.
    snapshot = _call("POST", "/datasets/v3/trigger",
                     params={"dataset_id": CRAWL_DATASET_ID,
                             "custom_output_fields": "markdown|url|page_title"},
                     json=[{"url": seed_url}])["snapshot_id"]

    # 2. Poll. Delivery only accepts a snapshot already in `ready` status.
    while (state := _call("GET", f"/datasets/v3/progress/{snapshot}")["status"]) != "ready":
        if state == "failed":
            raise RuntimeError(f"crawl {snapshot} failed")
        time.sleep(15)

    # 3. Deliver. Returns a delivery job ID, which you poll at
    #    GET /datasets/v3/delivery/{id} until its status is "done".
    return _call("POST", f"/datasets/v3/deliver/{snapshot}",
                 json={"type": "s3",
                       "bucket": bucket,
                       "directory": directory,
                       "region": REGION,
                       "credentials": {"aws-access-key": AWS_KEY,
                                       "aws-secret-key": AWS_SECRET},
                       "filename": {"template": "crawl", "extension": "json"}})["id"]
```

Bright Data livre les enregistrements en JSON, NDJSON, ou CSV plutôt qu’un fichier Markdown par page, donc il y a une étape de normalisation entre la livraison et l’ingestion. Une fonction Lambda déclenchée par S3 s’en occupe, se déclenchant quand la livraison écrit la sortie vers un préfixe d’atterrissage. La fonction divise chaque enregistrement en un document `<slug>.md` et son fichier annexe `.metadata.json` sous le préfixe source de la base de connaissances. C’est exactement la forme que vous avez écrite à la main à l’Étape 2. La source de données S3 de Bedrock les ingère ensuite à la synchronisation suivante.

L’exemple ci-dessus passe une paire de clés. Préférez un ARN de rôle IAM avec un ID externe, pour qu’aucune clé à longue durée de vie ne reste dans la requête.

Le compromis entre les deux chemins est contrôle contre échelle. Web Unlocker avec votre propre loader vous donne un contrôle exact sur chaque nom de fichier et champ de métadonnées. C’est idéal pour une liste organisée. L’API Crawl avec livraison S3 et une Lambda de normalisation vous donne une large couverture et aucune boucle de récupération à vous. C’est idéal quand le corpus est toute une section de site que vous voulez garder synchronisée.

## Considérations de coût

Traitez les chiffres ci-dessous comme un modèle pour vos propres chiffres plutôt qu’un devis, et évaluez votre propre corpus par rapport à la [tarification Bright Data](/pricing) et la [tarification Amazon S3](https://aws.amazon.com/s3/pricing/) avant de vous engager.

ComposantComment c’est tariféCe qui le détermineBright Data Web Unlocker1,50 $ pour 1 000 requêtes réussies à l’utilisation, avec un tarif premium de 2,50 $. Les échecs ne sont pas facturés1 requête par page scrapéeBright Data Crawl API1,50 $ pour 1 000 enregistrements à l’utilisationPages découvertes et crawlées par tâcheBedrock embeddings (Titan V2)Par jeton d’entréeTotal de jetons sur tous les chunks à l’ingestion, plus chaque requêteMagasin vectorielS3 Vectors à l’utilisation, ou OpenSearch Serverless par heure-OCUTaille du corpus et volume de requêtesAmazon S3Stockage et requêtes, quelques centimes à cette échelle1 `.md` plus 1 fichier annexe par pageRetrieveAndGeneratePar jeton sur le modèle de générationVolume de réponses et choix de modèleVoici ce que coûte un rafraîchissement du corpus de 6 pages, sur le chemin Web Unlocker au tarif standard.

- **Scraping.** 6 requêtes Web Unlocker, 0,009 $ à 1,50 $ pour 1 000.
- **Vectorisation.** 60 846 caractères nettoyés, environ 15 000 jetons à 4 caractères chacun, environ trois centièmes de centime à 0,00002 $ pour 1 000.
- **Stockage vectoriel.** Environ 50 chunks de taille par défaut, bien en dessous d’un mégaoctet, trop petit pour compter à 0,06 $ par Go-mois.

Un rafraîchissement hebdomadaire de ce pilote coûte environ 4 centimes par mois, presque tout en requêtes Web Unlocker. Le verrou de hachage garde la vectorisation à zéro quand rien n’a changé. Si vous évoluez linéairement, 500 pages que vous rafraîchissez chaque semaine coûtent environ 3,25 $ par mois en scraping et moins d’un centime en stockage.

Les jetons de génération par requête et le magasin vectoriel que vous avez choisi sont les deux coûts qui peuvent dépasser ces chiffres. Une collection Amazon OpenSearch Serverless classique a un coût de base même inactive. C’est environ 175 $ par mois au minimum réduit dev-test, et environ le double au plancher standard de 2-OCU. AWS offre aussi un type de collection qui évolue vers zéro, tarifé sur la [page de tarification OpenSearch Service](https://aws.amazon.com/opensearch-service/pricing/). Par rapport aux collections classiques, S3 Vectors change l’arithmétique pour les rafraîchissements planifiés à volume de requêtes modéré.

## Limitations et renforcement pour la production

Ce pipeline est une architecture de référence, pas un produit prêt pour la production.

- **La fraîcheur est un calendrier que vous possédez.** Une base de connaissances est un instantané de sa dernière synchronisation, et entre les synchronisations, elle se périme au rythme où ses données source se dégradent. Déclenchez une alerte quand une synchronisation échoue, car une exécution manquée laisse des données périmées en place.
- **Un scrape échoué se cache derrière de bonnes données.** Quand vous ne pouvez pas récupérer une page, sa version précédente continue de servir comme actuelle. Le loader du dépôt nomme les URL échouées et sort avec un code non nul pour qu’une exécution planifiée les signale. Repérer une page qui s’est tranquillement arrêtée de se rafraîchir est une question séparée. `scraped_date` ne peut pas y répondre, puisqu’une page peut se récupérer proprement pendant des mois sans changer. Le dépôt estampille une date de dernière observation à chaque récupération réussie et rapporte les URL qu’il n’a pas vues depuis une date limite.
- **Vous ne pouvez pas changer le découpage ou la vectorisation plus tard.** Testez les deux sur un échantillon de vos pages avant la première synchronisation complète. Corriger le modèle signifie recréer la base de connaissances, et corriger le découpage signifie recréer la source de données.
- **Le contenu récupéré n’est bon qu’autant que la page.** Bright Data renvoie ce que la page a servi et le convertit en Markdown. Il ne vérifie pas que la page est correcte. Pour tout ce sur quoi vous allez agir, gardez un humain dans la boucle, et utilisez la citation `source_url` pour faire de la vérification un clic plutôt qu’une supposition.
- **Le jeton dans les extraits est un espace réservé.** Tout ce qui est planifié devrait le lire depuis AWS Secrets Manager. Il ne devrait jamais atteindre un dépôt.
- **Les chiffres sont mesurés, mais pas à partir de votre corpus.** Reproduisez-les sur vos propres comptes et données avant de vous fier à un chiffre spécifique.

## Réflexions finales

Amazon Bedrock Knowledge Bases gère le découpage, la vectorisation, et la récupération citée, et ses connecteurs natifs couvrent les données que vous détenez déjà et les pages statiques que vous possédez. Le web public qui change, se rend côté client, et se défend se trouve hors de cette portée, et il contient souvent les données qui rendent une base de connaissances valable à construire. Bright Data comble ce vide, et les deux se rejoignent sur S3.

Pour étendre le pipeline, ajoutez une planification EventBridge pour un rafraîchissement automatique, utilisez l’API Crawl de Bright Data pour une couverture de site entier, ou activez le reclassement Bedrock une fois le découpage stabilisé.

*Le Web Unlocker de Bright Data inclut un niveau gratuit pour démarrer, l’API Crawl couvre les crawls de site entier, et vous configurez Amazon Bedrock Knowledge Bases depuis la [console Amazon Bedrock](https://console.aws.amazon.com/bedrock/). Le projet complet exécutable, avec le loader, le script de configuration de la base de connaissances, et les politiques IAM, est dans le [dépôt compagnon](https://github.com/luminati-io/bedrock-web-kb-brightdata).*

## Questions fréquemment posées

### Amazon Bedrock Knowledge Bases peut-il crawler le web par lui-même ?

Il a un Web Crawler natif en preview, un bon choix pour les pages statiques que vous possédez. Aujourd’hui, il gère uniquement les sites statiques, interdit un site sans `robots.txt`, plafonne à 25 000 pages par synchronisation, et a besoin d’OpenSearch Serverless. Pour les pages JavaScript ou protégées contre les bots, utilisez Bright Data pour rendre et débloquer le contenu, puis ingérez depuis S3.

### Pourquoi stocker les données sur S3 plutôt que de les récupérer depuis le web au moment de la requête ?

Une base de connaissances persistante vectorise chaque page une fois et sert de nombreuses requêtes à partir d’une recherche vectorielle à faible latence, avec citations, filtrage par métadonnées, et contrôle d’accès. La récupération en direct via Bright Data convient aux recherches rapidement changeantes ou ponctuelles. De nombreux systèmes de production utilisent les deux, et routent par requête selon le score.

### Dans quel format les pages scrapées doivent-elles être pour Bedrock ?

Markdown. Le Web Unlocker de Bright Data renvoie la page en Markdown quand vous définissez `data_format` sur `markdown`, et Bedrock l’ingère comme un type de document pris en charge. La conversion retire le balisage HTML mais pas la navigation du site, donc nettoyez le chrome répétitif avant d’écrire sur S3.

### Comment fonctionnent les citations dans les réponses ?

Vous écrivez un attribut `source_url` dans le fichier annexe `.metadata.json` de chaque document. Bedrock porte ces métadonnées dans la récupération, donc `Retrieve` les renvoie sur chaque chunk et `RetrieveAndGenerate` inclut un tableau de citations qui résout chaque portion de la réponse vers la page dont elle provient.

### Pourquoi ma tâche d’ingestion indique-t-elle COMPLETE alors que rien n’a été indexé ?

Parce que `status` n’est pas un signal de succès. Une tâche peut rapporter `COMPLETE` même quand la plupart de ses documents ont échoué, et sur ce pipeline elle a rapporté `COMPLETE` avec 5 sur 6 échoués. Lisez `statistics` pour les comptages par document et `failureReasons` pour l’erreur, qui ici était la limite de métadonnées filtrables de S3 Vectors.

### Comment garder la base de connaissances à jour ?

Re-scrapez selon un calendrier, écrivez seulement les objets dont le hachage de contenu a changé, et démarrez une tâche d’ingestion. Ce verrou de hachage empêche Bedrock de ré-vectoriser une page inchangée. Faites correspondre le calendrier à la vitesse de dégradation de vos sources, du quotidien pour les actualités à l’hebdomadaire ou plus lent pour la documentation.

### Combien de questions un ensemble de référence a-t-il besoin ?

Moins que ce que les gens attendent, et les questions doivent être réelles. Les questions tirées de ce que les utilisateurs posent réellement surpassent les questions inventées, car le but est de trouver ce que votre corpus ne peut pas ancrer plutôt que de produire un chiffre. Ajoutez-en une chaque fois que quelqu’un signale une mauvaise réponse, et l’ensemble devient une suite de régression.

### Combien cela coûte-t-il à exécuter ?

Les coûts principaux sont les requêtes Bright Data, qui évoluent avec les pages fois la fréquence de rafraîchissement, plus le magasin vectoriel, et la vectorisation et génération par jeton. S3 Vectors est à l’utilisation et convient à un rafraîchissement planifié, tandis qu’une collection OpenSearch Serverless classique coûte même inactive. Le pilote de 6 pages ici a coûté environ 4 centimes par mois pour un rafraîchissement hebdomadaire.



Contacter ventesEssai gratuit![google social icon](/wp-content/themes/brightdata/assets/images/ic_google.svg)









 Table des matières







Dedicated Scraper APIs &amp; No-Code Scrapers

Over 1000 scrapers for all popular domains. Simplify your web scraping.

[See pricing](/pricing/web-scraper "See pricing")

Just want data? Skip scraping.

Hundreds of ready-to-use datasets from all popular domains.

[See pricing](/pricing/datasets "See pricing")







 [ ](https://news.ycombinator.com/submitlink?t=Comment+alimenter+Amazon+Bedrock+Knowledge+Bases+avec+des+donn%C3%A9es+web+en+direct+gr%C3%A2ce+%C3%A0+Bright+Data&u=https://brightdata.fr/blog/savoir-faire/amazon-bedrock-knowledge-bases-with-bright-data) [ ](https://www.linkedin.com/shareArticle?mini=true&title=Comment+alimenter+Amazon+Bedrock+Knowledge+Bases+avec+des+donn%C3%A9es+web+en+direct+gr%C3%A2ce+%C3%A0+Bright+Data&url=https://brightdata.fr/blog/savoir-faire/amazon-bedrock-knowledge-bases-with-bright-data) [ ](http://www.reddit.com/submit?title=Comment+alimenter+Amazon+Bedrock+Knowledge+Bases+avec+des+donn%C3%A9es+web+en+direct+gr%C3%A2ce+%C3%A0+Bright+Data&url=https://brightdata.fr/blog/savoir-faire/amazon-bedrock-knowledge-bases-with-bright-data)







##  Vous pourriez aussi être intéressé par

 [ ![MiniMax M3 with Bright Data](https://media.brightdata.fr/2026/09/MiniMax-M3-with-Bright-Data.png) ](https://brightdata.fr/blog/ai/minimax-m3-with-bright-data "Donner aux agents MiniMax M3 auto-hébergés un accès web en direct avec Bright Data")

 [AI



 ![Satyam Tripathi](https://media.brightdata.fr/2024/09/Satyam-Tripathi-50x50.png)

Satyam Tripathi

Technical Writer





### Donner aux agents MiniMax M3 auto-hébergés un accès web en direct avec Bright Data

Les agents MiniMax M3 auto-hébergés obtiennent un accès web en direct grâce aux outils de recherche et de scraping de Bright Data. Contournez blocages et CAPTCHA.



 15-Oct-2026

 69 min de lecture

 ](https://brightdata.fr/blog/ai/minimax-m3-with-bright-data)

 [ ![Agentic Registration](https://media.brightdata.fr/2026/09/Agentic-Registration.png) ](https://brightdata.fr/blog/ai/agentic-registration "Inscription agentique : comment un agent IA s’inscrit à Bright Data avec auth.md")

 [AI



 ![Daniel Shashko](https://media.brightdata.fr/2022/04/Daniel-Shashko-2-50x50.png)

Daniel Shashko

Web Data &amp; AI Expert





### Inscription agentique : comment un agent IA s’inscrit à Bright Data avec auth.md

Comment un agent IA s’inscrit à Bright Data via auth.md et obtient un jeton API fonctionnel, avec un humain qui confirme uniquement un code email.



 15-Oct-2026

 17 min de lecture

 ](https://brightdata.fr/blog/ai/agentic-registration)

 [ ![Snowflake with Bright Data](https://media.brightdata.fr/2026/10/Bright-Data-__Snowflake_From-Web-Data-to-AI-Ready-Intelligence.svg) ](https://brightdata.fr/blog/ai/snowflake-with-bright-data "Bright Data + Snowflake : Des données web à l’intelligence prête pour l’IA")

 [AI



 ![Antonello Zanini](https://media.brightdata.fr/2022/12/Antonello-Zanini-2-50x50.jpg)

Antonello Zanini

Technical Writer





### Bright Data + Snowflake : Des données web à l’intelligence prête pour l’IA

Apprenez à envoyer des jeux de données web Bright Data vers Snowflake, à les activer avec Cortex AI, et à choisir entre jeux de données stockés et accès MCP en direct.



 15-Oct-2026

 19 min de lecture

 ](https://brightdata.fr/blog/ai/snowflake-with-bright-data)
