Membuat agen data menggunakan HTTP dan Python

Halaman ini memandu Anda menggunakan Python untuk membuat permintaan HTTP ke Conversational Analytics API (diakses melalui geminidataanalytics.googleapis.com).

Contoh kode Python di halaman ini menunjukkan cara menyelesaikan tugas berikut:

Versi lengkap kode contoh disertakan di akhir halaman, beserta fungsi pembantu yang digunakan untuk men-streaming respons API.

Mengonfigurasi setelan awal dan autentikasi

Contoh kode Python berikut melakukan tugas-tugas ini:

  • Mengimpor library Python yang diperlukan
  • Mendapatkan token akses untuk autentikasi HTTP menggunakan Google Cloud CLI
  • Menentukan variabel untuk project penagihan dan petunjuk sistem
from pygments import highlight, lexers, formatters
import pandas as pd
import json as json_lib
import requests
import json
import altair as alt
import IPython
from IPython.display import display, HTML
import google.auth
from google.auth.transport.requests import Request

from google.colab import auth
auth.authenticate_user()

access_token = !gcloud auth application-default print-access-token
headers = {
    "Authorization": f"Bearer {access_token[0]}",
    "Content-Type": "application/json",
}

billing_project = 'YOUR-BILLING-PROJECT'
system_instruction = 'YOUR-SYSTEM-INSTRUCTIONS'

Ganti nilai sampel sebagai berikut:

  • YOUR-BILLING-PROJECT: ID project penagihan tempat Anda mengaktifkan API yang diperlukan.
  • YOUR-SYSTEM-INSTRUCTIONS: Instruksi sistem untuk memandu perilaku agen dan menyesuaikannya dengan kebutuhan data Anda. Misalnya, Anda dapat menggunakan petunjuk sistem untuk menentukan istilah bisnis, mengontrol panjang respons, atau menetapkan pemformatan data. Idealnya, tentukan petunjuk sistem menggunakan format YAML yang direkomendasikan dalam Menulis petunjuk sistem yang efektif untuk memberikan panduan yang mendetail dan terstruktur.

Melakukan autentikasi ke Looker

Jika Anda berencana untuk terhubung ke sumber data Looker, Anda harus melakukan autentikasi ke instance Looker.

Menggunakan kunci API

Contoh kode Python berikut menunjukkan cara mengautentikasi agen Anda ke instance Looker menggunakan kunci API.

looker_credentials = {
    "oauth": {
        "secret": {
            "client_id": "YOUR-LOOKER-CLIENT-ID",
            "client_secret": "YOUR-LOOKER-CLIENT-SECRET",
        }
    }
}

Ganti nilai sampel sebagai berikut:

  • YOUR-LOOKER-CLIENT-ID: ID klien kunci API Looker yang Anda buat.
  • YOUR-LOOKER-CLIENT-SECRET: Rahasia klien dari kunci API Looker yang Anda buat.

Menggunakan token akses

Contoh kode Python berikut menunjukkan cara mengautentikasi agen Anda ke instance Looker menggunakan token akses.

looker_credentials = {
    "oauth": {
        "token": {
            "access_token": "YOUR-TOKEN",
        }
    }
}

Ganti nilai sampel sebagai berikut:

  • YOUR-TOKEN: Nilai access_token yang Anda buat untuk mengautentikasi ke Looker.

Menghubungkan ke sumber data

Contoh kode Python berikut menunjukkan cara menentukan sumber data Looker, BigQuery, atau Looker Studio yang akan digunakan oleh agen Anda.

Menghubungkan ke data Looker

Contoh kode berikut menentukan koneksi ke Jelajah Looker. Untuk membuat koneksi dengan instance Looker, pastikan Anda telah membuat kunci API Looker, seperti yang dijelaskan dalam Mengautentikasi dan menghubungkan ke sumber data dengan Conversational Analytics API.

looker_data_source = {
    "looker": {
        "explore_references": {
            "looker_instance_uri": "https://your_company.looker.com",
            "lookml_model": "your_model",
            "explore": "your_explore",
       },
    }
}

Ganti nilai sampel sebagai berikut:

  • https://your_company.looker.com: URL lengkap instance Looker Anda.
  • your_model: Nama model LookML yang menyertakan Eksplorasi yang ingin Anda hubungkan.
  • your_explore: Nama Eksplorasi Looker yang ingin Anda kueri oleh agen data.

Menghubungkan ke data BigQuery

Dengan Conversational Analytics API, Anda dapat terhubung ke dan membuat kueri hingga 10 tabel BigQuery sekaligus.

Contoh kode berikut menentukan koneksi ke tabel BigQuery.

bigquery_data_sources = {
    "bq": {
        "tableReferences": [
            {
                "projectId": "bigquery-public-data",
                "datasetId": "san_francisco",
                "tableId": "street_trees",
            }
        ]
    }
}

