Criar conector personalizado

Nesta página, descrevemos como criar um conector personalizado.

Antes de começar

Antes de começar, confira se você tem o seguinte:

  • Verifique se o faturamento está ativado no projeto do Google Cloud .

  • Instale e inicialize a CLI gcloud. Verifique se ele está autenticado para seu projeto.

  • Instale as bibliotecas necessárias do Python:

    pip install google-cloud-discoveryengine requests
    
  • Receba acesso de administrador do Discovery Engine para seu projeto do Google Cloud .

  • Consiga credenciais de acesso para sua fonte de dados de terceiros (como chaves de API ou autenticação de banco de dados).

  • Crie um plano claro de mapeamento de dados. Isso precisa incluir quais campos indexar e como representar o controle de acesso, incluindo identidades de terceiros.

Criar conector básico

Nesta seção, mostramos como criar um conector personalizado na linguagem escolhida. Os princípios e padrões mostrados aqui se aplicam a qualquer sistema externo. Basta adaptar as chamadas de API e as transformações de dados para sua fonte específica na linguagem escolhida para criar um conector básico.

Buscar dados

Para começar, recupere dados da sua fonte de dados de terceiros. Neste exemplo, mostramos como buscar postagens usando a paginação. Para ambientes de produção, recomendamos usar uma abordagem de streaming para conjuntos de dados grandes. Isso evita problemas de memória que podem ocorrer ao carregar todos os dados de uma só vez.

Python

    from typing import List
    import requests

    def fetch_posts(base_url: str, per_page: int = 15) -> List[dict]:
        #Fetch all posts from the given site.#
        url = base_url.rstrip("/") + "/wp-json/wp/v2/posts"
        posts: List[dict] = []
        page = 1
        while True:
            resp = requests.get(
                url,
                params={"page": page, "per_page": per_page},
                # headers={"Authorization": "Bearer YOUR_API_KEY"}, # Add auth if needed
            )
            resp.raise_for_status()
            batch = resp.json()
            posts.extend(batch)
            if len(batch) < per_page:
                break
            page += 1
        return posts

Transformar dados

Para converter os dados de origem no formato de documento do Discovery Engine, estruture-os como mostrado no exemplo de payload a seguir. É possível incluir quantos pares de chave-valor forem necessários. Por exemplo, é possível incluir todo o conteúdo para uma pesquisa abrangente. Como alternativa, é possível incluir campos estruturados para uma pesquisa facetada ou uma combinação de ambos.

Python

    from typing import List
    import json
    from google.cloud import discoveryengine_v1 as discoveryengine

    def convert_posts_to_documents(posts: List[dict]) -> List[discoveryengine.Document]:
        # Convert WP posts into Discovery Engine Document messages.
        docs: List[discoveryengine.Document] = []
        for post in posts:
            payload = {
                "title": post.get("title", {}).get("rendered"),
                "body": post.get("content", {}).get("rendered"),
                "url": post.get("link"),
                "author": post.get("author"),
                "categories": post.get("categories"),
                "tags": post.get("tags"),
                "date": post.get("date"),
            }
            doc = discoveryengine.Document(
                id=str(post["id"]),
                json_data=json.dumps(payload),
            )
            docs.append(doc)
        return docs

Recuperar ou criar repositório de identidades

Para gerenciar identidades e grupos de usuários para controle de acesso, é necessário recuperar ou criar um repositório de identidades. Essa função recebe um repositório de identidades pelo ID, projeto e local. Se o repositório de identidades não existir, ele vai criar e retornar um novo repositório de identidades vazio.

Python

    from google.cloud import discoveryengine_v1 as discoveryengine

    def get_or_create_ims_data_store(
        project_id: str,
        location: str,
        identity_mapping_store_id: str,
    ) -> discoveryengine.DataStore:
      """Get or create a DataStore."""
      # Initialize the client
      client_ims = discoveryengine.IdentityMappingStoreServiceClient()
      # Construct the parent resource name
      parent_ims = client_ims.location_path(project=project_id, location=location)

      try:
        # Create the request object
        name = f"projects/{project_id}/locations/{location}/identityMappingStores/{identity_mapping_store_id}"
        request = discoveryengine.GetIdentityMappingStoreRequest(
            name=name,
        )
        return client_ims.get_identity_mapping_store(request=request)
      except:
        # Create the IdentityMappingStore object (it can be empty for basic creation)
        identity_mapping_store = discoveryengine.IdentityMappingStore()
        # Create the request object
        request = discoveryengine.CreateIdentityMappingStoreRequest(
            parent=parent_ims,
            identity_mapping_store=identity_mapping_store,
            identity_mapping_store_id=identity_mapping_store_id,
        )
        return client_ims.create_identity_mapping_store(request=request)

