A2A Protocol

Échantillons A2A : Agent de Chat de Fichiers LlamaIndex

MILO
Share
Échantillons A2A : Agent de Chat de Fichiers LlamaIndex

Cet échantillon démontre un agent conversationnel construit avec LlamaIndex Workflows et exposé via le protocole A2A. Il présente le téléchargement et l'analyse de fichiers, les interactions conversationnelles avec support pour le dialogue multi-tours, les réponses/mises à jour en streaming, et les citations en ligne.

code source

a2a llama index file chat avec openrouter

Comment ça fonctionne

Cet agent utilise LlamaIndex Workflows avec OpenRouter pour fournir un agent conversationnel qui peut télécharger des fichiers, les analyser, et répondre aux questions sur le contenu. Le protocole A2A permet une interaction standardisée avec l'agent, permettant aux clients d'envoyer des requêtes et de recevoir des mises à jour en temps réel.

sequenceDiagram
    participant Client as Client A2A
    participant Server as Serveur A2A
    participant Workflow as Flux ParseAndChat
    participant Services as APIs Externes

    Client->>Server: Envoyer message (avec ou sans pièce jointe)
    Server->>Workflow: Transférer comme InputEvent

    alt A une pièce jointe
        Workflow-->>Server: Stream LogEvent "Analyse du document..."
        Server-->>Client: Mise à jour du statut en streaming
        Workflow->>Services: Analyser le document
        Workflow-->>Server: Stream LogEvent "Document analysé avec succès"
        Server-->>Client: Mise à jour du statut en streaming
    end

    Workflow-->>Server: Stream LogEvent sur le traitement du chat
    Server-->>Client: Mise à jour du statut en streaming
    
    Workflow->>Services: Chat LLM (avec contexte du document si disponible)
    Services->>Workflow: Réponse LLM structurée
    Workflow-->>Server: Stream LogEvent sur le traitement de la réponse
    Server-->>Client: Mise à jour du statut en streaming
    
    Workflow->>Server: Retourner ChatResponseEvent final
    Server->>Client: Retourner réponse avec citations (si disponibles)

    Note over Server: Le contexte est maintenu pour les questions de suivi

Fonctionnalités clés

  • Téléchargement de fichiers : Les clients peuvent télécharger des fichiers et les analyser pour fournir un contexte au chat
  • Conversations multi-tours : L'agent peut demander des informations supplémentaires quand nécessaire
  • Streaming en temps réel : Fournit des mises à jour de statut pendant le traitement
  • Notifications push : Support pour les notifications basées sur webhook
  • Mémoire conversationnelle : Maintient le contexte à travers les interactions dans la même session
  • Intégration LlamaParse : Utilise LlamaParse pour analyser les fichiers avec précision

NOTE : Cet agent échantillon accepte les entrées multimodales, mais au moment de l'écriture, l'interface utilisateur échantillon ne supporte que les entrées texte. L'interface utilisateur deviendra multimodale à l'avenir pour gérer ce cas d'usage et d'autres.

Prérequis

  • Python 3.12 ou supérieur
  • UV
  • Accès à un LLM et une clé API (Le code actuel suppose l'utilisation de l'API OpenRouter)
  • Une clé API LlamaParse (obtenez-en une gratuitement)

Configuration et exécution

  1. Clonez et naviguez vers le répertoire du projet :

    git clone https://github.com/sing1ee/a2a_llama_index_file_chat
    cd a2a_llama_index_file_chat
    
  2. Créez un environnement virtuel et installez les dépendances :

    uv venv
    uv sync
    
  3. Créez un fichier d'environnement avec vos clés API :

    echo "OPENROUTER_API_KEY=votre_cle_api_ici" >> .env
    echo "LLAMA_CLOUD_API_KEY=votre_cle_api_ici" >> .env
    

    Obtenir les clés API :

  4. Exécutez l'agent :

    # En utilisant uv
    uv run a2a-file-chat
    
    # Ou activez l'environnement virtuel et exécutez directement
    source .venv/bin/activate  # Sur Windows : .venv\Scripts\activate
    python -m a2a_file_chat
    
    # Avec hôte/port personnalisé
    uv run a2a-file-chat --host 0.0.0.0 --port 8080
    
  5. Dans un terminal séparé, exécutez un cli client A2A :