Ganti nilai sampel sebagai berikut:

  • bigquery-public-data: ID project Google Cloud yang berisi set data dan tabel BigQuery yang ingin Anda hubungkan. Untuk terhubung ke set data publik, tentukan bigquery-public-data.
  • san_francisco: ID set data BigQuery.
  • street_trees: ID tabel BigQuery.

Menghubungkan ke data Looker Studio

Contoh kode berikut menentukan koneksi ke sumber data Looker Studio.

looker_studio_data_source = {
    "studio":{
        "studio_references": [
            {
              "studio_datasource_id": "studio_datasource_id"
            }
        ]
    }
}

Ganti studio_datasource_id dengan ID sumber data.

Membuat agen data

Contoh kode berikut menunjukkan cara membuat agen data dengan mengirim permintaan POST HTTP ke endpoint pembuatan agen data. Payload permintaan mencakup detail berikut:

Anda juga dapat mengaktifkan analisis lanjutan dengan Python secara opsional dengan menyertakan parameter options dalam payload permintaan.

data_agent_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}/dataAgents"

data_agent_id = "data_agent_1"

data_agent_payload = {
      "name": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}", # Optional
      "description": "This is the description of data_agent_1.", # Optional

      "data_analytics_agent": {
          "published_context": {
              "datasource_references": bigquery_data_sources,
              "system_instruction": system_instruction,
              # Optional: To enable advanced analysis with Python, include the following options block:
              "options": {
                  "analysis": {
                      "python": {
                          "enabled": True
                      }
                  }
              }
          }
      }
  }

params = {"data_agent_id": data_agent_id} # Optional

data_agent_response = requests.post(
    data_agent_url, params=params, json=data_agent_payload, headers=headers
)

if data_agent_response.status_code == 200:
    print("Data Agent created successfully!")
    print(json.dumps(data_agent_response.json(), indent=2))
else:
    print(f"Error creating Data Agent: {data_agent_response.status_code}")
    print(data_agent_response.text)

Ganti nilai sampel sebagai berikut:

  • data_agent_1: ID unik untuk agen data. Nilai ini digunakan dalam nama resource agen dan sebagai parameter kueri URL data_agent_id.
  • This is the description of data_agent_1.: Deskripsi untuk agen data.

Buat percakapan

Contoh kode berikut menunjukkan cara membuat percakapan dengan agen data Anda.

conversation_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}/conversations"

data_agent_id = "data_agent_1"
conversation_id = "conversation_1"

conversation_payload = {
    "agents": [
        f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}"
    ],
    "name": f"projects/{billing_project}/locations/{location}/conversations/{conversation_id}"
}
params = {
    "conversation_id": conversation_id
}

conversation_response = requests.post(conversation_url, headers=headers, params=params, json=conversation_payload)

if conversation_response.status_code == 200:
    print("Conversation created successfully!")
    print(json.dumps(conversation_response.json(), indent=2))
else:
    print(f"Error creating Conversation: {conversation_response.status_code}")
    print(conversation_response.text)

Ganti nilai sampel sebagai berikut:

  • data_agent_1: ID agen data, seperti yang ditentukan dalam blok kode contoh di Membuat agen data.
  • conversation_1: ID unik untuk percakapan.

Mengelola agen data dan percakapan

Contoh kode berikut menunjukkan cara mengelola agen data dan percakapan menggunakan Conversational Analytics API. Anda dapat melakukan tugas berikut:

Mendapatkan agen data

Contoh kode berikut menunjukkan cara mengambil agen data yang ada dengan mengirim permintaan HTTP GET ke URL resource agen data.

data_agent_id = "data_agent_1"
data_agent_url = f"{base_url}/v1alpha/projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}"

data_agent_response = requests.get(
    data_agent_url, headers=headers
)

if data_agent_response.status_code == 200:
    print("Fetched Data Agent successfully!")
    print(json.dumps(data_agent_response.json(), indent=2))
else:
    print(f"Error: {data_agent_response.status_code}")
    print(data_agent_response.text)

Pada contoh sebelumnya, ganti data_agent_1 dengan ID agen data yang ingin Anda ambil.

Mencantumkan agen data

Kode berikut menunjukkan cara mencantumkan semua agen data untuk project tertentu dengan mengirim permintaan GET HTTP ke endpoint dataAgents.

Untuk mencantumkan semua agen, Anda harus memiliki izin geminidataanalytics.dataAgents.list di project. Untuk mengetahui informasi selengkapnya tentang peran IAM yang menyertakan izin ini, lihat daftar peran yang telah ditetapkan.

billing_project = "YOUR-BILLING-PROJECT"
location = "global"
data_agent_url = f"{base_url}/v1alpha/projects/{billing_project}/locations/{location}/dataAgents"

data_agent_response = requests.get(
    data_agent_url, headers=headers
)

if data_agent_response.status_code == 200:
    print("Data Agent Listed successfully!")
    print(json.dumps(data_agent_response.json(), indent=2))
else:
    print(f"Error Listing Data Agent: {data_agent_response.status_code}")

