Praktik terbaik dan pola

Panduan ini membagikan praktik terbaik dan pola desain yang telah terbukti untuk mengoptimalkan dan menskalakan aplikasi agen Anda. Konten ini dapat membantu Anda mengurangi biaya waktu desain, mengurangi biaya runtime, dan meningkatkan keandalan agen.

Umum

Bagian ini memberikan praktik terbaik umum untuk mulai mengembangkan agen dan menulis petunjuk.

Mulai dengan mudah

Saat pertama kali mulai membangun aplikasi agen, Anda harus memulai dengan kasus penggunaan sederhana. Setelah kasus penggunaan sederhana berfungsi, lanjutkan membangun kasus penggunaan yang lebih rumit.

Petunjuk harus spesifik

Petunjuk agen harus spesifik dan tidak ambigu. Petunjuk harus disusun dengan baik dan dikelompokkan berdasarkan topik. Hindari menyebarkan petunjuk tentang topik tertentu secara tidak teratur. Petunjuk juga harus mudah diikuti oleh manusia.

Menggunakan petunjuk terstruktur

Setelah selesai menulis petunjuk, Anda harus menggunakan fitur restructure instructions untuk memformat petunjuk. Dalam format ini, agen Anda akan lebih andal.

Menggunakan komponen modular dari berbagai modalitas dan saluran

Jika agen harus merespons dengan cara yang berbeda untuk modalitas (teks atau suara) atau saluran (API, telepon, atau web) yang berbeda, Anda harus menggunakan komponen modular dan memeriksa saluran dan modalitas di alat dan callback Python.

Alat

Bagian ini memberikan praktik terbaik untuk menentukan dan menggunakan alat, termasuk membungkus API eksternal dan merangkai panggilan alat.

Membungkus API dengan alat Python

Skema API eksternal dapat menentukan banyak parameter input dan output yang tidak relevan dengan agen Anda. Jika Anda menggunakan alat OpenAPI untuk kasus seperti ini, Anda mungkin memberikan konteks yang tidak perlu kepada model, yang dapat mengurangi keandalan. Misalnya, alat spesifikasi OpenAPI mengambil 3 parameter sebagai input dan menampilkan objek JSON besar dengan 100 key/value pair. Agen memprediksi 3 argumen input untuk alat ini, dan saat ditampilkan, agen melihat payload JSON lengkap dengan semua 100 key/value pair. Jika hanya 3 pasangan ini yang benar-benar relevan dengan percakapan, 97 pasangan lainnya adalah data yang tidak relevan yang menambahkan token ke histori percakapan. Meskipun tampak tidak berbahaya, hal ini dapat menimbulkan kebingungan yang tidak perlu bagi agen, meningkatkan waktu penalaran, dan meningkatkan latensi.

Praktik terbaiknya adalah menggunakan alat Python untuk membungkus panggilan API. Pembungkusan memungkinkan Anda meng-obfuscate data yang tidak perlu dari agen dan histori konteks. Anda dapat mengontrol konteks persis yang dilihat agen dengan hanya menampilkan data yang relevan dengan agen pada titik waktu tersebut. Tindakan ini memberi Anda kontrol penuh atas parameter input dan output yang ditentukan oleh alat, yang dibagikan dengan model. Praktik ini adalah bentuk Rekayasa Konteks dengan alat.

Contoh kode:

def python_wrapper(arg_a: str, arg_b: str) -> dict:
  """
  Call the scheduling service to schedule an appointment,
  returning only relevant fields.
  """
  res = complicated_external_api_call(...)
  # Process result to extract only relevant key-value pairs.
  processed_res = {
      "appointment_time": res.json()["appointment_time"],
      "appointment_location": res.json()["appointment_location"],
      "confirmation_id": res.json()["confirmation_id"],
  }
  return processed_res

Menggunakan alat dan callback untuk perilaku deterministik

Dalam skenario percakapan tertentu, Anda mungkin memerlukan perilaku yang lebih deterministik dari aplikasi agen Anda. Dalam kasus ini, Anda harus menggunakan alat atau callback.

Callback biasanya merupakan opsi terbaik untuk kontrol deterministik penuh. Callback terjadi di luar cakupan agen, sehingga agen tidak terlibat dalam eksekusi callback.

Bagian internal alat bersifat sepenuhnya deterministik, tetapi panggilan alat yang diorkestrasi oleh agen tidak deterministik. Agen memutuskan untuk memanggil alat, menyiapkan argumen input alat, dan menafsirkan hasil alat. Agen dapat berhalusinasi dalam orkestrasi ini.

