Eine strukturierte Zusammenfassung aus einem Dokument erzeugen

PythonBeginner
Jetzt üben

Einführung

Ein Betriebsteam benötigt eine strukturierte Zusammenfassung eines kurzen Vorfallberichts. Ein Modell kann plausible Texte erzeugen, doch die Anwendung braucht vorhersehbare Felder und muss ungültige Ausgaben ablehnen. Du forderst mit Bedrock Converse eine JSON-Zusammenfassung an, parst sie in Python und prüfst die Ablehnung mit klar gekennzeichneten lokalen Testfällen.

Du solltest Python-Grundlagen, JSON und die Converse-Anfragen des vorigen Labs kennen. Jede neue VM liefert eigenes Dokument, konfigurierte Identität und Inferenzkontingent. Frühere VM-Dateien oder Zugangsdaten sind nicht erforderlich.

Bezug zur Zertifizierung

Zertifizierung Prüfungsaufgabe Übung
AI Practitioner (AIF-C01) Aufgabe 3.2 Ausgabeformat vorgeben und eine Modellantwort vor ihrer Verwendung validieren.

Mit draw.io erstellte Übersicht: Das Dokument geht an Bedrock Converse; Parsing und Validierung wählen eine nutzbare Zusammenfassung oder kontrollierte Ablehnung.

Dokument und benötigte Felder prüfen

In diesem Schritt prüfst du einen bereitgestellten synthetischen Vorfallbericht und definierst die von der Anwendung erwartete Struktur.

Beginne im Arbeitsverzeichnis:

cd /home/labex/project

Das Beispieldokument ist reiner Text. Lies es mit cat, das den Dateiinhalt ausgibt:

cat incident.txt

Es beschreibt Vorfall INC-204: Ein Konfigurationsfehler verursachte 30 Minuten lang fehlgeschlagene Checkout-Vorgänge. Das Team setzte die Konfiguration zurück und stellte den Dienst wieder her. Ein weiterer Konfigurationstest ist geplant, aber nicht abgeschlossen. Diese Fakten begrenzen deine Zusammenfassung.

Die Anwendung erwartet genau drei Felder: incident_id, impact und next_action. Jedes muss eine nicht leere Zeichenkette enthalten. Ein Schema beschreibt diese Form; gültiges JSON allein reicht nicht, denn auch eine Liste, ein fehlendes Feld oder eine Zahl können gültiges JSON sein. Lies die bereitgestellte Schemareferenz:

cat summary-schema.json

Die Referenz erläutert die gewünschte Ausgabe. Du erzwingst ihre Felder mit normalem Python; sie garantiert nicht automatisch, dass ein Modell sie einhält. JSON anzufordern und JSON zu validieren sind getrennte Aufgaben.

Eine strukturierte Zusammenfassung erzeugen und prüfen

In diesem Schritt baust du einen kleinen Python-Befehl, der die Zusammenfassung anfordert und den Antworttext vor einer Erfolgsausgabe validiert.

boto3 ist das AWS SDK für Python. Es ist in der bereitgestellten Laufzeit installiert und nutzt konfigurierte Zugangsdaten und Dienstendpunkt. Der Code verwendet converse, dieselbe bereits mit der CLI geübte Operation. maxTokens begrenzt die Ausgabe; der Client deaktiviert automatische Wiederholungen, damit ein unklarer Fehler nicht unbemerkt eine weitere Inferenzanfrage sendet.

Erstelle summary.py mit folgendem Code. parse_response prüft den Abschlussgrund, parst Text mit json.loads und validiert exakte Schlüssel und Typen. ValueError bedeutet kontrollierte Ablehnung; ein ClientError oder Verbindungsfehler wird ohne Zugangsdaten oder vollständige Dienstexception gemeldet. Der optionale Modus --response-file liest eine lokale Antwort zum Parsertest und sendet keine Inferenzanfrage:

cat > summary.py <<'EOF'
import argparse
import json
from pathlib import Path
import boto3
from botocore.config import Config
from botocore.exceptions import BotoCoreError, ClientError


def parse_response(response):
    if not isinstance(response, dict):
        raise ValueError("invalid_response")
    if response.get("stopReason") != "end_turn":
        raise ValueError("incomplete_response")
    try:
        text = response["output"]["message"]["content"][0]["text"]
        value = json.loads(text)
        expected = {"incident_id", "impact", "next_action"}
        if not isinstance(value, dict) or set(value) != expected:
            raise ValueError("invalid_fields")
        if any(not isinstance(v, str) or not v.strip() for v in value.values()):
            raise ValueError("invalid_field_type")
        if value["incident_id"] != "INC-204":
            raise ValueError("unexpected_incident")
        return value
    except (KeyError, IndexError, TypeError, json.JSONDecodeError) as error:
        raise ValueError("invalid_response") from error


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--response-file", type=Path)
    args = parser.parse_args()
    try:
        if args.response_file:
            response = json.loads(args.response_file.read_text())
        else:
            client = boto3.client("bedrock-runtime", config=Config(
                connect_timeout=5, read_timeout=150,
                retries={"total_max_attempts": 1}))
            response = client.converse(
                modelId="labex.text-v1:0",
                system=[{"text": "Summarize only facts supplied in the incident document. Return exactly one JSON object with string fields incident_id, impact and next_action. No Markdown fences, extra keys or surrounding prose. Do not turn planned work into completed work."}],
                messages=[{"role": "user", "content": [
                    {"text": Path("incident.txt").read_text()}]}],
                inferenceConfig={"maxTokens": 768, "temperature": 0})
            Path("response.json").write_text(json.dumps(response, indent=2))
        value = parse_response(response)
    except (ValueError, KeyError, TypeError):
        print(json.dumps({"status": "rejected", "reason": "invalid_model_output"}))
        return 2
    except (BotoCoreError, ClientError):
        print(json.dumps({"status": "unavailable", "reason": "inference_failed"}))
        return 3
    print(json.dumps({"status": "ok", "summary": value}, indent=2))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