Ganti YOUR-BILLING-PROJECT dengan ID project penagihan Anda.

Memperbarui agen data

Contoh kode berikut menunjukkan cara memperbarui agen data dengan mengirim permintaan HTTP PATCH ke URL resource agen data. Payload permintaan mencakup nilai baru untuk kolom yang ingin Anda ubah, dan parameter permintaan mencakup parameter updateMask, yang menentukan kolom yang akan diupdate.

data_agent_id = "data_agent_1"
billing_project = "YOUR-BILLING-PROJECT"
location = "global"

data_agent_url = f"{base_url}/v1alpha/projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}"

payload = {
    "description": "Updated description of the data agent.",
    "data_analytics_agent": {
        "published_context": {
            "datasource_references": bigquery_data_sources,
            "system_instruction": system_instruction
        }
    },
}

fields = ["description", "data_analytics_agent"]
params = {
    "updateMask": ",".join(fields)
}

data_agent_response = requests.patch(
    data_agent_url, headers=headers, params=params, json=payload
)

if data_agent_response.status_code == 200:
    print("Data Agent updated successfully!")
    print(json.dumps(data_agent_response.json(), indent=2))
else:
    print(f"Error Updating Data Agent: {data_agent_response.status_code}")
    print(data_agent_response.text)

Ganti nilai sampel sebagai berikut:

  • data_agent_1: ID agen data yang ingin Anda perbarui.
  • YOUR-BILLING-PROJECT: ID project penagihan Anda.
  • Updated description of the data agent.: Deskripsi baru untuk agen data.

Menetapkan kebijakan IAM untuk agen data

Untuk membagikan agen, Anda dapat menggunakan metode setIamPolicy untuk menetapkan peran IAM kepada pengguna di agen tertentu. Contoh kode berikut menunjukkan cara melakukan panggilan POST ke URL agen data dengan payload yang menyertakan binding. Binding menentukan peran mana yang harus ditetapkan kepada pengguna mana.

billing_project = "YOUR-BILLING-PROJECT"
location = "global"
data_agent_id = "data_agent_1"
role = "roles/geminidataanalytics.dataAgentEditor"
users = "222larabrown@gmail.com, cloudysanfrancisco@gmail.com"

data_agent_url = f"{base_url}/v1alpha/projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}:setIamPolicy"

# Request body
payload = {
    "policy": {
        "bindings": [
            {
                "role": role,
                "members": [
                    f"user:{i.strip()}" for i in users.split(",")
                ]
            }
        ]
    }
}

data_agent_response = requests.post(
    data_agent_url, headers=headers, json=payload
)

if data_agent_response.status_code == 200:
    print("IAM Policy set successfully!")
    print(json.dumps(data_agent_response.json(), indent=2))
else:
    print(f"Error setting IAM policy: {data_agent_response.status_code}")
    print(data_agent_response.text)

Ganti nilai sampel sebagai berikut:

  • YOUR-BILLING-PROJECT: ID project penagihan Anda.
  • data_agent_1: ID agen data yang ingin Anda tetapkan kebijakan IAM-nya.
  • 222larabrown@gmail.com, cloudysanfrancisco@gmail.com: Daftar email pengguna yang dipisahkan koma yang ingin Anda beri peran tertentu.

Mendapatkan kebijakan IAM untuk agen data

Contoh kode berikut menunjukkan cara mengambil kebijakan IAM untuk agen data dengan mengirim permintaan HTTP POST ke URL agen data. Payload permintaan mencakup jalur agen data.

billing_project = "YOUR-BILLING-PROJECT"
location = "global"
data_agent_id = "data_agent_1"

data_agent_url = f"{base_url}/v1alpha/projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}:getIamPolicy"

# Request body
payload = {
    "resource": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}"
}

data_agent_response = requests.post(
    data_agent_url, headers=headers, json=payload
)

if data_agent_response.status_code == 200:
    print("IAM Policy fetched successfully!")
    print(json.dumps(data_agent_response.json(), indent=2))
else:
    print(f"Error fetching IAM policy: {data_agent_response.status_code}")
    print(data_agent_response.text)

Ganti nilai sampel sebagai berikut:

  • YOUR-BILLING-PROJECT: ID project penagihan Anda.
  • data_agent_1: ID agen data yang ingin Anda dapatkan kebijakan IAM-nya.

Menghapus agen data

Contoh kode berikut menunjukkan cara menghapus sementara agen data dengan mengirim permintaan HTTP DELETE ke URL resource agen data. Penghapusan sementara berarti agen dihapus, tetapi masih dapat diambil dalam waktu 30 hari.

billing_project = "YOUR-BILLING-PROJECT"
location = "global"
data_agent_id = "data_agent_1"

data_agent_url = f"{base_url}/v1alpha/projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}"

data_agent_response = requests.delete(
    data_agent_url, headers=headers
)

if data_agent_response.status_code == 200:
    print("Data Agent deleted successfully!")
    print(json.dumps(data_agent_response.json(), indent=2))