Merangkai panggilan alat

Mirip dengan membungkus panggilan API dengan alat, Jika beberapa alat perlu dijalankan selama giliran percakapan, Anda harus menginstruksikan agen untuk memanggil satu alat dan menerapkan alat tersebut untuk memanggil alat lainnya. Atau, Anda dapat menginstruksikan agen untuk memanggil alat pertama dan menentukan callback after_tool_callback untuk memanggil alat yang tersisa.

Pola buruk untuk membuat rangkaian panggilan alat

Menginstruksikan agen untuk memanggil beberapa alat selama giliran percakapan untuk mencapai tujuan yang sama dianggap sebagai pola yang buruk.

Model harus memprediksi setiap panggilan alat dan setiap parameter dalam panggilan alat tersebut. Kemudian, model harus memastikan bahwa model memprediksi panggilan alat secara berurutan juga. Artinya, Anda sangat mengandalkan model (yang secara inheren non-deterministik) untuk melakukan tugas deterministik.

Misalnya, pertimbangkan urutan alat berikut:

  • tool_1(arg_a, arg_b) -> output c
  • tool_2(arg_c) -> output d
  • tool_3(arg_d) -> output e

Jika Anda menentukan petunjuk untuk tiga panggilan alat ini, Anda akan mendapatkan urutan peristiwa runtime seperti berikut:

  • Input Pengguna
  • Model -> Agen memprediksi tool_1(arg_a, arg_b)
  • tool_1_response.json() dikembalikan
  • Agen menafsirkan tool_1_response.json() dan mengekstrak arg_c
  • Model -> Agen memprediksi tool_2(arg_c)
  • tool_2_response.json() dikembalikan
  • Agen menafsirkan tool_2_response.json() dan mengekstrak arg_d
  • Model -> Agen memprediksi tool_3(arg_d)
  • tool_3_response.json() dikembalikan
  • Model -> Agen memberikan respons akhir

Ada 4 panggilan model, 3 prediksi alat, dan 4 argumen input.

Pola yang baik untuk membuat rangkaian panggilan alat

Saat Anda perlu memanggil beberapa alat, pola yang baik adalah menginstruksikan agen untuk memanggil satu alat, dan menerapkan alat tersebut untuk memanggil alat lainnya.

Alat berikut memanggil tiga alat lainnya:

def python_wrapper(arg_a: str, arg_b: str) -> dict:
  """Makes some sequential API calls."""
  res1 = tools.tool_1({"arg_a": arg_a, "arg_b": arg_b})
  res2 = tools.tool_2(res1.json())
  res3 = tools.tool_3(res2.json())

  return res3.json()

Pertimbangkan urutan peristiwa untuk satu panggilan alat:

  • Input Pengguna
  • Model -> Agen memprediksi python_wrapper(arg_a, arg_b)
  • python_wrapper_response.json() dikembalikan
  • Model -> Agen memberikan respons akhir

Pendekatan ini mengurangi token dan mengurangi kemungkinan halusinasi.

Definisi alat yang jelas dan berbeda

Untuk definisi alat, praktik terbaik berikut harus diterapkan:

  • Alat yang berbeda tidak boleh memiliki nama yang serupa. Buat nama alat Anda berbeda satu sama lain.
  • Alat yang tidak digunakan harus dihapus dari node agen.
  • Untuk nama parameter, gunakan snake case, gunakan nama deskriptif, dan hindari singkatan yang tidak umum.

    Contoh yang baik: first_name, phone_number, url.

    Contoh yang salah: i, arg1, fn, pnum, rqst.

  • Parameter harus menggunakan struktur datar, bukan struktur bertingkat. Makin bertingkat struktur, makin Anda mengandalkan model untuk memprediksi pasangan kunci/nilai dan pengetikannya yang tepat.

Alur kerja pengembangan

Bagian ini memberikan praktik terbaik untuk kolaborasi tim, kontrol versi, dan pengujian selama pengembangan agen.

Menentukan proses pengembangan untuk kolaborasi agen

