Alat kode Python

Anda dapat menyediakan kode Python inline sebagai alat untuk agen Anda, yang memberikan fleksibilitas untuk memperluas kemampuan agen Anda. Kode ini dapat menerima input yang diberikan oleh agen, dan menampilkan hasil yang digunakan oleh agen dalam percakapan. Anda dapat menerapkan logika kustom apa pun, terhubung ke API atau database eksklusif, dan memastikan hasil deterministik untuk tugas yang memerlukan presisi.

Nama dan deskripsi

Saat membuat alat, nama alat dan nama fungsi utama yang akan dipanggil harus sama dalam snake case.

Docstring adalah bagian penting dalam menentukan alat Python. Docstring fungsi digunakan sebagai deskripsi alat, yang diberikan kepada agen yang menggunakan alat tersebut. Anda harus menganggap docstring sebagai ekstensi perintah. Docstring yang jelas, deskriptif, dan terstruktur dengan baik secara langsung memengaruhi seberapa baik model memahami fungsi alat Anda, kapan harus menggunakannya, dan argumen apa yang harus diberikan. Hal ini merupakan kunci untuk mencapai pemilihan alat yang andal dan akurat.

Lingkungan

Dalam kode alat Python, Anda memiliki akses ke class dan fungsi tertentu yang membantu Anda menulis kode. Untuk mengetahui informasi selengkapnya, lihat Referensi runtime Python.

Misalnya, objek context adalah variabel yang tersedia secara global yang memberikan snapshot status percakapan saat ini. Anda tidak perlu mengimpor atau menentukannya sebagai parameter; Anda dapat mengaksesnya secara langsung. Kolom ini berisi informasi berharga untuk menjalankan logika yang kompleks.

Berikut perincian kunci yang tersedia dalam objek konteks:

  • function_call_id: ID unik untuk panggilan alat tertentu yang sedang dieksekusi.
  • user_content: Kamus yang berisi pesan terbaru dari pengguna, termasuk teks dan peran. Ini adalah salah satu atribut yang paling umum digunakan.
  • state: Kamus yang mewakili status sesi. Anda dapat menggunakannya untuk menyimpan dan mengambil variabel yang perlu dipertahankan di beberapa giliran dalam percakapan (profil pengguna, isi keranjang belanja, dan sebagainya).
  • events: Daftar semua peristiwa dalam histori percakapan hingga saat ini, yang memungkinkan Anda membuat alat dengan kesadaran kontekstual yang lebih kompleks.
  • session_id: ID unik untuk seluruh sesi percakapan.
  • invocation_id: ID unik untuk giliran percakapan saat ini.
  • agent_name: Nama agen yang menjalankan alat.

Alat Python yang memanggil alat lain

Saat menentukan alat kode Python, Anda dapat secara eksplisit memanggil alat lain yang ditentukan dalam aplikasi agen. Misalnya, jika Anda memiliki alat OpenAPI bernama crm_service_get_cart_information, Anda dapat memanggil alat tersebut dengan kode berikut:

# Deterministically call another tool from this tool.
# This syntax for OpenAPI spec tool is:
# tools.<tool_name>_<endpoint_name>({tool_args})
res = tools.crm_service_get_cart_information({})

Contoh kode

Bagian berikut memberikan contoh.

Mendapatkan input pengguna terakhir

Contoh ini menunjukkan kemampuan mendasar: mengakses pesan terbaru pengguna. Alat ini memeriksa objek context.user_content dan mengekstrak teks dari giliran pengguna terakhir. Pola ini sangat penting untuk alat apa pun yang perlu melakukan tindakan berdasarkan langsung pada apa yang baru saja dikatakan pengguna.

from typing import Optional

# Docstrings in tools are important because they are directly
# sent to the model as the description for the tool. You should
# think of docstrings as an extension of prompting. Clear and
# descriptive docstrings will yield higher quality tool
# selection from the model.
def get_last_user_utterance() -> Optional[str]:
  """
  Retrieves the most recent message sent by the user from the conversation history.

  Returns:
    The text of the last user message, or None if no user messages are found.
  """
  # The 'context.user_content' contains the last input data
  # provided by the user.
  # We can filter it to find only the text input from the user.
  user_messages = [
    part["text"] for part in context.user_content["parts"]
    if context.user_content["role"] == "user"
  ]

  if user_messages:
    # The most recent message is the first one in the list.
    return user_messages[0]

  return None