else:
    print(f"Error Deleting Data Agent: {data_agent_response.status_code}")
    print(data_agent_response.text)

Ganti nilai sampel sebagai berikut:

  • YOUR-BILLING-PROJECT: ID project penagihan Anda.
  • data_agent_1: ID agen data yang ingin Anda hapus.

Mendapatkan percakapan

Contoh kode berikut menunjukkan cara mengambil percakapan yang ada dengan mengirim permintaan HTTP GET ke URL resource percakapan.

billing_project = "YOUR-BILLING-PROJECT"
location = "global"
conversation_id = "conversation_1"

conversation_url = f"{base_url}/v1alpha/projects/{billing_project}/locations/{location}/conversations/{conversation_id}"

conversation_response = requests.get(conversation_url, headers=headers)

# Handle the response
if conversation_response.status_code == 200:
    print("Conversation fetched successfully!")
    print(json.dumps(conversation_response.json(), indent=2))
else:
    print(f"Error while fetching conversation: {conversation_response.status_code}")
    print(conversation_response.text)

Ganti nilai sampel sebagai berikut:

  • YOUR-BILLING-PROJECT: ID project penagihan Anda.
  • conversation_1: ID percakapan yang ingin Anda ambil.

Membuat daftar percakapan

Contoh kode berikut menunjukkan cara mencantumkan percakapan untuk project tertentu dengan mengirim permintaan GET HTTP ke endpoint conversations.

Secara default, metode ini menampilkan percakapan yang Anda buat. Admin (pengguna dengan peran IAM cloudaicompanion.topicAdmin) dapat melihat semua percakapan dalam project.

billing_project = "YOUR-BILLING-PROJECT"
location = "global"
conversation_url = f"{base_url}/v1alpha/projects/{billing_project}/locations/{location}/conversations"

conversation_response = requests.get(conversation_url, headers=headers)

# Handle the response
if conversation_response.status_code == 200:
    print("Conversation fetched successfully!")
    print(json.dumps(conversation_response.json(), indent=2))
else:
    print(f"Error while fetching conversation: {conversation_response.status_code}")
    print(conversation_response.text)

Ganti YOUR-BILLING-PROJECT dengan ID project penagihan tempat Anda mengaktifkan API yang diperlukan.

Mencantumkan pesan dalam percakapan

Contoh kode berikut menunjukkan cara mencantumkan semua pesan dalam percakapan dengan mengirim permintaan GET HTTP ke endpoint messages percakapan.

Untuk mencantumkan pesan, Anda harus memiliki izin cloudaicompanion.topics.get dalam percakapan.

billing_project = "YOUR-BILLING-PROJECT"
location = "global"

conversation_id = "conversation_1"

conversation_url = f"{base_url}/v1alpha/projects/{billing_project}/locations/{location}/conversations/{conversation_id}/messages"

conversation_response = requests.get(conversation_url, headers=headers)

# Handle the response
if conversation_response.status_code == 200:
    print("Conversation fetched successfully!")
    print(json.dumps(conversation_response.json(), indent=2))
else:
    print(f"Error while fetching conversation: {conversation_response.status_code}")
    print(conversation_response.text)

Ganti nilai sampel sebagai berikut:

  • YOUR-BILLING-PROJECT: ID project penagihan Anda.
  • conversation_1: ID percakapan yang ingin Anda lihat pesannya.

Menggunakan API untuk mengajukan pertanyaan

Setelah membuat agen data dan percakapan, Anda dapat mengajukan pertanyaan tentang data Anda.

Conversational Analytics API mendukung percakapan multi-giliran, yang memungkinkan pengguna mengajukan pertanyaan lanjutan yang didasarkan pada konteks sebelumnya. API menyediakan metode berikut untuk mengelola histori percakapan:

  • Chat berstatus: Google Cloud menyimpan dan mengelola histori percakapan. Chat dengan status memiliki banyak giliran, karena API mempertahankan konteks dari pesan sebelumnya. Anda hanya perlu mengirim pesan saat ini untuk setiap giliran.
  • Chat tanpa status: Aplikasi Anda mengelola histori percakapan. Anda harus menyertakan pesan sebelumnya yang relevan dengan setiap pesan baru. Untuk contoh mendetail tentang cara mengelola percakapan multi-giliran dalam mode stateless, lihat Membuat percakapan multi-giliran stateless.

Chat dengan status

Mengirim permintaan chat stateful dengan referensi percakapan

Contoh kode berikut menunjukkan cara mengajukan pertanyaan ke API menggunakan conversation yang Anda tentukan pada langkah-langkah sebelumnya. Contoh ini menggunakan fungsi helper get_stream untuk melakukan streaming respons.

chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}:chat"

data_agent_id = "data_agent_1"
conversation_id = "conversation_1"