Saat berkolaborasi dengan tim dalam pengembangan aplikasi agen, Anda harus menentukan proses pengembangan. Berikut adalah contoh kemungkinan praktik kolaborasi:

  • Menggunakan kontrol versi pihak ketiga: Gunakan impor dan pulihkan untuk menyinkronkan perubahan dengan sistem kontrol versi pihak ketiga Anda. Menyetujui proses untuk menyinkronkan, meninjau, dan menggabungkan. Tentukan pemilik yang jelas dan langkah-langkah yang jelas untuk menerima perubahan (misalnya, memiliki hasil evaluasi).
  • Menggunakan kontrol versi bawaan: Siapkan proses untuk menggunakan kontrol versi bawaan. Menyetujui cara menggunakan snapshot untuk pembuatan versi. Misalnya, Anda dapat mewajibkan snapshot saat pencapaian tonggak pencapaian (serangkaian evaluasi lulus), atau sebelum pengembangan fitur baru selesai. Menyetujui proses untuk menyinkronkan, meninjau, dan menggabungkan perubahan.

Menggunakan versi untuk menyimpan status agen

Versi memungkinkan Anda mengabadikan pekerjaan atau perubahan yang telah Anda selesaikan dalam aplikasi agen Anda. Setelah membuat perubahan pada petunjuk, alat, variabel, dan item lainnya, Anda dapat menyimpan status tersebut sebelum perubahan lain dilakukan. Versi adalah snapshot agen yang tidak dapat diubah pada waktu tertentu. Anda harus membuat versi saat Anda puas dengan beberapa perubahan dan aplikasi agen berfungsi seperti yang Anda rancang, terutama setelah memvalidasi perubahan dengan evaluasi. Setelah membuat versi, Anda dapat melakukan roll back ke versi tersebut kapan saja.

Anda harus sering membuat versi, mungkin setelah setiap 10-15 perubahan besar. Penamaan versi secara semantik juga berguna, dan Anda harus memutuskan konvensi penamaan yang akan digunakan dengan tim pengembangan Anda. Contohnya mencakup nama deskriptif seperti pre-prod-instruction-changes atau prod-ready-for-testing. Anda juga dapat menggunakan standar seperti Pembuatan Versi Semantik, menggunakan nama seperti v1.0.0, v1.0.1, dll. Versi juga memiliki kolom deskripsi yang memungkinkan Anda menambahkan detail lainnya, mirip dengan isi pesan commit. Nama dan deskripsi versi harus singkat, bermakna, dan mudah dipahami jika Anda perlu melakukan roll back ke versi tersebut.

Melakukan pengujian menyeluruh

Proses pengembangan aplikasi agen Anda harus mencakup pengujian end-to-end untuk memverifikasi integrasi dengan sistem eksternal.

Evaluasi

Bagian ini memberikan praktik terbaik untuk menggunakan evaluasi guna memastikan keandalan agen.

Menggunakan evaluasi

Evaluasi membantu menjaga keandalan agen Anda. Gunakan properti tersebut untuk menetapkan ekspektasi pada agen Anda dan API yang dipanggil oleh agen Anda.

Penanganan sesi

Bagian ini memberikan pola untuk mengelola siklus proses sesi.

Sapaan deterministik dan latensi yang lebih rendah dengan respons statis

Anda dapat mengonfigurasi agen untuk mengucapkan respons deterministik saat sesi dimulai. Pendekatan ini dapat menghemat panggilan dan token model, serta mengurangi latensi.

Dengan menggunakan before_model_callback, Anda dapat mencegat input yang masuk, lalu merespons dengan pesan sapaan statis.

def before_model_callback(
    callback_context: CallbackContext,
    llm_request: LlmRequest
) -> Optional[LlmResponse]:
  for part in callback_context.get_last_user_input():
    # Or other events or texts
    if part.text == "<event>session start</event>":
      return LlmResponse.from_parts(parts=[
          Part.from_text(text="Hello how can I help you today?")
      ])
  return None

Memberikan respons cepat dengan pesan awalan saat model sedang bekerja

Saat sesi dimulai, hindari memaksa pengguna menunggu pembuatan model. Anda dapat menambahkan awalan pada respons sehingga agen dapat dengan cepat memberikan sapaan yang ramah dan bermerek (misalnya, "Halo, saya Gemini, asisten pribadi Anda"), sementara model secara bersamaan memproses permintaan utama pengguna di latar belakang.

Hal ini bergantung pada setelan partial = True. Biasanya, respons non-FuctionCall dianggap sebagai respons akhir. Menggunakan partial = True akan memaksa agen untuk melanjutkan pemrosesan setelah respons.

Dalam contoh berikut, aplikasi agen mengirimkan pesan selamat datang dengan cepat lalu melanjutkan pemrosesan permintaan utama. Hal ini menghilangkan jeda pengetikan yang canggung, sehingga agen merasa responsif.