A função get_or_create_ims_data_store usa as seguintes variáveis principais:

  • project_id: ID do seu projeto do Google Cloud .
  • location: o local do Google Cloud para o repositório de mapeamento de identidade.
  • identity_mapping_store_id: um identificador exclusivo do repositório de identidades.
  • client_ims: uma instância de discoveryengine.IdentityMappingStoreServiceClient usada para interagir com a API do repositório de identidades.
  • parent_ims: o nome do recurso do local pai, construído usando client_ims.location_path.
  • name: o nome completo do recurso do repositório de mapeamento de identidade, usado para GetIdentityMappingStoreRequest.

Ingerir o mapeamento de identidade no repositório de identidades

Para carregar entradas de mapeamento de identidade no repositório de identidades especificado, use esta função. Ele usa uma lista de entradas de mapeamento de identidade e inicia uma operação de importação inline. Isso é crucial para estabelecer as relações de usuário, grupo e identidade externa necessárias para o controle de acesso e a personalização.

Python

Python

from google.cloud import discoveryengine_v1 as discoveryengine

def load_ims_data(
    ims_store: discoveryengine.DataStore,
    id_mapping_data: list[discoveryengine.IdentityMappingEntry],
) -> discoveryengine.DataStore:
  """Get the IMS data store."""
  # Initialize the client
  client_ims = discoveryengine.IdentityMappingStoreServiceClient()

  #  Create the InlineSource object
  inline_source = discoveryengine.ImportIdentityMappingsRequest.InlineSource(
      identity_mapping_entries=id_mapping_data
  )

  # Create the main request object
  request_ims = discoveryengine.ImportIdentityMappingsRequest(
      identity_mapping_store=ims_store.name,
      inline_source=inline_source,
  )

  try:
    # Create the InlineSource object, which holds your list of entries
    operation = client_ims.import_identity_mappings(
        request=request_ims,
    )
    result = operation.result()
    return result

  except Exception as e:
    print(f"IMS Load Error: {e}")
    return None

A função load_ims_data usa as seguintes variáveis principais:

  • ims_store: o objeto discoveryengine.DataStore que representa o repositório de mapeamento de identidade em que os dados serão carregados.
  • id_mapping_data: uma lista de objetos discoveryengine.IdentityMappingEntry, cada um contendo uma identidade externa e o ID de usuário ou grupo correspondente.
  • result: valor de retorno do tipo discoveryengine.DataStore.

Criar repositório de dados

Para usar um conector personalizado, é necessário inicializar um repositório de dados para seu conteúdo. Use o default_collection para conectores personalizados. O parâmetro IndustryVertical personaliza o comportamento do repositório de dados para casos de uso específicos. GENERIC é adequado para a maioria dos cenários. No entanto, é possível escolher um valor diferente para um setor específico, como MEDIA ou HEALTHCARE_FHIR. Configure o nome de exibição e outras propriedades para se alinhar às convenções de nomenclatura e aos requisitos do projeto.

Python

from google.cloud import discoveryengine_v1 as discoveryengine

def get_or_create_data_store(
    project_id: str,
    location: str,
    display_name: str,
    data_store_id: str,
    identity_mapping_store: str,
) -> discoveryengine.DataStore:
  """Get or create a DataStore."""
  client = discoveryengine.DataStoreServiceClient()
  ds_name = client.data_store_path(project_id, location, data_store_id)
  try:
    result = client.get_data_store(request={"name": ds_name})
    return result
  except:
    parent = client.collection_path(project_id, location, "default_collection")
    operation = client.create_data_store(
        request={
            "parent": parent,
            "data_store": discoveryengine.DataStore(
                display_name=display_name,
                acl_enabled=True,
                industry_vertical=discoveryengine.IndustryVertical.GENERIC,
                identity_mapping_store=identity_mapping_store,
            ),
            "data_store_id": data_store_id,
        }
    )
    result = operation.result()
    return result