Téléchargez un fichier à analyser, ou liez vers votre propre fichier. Par exemple :

curl -L https://arxiv.org/pdf/1706.03762 -o attention.pdf
git clone https://github.com/google-a2a/a2a-samples.git
cd a2a-samples/samples/python/hosts/cli
uv run . --agent http://localhost:10010

Et entrez quelque chose comme ce qui suit :

======= Carte Agent ========
{"name":"Parse and Chat","description":"Analyse un fichier puis discute avec un utilisateur en utilisant le contenu analysé comme contexte.","url":"http://localhost:10010/","version":"1.0.0","capabilities":{"streaming":true,"pushNotifications":true,"stateTransitionHistory":false},"defaultInputModes":["text","text/plain"],"defaultOutputModes":["text","text/plain"],"skills":[{"id":"parse_and_chat","name":"Parse and Chat","description":"Analyse un fichier puis discute avec un utilisateur en utilisant le contenu analysé comme contexte.","tags":["parse","chat","file","llama_parse"],"examples":["De quoi parle ce fichier ?"]}]}
=========  démarrage d'une nouvelle tâche ======== 

Que voulez-vous envoyer à l'agent ? (:q ou quit pour quitter) : De quoi parle ce fichier ?
Sélectionnez un chemin de fichier à joindre ? (appuyez sur entrée pour ignorer) : ./attention.pdf

Implémentation technique

  • LlamaIndex Workflows : Utilise un flux de travail personnalisé pour analyser le fichier puis discuter avec l'utilisateur
  • Support de streaming : Fournit des mises à jour incrémentales pendant le traitement
  • Contexte sérialisable : Maintient l'état de conversation entre les tours, peut optionnellement être persisté vers redis, mongodb, sur disque, etc.
  • Système de notification push : Mises à jour basées sur webhook avec authentification JWK
  • Intégration du protocole A2A : Conformité complète avec les spécifications A2A

Limitations

  • Ne supporte que la sortie basée sur le texte
  • LlamaParse est gratuit pour les premiers 10K crédits (~3333 pages avec les paramètres de base)
  • La mémoire est basée sur la session et en mémoire, et donc pas persistée entre les redémarrages du serveur
  • Insérer l'ensemble du document dans la fenêtre de contexte n'est pas évolutif pour les fichiers plus volumineux. Vous pourriez vouloir déployer une base de données vectorielle ou utiliser une base de données cloud pour exécuter la récupération sur un ou plusieurs fichiers pour un RAG efficace. LlamaIndex s'intègre avec une tonne de bases de données vectorielles et de bases de données cloud.

Exemples

Requête synchrone

Requête :

POST http://localhost:10010
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 11,
  "method": "tasks/send",
  "params": {
    "id": "129",
    "sessionId": "8f01f3d172cd4396a0e535ae8aec6687",
    "acceptedOutputModes": [
      "text"
    ],
    "message": {
      "role": "user",
      "parts": [
        {
          "type": "text",
          "text": "De quoi parle ce fichier ?"
        },
        {
            "type": "file",
            "file": {
                "bytes": "...",
                "name": "attention.pdf"
            }
        }
      ]
    }
  }
}

Réponse :

{
  "jsonrpc": "2.0",
  "id": 11,
  "result": {
    "id": "129",
    "status": {
      "state": "completed",
      "timestamp": "2025-04-02T16:53:29.301828"
    },
    "artifacts": [
      {
        "parts": [
          {
            "type": "text",
            "text": "Ce fichier parle de XYZ... [1]"
          }
        ],
        "metadata": {
            "1": ["Texte pour la citation 1"]
        }
        "index": 0,
      }
    ],
  }
}