def before_model_callback(callback_context: CallbackContext, llm_request: LlmRequest) -> Optional[LlmResponse]:
  for part in callback_context.get_last_user_input():
    if part.text == "<event>session start</event>":
      response = LlmResponse.from_parts([Part.from_text("Hello, I'm Gemini, your personal AI assistant.")])
      response.partial = True
      return response
  return None

Memverifikasi dan menerapkan konten wajib

Dalam beberapa kasus, Anda mungkin ingin menginstruksikan agen untuk memberikan konten wajib tertentu (seperti pernyataan penyangkalan hukum), tetapi juga memverifikasi bahwa agen benar-benar menyertakannya. Pola ini memungkinkan Anda mengandalkan pembuatan alami model saat berfungsi, tetapi menerapkan konten secara deterministik saat gagal.

Anda dapat menggunakan after_model_callback untuk memeriksa output model. Jika konten wajib ada, callback akan menampilkan None (membiarkan respons model diteruskan). Jika tidak ada, callback akan membuat respons baru yang berisi konten wajib.

Variabel contoh:

Nama variabel Nilai default
first_turn Benar
DISCLAIMER = "THIS CONVERSATION MAY BE RECORDED FOR LEGAL PURPOSES."

def after_model_callback(
    callback_context: CallbackContext,
    llm_response: LlmResponse
) -> Optional[LlmResponse]:
  if callback_context.variables.get("first_turn"):
    callback_context.variables["first_turn"] = False

    # Check if the agent's response already contains the disclaimer.
    # The agent might have produced it based on instructions.
    for part in callback_context.get_last_agent_output():
      if part.text and DISCLAIMER in part.text:
        return None

    # If the agent failed to produce the disclaimer, force it.
    return LlmResponse.from_parts(parts=[
        Part.from_text(DISCLAIMER),
        *llm_response.content.parts
    ])

  return None

Panggil alat kustom saat sesi berakhir

Anda dapat mengonfigurasi agen untuk memanggil alat tertentu saat sesi berakhir. Hal ini dapat berguna untuk peristiwa penutup pasca-panggilan seperti menyinkronkan data saat keluar, mengirim data ke API eksternal, penyelesaian tugas backend, atau mencatat metadata panggilan.

Misalnya, anggaplah Anda memiliki alat yang sudah ada seperti post_call_logging yang ingin Anda panggil tepat sebelum sesi berakhir:

def post_call_logging(session_id: str) -> dict:
  """Logs the session ID to external API."""
  API_URL = "https://api.example.com"
  response = ces_requests.post(
    url=API_URL,
    data={"session_id": session_id}
  )

  return response.json()

Anda dapat menggunakan after_model_callback untuk melakukan urutan berikut:

  1. Periksa panggilan alat end_session dalam respons agen.
  2. Buat bagian alat post_call_logging.
  3. Sisipkan panggilan alat post_call_logging sebelum panggilan alat end_session.

Hal ini memastikan bahwa agen menjalankan alat logging sebelum mengakhiri sesi.

def after_model_callback(
    callback_context: CallbackContext,
    llm_response: LlmResponse
) -> Optional[LlmResponse]:
  for index, part in enumerate(llm_response.content.parts):
    if part.has_function_call('end_session'):
      # Add an additional "post_call_logging" function call before "end_session",
      # so the agent will execute the tool before ending the session.
      tool_call = Part.from_function_call(
          name="post_call_logging",
          args={"sessionId": callback_context.session_id}
      )
      return LlmResponse.from_parts(
          parts=llm_response.content.parts[:index] + [tool_call] + llm_response.content.parts[index:]
      )
  return None

Menggunakan respons parsial untuk pembaruan antarmuka pengguna real-time

Saat agen menjalankan tindakan (misalnya, memperbarui status pesanan), mungkin ada penundaan saat model memproses respons akhir. Dengan menggunakan respons parsial, Anda dapat mengirim notifikasi ke antarmuka pengguna klien saat alat selesai dieksekusi, sehingga memperkecil ketergantungan antara pembaruan visual dan pembuatan teks model.

Antarmuka pengguna Anda dapat memperbarui status, pelacak, atau tanda terima secara real-time.

Hal ini bergantung pada setelan partial = True. Biasanya, respons non-FuctionCall dianggap sebagai respons akhir. Menggunakan partial = True akan memaksa agen untuk melanjutkan pemrosesan setelah respons.

Payload JSON tidak akan dikirim ke model. Dengan demikian, agen tidak akan mengetahui keberadaan payload selama pembuatan respons.

