Nesta página, orientamos você a usar o Python para fazer solicitações HTTP à API Conversational Analytics (acessada por geminidataanalytics.googleapis.com).
O exemplo de código Python nesta página mostra como concluir as seguintes tarefas:
- Configure as definições iniciais e a autenticação.
- Conecte-se a uma fonte de dados do Looker, BigQuery, Looker Studio, AlloyDB para PostgreSQL, Cloud SQL ou Spanner.
- Crie um agente de dados.
- Criar uma conversa.
- Gerenciar agentes de dados e conversas.
- Usar a API para fazer perguntas.
- Criar uma conversa multiturno sem estado.
Uma versão completa do exemplo de código está incluída no final da página, junto com as funções auxiliares usadas para transmitir a resposta da API.
Configurar as definições iniciais e a autenticação
O exemplo de código Python a seguir executa estas tarefas:
- Importa as bibliotecas necessárias do Python.
- Recebe um token de acesso para autenticação HTTP usando a CLI do Google Cloud.
- Define variáveis para o projeto de faturamento, local e instruções do sistema.
import json
import json as json_lib
import textwrap
import altair as alt
import google.auth
from google.auth.transport.requests import Request
import IPython
from IPython.display import display, HTML
import pandas as pd
from pygments import highlight, lexers, formatters
import requests
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",
"x-server-timeout": "300", # Custom timeout up to 600s
}
billing_project = 'YOUR-BILLING-PROJECT'
location = "global"
system_instruction = 'YOUR-SYSTEM-INSTRUCTIONS'
Substitua os valores de exemplo da seguinte forma:
- YOUR-BILLING-PROJECT: o ID do projeto de faturamento em que você ativou as APIs necessárias.
- YOUR-SYSTEM-INSTRUCTIONS: instruções do sistema para orientar o comportamento do agente e personalizá-lo de acordo com suas necessidades de dados. Por exemplo, é possível usar instruções do sistema para definir termos comerciais, controlar o tamanho da resposta ou definir a formatação de dados. O ideal é definir instruções do sistema usando o formato YAML recomendado em Escrever instruções eficazes para o sistema para fornecer orientações detalhadas e estruturadas.
Autenticar no Looker
Se você planeja se conectar a uma fonte de dados do Looker, será necessário fazer a autenticação na instância do Looker.
Como usar chaves de API
O exemplo de código Python a seguir demonstra como autenticar seu agente em uma instância do Looker usando chaves de API.
looker_credentials = {
"oauth": {
"secret": {
"client_id": "YOUR-LOOKER-CLIENT-ID",
"client_secret": "YOUR-LOOKER-CLIENT-SECRET",
}
}
}
Substitua os valores de exemplo da seguinte forma:
- YOUR-LOOKER-CLIENT-ID: o ID do cliente da chave de API do Looker gerada.
- YOUR-LOOKER-CLIENT-SECRET: a chave secreta do cliente da chave de API do Looker gerada.
Como usar tokens de acesso
O exemplo de código Python a seguir demonstra como autenticar seu agente em uma instância do Looker usando tokens de acesso.
looker_credentials = {
"oauth": {
"token": {
"access_token": "YOUR-TOKEN",
}
}
}
Substitua os valores de exemplo da seguinte forma:
- YOUR-TOKEN: o valor
access_tokengerado para autenticar no Looker.
Autenticar no AlloyDB para PostgreSQL
Se você planeja se conectar a uma fonte de dados do AlloyDB, use a CLI gcloud para fazer a autenticação na instância do AlloyDB.
- Ative a autenticação do Identity and Access Management (IAM) no AlloyDB ativando a
flag
alloydb.iam_authenticationna instância do AlloyDB. - Conceda papéis do IAM. O principal (usuário ou conta de serviço) que chama a API Análises de conversação precisa ter as permissões adequadas do IAM no projetoGoogle Cloud . Isso geralmente inclui funções como
alloydb.databaseUser. - Crie um usuário de banco de dados correspondente. Crie um usuário do AlloyDB que espelhe o principal do IAM, usando o endereço de e-mail do usuário ou da conta de serviço como o nome de usuário.
Para mais informações, consulte Autenticação do banco de dados do IAM.
Autenticar no Cloud SQL para MySQL e no Cloud SQL para PostgreSQL
Se você planeja se conectar a uma fonte de dados do Cloud SQL para MySQL ou do Cloud SQL para PostgreSQL, autentique-se na instância do Cloud SQL.
Ative a autenticação do banco de dados do IAM. Verifique se a flag
cloudsql.iam_authenticationestá definida comoonna sua instância do Cloud SQL para MySQL. É possível adicionar isso ao criar ou fazer patch em uma instância.gcloud sql instances patch INSTANCE_NAME --database-flags cloudsql.iam_authentication=onConceda os papéis do IAM necessários.
O principal (usuário ou conta de serviço) que está tentando se conectar precisa das permissões
cloudsql.instances.loginecloudsql.instances.connectdo IAM no projeto. Para conceder essas funções e permissões, faça o seguinte:- Conceda o papel
roles/cloudsql.instanceUser. Isso inclui permissões para fazer login na instância (cloudsql.instances.login) e se conectar usando o proxy (cloudsql.instances.connect). - Outra opção é conceder uma função personalizada que contenha pelo menos
cloudsql.instances.loginecloudsql.instances.connect.
- Conceda o papel
Adicione o principal do IAM como um usuário do banco de dados. Crie um usuário na instância do Cloud SQL que corresponda ao endereço de e-mail do principal do IAM.
Para uma conta de serviço, execute o seguinte comando:
gcloud sql users create SERVICE_ACCOUNT_EMAIL --instance=INSTANCE_NAME --type=cloud_iam_service_accountPara uma conta de usuário, execute o seguinte comando:
gcloud sql users create USER_EMAIL --instance=INSTANCE_NAME --type=cloud_iam_userConceda privilégios de banco de dados. A conexão com o IAM autentica o usuário no banco de dados, mas não concede permissões automaticamente no banco de dados. É necessário usar comandos padrão do PostgreSQL, como
GRANT, para conceder permissões a esse novo usuário do banco de dados em objetos específicos, como tabelas e esquemas.Conecte-se como um superusuário, como o usuário postgres padrão, e execute os seguintes comandos:
-- Example: Connect using psql as the 'postgres' user GRANT SELECT ON ALL TABLES IN SCHEMA public TO "user-or-service-account@example.com";Conecte-se usando a autenticação do IAM.
Normalmente, os clientes se conectam pelo proxy do Cloud SQL Auth ou por uma biblioteca de conector, que processa a troca de tokens. O nome de usuário do banco de dados é o e-mail do principal do IAM. As senhas não são usadas. Em vez disso, um token OAuth 2.0, geralmente processado automaticamente pelo proxy Auth do Cloud SQL ou pela Google Cloud CLI, é usado.
O exemplo a seguir usa psql e a CLI gcloud para gerar um token:
PGPASSWORD=$(gcloud sql generate-login-token) psql --host=HOST_IP \ --username=IAM_PRINCIPAL_EMAIL --dbname=DATABASE_NAME\Para mais informações, consulte Autenticação do IAM.
Substitua os valores de exemplo da seguinte forma:
INSTANCE_NAME: o ID da instância do Cloud SQL que você quer corrigir para ativar a autenticação de banco de dados do IAM.SERVICE_ACCOUNT_EMAIL: o endereço de e-mail da conta de serviço.USER_EMAIL: o endereço de e-mail da conta de usuário.HOST_IP: o endereço IP da instância do Cloud SQL.IAM_PRINCIPAL_EMAIL: o endereço de e-mail do principal do IAM, por exemplo, conta de serviço ou usuário.DATABASE_NAME: o nome do banco de dados a ser conectado.
Autenticar no Spanner
Se você planeja se conectar a uma fonte de dados do Spanner, é necessário fazer a autenticação na instância do Spanner.
- Conceda papéis do IAM. O principal (usuário ou conta de serviço) que chama a API Análises de conversação precisa ter as permissões adequadas do IAM no projetoGoogle Cloud . Isso geralmente inclui funções como
databaseUser. - Crie papéis de banco de dados abstratos correspondentes no Spanner usando a linguagem de definição de dados (DDL).
- Use políticas do IAM para permitir que os principais do IAM assumam esses papéis de banco de dados.
Para mais informações, consulte Privilégios de controle de acesso detalhado.
Conectar a uma fonte de dados
As seções a seguir mostram como definir os detalhes da conexão para as fontes de dados do seu agente. Seu agente pode se conectar aos dados das seguintes maneiras:
- Looker
- Looker Studio
- BigQuery
- Dados do AlloyDB
- Dados do Cloud SQL para MySQL
- Dados do Cloud SQL para PostgreSQL
- Dados do Spanner
Conectar aos dados do Looker
O exemplo de código a seguir define uma conexão com uma análise detalhada do Looker. Para estabelecer uma conexão com uma instância do Looker, verifique se você gerou chaves de API do Looker, conforme descrito em Autenticar e conectar a uma fonte de dados com a API Conversational Analytics. É possível se conectar a até cinco Análises do Looker por vez com a API Análises de conversação.
Ao se conectar a uma fonte de dados do Looker, observe o seguinte:
- Você pode consultar qualquer Análise incluída em uma conversa.
- Um agente só pode consultar uma análise por vez. Não é possível fazer consultas em várias análises detalhadas ao mesmo tempo.
- Um agente pode consultar várias análises detalhadas na mesma conversa.
Um agente pode consultar várias análises detalhadas em uma conversa que inclui perguntas com várias partes ou em conversas com perguntas de acompanhamento.
Por exemplo, um usuário conecta duas análises detalhadas, uma chamada
cat-exploree outra chamadadog-explore. O usuário insere a pergunta "O que é maior: a quantidade de gatos ou a quantidade de cachorros?" Isso criaria duas consultas: uma para contar o número de gatos emcat-exploree outra para contar o número de cachorros emdog-explore. O agente compara os números das duas consultas depois de concluí-las.
O exemplo de código a seguir define uma conexão com várias análises detalhadas do Looker. Para melhorar a performance do agente, você pode fornecer consultas de ouro como contexto estruturado para suas análises detalhadas. Para mais informações, consulte Definir o contexto do agente de dados para fontes de dados do Looker.
looker_instance_uri = "https://your_company.looker.com"
looker_data_source = {
"looker": {
"explore_references": [
{
"looker_instance_uri": looker_instance_uri,
"lookml_model": "your_model",
"explore": "your_explore",
},
{
"looker_instance_uri": looker_instance_uri,
"lookml_model": "your_model_2",
"explore": "your_explore_2",
},
# Add up to 5 total Explore references
],
# Do not include the following line during agent creation
"credentials": looker_credentials
}
}
Substitua os valores de exemplo da seguinte forma:
- https://your_company.looker.com: o URL completo da sua instância do Looker.
- your_model: o nome do modelo do LookML que inclui a Análise de destino.
- your_explore: o nome da Análise do Looker que o agente de dados deve consultar.
- your_model_2: o nome do segundo modelo do LookML que inclui a Análise de destino. Você pode repetir essa variável para outros modelos em até cinco análises.
- your_explore_2: o nome da outra Análise do Looker que o agente de dados deve consultar. Você pode repetir essa variável para incluir até cinco análises detalhadas.
Conectar-se aos dados do BigQuery
Com a API Análises de conversação, não há limites rígidos para o número de tabelas do BigQuery a que você pode se conectar. No entanto, conectar um grande número de tabelas pode reduzir a acurácia ou fazer com que você exceda o limite de tokens de entrada do modelo.
O exemplo de código a seguir define uma conexão com várias tabelas do BigQuery e inclui exemplos de campos de contexto estruturado opcionais. Para melhorar a performance do agente, você pode fornecer um contexto estruturado para suas tabelas do BigQuery, como descrições de tabelas e colunas, sinônimos, tags e exemplos de consultas. Para mais informações, consulte Definir o contexto do agente de dados para fontes de dados do BigQuery.
bigquery_data_sources = {
"bq": {
"tableReferences": [
{
"projectId": "my_project_id",
"datasetId": "my_dataset_id",
"tableId": "my_table_id",
"schema": {
"description": "my_table_description",
"fields": [{
"name": "my_column_name",
"description": "my_column_description"
}]
}
},
{
"projectId": "my_project_id_2",
"datasetId": "my_dataset_id_2",
"tableId": "my_table_id_2"
},
{
"projectId": "my_project_id_3",
"datasetId": "my_dataset_id_3",
"tableId": "my_table_id_3"
},
]
}
}
Substitua os valores de exemplo da seguinte forma:
- my_project_id: o ID do projeto do Google Cloud que contém o conjunto de dados e a tabela do BigQuery a que você quer se conectar. Para se conectar a um conjunto de dados público, especifique
bigquery-public-data. - my_dataset_id: ID do conjunto de dados do BigQuery.
- my_table_id: ID da tabela do BigQuery.
- my_table_description: uma descrição opcional do conteúdo e da finalidade da tabela.
- my_column_name: o nome de uma coluna na tabela para a qual você está fornecendo uma descrição opcional.
- my_column_description: uma descrição opcional do conteúdo e da finalidade da coluna.
Conectar aos dados do Looker Studio
O exemplo de código a seguir define uma conexão com uma fonte de dados do Looker Studio.
looker_studio_data_source = {
"studio":{
"studio_references": [
{
"studio_datasource_id": "studio_datasource_id"
}
]
}
}
Substitua studio_datasource_id pelo ID da fonte de dados.
Conectar-se aos dados do AlloyDB
A API Análises de conversação usa um campo database_reference no campo alloydb para se conectar ao cluster do AlloyDB.
O exemplo a seguir define uma conexão com um banco de dados do AlloyDB.
alloydb_data_source = {
"alloydb": {
"database_reference":
{
"project_id":"PROJECT_ID",
"region":"REGION",
"cluster_id":"CLUSTER_ID",
"instance_id":"INSTANCE_ID",
"database_id":"DATABASE",
"table_ids":["TABLE_1_ID", "TABLE_2_ID"]
}
# Optional: Include this if you have pre-authored context for the agent
# "agent_context_reference": {
# "context_set_id": f"projects/billing_project/locations/location/contextSets/your_context_set_id"
# }
}
}
Substitua os valores de exemplo da seguinte forma:
PROJECT_ID: o ID do projeto Google Cloud que contém o cluster do AlloyDB.REGION: a região em que o cluster do AlloyDB reside, por exemplo,us-central1.CLUSTER_ID: o ID do cluster do AlloyDB.INSTANCE_ID: o ID da instância do AlloyDB.DATABASE: o nome do banco de dados de destino, por exemplo,financial.TABLE_1_ID,TABLE_2_ID: opcional. Uma lista das tabelas no banco de dados que o agente de dados é sugerido para usar. Por exemplo,"loan","client","disp".billing_project: o ID do projeto de faturamento em que você ativou as APIs necessárias.location: o local em que seu conjunto de contexto reside, por exemplo, "global".your_context_set_id: se você criou um contexto avançado para o agente, o ID do conjunto de contexto.
Conectar-se aos dados do Cloud SQL para MySQL e do Cloud SQL para PostgreSQL
A API Análises de conversação usa um campo database_reference no campo sql para se conectar
à sua instância do Cloud SQL.
O exemplo a seguir define uma conexão com um banco de dados do Cloud SQL para MySQL ou do Cloud SQL para PostgreSQL.
sql_data_source = {
"cloud_sql_reference": {
"database_reference":
{
"project_id":"PROJECT_ID",
"region":"REGION",
"cluster_id":"CLUSTER_ID",
"instance_id":"INSTANCE_ID",
"database_id":"DATABASE_ID",
"table_ids":["TABLE_1_ID", "TABLE_2_ID"]
}
# Optional: Include this if you have pre-authored context for the agent
# "agent_context_reference": {
# "context_set_id": f"projects/billing_project/locations/location/contextSets/your_context_set_id"
# }
}
}
Substitua os valores de exemplo da seguinte forma:
PROJECT_ID: o ID do projeto Google Cloud que contém a instância do Cloud SQL.REGION: a região em que a instância do Cloud SQL está localizada, por exemplo,us-central1.CLUSTER_ID: o ID do cluster do Cloud SQL.INSTANCE_ID: o ID da instância do Cloud SQL.DATABASE_ID: o nome do banco de dados de destino, por exemplo,financial.TABLE_1_ID,TABLE_2_ID: opcional. Uma lista das tabelas no banco de dados que o agente de dados é sugerido para usar. Por exemplo,"loan","client","disp".billing_project: o ID do projeto de faturamento em que você ativou as APIs necessárias.location: o local em que seu conjunto de contexto reside, por exemplo, "global".your_context_set_id: se você criou um contexto avançado para o agente, o ID do conjunto de contexto.
Conectar aos dados do Spanner
A API Análises de conversação usa um campo database_reference no campo spanner para se conectar à sua instância do Spanner.
O exemplo a seguir define uma conexão com um banco de dados do Spanner.
spanner_data_sources = {
"spanner_reference": {
"database_reference": {
"project_id": "PROJECT_ID",
"region": location,
"engine": GOOGLE_SQL,
"instance_id": "INSTANCE_ID",
"database_id": "DATABASE",
"table_ids":["TABLE_1_ID", "TABLE_2_ID"]
},
# Optional: Include this if you have pre-authored context for the agent
# "agent_context_reference": {
# "context_set_id": f"projects/billing_project/locations/location/contextSets/your_context_set_id"
# }
}
}
Substitua os valores de exemplo da seguinte forma:
PROJECT_ID: o ID do projeto Google Cloud que contém a instância do Spanner.INSTANCE_ID: o ID da instância do Spanner.DATABASE: o nome do banco de dados de destino, por exemplo,financial.TABLE_1_ID,TABLE_2_ID: uma lista das tabelas no banco de dados que o agente de dados é sugerido para usar. Por exemplo,"loan","client","disp".billing_project: o ID do projeto de faturamento em que você ativou as APIs necessárias.location: o local em que seu conjunto de contexto reside, por exemplo, global.your_context_set_id: se você criou um contexto avançado para o agente, o ID do conjunto de contexto.
Criar um agente de dados
O exemplo de código a seguir demonstra como criar o agente de dados de forma síncrona ou assíncrona enviando uma solicitação HTTP POST ao endpoint de criação do agente de dados. O payload da solicitação inclui os seguintes detalhes:
- O nome completo do recurso do agente. Esse valor inclui o ID do projeto, o local e um identificador exclusivo do agente.
- A descrição do agente de dados.
- O contexto do agente de dados, incluindo a descrição do sistema (definida em Configurar as definições iniciais e a autenticação) e a fonte de dados usada pelo agente (definida em Conectar a uma fonte de dados).
Você pode proteger o agente de dados com chaves de criptografia gerenciadas pelo cliente (CMEK) fornecendo um kms_key durante a criação. A CMEK é compatível apenas com fontes de dados do Looker. Para mais informações, consulte Chaves de criptografia gerenciadas pelo cliente (CMEK).
Você também pode ativar a análise avançada com Python incluindo o parâmetro options no payload da solicitação. Consulte Recurso REST: projects.locations.dataAgents para mais informações sobre o parâmetro options e as opções que podem ser configuradas para a conversa.
Síncrona
data_agent_url = f"https://geminidataanalytics.googleapis.com/v1beta/projects/{billing_project}/locations/{location}/dataAgents:createSync"
data_agent_id = "data_agent_1"
# Optional: If using CMEK, replace the empty strings with your KMS key details.
kms_project_id = "" # KMS_PROJECT_ID (Defaults to billing_project if empty)
key_ring_name = "" # KEY_RING_NAME
key_name = "" # KEY_NAME
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
}
}
}
}
}
}
# If key details are provided, construct and add the kms_key field.
if key_ring_name and key_name:
if not kms_project_id:
kms_project_id = billing_project
data_agent_payload["kms_key"] = f"projects/{kms_project_id}/locations/{location}/keyRings/{key_ring_name}/cryptoKeys/{key_name}"
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)
Assíncrono
data_agent_url = f"https://geminidataanalytics.googleapis.com/v1beta/projects/{billing_project}/locations/{location}/dataAgents"
data_agent_id = "data_agent_1"
# Optional: If using CMEK, replace the empty strings with your KMS key details.
kms_project_id = "" # KMS_PROJECT_ID (Defaults to billing_project if empty)
key_ring_name = "" # KEY_RING_NAME
key_name = "" # KEY_NAME
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
}
}
}
}
}
}
# If key details are provided, construct and add the kms_key field.
if key_ring_name and key_name:
if not kms_project_id:
kms_project_id = billing_project
data_agent_payload["kms_key"] = f"projects/{kms_project_id}/locations/{location}/keyRings/{key_ring_name}/cryptoKeys/{key_name}"
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)
Substitua os valores de exemplo da seguinte forma:
- data_agent_1: um identificador exclusivo para o agente de dados. Esse valor é usado no nome do recurso do agente e como o parâmetro de consulta de URL
data_agent_id. - KMS_PROJECT_ID: se você estiver usando a CMEK, o ID do projeto em que a chave está hospedada. Se não for fornecido, o padrão será seu projeto de faturamento.
- KEY_RING_NAME: se você estiver usando a CMEK, o nome do keyring do Cloud KMS.
- KEY_NAME: se você estiver usando a CMEK, o nome da chave do Cloud KMS.
- This is the description of data_agent_1.: uma descrição para o agente de dados.
Criar uma conversa
O exemplo de código a seguir demonstra como criar uma conversa com seu agente de dados.
Você também pode proteger a conversa com a CMEK fornecendo um kms_key durante a criação. A CMEK é compatível apenas com fontes de dados do Looker. Para mais informações, consulte Chaves de criptografia gerenciadas pelo cliente (CMEK).
conversation_url = f"https://geminidataanalytics.googleapis.com/v1beta/projects/{billing_project}/locations/{location}/conversations"
data_agent_id = "data_agent_1"
conversation_id = "conversation_1"
# Optional: If using CMEK, replace the empty strings with your KMS key details.
kms_project_id = "" # KMS_PROJECT_ID (Defaults to billing_project if empty)
key_ring_name = "" # KEY_RING_NAME
key_name = "" # KEY_NAME
conversation_payload = {
"agents": [
f"projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}"
],
"name": f"projects/{billing_project}/locations/{location}/conversations/{conversation_id}",
}
# If key details are provided, construct and add the kms_key field.
if key_ring_name and key_name:
if not kms_project_id:
kms_project_id = billing_project
conversation_payload["kms_key"] = f"projects/{kms_project_id}/locations/{location}/keyRings/{key_ring_name}/cryptoKeys/{key_name}"
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)
Substitua os valores de exemplo da seguinte forma:
- data_agent_1: o ID do agente de dados, conforme definido no bloco de exemplo de código em Criar agente de dados.
- conversation_1: um identificador exclusivo da conversa.
- KMS_PROJECT_ID: se você estiver usando a CMEK, o ID do projeto em que a chave está hospedada. Se não for fornecido, o padrão será seu projeto de faturamento.
- KEY_RING_NAME: se você estiver usando a CMEK, o nome do keyring do Cloud KMS.
- KEY_NAME: se você estiver usando a CMEK, o nome da chave do Cloud KMS.
Gerenciar agentes de dados e conversas
Os exemplos de código a seguir mostram como gerenciar agentes de dados e conversas usando a API Conversational Analytics. É possível fazer as seguintes tarefas:
- Recuperar um agente de dados
- Listar agentes de dados
- Listar agentes de dados acessíveis
- Atualizar um agente de dados
- Acessar a política do IAM de um agente de dados
- Definir a política do IAM de um agente de dados
- Excluir um agente de dados
- Acessar uma conversa
- Listar conversas
- Listar mensagens em uma conversa
Receber um agente de dados
O exemplo de código a seguir demonstra como buscar um agente de dados enviando uma solicitação HTTP GET para o URL do recurso do agente de dados.
data_agent_id = "data_agent_1"
data_agent_url = f"{base_url}/v1beta/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)
No exemplo anterior, substitua data_agent_1 pelo ID do agente de dados que você quer buscar.
Listar agentes de dados
O código a seguir demonstra como listar todos os agentes de dados de um determinado projeto enviando uma solicitação HTTP GET para o endpoint dataAgents.
Para listar todos os agentes, você precisa ter a permissão geminidataanalytics.dataAgents.list no projeto. Para mais informações sobre quais papéis do IAM incluem essa permissão, consulte a lista de papéis predefinidos.
billing_project = "YOUR-BILLING-PROJECT"
data_agent_url = f"{base_url}/v1beta/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 Agents Listed successfully!")
print(json.dumps(data_agent_response.json(), indent=2))
else:
print(f"Error Listing Data Agents: {data_agent_response.status_code}")
Substitua YOUR-BILLING-PROJECT pelo ID do seu projeto de faturamento.
Listar agentes de dados acessíveis
O código a seguir demonstra como listar todos os agentes de dados acessíveis de um determinado projeto enviando uma solicitação HTTP GET para o endpoint dataAgents:listAccessible.
billing_project = "YOUR-BILLING-PROJECT"
creator_filter = "YOUR-CREATOR-FILTER"
data_agent_url = f"{base_url}/v1beta/projects/{billing_project}/locations/{location}/dataAgents:listAccessible"
params = {
"creator_filter": creator_filter
}
data_agent_response = requests.get(
data_agent_url, headers=headers, params=params
)
if data_agent_response.status_code == 200:
print("Accessible Data Agents Listed successfully!")
print(json.dumps(data_agent_response.json(), indent=2))
else:
print(f"Error Listing Accessible Data Agents: {data_agent_response.status_code}")
Substitua os valores de exemplo da seguinte forma:
- YOUR-BILLING-PROJECT: o ID do seu projeto de faturamento.
- YOUR-CREATOR-FILTER: o filtro a ser aplicado com base no criador do agente de dados. Os valores possíveis incluem
NONE(padrão),CREATOR_ONLYeNOT_CREATOR_ONLY.
Atualizar um agente de dados
O exemplo de código a seguir demonstra como atualizar um agente de dados de forma síncrona ou assíncrona enviando uma solicitação HTTP PATCH para o URL do recurso do agente de dados. O payload da solicitação inclui os novos valores dos campos que você quer mudar, e os parâmetros da solicitação incluem um parâmetro updateMask, que especifica os campos a serem atualizados.
Síncrona
data_agent_id = "data_agent_1"
billing_project = "YOUR-BILLING-PROJECT"
data_agent_url = f"https://geminidataanalytics.googleapis.com/v1beta/projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}:updateSync"
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)
Assíncrono
data_agent_id = "data_agent_1"
billing_project = "YOUR-BILLING-PROJECT"
data_agent_url = f"https://geminidataanalytics.googleapis.com/v1beta/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)
Substitua os valores de exemplo da seguinte forma:
- data_agent_1: o ID do agente de dados que você quer atualizar.
- YOUR-BILLING-PROJECT: o ID do seu projeto de faturamento.
- Updated description of the data agent.: uma nova descrição para o agente de dados.
Acessar a política de IAM de um agente de dados
O exemplo de código a seguir demonstra como buscar a política do IAM de um agente de dados enviando uma solicitação HTTP POST para o URL do agente de dados. O payload da solicitação inclui o caminho do agente de dados.
billing_project = "YOUR-BILLING-PROJECT"
data_agent_id = "data_agent_1"
data_agent_url = f"{base_url}/v1beta/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)
Substitua os valores de exemplo da seguinte forma:
- YOUR-BILLING-PROJECT: o ID do seu projeto de faturamento.
- data_agent_1: o ID do agente de dados cuja política do IAM você quer buscar.
Definir a política do IAM para um agente de dados
Para compartilhar um agente, use o método setIamPolicy para atribuir papéis do IAM a usuários em um agente específico. O exemplo de código a seguir demonstra como fazer uma chamada POST para o URL do agente de dados com uma carga útil que inclui vinculações. A vinculação especifica quais papéis devem ser atribuídos a quais usuários.
billing_project = "YOUR-BILLING-PROJECT"
data_agent_id = "data_agent_1"
role = "roles/geminidataanalytics.dataAgentEditor"
users = "222larabrown@gmail.com, cloudysanfrancisco@gmail.com"
data_agent_url = f"{base_url}/v1beta/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)
Substitua os valores de exemplo da seguinte forma:
- YOUR-BILLING-PROJECT: o ID do seu projeto de faturamento.
- data_agent_1: o ID do agente de dados para o qual você quer definir a política do IAM.
- 222larabrown@gmail.com, cloudysanfrancisco@gmail.com: uma lista separada por vírgulas de e-mails de usuários a quem você quer conceder o papel especificado.
Excluir um agente de dados
O exemplo de código a seguir demonstra como fazer a exclusão reversível de um agente de dados de maneira síncrona ou assíncrona enviando uma solicitação HTTP DELETE para o URL do recurso do agente de dados. A exclusão temporária significa que o agente é excluído, mas ainda pode ser recuperado em até 30 dias.
Síncrona
billing_project = "YOUR-BILLING-PROJECT"
data_agent_id = "data_agent_1"
data_agent_url = f"https://geminidataanalytics.googleapis.com/v1beta/projects/{billing_project}/locations/{location}/dataAgents/{data_agent_id}:deleteSync"
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)
Assíncrono
billing_project = "YOUR-BILLING-PROJECT"
data_agent_id = "data_agent_1"
data_agent_url = f"https://geminidataanalytics.googleapis.com/v1beta/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)
Substitua os valores de exemplo da seguinte forma:
- YOUR-BILLING-PROJECT: o ID do seu projeto de faturamento.
- data_agent_1: o ID do agente de dados que você quer excluir.
Acessar uma conversa
O exemplo de código a seguir demonstra como buscar uma conversa enviando uma solicitação HTTP GET para o URL do recurso de conversa.
billing_project = "YOUR-BILLING-PROJECT"
conversation_id = "conversation_1"
conversation_url = f"{base_url}/v1beta/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)
Substitua os valores de exemplo da seguinte forma:
- YOUR-BILLING-PROJECT: o ID do seu projeto de faturamento.
- conversation_1: o ID da conversa que você quer buscar.
Listar conversas
O exemplo de código a seguir demonstra como listar conversas de um determinado projeto enviando uma solicitação HTTP GET para o endpoint conversations.
Por padrão, esse método retorna as conversas que você criou. Os administradores (usuários com o papel do IAM cloudaicompanion.topicAdmin) podem acessar todas as conversas no projeto.
billing_project = "YOUR-BILLING-PROJECT"
conversation_url = f"{base_url}/v1beta/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)
Substitua YOUR-BILLING-PROJECT pelo ID do projeto de faturamento em que você ativou as APIs necessárias.
Listar mensagens em uma conversa
O exemplo de código a seguir demonstra como listar todas as mensagens em uma conversa enviando uma solicitação HTTP GET para o endpoint messages da conversa.
Para listar mensagens, é necessário ter a permissão cloudaicompanion.topics.get na conversa.
billing_project = "YOUR-BILLING-PROJECT"
conversation_id = "conversation_1"
conversation_url = f"{base_url}/v1beta/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)
Substitua os valores de exemplo da seguinte forma:
- YOUR-BILLING-PROJECT: o ID do seu projeto de faturamento.
- conversation_1: o ID da conversa cujas mensagens você quer listar.
Excluir uma conversa
O exemplo de código a seguir demonstra como excluir uma conversa enviando uma solicitação HTTP DELETE para o URL do recurso de conversa. Os administradores (usuários com o papel de administrador de tópicos do Cloud AI Companion no Identity and Access Management) ou usuários com a permissão cloudaicompanion.topics.delete do Identity and Access Management podem excluir conversas no projeto.
billing_project = "YOUR-BILLING-PROJECT"
conversation_id = "conversation_1"
conversation_url = f"{base_url}/v1beta/projects/{billing_project}/locations/{location}/conversations/{conversation_id}"
conversation_response = requests.delete(conversation_url, headers=headers)
# Handle the response
if conversation_response.status_code == 200:
print("Conversation deleted successfully!")
print(json.dumps(conversation_response.json(), indent=2))
else:
print(f"Error while deleting conversation: {conversation_response.status_code}")
print(conversation_response.text)
Substitua os valores de exemplo da seguinte forma:
- YOUR-BILLING-PROJECT: o ID do seu projeto de faturamento.
- conversation_1: o ID da conversa que você quer excluir.
Usar a API para fazer perguntas
Depois de criar um agente de dados e, para conversas com estado, uma conversa, você pode enviar consultas ao agente.
Quando você envia uma consulta, a API retorna um fluxo de objetos Message. Esse stream pode conter diferentes tipos de mensagens, incluindo texto, tabelas de dados e gráficos. As mensagens de texto podem fornecer insights sobre o raciocínio do agente, informar sobre o progresso ou dar a resposta final. A finalidade de cada mensagem de texto é indicada pelo valor TextType:
THOUGHT: mostra o processo de raciocínio interno do agente enquanto ele planeja como responder à sua consulta. As mensagensTHOUGHTfornecem insights detalhados sobre o raciocínio e o processo de tomada de decisão do agente e contêm duas partes:parts[0]é o resumo do pensamento, que resume brevemente o texto completo, eparts[1]é o texto completo.PROGRESS: informa o progresso do agente em uma ação, como recuperação de dados ou uma ferramenta que está sendo invocada. Esse valor é retornado apenas para fontes de dados do Looker e contém duas partes:parts[0]é o resumo, eparts[1]é o texto completo do progresso.FINAL_RESPONSE: fornece a resposta final à sua consulta.
Os exemplos na seção a seguir usam as funções auxiliares definidas em Funções auxiliares do Python para transmitir respostas de chat para processar e mostrar cada mensagem na resposta transmitida da API. Para saber como renderizar essas mensagens em uma interface do usuário ao usar fontes de dados do Looker, consulte Renderizar respostas do agente para fontes de dados do Looker.
Fazer perguntas com conversas com e sem estado
Você pode interagir com a API nos seguintes modos principais:
- Conversa com estado:o Google Cloud armazena e gerencia o histórico de conversas. A conversa com estado é inerentemente multiturno, já que a API retém o contexto das mensagens anteriores. Você só precisa enviar a mensagem atual a cada turno.
- Chat sem estado: seu aplicativo gerencia o histórico de conversas. Você precisa incluir as mensagens anteriores relevantes em cada nova mensagem. Para exemplos detalhados de como gerenciar conversas multiturno no modo sem estado, consulte Criar uma conversa multiturno sem estado.
Os exemplos a seguir demonstram como usar a API para chat com e sem estado fazendo uma solicitação POST ao endpoint :chat.
Chat com estado
Enviar uma solicitação de chat com estado e uma referência de conversa
O exemplo de código a seguir demonstra como fazer perguntas à API usando a conversa definida nas etapas anteriores. Este exemplo usa uma função auxiliar get_stream para transmitir a resposta.
chat_url = f"https://geminidataanalytics.googleapis.com/v1beta/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)
Substitua os valores de exemplo da seguinte forma:
- data_agent_1: o ID do agente de dados, conforme definido no bloco de exemplo de código em Criar agente de dados.
- conversation_1: um identificador exclusivo da conversa.
Make a bar graph for the top 5 states by the total number of airportsfoi usado como o comando de exemplo.
Chat sem estado
Os exemplos a seguir mostram como enviar solicitações sem estado usando uma referência de agente de dados ou contexto inline.
Enviar uma solicitação de chat sem estado com uma referência de agente de dados
O exemplo de código a seguir demonstra como fazer uma pergunta sem estado à API usando o agente de dados que você definiu nas etapas anteriores. Este exemplo usa uma função auxiliar get_stream para transmitir a resposta.
chat_url = f"https://geminidataanalytics.googleapis.com/v1beta/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)
Substitua os valores de exemplo da seguinte forma:
- data_agent_1: o ID do agente de dados, conforme definido no bloco de código de exemplo em Criar um agente de dados.
Make a bar graph for the top 5 states by the total number of airportsfoi usado como o comando de exemplo.
Enviar uma solicitação de chat sem estado com contexto inline
O exemplo de código a seguir demonstra como fazer uma pergunta sem estado à API usando o contexto inline. Este exemplo usa uma função auxiliar get_stream para transmitir a resposta e usa uma fonte de dados do BigQuery como exemplo.
Você também pode ativar a análise avançada com Python incluindo o parâmetro options no payload da solicitação. Consulte a página Recurso REST: projects.locations.dataAgents para mais informações sobre o parâmetro options e as opções que podem ser configuradas para a conversa.
chat_url = f"https://geminidataanalytics.googleapis.com/v1beta/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)
O exemplo de código a seguir demonstra como fazer uma pergunta sem estado à API usando o contexto inline e uma fonte de dados do AlloyDB como exemplo.
chat_url = f"https://geminidataanalytics.googleapis.com/v1beta/projects/{billing_project}/locations/{location}:chat"
# The natural language question to ask the data agent
user_prompt = "what is the average loan amount in the US?" # Replace with your question
# Construct the payload
chat_payload = {
"parent": f"projects/{billing_project}/locations/global",
"messages": [
{
"userMessage": {
"text": user_prompt
}
}
],
"data_agent_context": {
"data_agent": f"projects/{billing_project}/locations/global/dataAgents/{data_agent_id}",
}
}
print(f"Sending prompt to :chat: '{user_prompt}'")
print(f"Endpoint: {chat_url}")
print(f"Payload: {json.dumps(chat_payload, indent=2)}")
get_stream(chat_url, chat_payload)
Criar uma conversa multiturno sem estado
Para fazer perguntas complementares em uma conversa sem estado, seu aplicativo precisa gerenciar o contexto da conversa enviando todo o histórico de mensagens com cada nova solicitação. As seções a seguir mostram como definir e chamar funções auxiliares para criar uma conversa multiturno:
Enviar solicitações multiturno
A função auxiliar multi_turn_Conversation a seguir gerencia o contexto da conversa armazenando mensagens em uma lista. Assim, você pode enviar perguntas de acompanhamento com base em interações anteriores. No payload da função, refira-se a um agente de dados ou forneça a fonte de dados diretamente usando o contexto inline.
chat_url = f"https://geminidataanalytics.googleapis.com/v1beta/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)
No exemplo anterior, substitua data_agent_1 pelo ID do agente de dados, conforme definido no bloco de exemplo de código em Criar agente de dados.
Você pode chamar a função auxiliar multi_turn_Conversation para cada turno da conversa. O exemplo de código a seguir mostra como enviar uma solicitação inicial e, em seguida, uma solicitação complementar que se baseia na resposta anterior.
# 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?")
No exemplo anterior, substitua os valores de amostra da seguinte forma:
- Which species of tree is most prevalent?: uma pergunta em linguagem natural para enviar ao agente de dados.
- Can you show me the results as a bar chart?: uma pergunta complementar que se baseia ou refina a pergunta anterior.
Processar respostas
A função get_stream_multi_turn a seguir processa a resposta da API Streaming. Essa função é semelhante à função auxiliar get_stream, mas armazena a resposta na lista conversation_messages para salvar o contexto da conversa para a próxima vez.
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 = ''
Exemplos de código completos
Os exemplos de código expansíveis a seguir contêm todas as tarefas abordadas neste guia.
Criar um agente de dados para o BigQuery e o Looker usando HTTP e Python
import json import json as json_lib import textwrap import altair as alt import google.auth from google.auth.transport.requests import Request import IPython from IPython.display import display, HTML import pandas as pd from pygments import formatters, highlight, lexers import requests 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", "x-server-timeout": "300", # Custom timeout up to 600s } ################### 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": looker_instance_uri, "lookml_model": "your_model", "explore": "your_explore", }, { "looker_instance_uri": looker_instance_uri, "lookml_model": "your_model_2", "explore": "your_explore_2", }, # Add up to 5 total Explore references ], # Do not include the following line during agent creation # "credentials": looker_credentials } # Looker Studio data source looker_studio_data_source = { "studio":{ "studio_references": [ { "studio_datasource_id": "studio_datasource_id" } ] } } ################### Create data agent ################### data_agent_url = f"https://geminidataanalytics.googleapis.com/v1beta/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/v1beta/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/v1beta/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/v1beta/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/v1beta/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/v1beta/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?")
Definir funções auxiliares
O exemplo de código a seguir contém as definições das funções auxiliares usadas nos exemplos anteriores. Essas funções ajudam a analisar respostas da API e mostrar os resultados.
Funções auxiliares do Python para transmitir respostas de 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'] full_text = "".join(parts) if "\n" not in full_text and len(full_text) > 80: wrapped_text = textwrap.fill(full_text, width=80) print(wrapped_text) else: print(full_text) 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'])) if 'question' in query: print('Question: {}'.format(query['question'])) if 'datasources' in query: 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 = ''