← Semua pembelajaran / AWS untuk AI Engineer
Fase 3 · Bedrock Dasar

Converse API

Converse menyatukan bentuk permintaan untuk semua model yang mendukung pesan. Ini API yang direkomendasikan AWS dan yang dipakai di sisa roadmap ini.

Intisari

  • Kelebihan utamanya: bentuk permintaan sama untuk semua model — ganti modelId, kode tetap.
  • Ada di client bedrock-runtime saja. Butuh izin bedrock:InvokeModel.
  • System prompt punya field sendiri (system), terpisah dari messages.
  • Parameter khas model dikirim lewat additionalModelRequestFields.
  • Tool use dan guardrail juga masuk lewat API yang sama — toolConfig dan guardrailConfig.

Kenapa Converse, bukan InvokeModel

InvokeModel mengirim body mentah yang bentuknya berbeda per penyedia model. Pindah dari satu model ke model lain berarti menulis ulang serialisasi permintaan dan parsing responsnya. Converse menormalkan itu:

InvokeModelConverse
Bentuk permintaanBeda per penyediaSama untuk semua
Ganti modelUbah kode serialisasiUbah satu string
Tool useFormat khas modeltoolConfig seragam
Parameter unik modelTercampur di bodyTerpisah di additionalModelRequestFields

Permintaan lengkap

import boto3

runtime = boto3.client("bedrock-runtime", region_name="us-east-1")

resp = runtime.converse(
    modelId=MODEL_ID,

    # System prompt: instruksi dan konteks, TERPISAH dari percakapan
    system=[{"text": "Kamu asisten teknis. Jawab ringkas dan berbahasa Indonesia."}],

    # Riwayat percakapan, bergantian user/assistant
    messages=[
        {"role": "user",      "content": [{"text": "Apa itu vector store?"}]},
        {"role": "assistant", "content": [{"text": "Basis data yang menyimpan embedding..."}]},
        {"role": "user",      "content": [{"text": "Kapan aku butuh itu?"}]},
    ],

    # Parameter yang berlaku untuk semua model
    inferenceConfig={"maxTokens": 512, "temperature": 0.2, "topP": 0.9},

    # Parameter khas model tertentu
    additionalModelRequestFields={"top_k": 50},
)

System prompt bukan sebuah message. Di beberapa SDK lain, instruksi sistem dikirim sebagai pesan pertama dengan role system. Di Converse ia punya field sendiri. Menaruhnya sebagai {"role": "system", …} di dalam messages menghasilkan ValidationException.

Membaca respons

jawaban = resp["output"]["message"]["content"][0]["text"]

pakai = resp["usage"]
print(pakai["inputTokens"], pakai["outputTokens"], pakai["totalTokens"])

print(resp["stopReason"])            # end_turn | max_tokens | tool_use | stop_sequence
print(resp["metrics"]["latencyMs"])
FieldKenapa penting
usageSatu-satunya sumber kebenaran biaya per permintaan. Catat ke log sejak hari pertama.
stopReasonmax_tokens berarti jawaban terpotong — jangan diperlakukan sebagai jawaban utuh.
metrics.latencyMsLatensi menurut Bedrock, tanpa overhead jaringanmu.
content berupa listBisa berisi lebih dari satu blok: teks, gambar, atau permintaan tool.

Multi-modal

gambar = open("diagram.png", "rb").read()

resp = runtime.converse(
    modelId=MODEL_ID,
    messages=[{
        "role": "user",
        "content": [
            {"image": {"format": "png", "source": {"bytes": gambar}}},
            {"text": "Jelaskan arsitektur pada diagram ini."},
        ],
    }],
)

Karena content adalah list blok, teks dan gambar hidup berdampingan dalam satu pesan. Bentuk yang sama juga dipakai untuk dokumen — berguna sekali untuk pipeline pemrosesan dokumen di Fase 4.

Fungsi pembungkus yang layak dipakai

from botocore.config import Config
import boto3, logging

log = logging.getLogger(__name__)
runtime = boto3.client(
    "bedrock-runtime",
    config=Config(retries={"max_attempts": 5, "mode": "adaptive"}, read_timeout=300),
)


def tanya(pertanyaan: str, *, sistem: str, model_id: str, maks_token: int = 512) -> str:
    resp = runtime.converse(
        modelId=model_id,
        system=[{"text": sistem}],
        messages=[{"role": "user", "content": [{"text": pertanyaan}]}],
        inferenceConfig={"maxTokens": maks_token, "temperature": 0.2},
    )

    log.info(
        "bedrock",
        extra={
            "model": model_id,
            "token_masuk": resp["usage"]["inputTokens"],
            "token_keluar": resp["usage"]["outputTokens"],
            "alasan_berhenti": resp["stopReason"],
        },
    )

    if resp["stopReason"] == "max_tokens":
        log.warning("jawaban terpotong — naikkan maxTokens atau perpendek konteks")

    return resp["output"]["message"]["content"][0]["text"]

Latihan: tulis fungsi tanya() di atas, lalu jalankan pertanyaan yang sama ke dua model berbeda hanya dengan mengganti model_id. Bandingkan usage dan metrics.latencyMs keduanya, dan catat selisih biayanya — data ini yang dipakai untuk memilih model di Fase 7.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.