def before_model_callback(
    callback_context: CallbackContext,
    llm_request: LlmRequest
) -> Optional[LlmResponse]:
  if  llm_request.contents[-1].parts[-1].has_function_response('update_order'):
    order_state =  llm_request.contents[-1].parts[-1].function_response.response['result']['order_state']
    # Return a custom JSON payload before calling the model to generate the final agent response.
    response = LlmResponse.from_parts([Part.from_json(data=json.dumps(order_state))])
    response.partial = True
    return response
  return None

Integrasi sisi klien

Bagian ini memberikan pola untuk berintegrasi dengan aplikasi sisi klien.

Menggunakan payload kustom untuk mengontrol antarmuka pengguna

Pengguna mengharapkan antarmuka yang dinamis dan interaktif. Anda dapat menggunakan payload kustom untuk mendorong rendering sisi klien, menjembatani kesenjangan antara agen dan aplikasi yang sudah sempurna. Daripada memberikan opsi teks biasa, konfigurasi agen Anda untuk mendeteksi pola tertentu dalam respons (misalnya, daftar pilihan) dan mengubahnya menjadi elemen antarmuka pengguna interaktif dengan konversi tinggi, seperti chip atau tombol yang dapat diklik.

Gunakan after_model_callback untuk memindai respons agen untuk pemicu tertentu. Misalnya, jika output model adalah: "Opsi yang tersedia adalah: Pengembalian Dana, Lacak Pesanan, Berbicara dengan Agen", callback berikut mencegat dan mengekstraksi opsi tersebut sebagai payload JSON, yang dapat digunakan untuk rendering antarmuka pengguna.

import json

def after_model_callback(
    callback_context: CallbackContext,
    llm_response: LlmResponse
) -> Optional[LlmResponse]:
  prefix = 'Available options are:'
  payload = {}
  for part in llm_response.content.parts:
    if part.text is not None and part.text.startswith(prefix):
      # Return available options as chip list
      payload['chips'] = part.text[len(prefix):].split(',')
      break

  new_parts = []
  # Keep the original agent response part, as the custom payload won't be sent
  # back to the model in the next turn.
  new_parts.extend(llm_response.content.parts)
  new_parts.append(Part.from_json(data=json.dumps(payload)))
  return LlmResponse.from_parts(parts=new_parts)

Menampilkan Markdown dan HTML

Jika antarmuka percakapan Anda mendukung Markdown dan HTML untuk respons agen, Anda dapat menggunakan simulator untuk menguji respons ini, karena simulator juga mendukung Markdown dan HTML.

Contoh petunjuk:

<role>
    You are a "Markdown Display Assistant," an AI agent designed to demonstrate
    various rich content formatting options like images, videos, and deep links
    using HTML-style markdown. Your purpose is to generate and display this
    content directly to the user based on their requests.
</role>
<persona>
    Your primary goal is to showcase the rich content rendering capabilities of
    the platform by generating HTML markdown for elements like images, videos,
    and hyperlinks. You are a helpful and direct assistant. When asked to show
    something, you generate the markdown for it and present it.
    You should not engage in conversations outside the scope of generating and
    displaying markdown. If the user asks for something unrelated, politely
    state that you can only help with displaying rich content. Adhere strictly
    to the defined constraints and task flow.
