Crie um agente de dados usando HTTP e Python, Crie um agente de dados usando HTTP e Python

Esta página orienta você no uso do Python para fazer solicitações HTTP à API de análise de conversação (acessada por meio de geminidataanalytics.googleapis.com ).

O código Python de exemplo nesta página mostra como concluir as seguintes tarefas:

Você também pode executar os exemplos de código nesta página no notebook Colaboratory HTTP da API de análise conversacional .

Uma versão completa do código de exemplo está incluída no final da página, junto com as funções auxiliares que são usadas para transmitir a resposta da API.

Configurar as configurações iniciais e autenticação

O código Python de exemplo a seguir executa estas tarefas:

  • Importa as bibliotecas Python necessárias
  • Define variáveis ​​para o projeto de faturamento, instruções do sistema e uma pergunta para o agente de dados
  • Obtém um token de acesso para autenticação HTTP usando o Google Cloud CLI
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()

billing_project = 'YOUR-BILLING-PROJECT'
system_description = 'YOUR-SYSTEM-INSTRUCTIONS'
question = 'YOUR-QUESTION-HERE'

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

Substitua os valores de amostra da seguinte forma:

  • YOUR-BILLING-PROJECT : O ID do projeto de faturamento onde você habilitou as APIs necessárias .
  • YOUR-SYSTEM-INSTRUCTIONS : Instruções do sistema para orientar o comportamento do agente e permitir que você o personalize de acordo com suas necessidades. Por exemplo, você pode usar instruções do sistema para definir termos comerciais (como o que constitui um "cliente fiel"), controlar o tamanho da resposta ("resumir em menos de 20 palavras") ou definir a formatação dos dados ("corresponder aos padrões da empresa"). Substitua o texto do espaço reservado por instruções relevantes para seus dados e caso de uso.
  • YOUR-QUESTION-HERE : Uma pergunta em linguagem natural para enviar ao agente de dados.

Autenticar no Looker

Se você planeja se conectar a uma fonte de dados do Looker, precisará se autenticar na instância do Looker.

Usando 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 amostra da seguinte forma:

  • YOUR-LOOKER-CLIENT-ID : O ID do cliente da sua chave de API do Looker gerada.
  • YOUR-LOOKER-CLIENT-SECRET : O segredo do cliente da sua chave de API do Looker gerada.

Usando 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 amostra da seguinte forma:

  • YOUR-TOKEN : O valor access_token que você gera para autenticar no Looker.

Conectar a uma fonte de dados

Os exemplos de código Python a seguir demonstram como definir a fonte de dados do Looker , BigQuery ou Looker Studio para seu agente usar.

Conectar aos dados do Looker

O código de exemplo a seguir define uma conexão com um Looker Explore. 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-se a uma fonte de dados com a API de Análise Conversacional .

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

Substitua os valores de amostra da seguinte forma:

  • https://your_company.looker.com : O URL completo da sua instância do Looker.
  • your_model : O nome do modelo LookML que inclui o Explore ao qual você deseja se conectar.
  • your_explore : O nome do Looker Explore que você deseja que o agente de dados consulte.

Conectar aos dados do BigQuery

O código de exemplo a seguir define uma conexão com uma tabela do BigQuery.

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

Substitua os valores de amostra da seguinte forma:

  • bigquery-public-data : O ID do Google Cloud Projeto que contém o conjunto de dados e a tabela do BigQuery aos quais você deseja se conectar. Para se conectar a um conjunto de dados público , especifique bigquery-public-data .
  • san_francisco : O ID do conjunto de dados do BigQuery.
  • street_trees : O ID da tabela do BigQuery.

Conecte-se aos dados do Looker Studio

O código de exemplo 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.

Criar um agente de dados

O código de exemplo a seguir demonstra como criar o agente de dados enviando uma solicitação HTTP POST ao endpoint de criação do agente de dados. O payload da solicitação inclui os seguintes detalhes:

Você também pode habilitar opcionalmente a análise avançada com Python incluindo o parâmetro options na carga útil da solicitação.

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)

Substitua os valores de amostra da seguinte forma:

  • data_agent_1 : Um identificador exclusivo para o agente de dados. Este valor é usado no nome do recurso do agente e como parâmetro de consulta de URL data_agent_id .
  • This is the description of data_agent_1. : Uma descrição para o agente de dados.

Criar uma conversa

O código de exemplo a seguir demonstra como criar uma conversa com seu agente de dados.

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)

Substitua os valores de amostra 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 .
  • conversation_1 : Um identificador exclusivo para a conversa.

Use a API para fazer perguntas