A função get_or_create_data_store usa as seguintes variáveis principais:

  • project_id: ID do seu projeto do Google Cloud .
  • location: o Google Cloud local do repositório de dados.
  • display_name: o nome de exibição legível por humanos do repositório de dados.
  • data_store_id: um identificador exclusivo para o repositório de dados.
  • identity_mapping_store: o nome do recurso do repositório de mapeamento de identidade a ser vinculado.
  • result: valor de retorno do tipo discoveryengine.DataStore.

Fazer upload de documentos inline

Para enviar documentos diretamente ao Discovery Engine, use o upload inline. Esse método usa o modo de reconciliação incremental por padrão e não é compatível com o modo de reconciliação completa. No modo incremental, novos documentos são adicionados e os atuais são atualizados, mas os documentos que não estão mais na origem não são excluídos. O modo de reconciliação completa sincroniza o repositório de dados com os dados de origem, incluindo a exclusão de documentos que não estão mais presentes na origem.

A reconciliação incremental é ideal para sistemas como um CRM que lidam com mudanças frequentes e pequenas nos dados. Em vez de sincronizar todo o banco de dados, envie apenas mudanças específicas, tornando o processo mais rápido e eficiente.

Como prática recomendada, faça uma sincronização completa inicial, seguida por sincronizações incrementais mais frequentes.

Python

    from typing import List
    from google.cloud import discoveryengine_v1 as discoveryengine

    def upload_documents_inline(
        project_id: str,
        location: str,
        data_store_id: str,
        branch_id: str,
        documents: List[discoveryengine.Document],
    ) -> discoveryengine.ImportDocumentsMetadata:
        """Inline import of Document messages."""
        client = discoveryengine.DocumentServiceClient()
        parent = client.branch_path(
            project=project_id,
            location=location,
            data_store=data_store_id,
            branch=branch_id,
        )
        request = discoveryengine.ImportDocumentsRequest(
            parent=parent,
            inline_source=discoveryengine.ImportDocumentsRequest.InlineSource(
                documents=documents,
            ),
        )
        operation = client.import_documents(request=request)
        operation.result()
        result = operation.metadata
        return result

A função upload_documents_inline usa as seguintes variáveis principais:

  • project_id: ID do seu projeto do Google Cloud .
  • location: o Google Cloud local do repositório de dados.
  • data_store_id: o ID do repositório de dados.
  • branch_id: o ID da ramificação no repositório de dados (normalmente "0").
  • documents: uma lista de objetos discoveryengine.Document a serem enviados.
  • result: valor de retorno do tipo discoveryengine.ImportDocumentsMetadata.

O campo uri no objeto discoveryengine.Document é usado para apontar para a própria origem do conteúdo ingerido, seja como bytes brutos ou um URI no Google Cloud Storage. Isso é diferente do URI do conteúdo de origem de terceiros. O URI do conteúdo de origem de terceiros precisa ser definido como um campo no payload json_data do documento. Por exemplo, na função convert_posts_to_documents, o campo url no payload serve para essa finalidade.

Validar o conector

Para validar se o conector está funcionando conforme o esperado, faça um teste para garantir o fluxo de dados adequado da origem para o Discovery Engine.

Python

    from google.cloud import discoveryengine_v1 as discoveryengine
    from google.api_core import exceptions as gcp_exceptions

    SITE = "https://altostrat.com"
    PROJECT_ID = "ucs-3p-connectors-testing"
    LOCATION = "global"
    IDENTITY_MAPPING_STORE_ID = "your-unique-ims-id17" # A unique ID for your new store
    DATA_STORE_ID = "my-acl-ds-id1"
    BRANCH_ID = "0"

    posts = fetch_posts(SITE)
    docs = convert_posts_to_documents(posts)
    print(f"Fetched {len(posts)} posts and converted to {len(docs)} documents.")

    try:
      # Step #1: Retrieve an existing identity mapping store or create a new identity mapping store
      ims_store = get_or_create_ims_data_store(PROJECT_ID, LOCATION, IDENTITY_MAPPING_STORE_ID)
      print(f"STEP #1: IMS Store Retrieval/Creation: {ims_store}")

      RAW_IDENTITY_MAPPING_DATA = [
          discoveryengine.IdentityMappingEntry(
              external_identity="external_id_1",
              user_id="testuser1@example.com",
          ),
          discoveryengine.IdentityMappingEntry(
              external_identity="external_id_2",
              user_id="testuser2@example.com",
          ),
          discoveryengine.IdentityMappingEntry(
              external_identity="external_id_2",
              group_id="testgroup1@example.com",
          )
      ]

      # Step #2: Load IMS Data
      response = load_ims_data(ims_store, RAW_IDENTITY_MAPPING_DATA)
      print(
          "\nStep #2: Load Data in IMS Store successful.", response
      )

      # Step #3: Create Entity Data Store & Bind IMS Data Store
      data_store =  get_or_create_data_store(PROJECT_ID, LOCATION, "my-acl-datastore", DATA_STORE_ID, ims_store.name)
      print("\nStep #3: Entity Data Store Create Result: ", data_store)

      metadata = upload_documents_inline(
          PROJECT_ID, LOCATION, DATA_STORE_ID, BRANCH_ID, docs
      )
      print(f"Uploaded {metadata.success_count} documents inline.")

    except gcp_exceptions.GoogleAPICallError as e:
      print(f"\n--- API Call Failed ---")
      print(f"Server Error Message: {e.message}")
      print(f"Status Code: {e.code}")

    except Exception as e:
      print(f"An error occurred: {e}")

