Práticas recomendadas do SDK para conectores do Copilot

Este artigo fornece as práticas recomendadas a serem seguidas ao usar o SDK dos conectores do Microsoft 365 Copilot (anteriormente conectores do Microsoft Graph) para implementar um conector personalizado.

Usando o marcador de progresso do rastreamento

O marcador de progresso do rastreamento atua como um identificador para o item específico enviado pelo conector que foi processado pela última vez pela plataforma. Você pode implementar dois tipos de rastreamento: periódico, completo e incremental.

Os rastreamentos completos periódicos obtêm todos os itens na fonte de dados e ingerem apenas os itens modificados ou que não estão presentes no índice. Se não encontrar um item, ele o exclui do índice.

Os rastreamentos incrementais fazem com que os itens sejam adicionados ou modificados desde o último rastreamento incremental. O conector também pode enviar itens para serem excluídos como parte desse rastreamento. Para o primeiro rastreamento incremental, a hora de início do último rastreamento completo também é enviada. Opcionalmente, o conector pode usar esse rastreamento para buscar itens alterados somente após o último rastreamento completo.

Os rastreamentos periódicos completos e incrementais têm seus marcadores de progresso de rastreamento.

Uso do marcador de progresso do rastreamento durante rastreamentos completos periódicos

O SDK envia o marcador de progresso do rastreamento se o rastreamento anterior travou ou um rastreamento agendado foi perdido porque o agente do conector do Copilot ficou offline durante rastreamentos completos periódicos.

Se o rastreamento anterior não falhou, você precisa rastrear a fonte de dados desde o início.

Uso do marcador de progresso do rastreamento durante rastreamentos incrementais

Durante um rastreamento incremental, o conector envia o marcador de progresso do rastreamento para a plataforma do conector e continuará a fazer isso para os próximos rastreamentos incrementais. O conector pode usar esse rastreamento para buscar itens adicionados ou modificados após esse marcador.

Construindo tipos genéricos

Os valores de propriedade do item de conteúdo podem ter um intervalo de tipos de dados. Como o gRPC não tem uma construção para objetos genéricos, o SDK inclui uma estrutura GenericType que pode conter qualquer um dos tipos de dados com suporte. GenericType tem a seguinte estrutura:

// Represents a generic type that can hold any supported value
message GenericType {
 // Value of the Generic type
 oneof value {
  // String type value
  string stringValue = 1;

  // Long value
  int64 intValue = 2;


  // Double value
  double doubleValue = 3;

  // DateTime value
  google.protobuf.Timestamp dateTimeValue = 4;

  // Boolean value
  bool boolValue = 5;

  // String collection value
  StringCollectionType stringCollectionValue = 6;

  // Long collection value
  IntCollectionType intCollectionValue = 7;

  // Double collection value
  DoubleCollectionType doubleCollectionValue = 8;

  // DateTime collection value
  TimestampCollectionType dateTimeCollectionValue = 9;
 }
}

// Collection of string
message StringCollectionType {
 // Value of string collection
 repeated string values = 1;
}

// Collection of long
message IntCollectionType {
 // Value of long collection
 repeated int64 values = 1;
}

// Collection of double
message DoubleCollectionType {
 // Value of double collection
 repeated double values = 1;
}

// Collection of DateTime
message TimestampCollectionType {
 // Value of DateTime collection
 repeated google.protobuf.Timestamp values = 1;
}

GenericType pode ter um dos seguintes tipos: string, int64, double, DateTime e Boolean ou uma coleção de string, int64, double e DateTime. Veja a seguir exemplos de como definir esses tipos:

// Setting string value in generic type
    GenericType stringType = new GenericType
    {
        StringValue = "Hello"
    };

    // Setting int64 value in generic type
    GenericType int64Type = new GenericType
    {
        IntValue = 1000
    };

    // Setting double value in generic type
    GenericType doubleType = new GenericType
    {
        DoubleValue = 12.54
    };

    // Setting dateTime value in generic type
    GenericType dateTimeType = new GenericType
    {
        DateTimeValue = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow)
    };

    // Setting Boolean value in generic type
    GenericType boolType = new GenericType
    {
        BoolValue = true
    };

    // Setting string collection value in generic type - Initialize the string collection first, add the values to the string collection and then set it in the generic type
    StringCollectionType stringCollection = new StringCollectionType();
    stringCollection.Values.Add("Value1");
    stringCollection.Values.Add("Value2");
    GenericType stringCollectionType = new GenericType
    {
        StringCollectionValue = stringCollection
    };

    // Setting int64 collection value in generic type - Initialize the int64 collection first, add the values to the int64 collection and then set it in the generic type
    IntCollectionType intCollection = new IntCollectionType();
    intCollection.Values.Add(1234);
    intCollection.Values.Add(5436);
    GenericType intCollectionType = new GenericType
    {
        IntCollectionValue = intCollection
    };

    // Setting double collection value in generic type - Initialize the double collection first, add the values to the double collection and then set it in the generic type
    DoubleCollectionType doubleCollection = new DoubleCollectionType();
    doubleCollection.Values.Add(12.54);
    doubleCollection.Values.Add(34.213);
    GenericType doubleCollectionType = new GenericType
    {
        DoubleCollectionValue = doubleCollection
    };

    // Setting datetime collection value in generic type - Initialize the datetime collection first, add the values to the datetime collection and then set it in the generic type
    TimestampCollectionType dateTimeCollection = new TimestampCollectionType();
    dateTimeCollection.Values.Add(Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow));
    dateTimeCollection.Values.Add(Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-1)));
    GenericType dateTimeCollectionType = new GenericType
    {
        DateTimeCollectionValue = dateTimeCollection
    };