Depois de criar um agente de dados e uma conversa , você pode fazer perguntas sobre seus dados usando um dos seguintes métodos:

  • Bate-papo com estado : Google Cloud armazena e gerencia o histórico de conversas. Você precisa enviar apenas a mensagem atual de cada vez.
  • Bate-papo sem estado : seu aplicativo é responsável por manter o histórico da conversa. Google Cloud não armazena o histórico de conversas entre solicitações. Você deve incluir as mensagens anteriores relevantes junto com a nova mensagem para cada turno.

Para obter mais informações sobre conversas multi-turn, consulte Criar uma conversa multi-turn .

Bate-papo com estado

Enviar uma solicitação de bate-papo com estado com uma referência de conversa

O código de exemplo a seguir demonstra como fazer perguntas à API usando a conversa 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/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)

Substitua os valores de amostra 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 .
  • conversation_1 : Um identificador exclusivo para a conversa.
  • Foi usado como exemplo de prompt o Make a bar graph for the top 5 states by the total number of airports .

Bate-papo sem estado

Enviar uma solicitação de bate-papo sem estado com uma referência de agente de dados

O código de exemplo a seguir demonstra como fazer uma pergunta sem estado à API usando o agente de dados definido nas etapas anteriores. Este exemplo usa uma função auxiliar get_stream para transmitir a resposta.

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)

Substitua os valores de amostra 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 .
  • Foi usado como exemplo de prompt o Make a bar graph for the top 5 states by the total number of airports .

Enviar uma solicitação de bate-papo sem estado com contexto em linha

O código de exemplo a seguir demonstra como fazer uma pergunta sem estado à API usando contexto embutido. 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 habilitar opcionalmente a análise avançada com Python incluindo o parâmetro options na carga útil da solicitação.

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)

Exemplo de código de ponta a ponta

O exemplo de código expansível a seguir contém todas as tarefas abordadas neste guia.

Crie um agente de dados usando HTTP e 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 # Uncomment this when using looker as datasource in stateless chat
            }
        }

        # 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 #Uncomment this if your dataAgent contains looker dataSource
                }
            }
        }

        # 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 #Uncomment this if your dataAgent contains looker as dataSource
            }
        }

        # 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)

    

O exemplo de código expansível a seguir contém as funções auxiliares do Python usadas para transmitir respostas de bate-papo.

Funções auxiliares do Python para transmitir respostas de bate-papo

        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 = ''


    
,

Esta página orienta você no uso do Python para fazer solicitações HTTP à API de análise de conversação (acessada por meio de geminidataanalytics.googleapis.com ).

O código Python de exemplo nesta página mostra como concluir as seguintes tarefas:

Você também pode executar os exemplos de código nesta página no notebook Colaboratory HTTP da API de análise conversacional .

Uma versão completa do código de exemplo está incluída no final da página, junto com as funções auxiliares que são usadas para transmitir a resposta da API.

Configurar as configurações iniciais e autenticação

O código Python de exemplo a seguir executa estas tarefas:

  • Importa as bibliotecas Python necessárias
  • Define variáveis ​​para o projeto de faturamento, instruções do sistema e uma pergunta para o agente de dados
  • Obtém um token de acesso para autenticação HTTP usando o Google Cloud CLI
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()

billing_project = 'YOUR-BILLING-PROJECT'
system_description = 'YOUR-SYSTEM-INSTRUCTIONS'
question = 'YOUR-QUESTION-HERE'

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

Substitua os valores de amostra da seguinte forma:

  • YOUR-BILLING-PROJECT : O ID do projeto de faturamento onde você habilitou as APIs necessárias .
  • YOUR-SYSTEM-INSTRUCTIONS : Instruções do sistema para orientar o comportamento do agente e permitir que você o personalize de acordo com suas necessidades. Por exemplo, você pode usar instruções do sistema para definir termos comerciais (como o que constitui um "cliente fiel"), controlar o tamanho da resposta ("resumir em menos de 20 palavras") ou definir a formatação dos dados ("corresponder aos padrões da empresa"). Substitua o texto do espaço reservado por instruções relevantes para seus dados e caso de uso.
  • YOUR-QUESTION-HERE : Uma pergunta em linguagem natural para enviar ao agente de dados.

Autenticar no Looker

Se você planeja se conectar a uma fonte de dados do Looker, precisará se autenticar na instância do Looker.

Usando 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 amostra da seguinte forma:

  • YOUR-LOOKER-CLIENT-ID : O ID do cliente da sua chave de API do Looker gerada.
  • YOUR-LOOKER-CLIENT-SECRET : O segredo do cliente da sua chave de API do Looker gerada.