</persona>
<constraints>
    1.  **Scope Limitation:** Only handle requests related to displaying
        markdown content (images, videos, links, etc.). Do not answer general
        knowledge questions or perform other tasks.
    2.  **Tool Interaction Protocol:** You must use the \`display_markdown\`
        tool to generate the formatted content string.
    3.  **Direct Output:** Your final response to the user must be the raw
        markdown string returned by the \`display_markdown\` tool. Do not add
        any conversational text around it unless the tool returns an error.
        For example, if the tool returns \`"<img src='...'>"\`, your response
        should be exactly \`"<img src='...'>"\`.
    4.  **Clarity and Defaults:** If a user's request is vague (e.g., "show me
        an image"), use the tool's default values to generate a response. There
        is no need to ask for clarification.
    5.  **Error Handling:** If the tool call fails or returns an error, inform
        the user about the issue in a conversational manner.
</constraints>
<taskflow>
    These define the conversational subtasks that you can take. Each subtask
    has a sequence of steps that should be taken in order.
    <subtask name="Generate and Display Markdown">
        <step name="Parse Request and Call Tool">
            <trigger>
                User initiates a request to see any form of rich content (image,
                video, link, etc.).
            </trigger>
            <action>
                1.  Identify the types of content the user wants to see (e.g.,
                    image, video, deep link).
                2.  Call the \`display_markdown\` tool. Set the corresponding
                    boolean arguments to \`True\` based on the user's request.
                    For example, if the user asks for a video and a link, call
                    \`display_markdown(show_video=True, show_deep_link=True)\`.
                3.  If the user makes a general request like "show me something
                    cool", you can enable all flags.
            </action>
        </step>
        <step name="Output Tool Response">
            <trigger>
                The \`display_markdown\` tool returns a successful response
                containing a \`markdown_string\`.
            </trigger>
            <action>
                1.  Extract the value of the \`markdown_string\` key from the
                    tool's output.
                2.  Use this value as your direct and final response to the
                    user, without any additional text or formatting.
            </action>
        </step>
    </subtask>
</taskflow>

Contoh alat python:

from typing import Any

def display_markdown(show_image: bool, show_video: bool, show_deep_link: bool) -> dict[str, Any]:
    """
    Constructs a markdown string containing HTML for various rich media elements.

    This function generates an HTML-formatted string based on the boolean flags provided.
    It can include an image, a video, and a hyperlink (deep link). The content for
    these elements is pre-defined.

    Args:
        show_image (bool): If True, an <img> tag will be included in the output.
        show_video (bool): If True, a <video> tag will be included in the output.
        show_deep_link (bool): If True, an <a> tag will be included in the output.

    Returns:
        dict[str, Any]: A dictionary with a single key 'markdown_string' containing the
                        generated HTML markdown. If no flags are set, it returns a
                        message indicating nothing was requested.
    """
    # MOCK: This is a mock implementation. It does not fetch any dynamic content.
    # It assembles a markdown string from hardcoded HTML snippets to demonstrate
    # the agent's ability to render rich content.

    markdown_parts = []

    if show_image:
        image_html = "This is a sample image:\n<img src='https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png' alt='Google Logo' width='272' height='92' />"
        markdown_parts.append(image_html)

    if show_video:
        video_html = "This is a sample video:\n<video controls width='320' height='240'><source src='https://www.w3schools.com/html/mov_bbb.mp4' type='video/mp4'>Sorry, your browser does not support embedded videos.</video>"
        markdown_parts.append(video_html)

    if show_deep_link:
        link_html = "This is a sample deep link:\n<a href='https://www.google.com'>Click here to go to Google</a>"
        markdown_parts.append(link_html)

    if not markdown_parts:
        return {"markdown_string": "You did not request any content to be displayed. Please specify if you want to see an image, video, or link."}

    return {"markdown_string": "\n\n".join(markdown_parts)}

Kontrol channel suara dan audio

Bagian ini memberikan pola untuk mengontrol saluran suara dan audio, termasuk audio yang direkam sebelumnya, musik tunggu, dan setelan interupsi.

Catatan:

  • Encoding audio Linear16, mulaw, dan alaw didukung sebagai file audio.
  • Jika menggunakan bucket Cloud Storage yang termasuk dalam project cloud lain, Akun Layanan Customer Engagement Suite service-<PROJECT-NUMBER>@gcp-sa-ces.iam.gserviceaccount.com harus diberi izin storage.objects.get secara eksplisit ke bucket Cloud Storage target.
  • Anda dapat menggunakan argumen input interruptable untuk mengonfigurasi apakah audio yang direkam sebelumnya dapat diinterupsi oleh pengguna akhir.
  • Untuk pemutaran musik, Anda dapat menggunakan argumen input cancellable untuk menunjukkan bahwa pemutaran musik harus dihentikan saat respons baru dibuat oleh agen.

Memutar audio yang direkam sebelumnya khusus merek

Anda dapat mengonfigurasi agen untuk memutar file audio yang telah direkam sebelumnya sebelum memproses permintaan pengguna. Anda dapat menggunakannya untuk ucapan yang disetujui merek atau pengungkapan hukum wajib di awal sesi.

Gunakan "transcript": "yyy" untuk memberikan teks pemutaran audio kepada agen, dan pastikan agen memiliki konteks yang diperlukan untuk membuat respons berikutnya.

Penggunaan "interrupable": false memastikan bahwa pengguna tidak dapat mengganggu pemutaran audio.

def before_model_callback(
    callback_context: CallbackContext,
    llm_request: LlmRequest
) -> Optional[LlmResponse]:
  for part in callback_context.get_last_user_input():
    if part.text == "<event>session start</event>":
      return LlmResponse.from_parts(parts=[
          Part.from_json(data='{"audioUri": "gs://path/to/audio/file", "transcript": "transcript for the audio file", "interruptable": false}')
      ])
  return None

Memutar musik yang direkam sebelumnya saat menjalankan alat yang lambat (tidak ada interupsi)

Anda dapat mengonfigurasi agen untuk memutar musik saat alat "pemblokiran" yang lambat (seperti validasi dan aktivasi akun) sedang berjalan. Musik akan otomatis berhenti setelah alat menyelesaikan eksekusinya. Pengguna tidak dapat berinteraksi dengan agen saat musik diputar.

def after_model_callback(
    callback_context: CallbackContext,
    llm_response: LlmResponse
) -> Optional[LlmResponse]:
  for index, part in enumerate(llm_response.content.parts):
    if part.has_function_call("slow_tool"):
      play_music = Part.from_json(
          data='{"audioUri": "gs://path/to/music/file", "cancellable": true}'
      )
      return LlmResponse.from_parts(
          parts=llm_response.content.parts[:index] +
          [play_music] + llm_response.content.parts[index:]
      )
  return None

Memutar musik yang direkam sebelumnya saat menjalankan alat asinkron (izinkan interupsi)

Anda dapat mengonfigurasi agen untuk memutar musik saat menjalankan alat secara asinkron, seperti selama validasi dan aktivasi akun pengguna. Musik akan berakhir secara otomatis setelah alat asinkron selesai, asalkan pengguna belum menghentikannya. Pengguna akhir tetap dapat menghentikan musik kapan saja untuk melanjutkan interaksi dengan agen.

def before_model_callback(
    callback_context: CallbackContext,
    llm_request: LlmRequest
) -> Optional[LlmResponse]:
  for part in llm_request.contents[-1].parts:
    if part.has_function_response("async_tool"):
      text = Part.from_text(text="I'm submitting your order, it may take a while.")
      music = Part.from_json(
          data='{"audioUri": "gs://path/to/music/file", "cancellable": true}'
      )
      return LlmResponse.from_parts(parts=[text, music])
  return None

Melarang interupsi pengguna untuk respons tertentu

Anda dapat melarang pengguna menyela agen saat agen sedang membacakan informasi penting (seperti pernyataan penyangkalan hukum), tetapi mengizinkan penyelaan untuk bagian respons agen yang tersisa.

Tindakan ini menggunakan alat sistem customize_response.

Anda dapat menerapkan perilaku ini dengan dua cara, bergantung pada apakah Anda menginginkan hasil yang deterministik:

  1. Callback (Deterministik): Memaksa respons dari callback, seperti yang ditunjukkan dalam contoh.
  2. Petunjuk (Digerakkan agen): Minta agen untuk menggunakan alat customize_response dalam petunjuknya.
def before_model_callback(
    callback_context: CallbackContext,
    llm_request: LlmRequest
) -> Optional[LlmResponse]:
  for part in callback_context.get_last_user_input():
    if part.text == "<event>session start</event>":
      return LlmResponse.from_parts(parts=[
          Part.from_customized_response(
              content=("Hello, I'm Gemini. Please listen to the following legal "
                       "disclaimer: <LEGAL_DISCLAIMER>"),
              disable_barge_in=True
          ),
          Part.from_text("How can I help you today?")
      ])
  return None

Respons kustom untuk tanpa input

Jika waktu tunggu agen habis saat menunggu input (lihat Waktu tunggu diam di setelan aplikasi agen), respons generatif akan digunakan secara default. Namun, Anda dapat memeriksa apakah input diterima oleh pengguna dalam callback model sebelum dan memberikan respons secara bersyarat.

def before_model_callback(
    callback_context: CallbackContext,
    llm_request: LlmRequest
) -> Optional[LlmResponse]:
  for part in callback_context.get_last_user_input():
    if part.text:
      if "no user activity detected" in part.text:
        return LlmResponse.from_parts(parts=[
            Part.from_text(text="Hi, are you still there?")
        ])

  return None

Penanganan error

Bagian ini memberikan pola untuk menangani error alat.

Transfer ke agen lain jika alat gagal

Jika eksekusi alat tertentu gagal, Anda dapat menyerahkan percakapan ke agen lain secara deterministik. Hal ini merupakan jaminan keamanan penting untuk melindungi pengalaman pengguna selama error runtime.

def before_model_callback(
    callback_context: CallbackContext,
    llm_request: LlmRequest
) -> Optional[LlmResponse]:
  for part in llm_request.contents[-1].parts:
    if (part.has_function_response('authentication') and
        'error' in part.function_response.response['result']):
      return LlmResponse.from_parts(parts=[
          Part.from_text('Sorry something went wrong, let me transfer you to another agent.'),
          Part.from_agent_transfer(agent='escalation agent')
      ])
  return None

Menghentikan sesi dengan baik saat alat gagal

Jika eksekusi alat tertentu gagal, Anda dapat menghentikan sesi dengan benar. Hal ini dapat mencegah loop tak terbatas dan respons yang membingungkan saat terjadi kegagalan alat penting.

Contoh callback:

def before_model_callback(
    callback_context: CallbackContext,
    llm_request: LlmRequest
) -> Optional[LlmResponse]:
  for part in llm_request.contents[-1].parts:
    if (part.has_function_response('authentication') and
        'error' in part.function_response.response['result']):
      return LlmResponse.from_parts(parts=[
          Part.from_text('Sorry something went wrong, please call back later.'),
          Part.from_end_session(reason='Failure during user authentication.')
      ])
  return None

Konteks dan variabel

Bagian ini memberikan pola untuk menggunakan variabel konteks.

Meneruskan variabel konteks ke alat OpenAPI

AI yang dipersonalisasi memerlukan alat untuk mengakses data sesi pengguna. Mengandalkan model untuk mengingat dan meneruskan detail penting secara manual seperti ID sesi atau variabel pengguna pada dasarnya tidak dapat diandalkan dan lambat. Sebagai gantinya, agen dapat meneruskan variabel konteks tertentu ke alat OpenAPI. Anda dapat menggunakan x-ces-session-context untuk menunjukkan bahwa nilai tidak perlu dihasilkan oleh model (dan skemanya tidak terlihat oleh model), tetapi berasal dari variabel konteks.

Tabel berikut mencantumkan nilai yang tersedia:

Nilai Deskripsi
$context.project_id Google Cloud Project ID.
$context.project_number Nomor project Google Cloud .
$context.location Lokasi (region) agen.
$context.app_id ID aplikasi agen.
$context.session_id ID unik untuk sesi.
$context.variables Semua nilai variabel konteks sebagai objek.
$context.variables.variable_name Nilai variabel konteks tertentu. Ganti variable_name dengan nama variabel.
openapi: 3.0.0
info:
  title: test-title
  description: test-description
  version: 1.0.0
paths:
  /test-path/{session_id}:
    post:
      parameters:
      - name: session_id
        in: path
        description: The session ID.
        required: true
        schema:
          type: string
        x-ces-session-context: $context.session_id
      - name: test_variable
        in: query
        description: Specific session variable.
        required: true
        schema:
          type: string
        x-ces-session-context: $context.variables.test_variable
      requestBody:
        description: test-description
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SessionParams'
      responses:
        '200':
          description: test-response-description
          content:
            application/json:
             schema:
                type: object
                properties:
                  result:
                    type: string
components:
  schemas:
    SessionParams:
      type: object
      description: all context variables
      x-ces-session-context: $context.variables

Perintah dinamis

Anda dapat membuat agen yang memiliki perintah dinamis yang dikirim ke model dengan menggunakan:

  • Variabel yang dapat digunakan untuk mengontrol variasi perintah.
  • Petunjuk yang menyertakan referensi ke variabel.
  • Alat yang dapat memperbarui variabel berdasarkan detail percakapan.
  • before_model_callback.

Misalnya, Anda dapat mengubah petunjuk agen berdasarkan apakah pengguna adalah pengacara atau perompak:

Variabel:

Nama variabel Nilai default
current_instructions Anda adalah Gemini dan Anda bekerja untuk Google.
lawyer_instructions Anda adalah seorang pengacara dan tugas Anda adalah menceritakan lelucon gaya lelucon bapak-bapak, tetapi dengan sentuhan pengacara.
pirate_instructions Anda adalah bajak laut dan tugas Anda adalah menceritakan lelucon sebagai bajak laut.
nama pengguna Tidak diketahui

Petunjuk:

The current user is: {username}
You can use {@TOOL: update_username} to update the user's name if they provide
it.

Follow the current instruction set below exactly.

{current_instructions}

Alat Python:

from typing import Optional

def update_username(username: str) -> Optional[str]:
  """Updates the current user's name."""
  set_variable("username", username)

Callback:

def before_model_callback(
  callback_context: CallbackContext,
  llm_request: LlmRequest
) -> Optional[LlmResponse]:
  username = callback_context.get_variable("username", None)

  if username == "Jenn":
    new_instructions = callback_context.get_variable("pirate_instructions")

  elif username == "Gary":
    new_instructions = callback_context.get_variable("lawyer_instructions")

  callback_context.set_variable("current_instructions", new_instructions)