# Construct the payload
chat_payload = {
    "parent": f"projects/{billing_project}/locations/global",
    "messages": [
        {
            "userMessage": {
                "text": "Make a bar graph for the top 5 states by the total number of airports"
            }
        }
    ],
    "conversation_reference": {
        "conversation": f"projects/{billing_project}/locations/{location}/conversations/{conversation_id}",
        "data_agent_context": {
            "data_agent": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}",
            # "credentials": looker_credentials
        }
    }
}

# Call the get_stream function to stream the response
get_stream(chat_url, chat_payload)

Ganti nilai sampel sebagai berikut:

  • data_agent_1: ID agen data, seperti yang ditentukan dalam blok kode contoh di Membuat agen data.
  • conversation_1: ID unik untuk percakapan.
  • Make a bar graph for the top 5 states by the total number of airports digunakan sebagai perintah contoh.

Chat tanpa status

Mengirim permintaan chat stateless dengan referensi agen data

Contoh kode berikut menunjukkan cara mengajukan pertanyaan tanpa status ke API menggunakan agen data yang Anda tentukan pada langkah-langkah sebelumnya. Contoh ini menggunakan fungsi helper get_stream untuk melakukan streaming respons.

chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}:chat"

data_agent_id = "data_agent_1"

# Construct the payload
chat_payload = {
    "parent": f"projects/{billing_project}/locations/global",
    "messages": [
        {
            "userMessage": {
                "text": "Make a bar graph for the top 5 states by the total number of airports"
            }
        }
    ],
    "data_agent_context": {
        "data_agent": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}",
        # "credentials": looker_credentials
    }
}

# Call the get_stream function to stream the response
get_stream(chat_url, chat_payload)

Ganti nilai sampel sebagai berikut:

  • data_agent_1: ID agen data, seperti yang ditentukan dalam blok kode contoh di Membuat agen data.
  • Make a bar graph for the top 5 states by the total number of airports digunakan sebagai perintah contoh.

Mengirim permintaan chat tanpa status dengan konteks inline

Contoh kode berikut menunjukkan cara mengajukan pertanyaan stateless ke API menggunakan konteks inline. Contoh ini menggunakan fungsi helper get_stream untuk mengalirkan respons dan menggunakan sumber data BigQuery sebagai contoh.

Anda juga dapat mengaktifkan analisis lanjutan dengan Python secara opsional dengan menyertakan parameter options dalam payload permintaan.

chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/global:chat"

# Construct the payload
chat_payload = {
    "parent": f"projects/{billing_project}/locations/global",
    "messages": [
        {
            "userMessage": {
                "text": "Make a bar graph for the top 5 states by the total number of airports"
            }
        }
    ],
    "inline_context": {
        "datasource_references": bigquery_data_sources,
          # Optional: To enable advanced analysis with Python, include the following options block:
          "options": {
              "analysis": {
                  "python": {
                      "enabled": True
                  }
              }
          }
    }
}

# Call the get_stream function to stream the response
get_stream(chat_url, chat_payload)

Membuat percakapan multi-giliran tanpa status

Untuk mengajukan pertanyaan lanjutan dalam percakapan tanpa status, aplikasi Anda harus mengelola konteks percakapan dengan mengirimkan seluruh histori pesan dengan setiap permintaan baru. Bagian berikut menunjukkan cara menentukan dan memanggil fungsi bantuan untuk membuat percakapan multi-giliran:

Mengirim permintaan multi-turn

Fungsi bantuan multi_turn_Conversation berikut mengelola konteks percakapan dengan menyimpan pesan dalam daftar. Hal ini memungkinkan Anda mengirim pertanyaan lanjutan yang didasarkan pada giliran sebelumnya. Dalam payload fungsi, Anda dapat mereferensikan agen data atau memberikan sumber data secara langsung dengan menggunakan konteks inline.

chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/global:chat"

# List that is used to track previous turns and is reused across requests
conversation_messages = []

data_agent_id = "data_agent_1"

# Helper function for calling the API
def multi_turn_Conversation(msg):

  userMessage = {
      "userMessage": {
          "text": msg
      }
  }

  # Send a multi-turn request by including previous turns and the new message
  conversation_messages.append(userMessage)

  # Construct the payload
  chat_payload = {
      "parent": f"projects/{billing_project}/locations/global",
      "messages": conversation_messages,
      # Use a data agent reference
      "data_agent_context": {
          "data_agent": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}",
          # "credentials": looker_credentials
      },
      # Use inline context
      # "inline_context": {
      #     "datasource_references": bigquery_data_sources,
      # }
  }

  # Call the get_stream_multi_turn helper function to stream the response
  get_stream_multi_turn(chat_url, chat_payload, conversation_messages)

Pada contoh sebelumnya, ganti data_agent_1 dengan ID agen data, seperti yang ditentukan dalam blok kode contoh di Membuat agen data.

Anda dapat memanggil fungsi bantuan multi_turn_Conversation untuk setiap giliran percakapan. Contoh kode berikut menunjukkan cara mengirim permintaan awal, lalu permintaan lanjutan yang didasarkan pada respons sebelumnya.

