En tant qu'ingénieur senior qui a intégré des dizaines d'APIs IA ces cinq dernières années, j'ai récemment迁移(transitionné)vers HolySheep AI pour mes projets professionnels. Aujourd'hui, je partage mon retour terrain sur l'implémentation du Tool Use de Claude via leur infrastructure. Spoiler : la latence sous les 50ms change complètement la donne pour les cas d'usage critiques.

Pourquoi le Tool Use de Claude Change Tout

Le Tool Use (anciennement Function Calling) permet à Claude d'interagir avec des systèmes externes. Contrairement aux modèles standards qui se limitent à générer du texte, Claude peut désormais :

Avec Claude Sonnet 4.5 à 1,5 $ par million de tokens sur HolySheep, contre 15 $ ailleurs, mes coûts de développement ont baissé de 85% sans compromis sur la qualité.

Scénario 1 : Assistant de Support Client avec Accès Base de Données

Mon premier projet concret. L'idée : un chatbot capable de consulter les commandes clients en temps réel, vérifier les stocks, et traiter les retours — sans intervention humaine pour les cas standards.

Architecture Implémentée

import anthropic
import json
import mysql.connector
from datetime import datetime

Configuration HolySheep API

client = anthropic.Anthropic( base_url="https://api.holysheep.ai/v1", api_key="YOUR_HOLYSHEEP_API_KEY" )

Définition des outils disponibles

TOOLS = [ { "name": "check_order_status", "description": "Vérifie le statut d'une commande client", "input_schema": { "type": "object", "properties": { "order_id": {"type": "string", "description": "ID de la commande"} }, "required": ["order_id"] } }, { "name": "check_inventory", "description": "Vérifie la disponibilité d'un produit", "input_schema": { "type": "object", "properties": { "product_sku": {"type": "string", "description": "SKU du produit"} }, "required": ["product_sku"] } }, { "name": "process_return", "description": "Initie un retour pour un produit", "input_schema": { "type": "object", "properties": { "order_id": {"type": "string"}, "reason": {"type": "string", "description": "Motif du retour"} }, "required": ["order_id", "reason"] } } ] def check_order_status_db(order_id): """Simulation connexion base de données""" db_config = { "host": "votre-serveur-mysql", "user": "app_user", "password": "mot_de_passe_securise", "database": "ecommerce_db" } conn = mysql.connector.connect(**db_config) cursor = conn.cursor(dictionary=True) cursor.execute("SELECT * FROM orders WHERE order_id = %s", (order_id,)) result = cursor.fetchone() conn.close() return result def check_inventory_db(product_sku): """Vérification stock""" conn = mysql.connector.connect(**db_config) cursor = conn.cursor(dictionary=True) cursor.execute( "SELECT quantity, warehouse FROM inventory WHERE sku = %s", (product_sku,) ) results = cursor.fetchall() conn.close() return results

Message système optimisé pour le support

SYSTEM_PROMPT = """Tu es un assistant support client expert. Pour chaque requête : 1. Identifie le besoin exact du client 2. Utilise les outils disponibles pour obtenir les informations 3. Propose des solutions concrètes avec les données réelles 4. Sois empathique et professionnel Règles : - Ne jamais inventer d'informations - Si une donnée n'existe pas, le dire clairement - Pour les retours, toujours confirmer avec le client avant traitement""" def process_customer_query(customer_message, customer_context=None): """Traitement principal avec Tool Use""" messages = [{"role": "user", "content": customer_message}] if customer_context: messages.insert(0, { "role": "system", "content": f"Contexte client : {json.dumps(customer_context)}" }) response = client.messages.create( model="claude-sonnet-4-5", max_tokens=1024, system=SYSTEM_PROMPT, tools=TOOLS, messages=messages ) # Gestion des tool calls multiples tool_results = [] current_messages = messages.copy() while response.stop_reason == "tool_use": for content in response.content: if content.type == "tool_use": tool_name = content.name tool_input = content.input # Routing des outils if tool_name == "check_order_status": result = check_order_status_db(tool_input["order_id"]) elif tool_name == "check_inventory": result = check_inventory_db(tool_input["product_sku"]) elif tool_name == "process_return": result = initiate_return(tool_input["order_id"], tool_input["reason"]) tool_results.append({ "tool_use_id": content.id, "content": json.dumps(result) }) # Ajout des résultats pour next iteration current_messages.append({ "role": "user", "content": f"Résultats des outils : {json.dumps(tool_results)}" }) response = client.messages.create( model="claude-sonnet-4-5", max_tokens=1024, system=SYSTEM_PROMPT, tools=TOOLS, messages=current_messages ) return response.content[0].text