Exemple multi-tours

Requête - Séq 1 :

POST http://localhost:10010
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 11,
  "method": "tasks/send",
  "params": {
    "id": "129",
    "sessionId": "8f01f3d172cd4396a0e535ae8aec6687",
    "acceptedOutputModes": [
      "text"
    ],
    "message": {
      "role": "user",
      "parts": [
        {
          "type": "text",
          "text": "De quoi parle ce fichier ?"
        },
        {
            "type": "file",
            "file": {
                "bytes": "...",
                "name": "attention.pdf"
            }
        }
      ]
    }
  }
}

Réponse - Séq 2 :

{
  "jsonrpc": "2.0",
  "id": 11,
  "result": {
    "id": "129",
    "status": {
      "state": "completed",
      "timestamp": "2025-04-02T16:53:29.301828"
    },
    "artifacts": [
      {
        "parts": [
          {
            "type": "text",
            "text": "Ce fichier parle de XYZ... [1]"
          }
        ],
        "metadata": {
            "1": ["Texte pour la citation 1"]
        }
        "index": 0,
      }
    ],
  }
}

Requête - Séq 3 :

POST http://localhost:10010
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 11,
  "method": "tasks/send",
  "params": {
    "id": "130",
    "sessionId": "8f01f3d172cd4396a0e535ae8aec6687",
    "acceptedOutputModes": [
      "text"
    ],
    "message": {
      "role": "user",
      "parts": [
        {
          "type": "text",
          "text": "Qu'en est-il de la chose X ?"
        }
      ]
    }
  }
}

Réponse - Séq 4 :

{
  "jsonrpc": "2.0",
  "id": 11,
  "result": {
    "id": "130",
    "status": {
      "state": "completed",
      "timestamp": "2025-04-02T16:53:29.301828"
    },
    "artifacts": [
      {
        "parts": [
          {
            "type": "text",
            "text": "La chose X est ... [1]"
          }
        ],
        "metadata": {
            "1": ["Texte pour la citation 1"]
        }
        "index": 0,
      }
    ],
  }
}

Exemple de streaming

Requête :

{
  "jsonrpc": "2.0",
  "id": 11,
  "method": "tasks/send",
  "params": {
    "id": "129",
    "sessionId": "8f01f3d172cd4396a0e535ae8aec6687",
    "acceptedOutputModes": [
      "text"
    ],
    "message": {
      "role": "user",
      "parts": [
        {
          "type": "text",
          "text": "De quoi parle ce fichier ?"
        },
        {
            "type": "file",
            "file": {
                "bytes": "...",
                "name": "attention.pdf"
            }
        }
      ]
    }
  }
}

Réponse :

stream event => {"jsonrpc":"2.0","id":"367d0ba9af97457890261ac29a0f6f5b","result":{"id":"373b26d64c5a4f0099fa906c6b7342d9","status":{"state":"working","message":{"role":"agent","parts":[{"type":"text","text":"Analyse du document..."}]},"timestamp":"2025-04-15T16:05:18.283682"},"final":false}}

stream event => {"jsonrpc":"2.0","id":"367d0ba9af97457890261ac29a0f6f5b","result":{"id":"373b26d64c5a4f0099fa906c6b7342d9","status":{"state":"working","message":{"role":"agent","parts":[{"type":"text","text":"Document analysé avec succès."}]},"timestamp":"2025-04-15T16:05:24.200133"},"final":false}}

stream event => {"jsonrpc":"2.0","id":"367d0ba9af97457890261ac29a0f6f5b","result":{"id":"373b26d64c5a4f0099fa906c6b7342d9","status":{"state":"working","message":{"role":"agent","parts":[{"type":"text","text":"Discussion avec 1 messages initiaux."}]},"timestamp":"2025-04-15T16:05:24.204757"},"final":false}}