Verifique se o código do conector usa as seguintes variáveis principais:

  • SITE: o URL de base da fonte de dados de terceiros.
  • PROJECT_ID: o ID do projeto do Google Cloud .
  • LOCATION: o local do Google Cloud para os recursos.
  • IDENTITY_MAPPING_STORE_ID: um ID exclusivo para o repositório de mapeamento de identidade.
  • DATA_STORE_ID: um ID exclusivo para o repositório de dados.
  • BRANCH_ID: o ID da ramificação no repositório de dados.
  • posts: armazena as postagens buscadas da fonte de terceiros.
  • docs: armazena os documentos convertidos no formato discoveryengine.Document.
  • ims_store: o objeto discoveryengine.DataStore recuperado ou criado para o mapeamento de identidade.
  • RAW_IDENTITY_MAPPING_DATA: uma lista de objetos discoveryengine.IdentityMappingEntry.

Saída esperada:

Shell

  Fetched 20 posts and converted to 20 documents.
  STEP #1: IMS Store Retrieval/Creation: "projects/ <Project Number>/locations/global/identityMappingStores/your-unique-ims-id17"
  Step #2: Load Data in IMS Store successful.
  Step #3: Entity Data Store Create Result: "projects/ <Project Number>/locations/global/collections/default_collection/dataStores/my-acl-ds-id1"
  display_name: "my-acl-datastore"
  industry_vertical: GENERIC
  create_time {
    seconds: 1760906997
    nanos: 192641000
  }
  default_schema_id: "default_schema"
  acl_enabled: true
  identity_mapping_store: "projects/ <Project Number>/locations/global/identityMappingStores/your-unique-ims-id17".
  Uploaded 20 documents inline.

Também é possível ver seu repositório de dados no console do Google Google Cloud :

Repositório de dados do conector personalizado
Repositório de dados do conector personalizado.

Quando uma pesquisa é realizada, os campos do payload são usados para a pesquisa, e o campo de URI do payload é usado para citações. Os três principais campos de propriedade que o Gemini Enterprise identifica são title, description e uri. Os campos de documento correspondentes podem ter nomes diferentes, e o mapeamento deles pode ser feito usando a opção Esquema -> Editar no console do Google Cloud .

Criar conector com upload do Storage do Google Cloud

Embora a importação inline funcione bem para o desenvolvimento, os conectores de produção precisam usar o Google Cloud Storage para melhorar a escalonabilidade e ativar o modo de reconciliação completa. Essa abordagem lida com grandes conjuntos de dados de maneira eficiente e permite a exclusão automática de documentos que não estão mais presentes na fonte de dados de terceiros.

Converter documentos em JSONL

Para preparar documentos para importação em massa para o Discovery Engine, converta-os para o formato JSON Lines.

Python

    from typing import List
    from google.cloud import discoveryengine_v1 as discoveryengine

    def convert_documents_to_jsonl(
        documents: List[discoveryengine.Document],
    ) -> str:
        """Serialize Document messages to JSONL."""
        return "\n".join(
            discoveryengine.Document.to_json(doc, indent=None)
            for doc in documents
        ) + "\n"

A função convert_documents_to_jsonl usa a seguinte variável:

  • documents: uma lista de objetos discoveryengine.Document a serem convertidos.

Fazer upload para o armazenamento do Google Cloud

