A2A Protocol
A2A Samples: LlamaIndex File Chat Agent

Dieses Beispiel demonstriert einen conversationalen Agenten, der mit LlamaIndex Workflows erstellt und über das A2A-Protocol bereitgestellt wird. Es zeigt Datei-Upload und -Parsing, conversationale Interaktionen mit Unterstützung für Multi-Turn-Dialoge, Streaming-Antworten/-Updates und Inline-Zitate.

Quellcode

a2a llama index file chat with openrouter

Funktionsweise

Dieser Agent verwendet LlamaIndex Workflows mit OpenRouter, um einen conversationalen Agenten bereitzustellen, der Dateien hochladen, parsen und Fragen zum Inhalt beantworten kann. Das A2A-Protocol ermöglicht standardisierte Interaktion mit dem Agenten, wodurch Clients Anfragen senden und Echtzeit-Updates erhalten können.

sequenceDiagram
    participant Client as A2A Client
    participant Server as A2A Server
    participant Workflow as ParseAndChat Workflow
    participant Services as Externe APIs

    Client->>Server: Nachricht senden (mit oder ohne Anhang)
    Server->>Workflow: Als InputEvent weiterleiten

    alt Hat Anhang
        Workflow-->>Server: Stream LogEvent "Dokument wird geparst..."
        Server-->>Client: Status-Update streamen
        Workflow->>Services: Dokument parsen
        Workflow-->>Server: Stream LogEvent "Dokument erfolgreich geparst"
        Server-->>Client: Status-Update streamen
    end

    Workflow-->>Server: Stream LogEvent über Chat-Verarbeitung
    Server-->>Client: Status-Update streamen
    
    Workflow->>Services: LLM Chat (mit Dokumentkontext falls verfügbar)
    Services->>Workflow: Strukturierte LLM-Antwort
    Workflow-->>Server: Stream LogEvent über Antwortverarbeitung
    Server-->>Client: Status-Update streamen
    
    Workflow->>Server: Finale ChatResponseEvent zurückgeben
    Server->>Client: Antwort mit Zitaten zurückgeben (falls verfügbar)

    Note over Server: Kontext wird für Folgefragen beibehalten

Hauptfunktionen

  • Datei-Upload: Clients können Dateien hochladen und parsen, um Kontext für den Chat zu bieten
  • Multi-Turn-Gespräche: Agent kann zusätzliche Informationen anfordern, wenn nötig
  • Echtzeit-Streaming: Bietet Status-Updates während der Verarbeitung
  • Push-Benachrichtigungen: Unterstützung für Webhook-basierte Benachrichtigungen
  • Conversational Memory: Behält Kontext über Interaktionen in derselben Sitzung bei
  • LlamaParse Integration: Verwendet LlamaParse für präzises Datei-Parsing

HINWEIS: Dieser Beispiel-Agent akzeptiert multimodale Eingaben, aber zum Zeitpunkt der Erstellung unterstützt die Beispiel-UI nur Texteingaben. Die UI wird in Zukunft multimodal werden, um diesen und andere Anwendungsfälle zu handhaben.

Voraussetzungen

  • Python 3.12 oder höher
  • UV
  • Zugang zu einem LLM und API Key (Aktueller Code verwendet OpenRouter API)
  • Ein LlamaParse API Key (kostenlos erhalten)

Setup & Ausführung

  1. Projekt klonen und zum Verzeichnis navigieren:

    git clone https://github.com/sing1ee/a2a_llama_index_file_chat
    cd a2a_llama_index_file_chat
    
  2. Virtuelle Umgebung erstellen und Abhängigkeiten installieren:

    uv venv
    uv sync
    
  3. Eine Umgebungsdatei mit Ihren API-Schlüsseln erstellen:

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

    API-Schlüssel erhalten:

  4. Den Agenten ausführen:

    # Mit uv
    uv run a2a-file-chat
    
    # Oder virtuelle Umgebung aktivieren und direkt ausführen
    source .venv/bin/activate  # Unter Windows: .venv\Scripts\activate
    python -m a2a_file_chat
    
    # Mit benutzerdefinierten Host/Port
    uv run a2a-file-chat --host 0.0.0.0 --port 8080
    
  5. In einem separaten Terminal einen A2A Client CLI ausführen:

Eine Datei zum Parsen herunterladen oder zu Ihrer eigenen Datei verlinken. Zum Beispiel:

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