Como criar um esquema de pesquisa

O esquema de conectores tem as seguintes restrições:

  • Nome da propriedade: o nome da propriedade pode ter no máximo 32 caracteres e apenas caracteres alfanuméricos são permitidos.
  • Pesquisar anotações:
    • Somente as propriedades do tipo String ou StringCollection podem ser pesquisáveis.
    • Somente as propriedades do tipo String podem ser uma propriedade de conteúdo.
    • As propriedades de conteúdo devem ser pesquisáveis.
    • As propriedades de conteúdo não podem ser consultadas ou recuperáveis.
    • A propriedade refinável não deve ser pesquisável.
    • A propriedade refinável deve ser consultável e recuperável.
    • As propriedades booleanas não podem ser refináveis.
  • Aliases: um conjunto de aliases ou um nome amigável para a propriedade pode ter no máximo 32 caracteres e apenas caracteres alfanuméricos permitidos.

Buscando itens durante um rastreamento

O método GetCrawlStream é um método de streaming do servidor. Ele converte cada item da fonte de dados em um CrawlStreamBit durante o rastreamento e o envia pelo fluxo de resposta.

Para obter uma boa taxa de transferência, o conector deve recuperar um lote de itens da fonte de dados, converter cada item em CrawlStreamBit e enviá-los pelo fluxo de resposta. O tamanho do lote depende da fonte de dados. Recomendamos 25 como um tamanho ideal para manter o fluxo contínuo de itens pelo fluxo.

Tratamento de exceções no código do conector

Todas as respostas das chamadas gRPC têm um OperationStatus que indica se a operação foi bem-sucedida ou falhou, o motivo da falha e detalhes de repetição se houver falhas. Recomendamos encapsular todo o código em um bloco try-catch. O conector deve registrar todas as exceções e enviar um status de operação adequado para a plataforma.

Os fluxos de gerenciamento de conexões enviam uma resposta com o StatusMessage que aparece no Centro de administração do Microsoft 365. O envio de mensagens significativas facilita a depuração dos erros na interface do usuário e evita deixar exceções sem tratamento.

Tempos limite

Todos os métodos em ConnectionManagementService devem ser concluídos e retornados em 30 segundos; Caso contrário, a plataforma retornará uma mensagem de erro de tempo limite para a solicitação.

Enviando de volta erros do conector para a plataforma

Todas as respostas usam o OperationStatus na estrutura de resposta. Se ocorrer algum erro, os conectores deverão usar OperationStatus para enviar o motivo da falha e repetir as informações de volta para a plataforma. Use OperationStatus para definir os erros durante rastreamentos se ocorrerem erros no nível da conexão, como credenciais expiradas para acessar a fonte de dados.

A estrutura OperationStatus tem três campos que podem ser usados para representar quaisquer erros.

OperationResult

OperationResult é uma enumeração que pode conter o motivo da falha.

StatusMessage

StatusMessage é uma propriedade de OperationStatus que pode armazenar a mensagem personalizada para mostrar o motivo da falha que aparecerá para o administrador durante a configuração da conexão. Por exemplo, se as credenciais estiverem incorretas durante a validação com o método ValidateAuthentic , a propriedade result poderá ser definida como AuthenticationIssue e a propriedade statusMessage poderá ser definida como Credenciais incorretas fornecidas. Quando o método ValidateAuthentication for chamado, essa statusMessage será exibida para o administrador de pesquisa. Durante os rastreamentos, esse cenário moverá a conexão para o estado de falha, exibirá o erro de autenticação para o administrador e solicitará que ele atualize as credenciais para acessar a fonte de dados.

RetryDetails

RetryDetails permite que o conector reenvie informações para a plataforma sobre erros transitórios durante os rastreamentos e use-o para repetir a operação.

A nova tentativa pode ser uma retirada padrão ou exponencial. O conector pode definir o tempo de pausa, a taxa de retirada e o coeficiente de retirada e enviá-los de volta. Por exemplo, se a fonte de dados for limitada durante o rastreamento, o conector poderá definir o OperationResult como DatasourceError e enviar os detalhes de repetição de acordo com o cabeçalho de repetição nos cabeçalhos de resposta da fonte de dados.

Mapeamento de erro para OperationResult

Os seguintes erros movem a conexão para o estado de falha:

  • OperationResult.AuthenticationIssue

  • OperationResult.ValidationFailure

Os outros códigos de operação serão tratados como falhas transitórias e serão repetidos em rastreamentos subsequentes.