# Send first-turn request
multi_turn_Conversation("Which species of tree is most prevalent?")

# Send follow-up-turn request
multi_turn_Conversation("Can you show me the results as a bar chart?")

Dalam contoh sebelumnya, ganti nilai sampel sebagai berikut:

  • Which species of tree is most prevalent?: Pertanyaan dalam bahasa alami untuk dikirim ke agen data.
  • Can you show me the results as a bar chart?: Pertanyaan lanjutan yang dibuat berdasarkan atau menyempurnakan pertanyaan sebelumnya.

Memproses respons

Fungsi get_stream_multi_turn berikut memproses respons API streaming. Fungsi ini mirip dengan fungsi helper get_stream, tetapi menyimpan respons dalam daftar conversation_messages untuk menyimpan konteks percakapan untuk giliran berikutnya.

def get_stream_multi_turn(url, json, conversation_messages):
    s = requests.Session()

    acc = ''

    with s.post(url, json=json, headers=headers, stream=True) as resp:
        for line in resp.iter_lines():
            if not line:
                continue

            decoded_line = str(line, encoding='utf-8')

            if decoded_line == '[{':
                acc = '{'
            elif decoded_line == '}]':
                acc += '}'
            elif decoded_line == ',':
                continue
            else:
                acc += decoded_line

            if not is_json(acc):
                continue

            data_json = json_lib.loads(acc)
            # Store the response that will be used in the next iteration
            conversation_messages.append(data_json)

            if not 'systemMessage' in data_json:
                if 'error' in data_json:
                    handle_error(data_json['error'])
                continue

            if 'text' in data_json['systemMessage']:
                handle_text_response(data_json['systemMessage']['text'])
            elif 'schema' in data_json['systemMessage']:
                handle_schema_response(data_json['systemMessage']['schema'])
            elif 'data' in data_json['systemMessage']:
                handle_data_response(data_json['systemMessage']['data'])
            elif 'chart' in data_json['systemMessage']:
                handle_chart_response(data_json['systemMessage']['chart'])
            else:
                colored_json = highlight(acc, lexers.JsonLexer(), formatters.TerminalFormatter())
                print(colored_json)
            print('\n')
            acc = ''

Contoh kode end-to-end

Contoh kode yang dapat diluaskan berikut berisi semua tugas yang dibahas dalam panduan ini.