Und etwas Folgendes eingeben:

======= Agent Card ========
{"name":"Parse and Chat","description":"Parses a file and then chats with a user using the parsed content as context.","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":"Parses a file and then chats with a user using the parsed content as context.","tags":["parse","chat","file","llama_parse"],"examples":["What does this file talk about?"]}]}
=========  starting a new task ======== 

What do you want to send to the agent? (:q or quit to exit): Wovon handelt diese Datei?
Select a file path to attach? (press enter to skip): ./attention.pdf

Technische Implementierung

  • LlamaIndex Workflows: Verwendet einen benutzerdefinierten Workflow zum Parsen der Datei und anschließenden Chat mit dem Benutzer
  • Streaming-Unterstützung: Bietet inkrementelle Updates während der Verarbeitung
  • Serialisierbarer Kontext: Behält Gesprächsstatus zwischen Turns bei, kann optional in Redis, MongoDB, auf Festplatte etc. persistiert werden
  • Push-Benachrichtigungssystem: Webhook-basierte Updates mit JWK-Authentifizierung
  • A2A Protocol Integration: Vollständige Konformität mit A2A-Spezifikationen

Einschränkungen

  • Unterstützt nur textbasierte Ausgabe
  • LlamaParse ist kostenlos für die ersten 10K Credits (~3333 Seiten mit Grundeinstellungen)
  • Speicher ist sitzungsbasiert und im Arbeitsspeicher, daher nicht zwischen Server-Neustarts persistiert
  • Das Einfügen des gesamten Dokuments in das Kontextfenster ist nicht skalierbar für größere Dateien. Sie möchten möglicherweise eine Vektor-DB oder eine Cloud-DB bereitstellen, um Retrieval über eine oder mehrere Dateien für effektives RAG auszuführen. LlamaIndex integriert sich mit vielen Vektor-DBs und Cloud-DBs.

Beispiele

Synchrone Anfrage

Anfrage:

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": "Wovon handelt diese Datei?"
        },
        {
            "type": "file",
            "file": {
                "bytes": "...",
                "name": "attention.pdf"
            }
        }
      ]
    }
  }
}

Antwort:

{
  "jsonrpc": "2.0",
  "id": 11,
  "result": {
    "id": "129",
    "status": {
      "state": "completed",
      "timestamp": "2025-04-02T16:53:29.301828"
    },
    "artifacts": [
      {
        "parts": [
          {
            "type": "text",
            "text": "Diese Datei handelt von XYZ... [1]"
          }
        ],
        "metadata": {
            "1": ["Text für Zitat 1"]
        }
        "index": 0,
      }
    ],
  }
}

Multi-Turn-Beispiel

Anfrage - Seq 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": "Wovon handelt diese Datei?"
        },
        {
            "type": "file",
            "file": {
                "bytes": "...",
                "name": "attention.pdf"
            }
        }
      ]
    }
  }
}

Antwort - Seq 2:

{
  "jsonrpc": "2.0",
  "id": 11,
  "result": {
    "id": "129",
    "status": {
      "state": "completed",
      "timestamp": "2025-04-02T16:53:29.301828"
    },
    "artifacts": [
      {
        "parts": [
          {
            "type": "text",
            "text": "Diese Datei handelt von XYZ... [1]"
          }
        ],
        "metadata": {
            "1": ["Text für Zitat 1"]
        }
        "index": 0,
      }
    ],
  }
}

Anfrage - Seq 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": "Was ist mit Sache X?"
        }
      ]
    }
  }
}

Antwort - Seq 4:

{
  "jsonrpc": "2.0",
  "id": 11,
  "result": {
    "id": "130",
    "status": {
      "state": "completed",
      "timestamp": "2025-04-02T16:53:29.301828"
    },
    "artifacts": [
      {
        "parts": [
          {
            "type": "text",
            "text": "Sache X ist ... [1]"
          }
        ],
        "metadata": {
            "1": ["Text für Zitat 1"]
        }
        "index": 0,
      }
    ],
  }
}

Streaming-Beispiel

Anfrage:

{
  "jsonrpc": "2.0",
  "id": 11,
  "method": "tasks/send",
  "params": {
    "id": "129",
    "sessionId": "8f01f3d172cd4396a0e535ae8aec6687",
    "acceptedOutputModes": [
      "text"
    ],
    "message": {
      "role": "user",
      "parts": [
        {
          "type": "text",
          "text": "Wovon handelt diese Datei?"
        },
        {
            "type": "file",
            "file": {
                "bytes": "...",
                "name": "attention.pdf"
            }
        }
      ]
    }
  }
}