Mendapatkan dan memperbarui variabel

Model bahasa tidak dapat langsung mengubah status sesi. Hal ini disengaja, karena memastikan bahwa perubahan status ditangani dengan cara yang terkontrol dan dapat diprediksi. Status hanya dapat diubah melalui dua mekanisme: Alat Python atau Callback.

Contoh ini menunjukkan cara alat Python dapat mengelola status. Alat ini pertama-tama membaca customer_profile saat ini dari context.state. Kemudian, ia menjalankan logika bisnisnya (menambahkan poin) dan menulis kembali profil yang diperbarui ke context.state. Status baru ini kemudian akan tersedia untuk agen dan alat lainnya selama sesi berlangsung.

from pydantic import BaseModel, Field
from typing import Optional, Dict, Any

# Using Pydantic defines the expected structure of your state variables. This makes your code more reliable and easier to
# debug.
class CustomerProfile(BaseModel):
  email: Optional[str] = None
  loyalty_points: int = Field(default=0, ge=0) # Must be >= 0
  plan: str = "Standard"

# Docstrings in tools are important because they are directly
# sent to the model as the description for the tool. You should
# think of docstrings as an extension of prompting. Clear and
# descriptive docstrings will yield higher quality tool
# selection from the model.
def update_customer_loyalty_points(points_to_add: int) -> Dict[str, Any]:
  """
  Adds loyalty points to the customer's profile and returns the updated profile.

  Args:
    points_to_add: The number of loyalty points to add to the existing total.

  Returns:
    A dictionary containing the customer's updated profile information.
  """
  # 1. Get the current profile data from the session state.
  # The .get() method safely returns an empty dict if
  # 'customer_profile' doesn't exist.
  current_profile_data = context.state.get("customer_profile", {})

  # 2. Load the data into a Pydantic model for validation and easy access.
  profile = CustomerProfile(**current_profile_data)

  # 3. Perform the business logic.
  # Print statements can be used for debugging and will show
  # up in the tracing details.
  profile.loyalty_points += points_to_add
  print(f"Updated loyalty points to: {profile.loyalty_points}")

  # 4. Save the updated data back into the session state.
  # .model_dump() converts the Pydantic model back to a
  # dictionary.
  context.state["customer_profile"] = profile.model_dump()

  return context.state["customer_profile"]

Permintaan jaringan eksternal

Alat Python dapat membuat permintaan jaringan eksternal, yang berguna untuk mengambil data real-time atau berintegrasi dengan layanan pihak ketiga yang tidak memiliki spesifikasi OpenAPI. Hal ini memberikan alternatif yang fleksibel untuk menggunakan alat berbasis OpenAPI. Contoh ini menggunakan library permintaan standar (tersedia di lingkungan) untuk memanggil API publik dan mengambil fakta acak.

from typing import Optional

# Docstrings in tools are important because they are directly sent to the model as the
# description for the tool. You should think of docstrings as an extension of prompting.
# Clear and descriptive docstrings will yield higher quality tool selection from the model.

def get_random_fact() -> Optional[str]:
  """
  Fetches a random fact from a public API.

  Returns:
      A string containing the fact on success, or None if an error occurs.
  """
  # The 'ces_requests' library is inspired by 'requests', a  standard and powerful way in Python
  # to make HTTP network calls to any external API, just like you would with `curl` or a web browser.
  url = "https://uselessfacts.jsph.pl/api/v2/facts/random"

  try:
      # This example calls a public API that is completely open and requires no authentication
      # (like an API key). Many other APIs for services like weather or e-commerce require you
      # to send credentials, often as an API key in the request headers or parameters.
      res = ces_requests.get(url=url, json=request_body, headers=headers)

      # Example POST request
      #res = ces_requests.post(url=url, json=request_body, headers=headers)

      # This is a standard practice with 'ces_requests' to check if the call was successful. It will
      # raise an error for statuses like 404 or 500.
      res.raise_for_status()

      fact_data = res.json()
      return fact_data.get("text")

  except:
      return None