08. RunnableWithMessageHistory

Menambahkan riwayat pesan (memori)

Memanfaatkan RunnableWithMessageHistory untuk menambahkan riwayat pesan ke jenis tugas (rantai) tertentu adalah fitur yang sangat berguna dalam pemrograman.

Fitur ini sangat penting ketika mengimplementasikan aplikasi interaktif atau tugas pemrosesan data yang kompleks, di mana ada kebutuhan untuk mempertahankan konteks pesan sebelumnya.

Dengan mengelola riwayat pesan, pengembang dapat mengontrol aliran aplikasi dengan lebih baik dan merespons permintaan sebelumnya dari pengguna dengan tepat.

Contoh

  • Mengembangkan chatbot percakapan: Sesuaikan respons chatbot berdasarkan riwayat dialog dengan pengguna.

  • Pemrosesan data yang kompleks: Selama pemrosesan data, Anda dapat merujuk ke hasil dari langkah sebelumnya untuk menentukan logika langkah berikutnya.

  • Aplikasi yang memerlukan manajemen status: Anda dapat mengingat pilihan pengguna sebelumnya dan memberikan layar atau informasi berikutnya yang sesuai.

RunnableWithMessageHistory adalah alat canggih yang memungkinkan Anda mempertahankan status aplikasi, meningkatkan pengalaman pengguna, dan mengimplementasikan mekanisme respons yang lebih canggih.

Tutorial

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI

model = ChatOpenAI()
prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "Anda adalah asisten yang mahir dalam {ability}. Harap jawab dalam 20 karakter atau kurang",
        ),
        # menggunakan riwayat percakapan sebagai variabel, dengan riwayat sebagai kunci dari MessageHistory
        MessagesPlaceholder(variable_name="history"),
        ("human", "{input}"), # gunakan masukan pengguna sebagai variabel
    ]
)
runnable = prompt | model # menggabungkan prompt dan model untuk membuat objek yang dapat dijalankan

Mengelola riwayat pesan sangat penting dalam aplikasi interaktif atau tugas pemrosesan data yang kompleks. Untuk mengelola riwayat pesan secara efektif, Anda memerlukan dua elemen utama

  • Runnable: objek yang dapat dijalankan yang berinteraksi dengan BaseChatMessageHistory, terutama Retriever dan Chain.

  • Objek yang dapat dipanggil yang mengembalikan sebuah instance dari BaseChatMessageHistory: Objek untuk mengelola riwayat pesan. Objek ini digunakan untuk menyimpan, mengambil, dan memperbarui riwayat pesan. Riwayat pesan diperlukan untuk menjaga konteks percakapan dan untuk menghasilkan respons berdasarkan masukan pengguna sebelumnya.

Ada banyak cara untuk mengimplementasikan riwayat pesan, dan halaman integrasi memori menjelaskan berbagai pilihan penyimpanan dan integrasi.

Di sini kita akan melihat dua metode utama

Menggunakan ChatMessageHistory dalam memori

Metode ini mengelola riwayat pesan dalam memori. Metode ini sering digunakan selama fase pengembangan atau dalam aplikasi sederhana. Metode in-memory menyediakan kecepatan akses yang cepat, tetapi kekurangannya adalah riwayat pesan akan hilang ketika aplikasi dimulai ulang.

Memanfaatkan penyimpanan persisten dengan RedisChatMessageHistory

Menggunakan Redis memungkinkan Anda untuk menyimpan riwayat pesan secara persisten. Redis merupakan penyimpanan struktur data dalam-memori berkinerja tinggi, bersumber terbuka, dan dapat diandalkan untuk mengelola riwayat pesan dalam lingkungan terdistribusi. Metode ini ideal untuk aplikasi yang kompleks atau layanan yang sudah berjalan lama.

Ketika memilih metode untuk mengelola riwayat pesan, Anda harus mempertimbangkan kebutuhan aplikasi Anda, jumlah lalu lintas yang Anda perkirakan, pentingnya data pesan, dan berapa lama Anda ingin menyimpannya. Metode dalam memori sederhana dan cepat untuk diimplementasikan, tetapi jika Anda memerlukan persistensi data, penyimpanan persisten seperti Redis mungkin lebih cocok.

Riwayat percakapan yang volatil: In-Memory.

Di bawah ini adalah contoh sederhana riwayat obrolan yang disimpan dalam memori.

Parameter pengaturan RunnableWithMessageHistory

  • Runnable

  • BaseChatMessageHistory atau objek yang diwarisi. misalnya ChatMessageHistory

  • input_messages_key: kunci untuk menentukan sebagai input kueri pengguna saat memanggil rantai

  • history_messages_key: kunci untuk menentukan sebagai riwayat percakapan

