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)-> outputctool_2(arg_c)-> outputdtool_3(arg_d)-> outpute
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 mengekstrakarg_c - Model -> Agen memprediksi
tool_2(arg_c) tool_2_response.json()dikembalikan- Agen menafsirkan
tool_2_response.json()dan mengekstrakarg_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:
- Periksa panggilan alat
end_sessiondalam respons agen. - Buat bagian alat
post_call_logging. - Sisipkan panggilan alat
post_call_loggingsebelum panggilan alatend_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.comharus diberi izinstorage.objects.getsecara eksplisit ke bucket Cloud Storage target. - Anda dapat menggunakan argumen input
interruptableuntuk mengonfigurasi apakah audio yang direkam sebelumnya dapat diinterupsi oleh pengguna akhir. - Untuk pemutaran musik, Anda dapat menggunakan argumen input
cancellableuntuk 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:
- Callback (Deterministik): Memaksa respons dari callback, seperti yang ditunjukkan dalam contoh.
- Petunjuk (Digerakkan agen): Minta agen untuk menggunakan alat
customize_responsedalam 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)