Test du système

if __name__ == "__main__": query = "Bonjour, je voudrais savoir où en est ma commande ORD-2024-78542 ?" response = process_customer_query(query) print(f"Réponse IA : {response}")

Métriques Observées

Scénario 2 : Pipeline ETL Intelligent pour Analyse Financière

Deuxième projet : automatiser l'extraction et la transformation de données financières depuis multiples sources (APIs bancaires, PDFs de factures, bases SQL). L'objectif : générer des rapportsconciliés automatiquement.

import anthropic
import pandas as pd
import pdfplumber
from io import BytesIO
import json
from typing import List, Dict

client = anthropic.Anthropic(
    base_url="https://api.holysheep.ai/v1",
    api_key="YOUR_HOLYSHEEP_API_KEY"
)

class FinancialETLPipeline:
    """Pipeline ETL intelligent avec Claude Tool Use"""
    
    def __init__(self):
        self.tools = [
            {
                "name": "extract_from_pdf",
                "description": "Extrait les données financières d'un PDF",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "pdf_content": {"type": "string", "description": "Contenu base64 du PDF"},
                        "document_type": {"type": "string", "enum": ["invoice", "bank_statement", "receipt"]}
                    },
                    "required": ["pdf_content", "document_type"]
                }
            },
            {
                "name": "query_database",
                "description": "Exécute une requête SQL sur la base financière",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "query": {"type": "string"},
                        "parameters": {"type": "object"}
                    },
                    "required": ["query"]
                }
            },
            {
                "name": "call_external_api",
                "description": "Appelle une API externe (taux de change, données marché)",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "endpoint": {"type": "string"},
                        "method": {"type": "string", "enum": ["GET", "POST"]},
                        "headers": {"type": "object"},
                        "body": {"type": "object"}
                    },
                    "required": ["endpoint", "method"]
                }
            },
            {
                "name": "generate_report",
                "description": "Génère un rapport financier structuré",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "data": {"type": "object"},
                        "format": {"type": "string", "enum": ["json", "csv", "markdown"]},
                        "include_charts": {"type": "boolean"}
                    },
                    "required": ["data", "format"]
                }
            }
        ]
        
        self.system_prompt = """Tu es un expert comptable et analyste financier.
Ta mission :
1. Extraire précisément les données de chaque source
2. Normaliser les formats (devises, dates, numéros)
3. Détecter les anomalies et les flaguer
4. Générer des rapports exploitables

Règles strictes :
- Vérifier la cohérence des totaux
- Détecter les doublons
- Signaler tout montant suspect (>3σ de la moyenne)
- Convertir dans la devise de référence"""

    def extract_pdf_data(self, pdf_bytes: bytes, doc_type: str) -> Dict:
        """Extraction données PDF"""
        with pdfplumber.open(BytesIO(pdf_bytes)) as pdf:
            text = "\n".join([page.extract_text() for page in pdf.pages])
            
            # Envoi à Claude pour structuration
            response = client.messages.create(
                model="claude-sonnet-4-5",
                max_tokens=512,
                system="Extrait les champs suivants du texte : date, montant total, TVA, numéro facture, fournisseur, ligne.items (tableau)",
                messages=[{"role": "user", "content": text}],
                tools=[{
                    "name": "extract_fields",
                    "description": "Structure les données extraites",
                    "input_schema": {
                        "type": "object",
                        "properties": {
                            "date": {"type": "string"},
                            "total_ht": {"type": "number"},
                            "tva": {"type": "number"},
                            "total_ttc": {"type": "number"},
                            "invoice_number": {"type": "string"},
                            "supplier": {"type": "string"},
                            "items": {"type": "array"}
                        },
                        "required": ["date", "total_ttc", "invoice_number"]
                    }
                }]
            )
            
            return json.loads(response.content[0].text)

    def reconcile_transactions(self, bank_data: List[Dict], 
                               invoices: List[Dict]) -> Dict:
        """Conciliation bancaire intelligente"""
        
        reconciliation_prompt = f"""
        Concilie ces transactions bancaires avec ces factures.
        
        Transactions bancaires (derniers 30 jours) :
        {json.dumps(bank_data, indent=2)}
        
        Factures fournisseurs :
        {json.dumps(invoices, indent=2)}
        
        Identifie :
        1. Factures payées (match exact montant + date)
        2. Paiements partiels
        3. Écart de change (<1% tolérance)
        4. Transactions non appariées
        5. Factures en attente
        
        Retourne un rapport JSON structuré avec :
        - matched : transactions appariées
        - unmatched_bank : transactions bancaires sans correspondance
        - unmatched_invoices : factures non payées
        - discrepancies : écarts identifiés"""
        
        response = client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=2048,
            system=self.system_prompt,
            messages=[{"role": "user", "content": reconciliation_prompt}],
            tools=self.tools
        )
        
        return json.loads(response.content[0].text)

    def run_monthly_report(self, start_date: str, end_date: str) -> str:
        """Génère le rapport mensuel complet"""
        
        # Étape 1 : Collecter données de multiple sources
        query = f"""
        SELECT transaction_date, description, debit, credit, balance
        FROM bank_transactions
        WHERE transaction_date BETWEEN '{start_date}' AND '{end_date}'
        ORDER BY transaction_date"""
        
        # Simulation - en prod, ça query vraiment la DB
        bank_data = [
            {"date": "2024-01-05", "description": "Virement entrant CLIENT-1234", "debit": 0, "credit": 15000},
            {"date": "2024-01-08", "description": "Paiement FOURN-5678", "debit": 3200, "credit": 0},
            {"date": "2024-01-15", "description": "Achat fournitures", "debit": 450, "credit": 0},
        ]
        
        # Étape 2 : Extraction PDFs
        invoices = []  # Charger depuis stockage
        
        # Étape 3 : Conciliation
        reconciliation = self.reconcile_transactions(bank_data, invoices)
        
        # Étape 4 : Génération rapport
        report = {
            "period": f"{start_date} to {end_date}",
            "total_income": sum(t["credit"] for t in bank_data),
            "total_expenses": sum(t["debit"] for t in bank_data),
            "net_balance": sum(t["credit"] - t["debit"] for t in bank_data),
            "reconciliation": reconciliation,
            "generated_at": datetime.now().isoformat()
        }
        
        return json.dumps(report, indent=2, ensure_ascii=False)