from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

store = {}  # Kamus untuk menyimpan riwayat sesi


# Fungsi untuk mengambil riwayat sesi berdasarkan ID sesi
def get_session_history(session_ids: str) -> BaseChatMessageHistory:
    print(session_ids)
    if session_ids not in store:  # Jika ID sesi tidak ada di store
        # Buat objek ChatMessageHistory baru dan simpan ke store
        store[session_ids] = ChatMessageHistory()
    return store[session_ids]  # Kembalikan riwayat sesi untuk ID sesi tersebut


with_message_history = (
    RunnableWithMessageHistory(  # Buat objek RunnableWithMessageHistory
        runnable,  # Objek Runnable yang akan dijalankan
        get_session_history,  # Fungsi untuk mengambil riwayat sesi
        input_messages_key="input",  # Kunci untuk pesan input
        history_messages_key="history",  # Kunci untuk pesan riwayat
    )
)

Input_messages_key menentukan kunci yang akan diperlakukan sebagai pesan masukan terbaru, dan history_messages_key menentukan kunci yang akan ditambahkan pesan lama.

Pada kode berikut, kita dapat melihat bahwa kunci session_id dimasukkan sebagai Default pada nilai awal RunnableWithMessageHistory, yang secara tidak langsung memberi tahu kita bahwa RunnableWithMessageHistory mengelola utas dialog dengan session_id.

Dengan kata lain, kita dapat melihat bahwa manajemen per-thread diimplementasikan oleh session_id.

Lihat referensi kode: Implementasi RunnableWithMessageHistory,

if history_factory_config:
    _config_specs = history_factory_config
else:
    # If not provided, then we'll use the default session_id field
    _config_specs = [
        ConfigurableFieldSpec(
            id="session_id",
            annotation=str,
            name="Session ID",
            description="Unique identifier for a session.",
            default="",
            is_shared=True,
        ),
    ]

Jadi, pada invoke(), config = {“configurable”: {“session_id”: “Masukkan ID sesi"}} Anda dapat melihat bahwa kita harus menentukan kode.

with_message_history.invoke(
    # Mengirimkan pertanyaan terkait matematika "Apa arti dari kosinus?" sebagai input.
    {"ability": "math", "input": "Apa itu kosinus?"},
    # Mengirimkan ID sesi "abc123" sebagai informasi konfigurasi.
    config={"configurable": {"session_id": "abc123"}},
)
abc123
content='Fungsi trigonometri.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 39, 'total_tokens': 47}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-c5a53d52-dcaa-4afd-a0f9-304a437f8199-0' usage_metadata={'input_tokens': 39, 'output_tokens': 8, 'total_tokens': 47}

Jika Anda memasukkan session_id yang sama, Anda akan mendapatkan konten dari utas percakapan sebelumnya, sehingga Anda dapat melanjutkan percakapan!

# Memanggil dengan menyertakan riwayat pesan.
with_message_history.invoke(
    # Menetapkan kemampuan dan input.
    {"ability": "math", "input": "Tolong jawab dalam bahasa Inggris berdasarkan percakapan sebelumnya."},
    # Menetapkan opsi konfigurasi.
    config={"configurable": {"session_id": "abc123"}},
)
abc123
content='Trigonometry function.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 5, 'prompt_tokens': 76, 'total_tokens': 81}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-db9473e7-c884-470a-a618-7088e91989d9-0' usage_metadata={'input_tokens': 76, 'output_tokens': 5, 'total_tokens': 81}

Namun, jika Anda menentukan session_id yang berbeda, ia tidak akan menjawab dengan benar karena tidak ada riwayat percakapan.

(Pada contoh di bawah ini, Anda dapat melihat bahwa session_id: def234 memberikan jawaban yang salah karena tidak ada)

# Karena session_id baru, tidak mengingat percakapan sebelumnya.
with_message_history.invoke(
    # Mengirimkan kemampuan matematika dan pesan input.
    {"ability": "math", "input": "Tolong jawab dalam bahasa Inggris berdasarkan percakapan sebelumnya"},
    # Menetapkan session_id baru.
    config={"configurable": {"session_id": "def234"}},
)
def234
content='Sure, how can I help you?' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 50, 'total_tokens': 58}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-23961fe3-af1b-4711-b0be-34b0a09b6aa4-0' usage_metadata={'input_tokens': 50, 'output_tokens': 8, 'total_tokens': 58}

Parameter konfigurasi yang digunakan untuk melacak riwayat pesan dapat disesuaikan dengan mengoper daftar objek ConfigurableFieldSpec ke parameter history_factory_config.

Pengaturan baru history_factory_config ini akan menimpa pengaturan session_id yang sudah ada.

Contoh di bawah ini menggunakan dua parameter: user_id dan conversation_id.

from langchain_core.runnables import ConfigurableFieldSpec

store = {}  # Inisialisasi kamus kosong.


def get_session_history(user_id: str, conversation_id: str) -> BaseChatMessageHistory:
    # Mengembalikan riwayat sesi yang sesuai dengan user_id dan conversation_id yang diberikan.
    if (user_id, conversation_id) not in store:
        # Jika kunci tersebut tidak ada di store, buat dan simpan ChatMessageHistory baru.
        store[(user_id, conversation_id)] = ChatMessageHistory()
    return store[(user_id, conversation_id)]


with_message_history = RunnableWithMessageHistory(
    runnable,
    get_session_history,
    input_messages_key="input",
    history_messages_key="history",
    history_factory_config=[  # Ini akan menggantikan pengaturan "session_id" yang ada.
        ConfigurableFieldSpec(
            id="user_id",  # Digunakan sebagai argumen pertama dari fungsi get_session_history.
            annotation=str,
            name="User ID",
            description="Pengenal unik untuk pengguna.",
            default="",
            is_shared=True,
        ),
        ConfigurableFieldSpec(
            id="conversation_id",  # Digunakan sebagai argumen kedua dari fungsi get_session_history.
            annotation=str,
            name="Conversation ID",
            description="Pengenal unik untuk percakapan.",
            default="",
            is_shared=True,
        ),
    ],
)
with_message_history.invoke(
    # Mengirimkan kamus yang berisi kemampuan (ability) dan input (input).
    {"ability": "math", "input": "Hello"},
    # Mengirimkan kamus konfigurasi (config).
    config={"configurable": {"user_id": "123", "conversation_id": "1"}},
)
content='Hi! What can I help you with today?' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 34, 'total_tokens': 44}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-c22b0ab2-3ae8-474b-956a-615b6d0a2f04-0' usage_metadata={'input_tokens': 34, 'output_tokens': 10, 'total_tokens': 44}

