درس 2 — Construire pas à pas

Le toolset BigQuery d'ADK

6 دقائق قراءة

هذا المحتوى غير مترجم بعد. تُعرض النسخة الأصلية.

Le toolset BigQuery d'ADK

Un toolset plutôt que des outils maison

Un toolset est un ensemble d'outils prêts à l'emploi qu'ADK expose au modèle. Le BigQueryToolset d'ADK 2.10 en contient onze (métadonnées, execute_sql, prévisions, détection d'anomalies, recherche de catalogue…). Nous n'en gardons que deux :

OutilRôlePourquoi le garder
get_table_infoschéma et description d'une tablele modèle vérifie les noms de colonnes au lieu de les deviner
execute_sqlexécute une requête et renvoie au plus N lignesle cœur de l'analyste

La configuration

files/agent.py
from google.adk.integrations.bigquery import BigQueryToolset
from google.adk.integrations.bigquery.config import BigQueryToolConfig, WriteMode

PROJET = os.environ.get("GOOGLE_CLOUD_PROJECT", "votre-projet")
MAX_OCTETS = int(os.environ.get("MAX_OCTETS", 1_000_000_000))     # 1 Go par requête
LABELS = {"formation-lab": "analyste-bigquery"}

boite_a_outils = BigQueryToolset(
    tool_filter=["get_table_info", "execute_sql"],
    bigquery_tool_config=BigQueryToolConfig(
        write_mode=WriteMode.BLOCKED,          # lecture seule (vérifiée aussi par dry-run)
        maximum_bytes_billed=MAX_OCTETS,       # plafond appliqué par BigQuery lui-même
        max_query_result_rows=50,
        compute_project_id=PROJET, default_project_id=PROJET,
        location="US",                          # thelook_ecommerce est en multirégion US
        application_name="lab-analyste-bigquery", job_labels=LABELS,
    ),
)
ParamètreEffetÀ retenir
write_mode=WriteMode.BLOCKEDavant d'exécuter, ADK fait un dry-run et refuse tout ce qui n'est pas SELECTvaleur par défaut, mais écrivez-la : c'est une décision de sécurité
maximum_bytes_billedtransmis à chaque job ; BigQuery refuse au-delàminimum accepté : 10 485 760 octets (10 Mo)
max_query_result_rows=50au plus 50 lignes renvoyées au modèleun résultat tronqué est signalé par result_is_likely_truncated
compute_project_idles requêtes ne peuvent tourner (et être facturées) que dans ce projetle modèle ne peut pas choisir un autre projet payeur
default_project_idprojet utilisé quand le modèle n'en donne pasdoit être égal à compute_project_id s'il est défini
location="US"région de calculdoit correspondre à la région des données lues
job_labelsétiquettes sur chaque jobretrouver et chiffrer les requêtes du lab (leçon « Coûts »)

Que se passe-t-il si le modèle appelle execute_sql avec project_id="autre-projet" alors que compute_project_id vaut votre projet ?

Identifiants et modèle

Aucun identifiant n'apparaît dans le code. Sans credentials_config, les outils créent un client BigQuery qui utilise les ADC de la machine : votre compte en local (gcloud auth application-default login), le compte de service en production.

Le modèle passe par Vertex AI (GOOGLE_GENAI_USE_VERTEXAI=TRUE). Comme le quota est partagé, on demande au client Gemini de réessayer seul les erreurs 429 (quota) et 503 (indisponible) :

files/agent.py
from google.adk.models.google_llm import Gemini

def modele_avec_reessais() -> Gemini:
    """Quota partagé : on réessaie les 429/503 avec un délai croissant (2 s, 4 s, 8 s...)."""
    return Gemini(model=MODEL, retry_options=types.HttpRetryOptions(initial_delay=2, attempts=6))

L'instruction

files/agent.py (extrait)
instruction=f"""Tu es un analyste de données. Tu réponds en français.
Données : jeu public fictif {DATASET} (boutique de vêtements en ligne).
Tables autorisées (et AUCUNE autre) : {', '.join(sorted(TABLES_AUTORISEES))}.
Écris toujours le nom complet des tables entre accents graves [...]
2. Écris UNE requête GoogleSQL SELECT qui calcule directement le résultat final, en ne
   sélectionnant que les colonnes utiles (BigQuery facture les colonnes lues) [...]
   Ne réponds jamais à partir des métadonnées de get_table_info (nombre de lignes...) [...]
3. [...] la dernière requête exécutée doit être celle que tu cites dans ta réponse.
Règles métier (sauf demande contraire) :
- chiffre d'affaires = SUM(order_items.sale_price) sur les articles au statut 'Complete' ;
- la date de référence d'une vente est order_items.created_at (TIMESTAMP, UTC) ; [...]"""

Chaque phrase a une raison mesurée (voir l'évaluation) : sans la règle sur les métadonnées, l'agent a répondu « 10 centres de distribution » en lisant le nombre de lignes renvoyé par get_table_info, sans requête ; sans la règle sur la dernière requête, il a lancé une vérification après le bon calcul, ce qui brouille l'audit.

flowchart TB
  Q["Question"] --> I{"Colonnes connues ?"}
  I -->|"non"| G["get_table_info"]
  G --> S["Écrire une requête SELECT, colonnes utiles seulement"]
  I -->|"oui"| S
  S --> E["execute_sql"]
  E -->|"erreur"| S
  E -->|"lignes"| R["Réponse, Requête, Explication"]

Pourquoi l'instruction demande-t-elle de ne sélectionner que les colonnes utiles ?

Exercice : ajouter les prévisions

Votre équipe veut demander « prévois les ventes des 30 prochains jours ». Le toolset contient un outil forecast. Que faut-il modifier, et quel risque cela ajoute-t-il ?

Voir la solution

Ajoutez "forecast" à tool_filter. Dans ADK 2.10, cet outil construit une requête utilisant la fonction AI.FORECAST de BigQuery, qui s'exécute aussi dans votre projet de calcul.

Risques à traiter :

  • le contrôle controle_cout ne regarde que execute_sql : étendez-le à forecast (le dry-run de la requête générée), sinon cet outil échappe à la liste blanche ;
  • les fonctions d'IA de BigQuery peuvent avoir une tarification propre : vérifiez la page des tarifs avant de l'ouvrir à toute une équipe.

Résultat obtenu

Exécution réelle le 2026-10-15 (gemini-2.5-flash sur Vertex AI, europe-west1) : « Quel est le chiffre d'affaires par catégorie de produit en 2025 ? Donne les 5 premières. »

**Réponse**
1.  **Outerwear & Coats** : 80 554,47
2.  **Jeans** : 72 003,87
3.  **Sweaters** : 46 898,11
[...]
**Requête**
SELECT t2.category, ROUND(SUM(t1.sale_price), 2) AS revenue
FROM `bigquery-public-data.thelook_ecommerce.order_items` AS t1
INNER JOIN `bigquery-public-data.thelook_ecommerce.products` AS t2 ON t1.product_id = t2.id
WHERE t1.status = 'Complete' AND EXTRACT(YEAR FROM t1.delivered_at) = 2025
GROUP BY t2.category ORDER BY revenue DESC LIMIT 5

estimation du dry-run : 5 852 459 octets, tables order_items et products

Ce premier essai a pris delivered_at comme date de référence : c'est ce qui a motivé la règle métier « la date de référence d'une vente est order_items.created_at ». Les montants affichés ici avec le symbole € ont aussi conduit à la règle « pas de devise ».

Je sais faire

  • Filtrer les outils d'un toolset ADK avec tool_filter
  • Configurer BigQueryToolConfig : lecture seule, plafond, projet de calcul, région, labels
  • Utiliser les ADC au lieu d'identifiants dans le code
  • Activer les réessais automatiques de Gemini sur les erreurs 429/503
التالي