stream event => {"jsonrpc":"2.0","id":"367d0ba9af97457890261ac29a0f6f5b","result":{"id":"373b26d64c5a4f0099fa906c6b7342d9","status":{"state":"working","message":{"role":"agent","parts":[{"type":"text","text":"Insertion du prompt système..."}]},"timestamp":"2025-04-15T16:05:24.204810"},"final":false}}

stream event => {"jsonrpc":"2.0","id":"367d0ba9af97457890261ac29a0f6f5b","result":{"id":"373b26d64c5a4f0099fa906c6b7342d9","status":{"state":"working","message":{"role":"agent","parts":[{"type":"text","text":"Réponse LLM reçue, analyse des citations..."}]},"timestamp":"2025-04-15T16:05:26.084829"},"final":false}}

stream event => {"jsonrpc":"2.0","id":"367d0ba9af97457890261ac29a0f6f5b","result":{"id":"373b26d64c5a4f0099fa906c6b7342d9","artifact":{"parts":[{"type":"text","text":"Ce fichier discute du Transformer, une nouvelle architecture de réseau de neurones basée uniquement sur des mécanismes d'attention, se dispensant entièrement de récurrence et de convolutions [1]. Le document compare le Transformer aux couches récurrentes et convolutionnelles [2], détaille l'architecture du modèle [3], et présente les résultats des tâches de traduction automatique et d'analyse syntaxique de l'anglais [4]."}],"metadata":{"1":["Les modèles de transduction de séquence dominants sont basés sur des réseaux de neurones récurrents ou convolutionnels complexes qui incluent un encodeur et un décodeur. Les modèles les plus performants connectent également l'encodeur et le décodeur via un mécanisme d'attention. Nous proposons une nouvelle architecture de réseau simple, le Transformer, basée uniquement sur des mécanismes d'attention, se dispensant entièrement de récurrence et de convolutions. Les expériences sur deux tâches de traduction automatique montrent que ces modèles sont supérieurs en qualité tout en étant plus parallélisables et nécessitant significativement moins de temps d'entraînement. Notre modèle atteint 28,4 BLEU sur la tâche de traduction anglais-allemand WMT 2014, améliorant les meilleurs résultats existants, y compris les ensembles, de plus de 2 BLEU. Sur la tâche de traduction anglais-français WMT 2014, notre modèle établit un nouveau score BLEU état de l'art à modèle unique de 41,8 après entraînement pendant 3,5 jours sur huit GPU, une petite fraction des coûts d'entraînement des meilleurs modèles de la littérature. Nous montrons que le Transformer se généralise bien à d'autres tâches en l'appliquant avec succès à l'analyse syntaxique de l'anglais avec des données d'entraînement importantes et limitées."],"2":["Dans cette section, nous comparons divers aspects des couches d'auto-attention aux couches récurrentes et convolutionnelles couramment utilisées pour mapper une séquence de longueur variable de représentations de symboles (x1, ..., xn) à une autre séquence de longueur égale (z1, ..., zn), avec xi, zi ∈ Rd, comme une couche cachée dans un encodeur ou décodeur de transduction de séquence typique. Motivant notre utilisation de l'auto-attention, nous considérons trois desiderata.",""],"3":["# 3 Architecture du modèle"],"4":["# 6   Résultats"]},"index":0,"append":false}}}

stream event => {"jsonrpc":"2.0","id":"367d0ba9af97457890261ac29a0f6f5b","result":{"id":"373b26d64c5a4f0099fa906c6b7342d9","status":{"state":"completed","timestamp":"2025-04-15T16:05:26.111314"},"final":true}}

Vous pouvez voir que le flux de travail a produit un artefact avec des citations en ligne, et le texte source de ces citations est inclus dans les métadonnées de l'artefact. Si nous envoyons plus de réponses dans la même session, l'agent se souviendra des messages précédents et continuera la conversation.

En savoir plus