Contoh penggunaan Runnable dengan berbagai keys.

Masukkan objek Pesan, keluarkan sebagai dictionary

Ini mengambil pesan sebagai masukan dan mengembalikan kamus sebagai keluaran.

  • [Penting]: Hilangkan input_messages_key = “input”, yang akan mengaturnya untuk mengambil objek Pesan sebagai input.

from langchain_core.messages import HumanMessage
from langchain_core.runnables import RunnableParallel

# Membuat chain
chain = RunnableParallel({"output_message": ChatOpenAI()})


def get_session_history(session_id: str) -> BaseChatMessageHistory:
    # Jika riwayat percakapan untuk session ID tidak ada di penyimpanan, buat ChatMessageHistory baru.
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    # Kembalikan riwayat percakapan untuk session ID yang diberikan.
    return store[session_id]


# Membuat objek RunnableWithMessageHistory yang menambahkan fungsi riwayat percakapan ke dalam chain.
with_message_history = RunnableWithMessageHistory(
    chain,
    get_session_history,
    # Mengatur kunci pesan input ke "input". (Diabaikan jika input berupa objek Message)
    # input_messages_key="input",
    # Mengatur kunci pesan output ke "output_message". (Diabaikan jika output berupa objek Message)
    output_messages_key="output_message",
)