Antwort:

stream event => {"jsonrpc":"2.0","id":"367d0ba9af97457890261ac29a0f6f5b","result":{"id":"373b26d64c5a4f0099fa906c6b7342d9","status":{"state":"working","message":{"role":"agent","parts":[{"type":"text","text":"Dokument wird geparst..."}]},"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":"Dokument erfolgreich geparst."}]},"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":"Chat mit 1 anfänglichen Nachrichten."}]},"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":"System-Prompt wird eingefügt..."}]},"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":"LLM-Antwort erhalten, Zitate werden geparst..."}]},"timestamp":"2025-04-15T16:05:26.084829"},"final":false}}

stream event => {"jsonrpc":"2.0","id":"367d0ba9af97457890261ac29a0f6f5b","result":{"id":"373b26d64c5a4f0099fa906c6b7342d9","artifact":{"parts":[{"type":"text","text":"Diese Datei behandelt den Transformer, eine neuartige neuronale Netzwerkarchitektur, die ausschließlich auf Aufmerksamkeitsmechanismen basiert und völlig auf Rekurrenz und Faltungen verzichtet [1]. Das Dokument vergleicht den Transformer mit rekurrenten und Faltungsschichten [2], beschreibt die Modellarchitektur [3] und präsentiert Ergebnisse von maschinellen Übersetzungs- und englischen Konstituenten-Parsing-Aufgaben [4]."}],"metadata":{"1":["Die dominierenden Sequenz-Transduktionsmodelle basieren auf komplexen rekurrenten oder Faltungsneuronalen Netzen, die einen Encoder und einen Decoder enthalten. Die leistungsstärksten Modelle verbinden auch den Encoder und Decoder über einen Aufmerksamkeitsmechanismus. Wir schlagen eine neue einfache Netzwerkarchitektur vor, den Transformer, der ausschließlich auf Aufmerksamkeitsmechanismen basiert und völlig auf Rekurrenz und Faltungen verzichtet. Experimente mit zwei maschinellen Übersetzungsaufgaben zeigen, dass diese Modelle qualitativ überlegen sind, während sie parallelisierbarer sind und deutlich weniger Trainingszeit benötigen. Unser Modell erreicht 28,4 BLEU bei der WMT 2014 Englisch-zu-Deutsch-Übersetzungsaufgabe und übertrifft die bestehenden besten Ergebnisse, einschließlich Ensembles, um über 2 BLEU. Bei der WMT 2014 Englisch-zu-Französisch-Übersetzungsaufgabe etabliert unser Modell einen neuen Single-Model-State-of-the-Art BLEU-Score von 41,8 nach dem Training für 3,5 Tage auf acht GPUs, ein kleiner Bruchteil der Trainingskosten der besten Modelle aus der Literatur. Wir zeigen, dass der Transformer gut auf andere Aufgaben generalisiert, indem wir ihn erfolgreich auf englisches Konstituenten-Parsing sowohl mit großen als auch begrenzten Trainingsdaten anwenden."],"2":["In diesem Abschnitt vergleichen wir verschiedene Aspekte von Selbstaufmerksamkeitsschichten mit den rekurrenten und Faltungsschichten, die üblicherweise zur Abbildung einer variablen Längensequenz von Symboldarstellungen (x1, ..., xn) auf eine andere Sequenz gleicher Länge (z1, ..., zn) verwendet werden, mit xi, zi ∈ Rd, wie eine versteckte Schicht in einem typischen Sequenz-Transduktions-Encoder oder -Decoder. Um unsere Verwendung von Selbstaufmerksamkeit zu motivieren, betrachten wir drei Desiderata.",""],"3":["# 3 Modellarchitektur"],"4":["# 6   Ergebnisse"]},"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}}

Sie können sehen, dass der Workflow ein Artefakt mit Inline-Zitaten produziert hat, und der Quelltext dieser Zitate ist in den Metadaten des Artefakts enthalten. Wenn wir weitere Antworten in derselben Sitzung senden, wird sich der Agent an die vorherigen Nachrichten erinnern und das Gespräch fortsetzen.

Mehr erfahren