Compartilhar via


Melhores práticas do SDK dos conectores Copilot

Este artigo fornece as melhores práticas a seguir quando utiliza o SDK de conectores Microsoft 365 Copilot (anteriormente conectores do Microsoft Graph) para implementar um conector personalizado.

Utilizar o marcador de progresso da pesquisa

O marcador de progresso da pesquisa atua como um identificador para o item específico enviado pelo conector que foi processado pela última vez pela plataforma. Pode implementar dois tipos de pesquisa: completa e incremental periódica.

As pesquisas completas periódicas obtêm todos os itens na origem de dados e ingerem apenas os itens que são modificados ou não estão presentes no índice. Se não encontrar um item, elimina-o do índice.

As pesquisas incrementais obtêm itens adicionados ou modificados desde a última pesquisa incremental. O conector também pode enviar itens para serem eliminados como parte desta pesquisa. Para a primeira pesquisa incremental, a última hora de início da pesquisa completa também é enviada. Opcionalmente, o conector pode utilizar esta pesquisa para obter itens alterados apenas após a última pesquisa completa.

As pesquisas periódicas completas e incrementais têm os marcadores de progresso da pesquisa.

Utilização do marcador de progresso da pesquisa durante pesquisas completas periódicas

O SDK envia o marcador de progresso da pesquisa se a pesquisa anterior tiver falhado ou se uma pesquisa agendada tiver sido perdida devido ao agente do conector Copilot estar offline durante pesquisas completas periódicas.

Se a pesquisa anterior não falhar, terá de pesquisar a origem de dados desde o início.

Utilização do marcador de progresso da pesquisa durante pesquisas incrementais

Durante uma pesquisa incremental, o conector envia o marcador de progresso da pesquisa para a plataforma do conector e continuará a fazê-lo para as próximas pesquisas incrementais. O conector pode utilizar esta pesquisa para obter itens adicionados ou modificados após este marcador.

Construir tipos genéricos

Os valores de propriedade do item de conteúdo podem ter um intervalo de tipos de dados. Uma vez que 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 suportados. O 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;
}

O GenericType pode ter um dos seguintes tipos: cadeia, int64, double, DateTime e Booleano ou uma coleção de cadeia, int64, double e DateTime. Seguem-se exemplos de como definir estes 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
    };

Criar esquema de pesquisa

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

  • Nome da propriedade: o nome da propriedade pode ter um máximo de 32 carateres e só são permitidos carateres alfanuméricos.
  • Anotações de pesquisa:
    • Apenas as propriedades do tipo String ou StringCollection podem ser pesquisáveis.
    • Apenas as propriedades do tipo Cadeia podem ser uma propriedade de conteúdo.
    • As propriedades do conteúdo têm de ser pesquisáveis.
    • As propriedades de conteúdo não podem ser consultados ou recuperáveis.
    • A propriedade refinável não deve ser pesquisável.
    • A propriedade refinável deve ser consultada 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 um máximo de 32 carateres e apenas carateres alfanuméricos permitidos.

Obter itens durante uma pesquisa

O método GetCrawlStream é um método de transmissão em fluxo de servidor. Converte cada item da origem de dados num CrawlStreamBit durante a pesquisa e envia-o através do fluxo de resposta.

Para obter um bom débito, o conector deve obter um lote de itens da origem de dados, converter cada item no CrawlStreamBit e enviá-los através do fluxo de resposta. O tamanho do lote depende da origem de dados. Recomendamos 25 como um tamanho ideal para manter o fluxo contínuo de itens através do fluxo.

Processamento 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 os detalhes de repetição se existirem falhas. Recomendamos encapsular todo o código num bloco try-catch. O conector deve registar todas as exceções e enviar uma operação adequada status para a plataforma.

Os fluxos de gestão de ligações enviam uma resposta com o StatusMessage que aparece no Centro de administração do Microsoft 365. Enviar mensagens significativas facilita a depuração dos erros na interface de utilizador e evita deixar exceções não processadas.

Tempos limite

Todos os métodos no ConnectionManagementService devem ser concluídos e devolvidos dentro de 30 segundos; caso contrário, a plataforma irá devolver uma mensagem de erro de tempo limite excedido para o pedido.

Enviar erros de volta do conector para a plataforma

Todas as respostas utilizam o OperationStatus na estrutura de resposta. Se ocorrerem erros, os conectores devem utilizar OperationStatus para enviar o motivo da falha e repetir as informações para a plataforma. Utilize OperationStatus para definir os erros durante as pesquisas se ocorrerem erros ao nível da ligação, como credenciais expiradas, para aceder à origem de dados.

A estrutura OperationStatus tem três campos que podem ser utilizados para representar 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 será apresentado ao administrador durante a configuração da ligação. Por exemplo, se as credenciais estiverem incorretas durante a validação com o método ValidateAuthentication, a propriedade result pode ser definida como AuthenticationIssue e a propriedade statusMessage pode ser definida como Credenciais incorretas fornecidas. Quando o método ValidateAuthentication é chamado, este statusMessage será mostrado ao administrador de pesquisa. Durante as pesquisas, este cenário irá mover a ligação para o estado com falha, apresentar o erro de autenticação ao administrador e pedir ao administrador para atualizar as credenciais para aceder à origem de dados.

RetryDetails

RetryDetails permite ao conector reenviar informações para a plataforma sobre erros transitórios durante as pesquisas e utilizá-lo para repetir a operação.

A repetição pode ser um trás-off padrão ou exponencial. O conector pode definir o tempo de pausa, a taxa de recuo e o coeficiente de trás e enviá-los de volta. Por exemplo, se a origem de dados for limitada durante a pesquisa, o conector pode definir OperationResult como DatasourceError e enviar os detalhes da repetição de acordo com o cabeçalho de repetição nos cabeçalhos de resposta da origem de dados.

Mapeamento de erros para OperationResult

Os seguintes erros movem a ligaçã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 pesquisas subsequentes.