# Menjalankan chain dengan pesan dan konfigurasi yang diberikan.
with_message_history.invoke(
    # Atau bisa juga menggunakan "what is the definition of cosine?"
    [HumanMessage(content="Apa definisi dari kosinus?")],
    config={"configurable": {"session_id": "abc123"}},
)
{'output_message': AIMessage(content='Kosinus adalah fungsi trigonometri yang merupakan rasio panjang sisi sejajar dengan sudut dalam sebuah segitiga siku-siku terhadap panjang sisi miring segitiga tersebut. Dalam matematika, kosinus sering dilambangkan dengan simbol "cos".', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 66, 'prompt_tokens': 15, 'total_tokens': 81}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-9fe92482-e149-4a32-b1b1-4243ad69a9d7-0', usage_metadata={'input_tokens': 15, 'output_tokens': 66, 'total_tokens': 81})}
with_message_history.invoke(
    # Meminta ulang jawaban sebelumnya dalam bahasa Korea.
    [HumanMessage(content="Tolong jawab dalam bahasa Inggris berdasarkan pertanyaan sebelumnya!")],
    # Mengirimkan opsi konfigurasi dalam bentuk kamus.
    config={"configurable": {"session_id": "abc123"}},
)
{'output_message': AIMessage(content='Cosine is a mathematical function that measures the ratio of the length of the adjacent side to the length of the hypotenuse in a right triangle. In trigonometry, the cosine of a specific angle in a right triangle is defined as the length of the adjacent side to that angle divided by the length of the hypotenuse of the triangle.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 70, 'prompt_tokens': 141, 'total_tokens': 211}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-2a4115e8-91a4-4100-9b6e-98459b83dd0a-0', usage_metadata={'input_tokens': 141, 'output_tokens': 70, 'total_tokens': 211})}

Memasukkan objek Pesan, mengeluarkan objek Pesan

[Penting]: output_messages_key = “output_message”, yang akan mengembalikan objek Message sebagai output.

with_message_history = RunnableWithMessageHistory(
    ChatOpenAI(),  # Menggunakan model bahasa ChatOpenAI.
    get_session_history,  # Menetapkan fungsi untuk mengambil riwayat sesi percakapan.
    # Mengatur kunci pesan input ke "input". (Diabaikan jika input berupa objek Message)
    # input_messages_key="input",
    # Mengatur kunci pesan output ke "output_message". (Diabaikan jika output berupa objek Message)
    # output_messages_key="output_message",
)
with_message_history.invoke(
    # Meminta ulang jawaban dalam bahasa Korea berdasarkan percakapan sebelumnya.
    [HumanMessage(content="Apa arti dari kosinus?")],
    # Mengirimkan opsi konfigurasi dalam bentuk kamus.
    config={"configurable": {"session_id": "def123"}},
)
content='Kosinus adalah fungsi matematika yang menghasilkan nilai rasio dari panjang sisi sejajar terhadap panjang sisi miring pada segitiga siku-siku. Dalam trigonometri, kosinus dari suatu sudut dalam sebuah segitiga siku-siku adalah nilai rasio antara panjang sisi sejajar dengan sudut tersebut terhadap panjang sisi miring segitiga. Kosinus biasanya dilambangkan dengan simbol cos.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 107, 'prompt_tokens': 15, 'total_tokens': 122}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-ea96a85b-3072-4c4a-81a0-5ede74b6b4f0-0' usage_metadata={'input_tokens': 15, 'output_tokens': 107, 'total_tokens': 122}

Dict dengan satu key untuk semua input dan output pesan

Pendekatan ini menggunakan satu kunci untuk semua pesan masukan dan pesan keluaran.

  • Gunakan itemgetter(“input_messages”) untuk mengekstrak pesan masukan.

from operator import itemgetter

with_message_history = RunnableWithMessageHistory(
    # Menggunakan kunci "input_messages" untuk mengambil pesan input dan mengirimkannya ke ChatOpenAI().
    itemgetter("input_messages") | ChatOpenAI(),
    get_session_history,  # Fungsi untuk mengambil riwayat sesi.
    input_messages_key="input_messages",  # Menetapkan kunci untuk pesan input.
)
with_message_history.invoke(
    {"input_messages": "Apa arti dari kosinus?"},
    # Mengirimkan opsi konfigurasi dalam bentuk kamus.
    config={"configurable": {"session_id": "xyz123"}},
)
content='Kosinus adalah sebuah fungsi matematika yang menghasilkan nilai rasio dari panjang sisi sejajar dengan sudut tertentu dalam segitiga siku-siku, dibagi dengan panjang sisi miring segitiga tersebut. Kosinus digunakan dalam trigonometri untuk menghitung panjang sisi segitiga dan sudut-sudutnya.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 82, 'prompt_tokens': 15, 'total_tokens': 97}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-89eaedc8-3ab3-4f73-bac9-e0743eb68b47-0' usage_metadata={'input_tokens': 15, 'output_tokens': 82, 'total_tokens': 97}

Persistent Storage

Penyimpanan persisten mengacu pada mekanisme penyimpanan yang mempertahankan data bahkan ketika sebuah program dihentikan atau sistem di-boot ulang. Hal ini dapat diimplementasikan melalui database, sistem file, atau perangkat penyimpanan non-volatile lainnya.

Penyimpanan persisten sangat penting untuk menyimpan status aplikasi, mempertahankan pengaturan pengguna, dan menyimpan data untuk jangka waktu yang lama. Hal ini memungkinkan program untuk melanjutkan dari tempat yang ditinggalkannya pada proses sebelumnya, dan memungkinkan pengguna untuk terus bekerja tanpa kehilangan data.

Menginstall Redis

Jika Anda belum menginstal Redis, Anda harus menginstalnya terlebih dahulu.

pip install -qU redis

Menjalankan server Redis

Jika Anda tidak memiliki penerapan Redis yang sudah ada untuk disambungkan, mulai server Redis Stack lokal.

Berikut ini adalah perintah untuk memulai server Redis dengan Docker.

docker run -d -p 6379:6379 -p 8001:8001 redis/redis-stack:latest

Tetapkan URL koneksi basis data Redis ke variabel REDIS_URL.

  • URL ditetapkan ke “redis://localhost:6379/0”.

# Tentukan URL server Redis.
REDIS_URL = "redis://localhost:6379/0"

Menyiapkan pelacakan LangSmith

Siapkan LangSmith untuk pelacakan. LangSmith tidak diperlukan, tetapi dapat membantu.

from dotenv import load_dotenv
import os

load_dotenv()

# Tetapkan variabel lingkungan LANGCHAIN_TRACING_V2 ke “true”.
os.environ["LANGCHAIN_TRACING_V2"] = "true"
# Mengatur LANGCHAIN_PROJECT
os.environ["LANGCHAIN_PROJECT"] = "RunnableWithMessageHistory"

Untuk memperbarui implementasi riwayat pesan, cukup definisikan objek baru yang dapat dipanggil, kali ini mengembalikan sebuah instance RedisChatMessageHistory.

from langchain_community.chat_message_histories import RedisChatMessageHistory


def get_message_history(session_id: str) -> RedisChatMessageHistory:
    # Mengembalikan objek RedisChatMessageHistory berdasarkan session ID.
    return RedisChatMessageHistory(session_id, url=REDIS_URL)


with_message_history = RunnableWithMessageHistory(
    runnable,  # Objek yang dapat dijalankan
    get_message_history,  # Fungsi untuk mengambil riwayat pesan
    input_messages_key="input",  # Kunci untuk pesan input
    history_messages_key="history",  # Kunci untuk pesan riwayat
)

Anda dapat memanggilnya dengan cara yang sama seperti sebelumnya.

with_message_history.invoke(
    # Mengirimkan pertanyaan terkait matematika "Apa arti dari kosinus?" sebagai input.
    {"ability": "math", "input": "Apa arti dari kosinus?"},
    # Menetapkan session ID menjadi "redis123" sebagai opsi konfigurasi.
    config={"configurable": {"session_id": "redis123"}},
)
content='Trigonometri fungsi.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 7, 'prompt_tokens': 41, 'total_tokens': 48}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-1e5c490f-7406-406b-aaaa-f901750bd333-0' usage_metadata={'input_tokens': 41, 'output_tokens': 7, 'total_tokens': 48}

Lakukan panggilan kedua dengan menggunakan session_id yang sama. Kali ini, kami akan meminta jawaban sebelumnya dalam bahasa Korea.

with_message_history.invoke(
    # Meminta terjemahan jawaban sebelumnya ke dalam bahasa Korea.
    {"ability": "math", "input": "Tolong terjemahkan jawaban sebelumnya ke dalam bahasa Korea."},
    # Menetapkan session ID menjadi "redis123" sebagai nilai konfigurasi.
    config={"configurable": {"session_id": "redis123"}},
)
content='Trigonometry function.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 5, 'prompt_tokens': 75, 'total_tokens': 80}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-c666e30b-9bf0-472e-8d4e-6679bfe2b539-0' usage_metadata={'input_tokens': 75, 'output_tokens': 5, 'total_tokens': 80}

Kali ini, kita akan mengajukan pertanyaan dengan menggunakan session_id yang berbeda.

with_message_history.invoke(
    # Meminta terjemahan jawaban sebelumnya ke dalam bahasa Korea.
    {"ability": "math", "input": "Tolong terjemahkan jawaban sebelumnya ke dalam bahasa Korea."},
    # Menetapkan session ID menjadi "redis456" sebagai nilai konfigurasi.
    config={"configurable": {"session_id": "redis456"}},
)
content='Translate the previous answer into English.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 7, 'prompt_tokens': 52, 'total_tokens': 59}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-69c3e6a1-4cbc-4e7f-bf13-8285cb9fc617-0' usage_metadata={'input_tokens': 52, 'output_tokens': 7, 'total_tokens': 59}

Yang terakhir ini tidak memiliki riwayat percakapan sebelumnya, jadi Anda tidak akan mendapatkan jawaban yang tepat.

Last updated