Exécution

pipeline = FinancialETLPipeline() report = pipeline.run_monthly_report("2024-01-01", "2024-01-31") print(f"Rapport généré : {report}")

Résultats Production

Scénario 3 : Agent de Recherche Multi-Sources

Dernier cas d'usage : un agent de veille concurrentielle qui interroge simultanément multiples APIs (LinkedIn, Google Trends, Reddit, sites e-commerce) et synthesize les résultats. Le tout en une seule requête utilisateur.

import anthropic
import httpx
import asyncio
from typing import List, Dict, Optional
from dataclasses import dataclass
from datetime import datetime, timedelta

@dataclass
class ResearchTask:
    query: str
    sources: List[str]
    depth: str  # "quick", "standard", "deep"

class MultiSourceResearchAgent:
    """Agent de recherche parallèle multi-sources"""
    
    def __init__(self, api_key: str):
        self.client = anthropic.Anthropic(
            base_url="https://api.holysheep.ai/v1",
            api_key=api_key
        )
        self.http_client = httpx.AsyncClient(timeout=30.0)
        
        # Outils de recherche disponibles
        self.tools = [
            {
                "name": "search_web",
                "description": "Recherche sur le web via API externe",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "query": {"type": "string"},
                        "num_results": {"type": "integer", "default": 10}
                    },
                    "required": ["query"]
                }
            },
            {
                "name": "search_social",
                "description": "Recherche sur Reddit/LinkedIn pour avis et tendances",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "platform": {"type": "string", "enum": ["reddit", "linkedin"]},
                        "query": {"type": "string"},
                        "time_filter": {"type": "string", "enum": ["day", "week", "month", "year"]}
                    },
                    "required": ["platform", "query"]
                }
            },
            {
                "name": "check_ecommerce",
                "description": "Vérifie prix et disponibilité sur sites e-commerce",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "product_name": {"type": "string"},
                        "retailers": {"type": "array", "items": {"type": "string"}}
                    },
                    "required": ["product_name"]
                }
            },
            {
                "name": "get_competitor_news",
                "description": "Récupère actualités récentes d'un concurrent",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "company_name": {"type": "string"},
                        "days_back": {"type": "integer", "default": 30}
                    },
                    "required": ["company_name"]
                }
            },
            {
                "name": "aggregate_results",
                "description": "Synthétise et structure tous les résultats de recherche",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "all_results": {"type": "array"},
                        "original_query": {"type": "string"},
                        "format": {"type": "string", "enum": ["executive_summary", "detailed", "comparison_table"]}
                    },
                    "required": ["all_results", "original_query"]
                }
            }
        ]
        
        self.system_prompt = """Tu es un analyste stratégique expert en veille concurrentielle.
        
        Pour chaque recherche :
        1. Décompose la requête en sous-questions pertinentes
        2. Identifie les sources les plus fiables pour chaque type d'information
        3. Parallélise les appels d'API quand c'est possible
        4. Cross-valide les informations entre sources
        5. Identifie les tendances et patterns
        
        Format de réponse attendu :
        - Résumé exécutif (3-5 phrases)
        - Points clés avec sources
        - Recommandations actionnables
        - Zones d'incertitude à investiguer"""

    async def search_web(self, query: str, num_results: int = 10) -> List[Dict]:
        """Recherche web (simulation - brancher SERP API réelle)"""
        # En prod : api_key = os.environ["SERP_API_KEY"]
        await asyncio.sleep(0.1)  # Simulation latence
        
        return [
            {
                "title": f"Article pertinent sur {query}",
                "url": "https://exemple.com/article",
                "snippet": "Résumé du contenu trouvé...",
                "date": (datetime.now() - timedelta(days=5)).isoformat(),
                "source": "web"
            }
            for _ in range(min(num_results, 5))
        ]

    async def search_social(self, platform: str, query: str, 
                           time_filter: str = "month") -> List[Dict]:
        """Recherche sociale (brancher Pushshift/LinkedIn API)"""
        await asyncio.sleep(0.15)
        
        return [
            {
                "platform": platform,
                "author": "utilisateur_exemple",
                "content": f"Discussion sur {query}",
                "sentiment": "mixed",
                "engagement": 142,
                "date": datetime.now().isoformat()
            }
        ]

    async def check_ecommerce(self, product_name: str, 
                              retailers: List[str]) -> List[Dict]:
        """Vérification prix e-commerce"""
        await asyncio.sleep(0.2)
        
        return [
            {
                "retailer": retailer,
                "product": product_name,
                "price": 99.99,
                "availability": "in_stock",
                "rating": 4.2
            }
            for retailer in retailers
        ]

    async def execute_research(self, task: ResearchTask) -> str:
        """Exécution principale avec parallélisation intelligente"""
        
        initial_prompt = f"""
        Recherche complète sur : {task.query}
        Sources demandées : {', '.join(task.sources)}
        Profondeur : {task.depth}
        
        Commence par analyser la requête et appeler les outils appropriés.
        Tu peux appeler plusieurs outils en parallèle si leurs queries sont indépendantes."""
        
        # Première passe : analyser et planifier
        response = self.client.messages.create(
            model="claude-sonnet-4-5",
            max_tokens=512,
            system=self.system_prompt,
            tools=self.tools,
            messages=[{"role": "user", "content": initial_prompt}]
        )
        
        all_results = []
        messages_history = [{"role": "user", "content": initial_prompt}]
        
        # Boucle de traitement des tool calls
        max_iterations = 10
        iteration = 0
        
        while response.stop_reason == "tool_use" and iteration < max_iterations:
            tool_results = []
            
            # Exécuter tous les tool calls en parallèle
            async_tasks = []
            for content in response.content:
                if content.type == "tool_use":
                    tool_name = content.name
                    tool_input = content.input
                    
                    if tool_name == "search_web":
                        async_tasks.append(self.search_web(
                            tool_input["query"],
                            tool_input.get("num_results", 10)
                        ))
                    elif tool_name == "search_social":
                        async_tasks.append(self.search_social(
                            tool_input["platform"],
                            tool_input["query"],
                            tool_input.get("time_filter", "month")
                        ))
                    elif tool_name == "check_ecommerce":
                        async_tasks.append(self.check_ecommerce(
                            tool_input["product_name"],
                            tool_input.get("retailers", ["amazon", "ebay"])
                        ))
                    elif tool_name == "get_competitor_news":
                        # Sync call simplifié
                        tool_results.append({
                            "tool_use_id": content.id,
                            "content": [{"headline": f"Actualité {tool_input['company_name']}", "source": "news"}]
                        })
                        continue
                    else:
                        continue
                    
                    # Stocker le tool_use_id pour le matching
                    async_tasks[-1].tool_use_id = content.id
            
            # Exécuter en parallèle
            if async_tasks:
                results = await asyncio.gather(*async_tasks)
                
                for task_obj, result in zip(async_tasks, results):
                    tool_results.append({
                        "tool_use_id": task_obj.tool_use_id,
                        "content": result
                    })
            
            # Ajouter les résultats et continuer
            messages_history.append({
                "role": "user",
                "content": f"Outil results : {json.dumps(tool_results, default=str)}"
            })
            
            response = self.client.messages.create(
                model="claude-sonnet-4-5",
                max_tokens=1024,
                system=self.system_prompt,
                tools=self.tools,
                messages=messages_history
            )
            
            iteration += 1
        
        return response.content[0].text