Membangun agen data menggunakan HTTP dan Python

    from pygments import highlight, lexers, formatters
    import pandas as pd
    import json as json_lib
    import requests
    import json
    import altair as alt
    import IPython
    from IPython.display import display, HTML
    import requests
    import google.auth
    from google.auth.transport.requests import Request

    from google.colab import auth
    auth.authenticate_user()

    access_token = !gcloud auth application-default print-access-token
    headers = {
        "Authorization": f"Bearer {access_token[0]}",
        "Content-Type": "application/json",
    }

    ################### Data source details ###################

    billing_project = "your_billing_project"
    location = "global"
    system_instruction = "Help the user in analyzing their data"


    # BigQuery data source
    bigquery_data_sources = {
        "bq": {
        "tableReferences": [
            {
            "projectId": "bigquery-public-data",
            "datasetId": "san_francisco",
            "tableId": "street_trees"
            }
        ]
        }
    }

    # Looker data source
    looker_credentials = {
        "oauth": {
            "secret": {
            "client_id": "your_looker_client_id",
            "client_secret": "your_looker_client_secret",
            }
        }
    }
    # # To use access_token for authentication, uncomment the following looker_credentials code block and comment out the previous looker_credentials code block.
    # looker_credentials = {
    #     "oauth": {
    #         "token": {
    #           "access_token": "your_looker_access_token",
    #         }
    #     }
    # }
    looker_data_source = {
        "looker": {
        "explore_references": {
            "looker_instance_uri": "https://my_company.looker.com",
            "lookml_model": "my_model",
            "explore": "my_explore",
        },
        # "credentials": looker_credentials
    }

    # Looker Studio data source
    looker_studio_data_source = {
        "studio":{
            "studio_references":
            [
                {
                "datasource_id": "your_studio_datasource_id"
                }
            ]
        }
    }

    ################### Create data agent ###################
    data_agent_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}/dataAgents"

    data_agent_id = "data_agent_1"

    data_agent_payload = {
        "name": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}", # Optional
        "description": "This is the description of data_agent.", # Optional

        "data_analytics_agent": {
            "published_context": {
                "datasource_references": bigquery_data_sources,
                "system_instruction": system_instruction,
                # Optional: To enable advanced analysis with Python, include the following options block:
                "options": {
                    "analysis": {
                        "python": {
                            "enabled": True
                        }
                    }
                }
            }
        }
    }

    params = {"data_agent_id": data_agent_id} # Optional

    data_agent_response = requests.post(
        data_agent_url, params=params, json=data_agent_payload, headers=headers
    )

    if data_agent_response.status_code == 200:
        print("Data Agent created successfully!")
        print(json.dumps(data_agent_response.json(), indent=2))
    else:
        print(f"Error creating Data Agent: {data_agent_response.status_code}")
        print(data_agent_response.text)


    ################### Create conversation ###################

    conversation_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}/conversations"

    data_agent_id = "data_agent_1"
    conversation_id = "conversation _1"

    conversation_payload = {
        "agents": [
            f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}"
        ],
        "name": f"projects/{billing_project}/locations/{location}/conversations/{conversation_id}"
    }
    params = {
        "conversation_id": conversation_id
    }

    conversation_response = requests.post(conversation_url, headers=headers, params=params, json=conversation_payload)

    if conversation_response.status_code == 200:
        print("Conversation created successfully!")
        print(json.dumps(conversation_response.json(), indent=2))
    else:
        print(f"Error creating Conversation: {conversation_response.status_code}")
        print(conversation_response.text)


    ################### Chat with the API by using conversation (stateful) ####################

    chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}:chat"

    data_agent_id = "data_agent_1"
    conversation_id = "conversation _1"

    # Construct the payload
    chat_payload = {
        "parent": f"projects/{billing_project}/locations/global",
        "messages": [
            {
                "userMessage": {
                    "text": "Make a bar graph for the top 5 states by the total number of airports"
                }
            }
        ],
        "conversation_reference": {
            "conversation": f"projects/{billing_project}/locations/{location}/conversations/{conversation_id}",
            "data_agent_context": {
                "data_agent": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}",
                # "credentials": looker_credentials
            }
        }
    }

    # Call the get_stream function to stream the response
    get_stream(chat_url, chat_payload)

    ################### Chat with the API by using dataAgents (stateless) ####################

    chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/{location}:chat"

    data_agent_id = "data_agent_1"

    # Construct the payload
    chat_payload = {
        "parent": f"projects/{billing_project}/locations/global",
        "messages": [
            {
                "userMessage": {
                    "text": "Make a bar graph for the top 5 states by the total number of airports"
                }
            }
        ],
        "data_agent_context": {
            "data_agent": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}",
            # "credentials": looker_credentials
        }
    }

    # Call the get_stream function to stream the response
    get_stream(chat_url, chat_payload)

    ################### Chat with the API by using inline context (stateless) ####################

    chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/global:chat"

    # Construct the payload
    chat_payload = {
        "parent": f"projects/{billing_project}/locations/global",
        "messages": [
            {
                "userMessage": {
                    "text": "Make a bar graph for the top 5 states by the total number of airports"
                }
            }
        ],
        "inline_context": {
            "datasource_references": bigquery_data_sources,
            # Optional - if wanting to use advanced analysis with python
            "options": {
                "analysis": {
                    "python": {
                        "enabled": True
                    }
                }
            }
        }
    }

    # Call the get_stream function to stream the response
    get_stream(chat_url, chat_payload)

    ################### Multi-turn conversation ###################

    chat_url = f"https://geminidataanalytics.googleapis.com/v1alpha/projects/{billing_project}/locations/global:chat"

    # List that is used to track previous turns and is reused across requests
    conversation_messages = []

    data_agent_id = "data_agent_1"

    # Helper function for calling the API
    def multi_turn_Conversation(msg):

      userMessage = {
          "userMessage": {
              "text": msg
          }
      }

      # Send a multi-turn request by including previous turns and the new message
      conversation_messages.append(userMessage)

      # Construct the payload
      chat_payload = {
          "parent": f"projects/{billing_project}/locations/global",
          "messages": conversation_messages,
          # Use a data agent reference
          "data_agent_context": {
              "data_agent": f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}",
              # "credentials": looker_credentials
          },
          # Use inline context
          # "inline_context": {
          #     "datasource_references": bigquery_data_sources,
          # }
      }

      # Call the get_stream_multi_turn helper function to stream the response
      get_stream_multi_turn(chat_url, chat_payload, conversation_messages)

    # Send first-turn request
    multi_turn_Conversation("Which species of tree is most prevalent?")

    # Send follow-up-turn request
    multi_turn_Conversation("Can you show me the results as a bar chart?")
    

Contoh kode yang dapat diluaskan berikut berisi fungsi bantuan Python yang digunakan untuk melakukan streaming respons chat.