Para permitir uma importação em massa eficiente, prepare os dados no Google Cloud Storage.

Python

    from google.cloud import storage

    def upload_jsonl_to_gcs(jsonl: str, bucket_name: str, blob_name: str) -> str:
        """Upload JSONL content to Google Cloud Storage."""
        client = storage.Client()
        bucket = client.bucket(bucket_name)
        blob = bucket.blob(blob_name)
        blob.upload_from_string(jsonl, content_type="application/json")
        return f"gs://{bucket_name}/{blob_name}"

A função upload_jsonl_to_gcs usa as seguintes variáveis principais:

  • jsonl: o conteúdo da string formatada em JSONL que será enviado.
  • bucket_name: o nome do bucket do Google Cloud Storage.
  • blob_name: o nome do blob (objeto) no bucket especificado.

Importar do armazenamento do Google Cloud com reconciliação completa

Para realizar uma sincronização de dados completa usando o modo de reconciliação total, use este método. Isso garante que o repositório de dados espelhe exatamente a fonte de dados de terceiros, removendo automaticamente todos os documentos que não existem mais.

Ao importar do Google Cloud Storage, esteja ciente das seguintes limitações:

  • Uma única solicitação de importação pode conter no máximo 100 arquivos ou 100.000 arquivos se o parâmetro dataSchema estiver definido como content.
  • Cada arquivo pode ter até 2 GB ou 100 MB se o parâmetro dataSchema estiver definido como content.

Python

    from google.cloud import discoveryengine_v1 as discoveryengine

    def import_documents_from_gcs(
        project_id: str,
        location: str,
        data_store_id: str,
        branch_id: str,
        gcs_uri: str,
    ) -> discoveryengine.ImportDocumentsMetadata:
        """Bulk-import documents from Google Cloud Storage with FULL reconciliation mode."""
        client = discoveryengine.DocumentServiceClient()
        parent = client.branch_path(
            project=project_id,
            location=location,
            data_store=data_store_id,
            branch=branch_id,
        )
        gcs_source = discoveryengine.GcsSource(input_uris=[gcs_uri])
        request = discoveryengine.ImportDocumentsRequest(
            parent=parent,
            gcs_source=gcs_source,
            reconciliation_mode=
                discoveryengine.ImportDocumentsRequest
                .ReconciliationMode.FULL,
        )
        operation = client.import_documents(request=request)
        operation.result()
        return operation.metadata

A função import_documents_from_gcs usa as seguintes variáveis principais:

  • project_id: ID do seu projeto do Google Cloud .
  • location: o Google Cloud local do repositório de dados.
  • data_store_id: o ID do repositório de dados.
  • branch_id: o ID da ramificação no repositório de dados (normalmente "0").
  • gcs_uri: o URI do Google Cloud Storage que aponta para o arquivo JSONL.

Teste Google Cloud Upload do Storage

Para verificar o fluxo de trabalho de importação baseado no Google Cloud Storage, execute o seguinte:

Python

  BUCKET = "your-existing-bucket"
  BLOB = "path-to-any-blob/wp/posts.jsonl"
  SITE = "https://altostrat.com"
  PROJECT_ID = "ucs-3p-connectors-testing"
  LOCATION = "global"
  IDENTITY_MAPPING_STORE_ID = "your-unique-ims-id17" # A unique ID for your new store
  DATA_STORE_ID = "your-data-store-id"
  BRANCH_ID = "0"
  posts = fetch_posts(SITE)
  docs = convert_posts_to_documents(posts)
  print(f"Fetched {len(posts)} posts and converted to {len(docs)} documents.")
  jsonl_payload = convert_documents_to_jsonl(docs)
  gcs_uri = upload_jsonl_to_gcs(jsonl_payload, BUCKET, BLOB)
  print("Uploaded to:", gcs_uri)

  metadata = import_documents_from_gcs(
      PROJECT_ID, LOCATION, DATA_STORE_ID, BRANCH_ID, gcs_uri
  )
  print(f"Imported: {metadata.success_count} documents")