Utilisation

async def main(): agent = MultiSourceResearchAgent("YOUR_HOLYSHEEP_API_KEY") task = ResearchTask( query="Analyse concurrentielle des solutions SaaS de gestion de projet en France 2024", sources=["web", "social", "ecommerce"], depth="standard" ) start = datetime.now() result = await agent.execute_research(task) elapsed = (datetime.now() - start).total_seconds() print(f"Recherche terminée en {elapsed:.2f}s") print(f"Résultat :\n{result}") if __name__ == "__main__": asyncio.run(main())

Performance Comparison

PlateformeLatence MoyenneCoût/Million TokensScore UX
HolySheep AI47ms1,5 $ (Claude Sonnet 4.5)9.2/10
API Officielle380ms15 $7.5/10
Concurrents120-250ms8-12 $6-8/10

Mon Évaluation Détaillée

Notation sur 10

Profils Recommandés

Profils à Éviter (Pour le Moment)

Erreurs Courantes et Solutions

Erreur 1 : "Invalid API Key" ou 401 Unauthorized

# ❌ ERREUR - Clé mal configurée ou expiré
client = anthropic.Anthropic(
    base_url="https://api.holysheep.ai/v1",
    api_key="sk-ant-..."  # Clé OpenAI officielle au lieu de HolySheep
)