EOF

Führe das Skript mit der installierten AWS-Python-Laufzeit aus. Das abschließende > summary.json speichert die ausgegebene Antwort:

/opt/labex/aws/venv/bin/python summary.py > summary.json

Warte auf die Eingabeaufforderung und prüfe das Ergebnis:

cat summary.json

Ein erfolgreicher Lauf enthält "status": "ok" und ein summary-Objekt mit den drei erforderlichen Zeichenketten. Lies auch die rohe Converse-Antwort:

python3 -m json.tool response.json

response.json speichert tatsächliche Modellausgabe, Abschlussgrund und Tokenverbrauch. Klappe die abgeschlossene Anfrage in AWS View auf und vergleiche ihren Text. Die Formulierung kann variieren. Prüfe, ob impact fehlgeschlagene Checkouts und next_action geplante Arbeit beschreibt. Ein gültiges Schema beweist nicht, dass diese Aussagen richtig sind.

Tatsächliche AWS View einer VM: Die abgeschlossene Anfrage enthält eine JSON-Zusammenfassung, Tokenverbrauch und Restkontingent. Formulierung, Zeit und Kontingent können abweichen.

Meldet das Skript Ablehnung, lies vor einem neuen Versuch die rohe Antwort. Das Modell kann abschneiden oder das Format missachten; ersetze die Zusammenfassung nicht durch fest eingebauten Erfolg. Fehlgeschlagene Inferenz kann Kontingent verbrauchen.

Die Grenze für ungültige Antworten testen

In diesem Schritt bestätigst du, dass fehlerhaftes JSON, falsche Typen und abgeschnittene Antworten ohne neue Modellanfrage abgelehnt werden.

Das Verzeichnis fixtures/ enthält vorbereitete Parser-Testeingaben. Es sind lokale Testdaten, keine Inferenzergebnisse. Liste sie auf:

ls fixtures

Führe das Skript mit dem fehlerhaften JSON-Testfall aus:

/opt/labex/aws/venv/bin/python summary.py --response-file fixtures/malformed.json

Erwartet wird {"status": "rejected", "reason": "invalid_model_output"}. Exitcode 2 kennzeichnet diese kontrollierte Ablehnung. echo $? zeigt den Exitcode des unmittelbar vorigen Befehls:

echo $?

Eine Antwort kann gültiges JSON sein und dennoch das Schema verletzen. Teste den Fall mit numerischem impact:

/opt/labex/aws/venv/bin/python summary.py --response-file fixtures/wrong-type.json

Er muss ebenso abgelehnt werden. Auch ein vollständig wirkendes Objekt muss abgelehnt werden, wenn das Modell sein Tokenlimit erreichte. Teste diese Grenze:

/opt/labex/aws/venv/bin/python summary.py --response-file fixtures/truncated.json

Der Test muss Ablehnung melden, da sein stopReason max_tokens ist. Diese Tests erzeugen keine erfolgreiche Zusammenfassung und keine zusätzlichen Anfragen in AWS View.

Parse zum Schluss die tatsächlich gespeicherte Antwort erneut:

/opt/labex/aws/venv/bin/python summary.py --response-file response.json

Sie muss weiterhin status: ok zurückgeben. Du hast eine nutzbare tatsächliche Antwort und kontrollierte Fehlereingaben geprüft. Parser-Testfälle beweisen keine erfolgreiche Inferenz; die abgeschlossene Anfrage und rohe Antwort belegen das separat.

Die eigenen Übungsartefakte entfernen

In diesem Schritt entfernst du nach bestandenen Funktionstests dein Skript und seine zwei Ergebnisdateien.

Dokument, Schema und Parser-Testfälle gehören zur neuen Umgebung. Behalte sie und den Backenddienst. rm entfernt nur die drei genannten Lernendenartefakte:

rm summary.py summary.json response.json

Bestätige, dass die bereitgestellten Eingaben erhalten sind:

ls

Converse erstellt keinen dauerhaften Cloudserver zum Löschen. Lokale Dateilöschung erstattet keine Credits und löscht keine tatsächlichen Inferenzaufzeichnungen in AWS View.

Zusammenfassung

Du hast mit einer tatsächlichen Bedrock-Converse-Antwort eine strukturierte Zusammenfassung erzeugt, Feldnamen und Typen erzwungen, den Abschlussgrund geprüft und kontrollierte ungültige Antworten abgelehnt. Du hast Faktenprüfung von Schemavalidität getrennt und nur eigene Dateien entfernt.

Weitere Informationen bietet die AWS-Dokumentation: Converse-Antwortinhalt, Stoppgründe und Nutzung.