Fungsi Python pembantu untuk men-streaming respons chat

    def is_json(str):
      try:
          json_object = json_lib.loads(str)
      except ValueError as e:
          return False
      return True

    def handle_text_response(resp):
      parts = resp['parts']
      print(''.join(parts))

    def get_property(data, field_name, default = ''):
      return data[field_name] if field_name in data else default

    def display_schema(data):
      fields = data['fields']
      df = pd.DataFrame({
        "Column": map(lambda field: get_property(field, 'name'), fields),
        "Type": map(lambda field: get_property(field, 'type'), fields),
        "Description": map(lambda field: get_property(field, 'description', '-'), fields),
        "Mode": map(lambda field: get_property(field, 'mode'), fields)
      })
      display(df)

    def display_section_title(text):
      display(HTML('<h2>{}</h2>'.format(text)))

    def format_bq_table_ref(table_ref):
      return '{}.{}.{}'.format(table_ref['projectId'], table_ref['datasetId'], table_ref['tableId'])

    def format_looker_table_ref(table_ref):
      return 'lookmlModel: {}, explore: {}, lookerInstanceUri: {}'.format(table_ref['lookmlModel'], table_ref['explore'], table_ref['lookerInstanceUri'])

    def display_datasource(datasource):
      source_name = ''

      if 'studioDatasourceId' in datasource:
        source_name = datasource['studioDatasourceId']
      elif 'lookerExploreReference' in datasource:
        source_name = format_looker_table_ref(datasource['lookerExploreReference'])
      else:
        source_name = format_bq_table_ref(datasource['bigqueryTableReference'])

      print(source_name)
      display_schema(datasource['schema'])

    def handle_schema_response(resp):
      if 'query' in resp:
        print(resp['query']['question'])
      elif 'result' in resp:
        display_section_title('Schema resolved')
        print('Data sources:')
        for datasource in resp['result']['datasources']:
          display_datasource(datasource)

    def handle_data_response(resp):
      if 'query' in resp:
        query = resp['query']
        display_section_title('Retrieval query')
        print('Query name: {}'.format(query['name']))
        print('Question: {}'.format(query['question']))
        print('Data sources:')
        for datasource in query['datasources']:
          display_datasource(datasource)
      elif 'generatedSql' in resp:
        display_section_title('SQL generated')
        print(resp['generatedSql'])
      elif 'result' in resp:
        display_section_title('Data retrieved')

        fields = map(lambda field: get_property(field, 'name'), resp['result']['schema']['fields'])
        dict = {}

        for field in fields:
          dict[field] = map(lambda el: get_property(el, field), resp['result']['data'])

        display(pd.DataFrame(dict))

    def handle_chart_response(resp):
      if 'query' in resp:
        print(resp['query']['instructions'])
      elif 'result' in resp:
        vegaConfig = resp['result']['vegaConfig']
        alt.Chart.from_json(json_lib.dumps(vegaConfig)).display();

    def handle_error(resp):
      display_section_title('Error')
      print('Code: {}'.format(resp['code']))
      print('Message: {}'.format(resp['message']))

    def get_stream(url, json):
      s = requests.Session()

      acc = ''

      with s.post(url, json=json, headers=headers, stream=True) as resp:
        for line in resp.iter_lines():
          if not line:
            continue

          decoded_line = str(line, encoding='utf-8')

          if decoded_line == '[{':
            acc = '{'
          elif decoded_line == '}]':
            acc += '}'
          elif decoded_line == ',':
            continue
          else:
            acc += decoded_line

          if not is_json(acc):
            continue

          data_json = json_lib.loads(acc)

          if not 'systemMessage' in data_json:
            if 'error' in data_json:
                handle_error(data_json['error'])
            continue

          if 'text' in data_json['systemMessage']:
            handle_text_response(data_json['systemMessage']['text'])
          elif 'schema' in data_json['systemMessage']:
            handle_schema_response(data_json['systemMessage']['schema'])
          elif 'data' in data_json['systemMessage']:
            handle_data_response(data_json['systemMessage']['data'])
          elif 'chart' in data_json['systemMessage']:
            handle_chart_response(data_json['systemMessage']['chart'])
          else:
            colored_json = highlight(acc, lexers.JsonLexer(), formatters.TerminalFormatter())
            print(colored_json)
            print('\n')
            acc = ''

    def get_stream_multi_turn(url, json, conversation_messages):
        s = requests.Session()

        acc = ''

        with s.post(url, json=json, headers=headers, stream=True) as resp:
            for line in resp.iter_lines():
                if not line:
                    continue

                decoded_line = str(line, encoding='utf-8')

                if decoded_line == '[{':
                    acc = '{'
                elif decoded_line == '}]':
                    acc += '}'
                elif decoded_line == ',':
                    continue
                else:
                    acc += decoded_line

                if not is_json(acc):
                    continue

                data_json = json_lib.loads(acc)
                # Store the response that will be used in the next iteration
                conversation_messages.append(data_json)

                if not 'systemMessage' in data_json:
                    if 'error' in data_json:
                        handle_error(data_json['error'])
                    continue

                if 'text' in data_json['systemMessage']:
                    handle_text_response(data_json['systemMessage']['text'])
                elif 'schema' in data_json['systemMessage']:
                    handle_schema_response(data_json['systemMessage']['schema'])
                elif 'data' in data_json['systemMessage']:
                    handle_data_response(data_json['systemMessage']['data'])
                elif 'chart' in data_json['systemMessage']:
                    handle_chart_response(data_json['systemMessage']['chart'])
                else:
                    colored_json = highlight(acc, lexers.JsonLexer(), formatters.TerminalFormatter())
                    print(colored_json)
                print('\n')
                acc = ''