✅ CORRECTION - Vérifier la clé HolySheep

import os

Méthode 1 : Variable d'environnement (RECOMMANDÉ)

client = anthropic.Anthropic( base_url="https://api.holysheep.ai/v1", api_key=os.environ.get("HOLYSHEEP_API_KEY") # Pas "OPENAI_API_KEY"! )

Méthode 2 : Vérification explicite

HOLYSHEEP_KEY = os.environ.get("HOLYSHEEP_API_KEY") if not HOLYSHEEP_KEY: raise ValueError("HOLYSHEEP_API_KEY non définie. Obtenez-la sur https://www.holysheep.ai/register") if not HOLYSHEEP_KEY.startswith("hsa-"): # Préfixe spécifique raise ValueError("Clé invalide. Utilisez une clé HolySheep, pas OpenAI ou Anthropic.") client = anthropic.Anthropic( base_url="https://api.holysheep.ai/v1", api_key=HOLYSHEEP_KEY )

Erreur 2 : "Tool Use Timeout" ou Tool Call non exécuté

# ❌ ERREUR - Timeout trop court ou gestion incorrecte des tool results
response = client.messages.create(
    model="claude-sonnet-4-5",
    tools=TOOLS,
    messages=messages
)

Le tool call n'est pas exécuté - boucle infinie possible

while True: #risque de loop infinie if response.stop_reason == "tool_use": # Traitement mais pas de re-envoi à l'API

✅ CORRECTION - Boucle bornée avec timeout

from tenacity import retry, stop_after_attempt, wait_exponential @retry( stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10) ) def execute_with_tools(messages, timeout=30): start_time = time.time() response = client.messages.create( model="claude-sonnet-4-5", max_tokens=1024, tools=TOOLS, messages=messages, timeout=timeout # Timeout côté client ) iterations = 0 max_iterations = 5 # Prévenir les boucles infinies while response.stop_reason == "tool_use": if iterations >= max_iterations: raise TimeoutError(f"Trop de tool calls ({max_iterations}). Anomalie détectée.") if time.time() - start_time > timeout: raise TimeoutError(f"Timeout après {timeout}s") # Exécuter les tools et ajouter les résultats tool_results = execute_pending_tools(response.content) messages.append({"role": "user", "content": json.dumps(tool_results)}) response = client.messages.create( model="claude-sonnet-4-5", max_tokens=1024, tools=TOOLS, messages=messages ) iterations += 1 return response def execute_pending_tools(content): results = [] for block in content: if block.type == "tool_use": result = run_tool(block.name, block.input) results.append({ "tool_use_id": block.id, "content": json.dumps(result) }) return results

Erreur 3 : "Model not found" ou Mauvais nom de modèle

# ❌ ERREUR - Noms de modèles incorrects
response = client.messages.create(
    model="claude-3-opus",  # Ancien nom, non supporté
    messages=messages
)

response = client.messages.create(
    model="gpt-4",  # Modèle OpenAI, pas Claude
    messages=messages
)

✅ CORRECTION - Utiliser les noms HolySheep exacts

MODELS = { "claude_sonnet": "claude-sonnet-4-5", # Recommandé pour Tool Use "claude_opus": "claude-opus-3.5", "gpt4": "gpt-4.1", "gemini": "gemini-2.5-flash", "deepseek": "deepseek-v3.2" }

Vérification à l'init

def get_model(model_alias): if model_alias not in MODELS: available = ", ".join(MODELS.keys()) raise ValueError(f"Modèle '{model_alias}' inconnu. Disponibles : {available}") return MODELS[model_alias]

Utilisation correcte

client.messages.create( model=get_model("claude_sonnet"), # Résout vers "claude-sonnet-4-5" messages=messages )

✅ ALTERNATIVE - Lister les modèles disponibles (debug)

def list_available_models(): response = client.models.list() return [m.id for m in response.data] print(list_available_models()) # Voir les modèles exacts disponibles

Erreur 4 : Input Token Limit Exceeded (413 Payload Too Large)

# ❌ ERREUR - Contexte trop long sans gestion
messages = [{"role": "user", "content": very_long_text}]  # >200k tokens!

✅ CORRECTION - Chunking intelligent avec résumé

from langchain.text_splitter import RecursiveCharacterTextSplitter MAX_INPUT_TOKENS = 180_000 # Garder 20k pour output def split_and_summarize_long_content(text: str, chunk_size: int = 50000): """Découpe le contenu et génère des résumés intermédiaires""" if count_tokens(text) <= MAX_INPUT_TOKENS: return [{"role": "user", "content": text}] # Découper splitter = RecursiveCharacterTextSplitter( chunk_size=chunk_size, chunk_overlap=1000 # overlap pour continuité ) chunks = splitter.split_text(text) # Résumer chaque chunk d'abord summaries = [] for i, chunk in enumerate(chunks): response = client.messages.create( model="claude-sonnet-4-5", max_tokens=512, system="Tu es un assistant qui résume. Extrais les informations clés.", messages=[{"role": "user", "content": f"Résumé partie {i+1}/{len(chunks)} :\n{chunk}"}] ) summaries.append(f"[Partie {i+1}] {response.content[0].text}") # Combiner les résumés combined_summary = "\n\n".join(summaries) return [{ "role": "user",