Usando 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 amostra da seguinte forma:

  • YOUR-TOKEN : O valor access_token que você gera para autenticar no Looker.

Conectar a uma fonte de dados

Os exemplos de código Python a seguir demonstram como definir a fonte de dados do Looker , BigQuery ou Looker Studio para seu agente usar.

Conectar aos dados do Looker

O código de exemplo a seguir define uma conexão com um Looker Explore. 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-se a uma fonte de dados com a API de Análise Conversacional .

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

Substitua os valores de amostra da seguinte forma:

  • https://your_company.looker.com : O URL completo da sua instância do Looker.
  • your_model : O nome do modelo LookML que inclui o Explore ao qual você deseja se conectar.
  • your_explore : O nome do Looker Explore que você deseja que o agente de dados consulte.

Conectar aos dados do BigQuery

O código de exemplo a seguir define uma conexão com uma tabela do BigQuery.

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

Substitua os valores de amostra da seguinte forma:

  • bigquery-public-data : O ID do Google Cloud Projeto que contém o conjunto de dados e a tabela do BigQuery aos quais você deseja se conectar. Para se conectar a um conjunto de dados público , especifique bigquery-public-data .
  • san_francisco : O ID do conjunto de dados do BigQuery.
  • street_trees : O ID da tabela do BigQuery.

Conecte-se aos dados do Looker Studio

O código de exemplo 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.

Criar um agente de dados

O código de exemplo a seguir demonstra como criar o agente de dados enviando uma solicitação HTTP POST ao endpoint de criação do agente de dados. O payload da solicitação inclui os seguintes detalhes:

Você também pode habilitar opcionalmente a análise avançada com Python incluindo o parâmetro options na carga útil da solicitação.

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)

Substitua os valores de amostra da seguinte forma:

  • data_agent_1 : Um identificador exclusivo para o agente de dados. Este valor é usado no nome do recurso do agente e como parâmetro de consulta de URL data_agent_id .
  • This is the description of data_agent_1. : Uma descrição para o agente de dados.

Criar uma conversa

O código de exemplo a seguir demonstra como criar uma conversa com seu agente de dados.

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)

Substitua os valores de amostra 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 .
  • conversation_1 : Um identificador exclusivo para a conversa.

Use a API para fazer perguntas

Depois de criar um agente de dados e uma conversa , você pode fazer perguntas sobre seus dados usando um dos seguintes métodos:

  • Bate-papo com estado : Google Cloud armazena e gerencia o histórico de conversas. Você precisa enviar apenas a mensagem atual de cada vez.
  • Bate-papo sem estado : seu aplicativo é responsável por manter o histórico da conversa. Google Cloud não armazena o histórico de conversas entre solicitações. Você deve incluir as mensagens anteriores relevantes junto com a nova mensagem para cada turno.

Para obter mais informações sobre conversas multi-turn, consulte Criar uma conversa multi-turn .

Bate-papo com estado

Enviar uma solicitação de bate-papo com estado com uma referência de conversa

O código de exemplo a seguir demonstra como fazer perguntas à API usando a conversa 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/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)

Substitua os valores de amostra 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 .
  • conversation_1 : Um identificador exclusivo para a conversa.
  • Foi usado como exemplo de prompt o Make a bar graph for the top 5 states by the total number of airports .

Bate-papo sem estado

Enviar uma solicitação de bate-papo sem estado com uma referência de agente de dados

O código de exemplo a seguir demonstra como fazer uma pergunta sem estado à API usando o agente de dados definido nas etapas anteriores. Este exemplo usa uma função auxiliar get_stream para transmitir a resposta.

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)

Substitua os valores de amostra 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 .
  • Foi usado como exemplo de prompt o Make a bar graph for the top 5 states by the total number of airports .

Enviar uma solicitação de bate-papo sem estado com contexto em linha

O código de exemplo a seguir demonstra como fazer uma pergunta sem estado à API usando contexto embutido. 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 habilitar opcionalmente a análise avançada com Python incluindo o parâmetro options na carga útil da solicitação.

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)

Exemplo de código de ponta a ponta

O exemplo de código expansível a seguir contém todas as tarefas abordadas neste guia.

Crie um agente de dados usando HTTP e 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 # Uncomment this when using looker as datasource in stateless chat
            }
        }

        # 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 #Uncomment this if your dataAgent contains looker dataSource
                }
            }
        }

        # 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 #Uncomment this if your dataAgent contains looker as dataSource
            }
        }

        # 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)

    

O exemplo de código expansível a seguir contém as funções auxiliares do Python usadas para transmitir respostas de bate-papo.

Funções auxiliares do Python para transmitir respostas de bate-papo

        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 = ''