As seguintes variáveis principais são usadas para testar o upload do Google Cloud Storage:

  • BUCKET: o nome do bucket do Google Cloud Storage.
  • BLOB: o caminho para o blob no bucket.
  • SITE: o URL de base da fonte de dados de terceiros.
  • PROJECT_ID: o ID do projeto do Google Cloud .
  • LOCATION: o local do Google Cloud para os recursos (por exemplo, "global").
  • IDENTITY_MAPPING_STORE_ID: um ID exclusivo para o repositório de mapeamento de identidade.
  • DATA_STORE_ID: um ID exclusivo para o repositório de dados.
  • BRANCH_ID: o ID da ramificação no repositório de dados (normalmente "0").
  • jsonl_payload: os documentos convertidos para o formato JSONL.
  • gcs_uri: o URI do Storage do Google Cloud arquivo JSONL enviado.

Saída esperada:

Shell

    Fetched 20 posts and converted to 20 documents.
    Uploaded to: gs://alex-de-bucket/wp/posts.jsonl
    Imported: 20 documents

Gerenciar permissões

Para gerenciar o acesso no nível do documento em ambientes corporativos, o Gemini Enterprise é compatível com listas de controle de acesso (ACLs) e mapeamento de identidade, que ajudam a limitar o conteúdo que os usuários podem ver.

Ativar ACLs no repositório de dados

Para ativar as ACLs ao criar o repositório de dados, execute o seguinte:

Python

  # get_or_create_data_store()
  "data_store": discoveryengine.DataStore(
      display_name=data_store_id,
      industry_vertical=discoveryengine.IndustryVertical.GENERIC,
      acl_enabled=True, # ADDED
  )

Adicionar ACLs a documentos

Para calcular e incluir AclInfo ao transformar os documentos, execute o seguinte:

Python

  # convert_posts_to_documents()
  doc = discoveryengine.Document(
      id=str(post["id"]),
      json_data=json.dumps(payload),
      acl_info=discoveryengine.Document.AclInfo(
          readers=[{
              "principals": [
                  {"user_id": "baklavainthebalkans@gmail.com"},
                  {"user_id": "cloudysanfrancisco@gmail.com"}
              ]
          }]
      ),
  )

Tornar o conteúdo público

Para tornar um documento acessível publicamente, defina o campo readers da seguinte maneira:

Python

  readers=[{"idp_wide": True}]

Validar ACLs

Para validar se as configurações de ACL estão funcionando conforme o esperado, considere o seguinte:

  • Pesquise como um usuário que não tem acesso ao documento.

  • Inspecione a estrutura do documento enviado no Cloud Storage e compare-a com uma referência.

JSON

  {
    "id": "108",
    "jsonData": "{...}",
    "aclInfo": {
      "readers": [
        {
          "principals": [
            { "userId": "baklavainthebalkans@gmail.com" },
            { "userId": "cloudysanfrancisco@gmail.com" }
          ],
          "idpWide": false
        }
      ]
    }
  }

Usar o mapeamento de identidade

Use o mapeamento de identidade nos seguintes cenários:

  • Sua fonte de dados de terceiros usa identidades que não são do Google

  • Você quer referenciar grupos personalizados (por exemplo, wp-admins) em vez de usuários individuais.

  • Sua API retorna apenas nomes de grupos

  • Você precisa agrupar manualmente os usuários para escalonamento ou consistência

  • Seu sistema de terceiros implementa ACLs usando grupos que não são baseados em IDP, e você quer respeitar essas ACLs usando o repositório de dados personalizado no Gemini Enterprise.

Para mapear identidades, siga estas etapas:

  1. Crie e vincule o repositório de dados de identidade.
  2. Importe identidades externas (por exemplo, external_group:wp-admins). Não inclua o external_group: prefix ao importar, por exemplo:

    JSON

      {
        "externalIdentity": "wp-admins",
        "userId": "user@example.com"
      }
    
  3. Nas informações da ACL do seu documento, defina o ID da entidade externa no principal identifier. Ao referenciar grupos personalizados, use o prefixo external_group: no campo groupId.

  4. O prefixo external_group: é obrigatório para IDs de grupo nas informações de ACL do documento durante a importação, mas não é usado ao importar identidades para o repositório de mapeamento. Exemplo de documento com mapeamento de identidade:

    JSON

      {
        "id": "108",
        "aclInfo": {
          "readers": [
            {
              "principals": [
                {
                  "userId": "cloudysanfrancisco@gmail.com"
                },
                {
                  "groupId": "external_group:wp-admins"
                }
              ]
            }
          ]
        },
        "structData": {
          "id": 108,
          "date": "2025-04-24T18:16:04",
          ...
        }
      }
    

A seguir

Bibliotecas de cliente do Gemini Enterprise