Partager via


Créer un bot RAG dans Teams

Les chatbots Q&A avancés sont des applications puissantes créées à l’aide de modèles de langage volumineux (LLM). Les chatbots répondent aux questions en extrayant des informations de sources spécifiques à l’aide d’une méthode appelée Récupération augmentée de génération (RAG). L’architecture RAG a deux flux principaux :

  • Ingestion des données : pipeline pour ingérer des données à partir d’une source et les indexer. Cela se produit généralement hors connexion.

  • Récupération et génération : la chaîne RAG, qui prend la requête de l’utilisateur au moment de l’exécution et récupère les données pertinentes à partir de l’index, puis les transmet au modèle.

Microsoft Teams vous permet de créer un bot conversationnel avec RAG pour créer une expérience améliorée afin d’optimiser la productivité. Teams Toolkit fournit une série de modèles d’application prêts à l’emploi dans la catégorie Conversation avec vos données qui combine les fonctionnalités de recherche Azure AI, Microsoft 365 SharePoint et l’API personnalisée en tant que source de données et llms différents pour créer une expérience de recherche conversationnelle dans Teams.

Configuration requise

Installer Pour l’utilisation...
Visual Studio Code Environnements de build JavaScript, TypeScript ou Python. Utilisez la dernière version.
Toolkit Teams Extension Microsoft Visual Studio Code qui crée une structure de projet pour votre application. Utilisez la dernière version.
Node.js Environnement runtime JavaScript principal. Pour plus d’informations, consultez Node.js table de compatibilité des versions pour le type de projet.
Microsoft Teams Microsoft Teams pour collaborer avec toutes les personnes avec lesquelles vous travaillez via des applications de conversation, de réunions et d’appels au même endroit.
Azure OpenAI Commencez par créer votre clé API OpenAI pour utiliser le transformateur préentraîné génératif (GPT) d’OpenAI. Si vous souhaitez héberger votre application ou accéder à des ressources dans Azure, vous devez créer un service Azure OpenAI.

Créer un projet de chatbot IA de base

  1. Ouvrez Visual Studio Code.

  2. Sélectionnez l’icône Teams Toolkit dans la barre d’activité de Visual Studio Code.

  3. Sélectionnez Créer une application.

    Capture d’écran montrant l’emplacement du lien Créer un projet dans la barre latérale du Kit de ressources Teams.

  4. Sélectionnez Custom Copilot.

    Capture d’écran montrant l’option permettant de sélectionner le projet Copilot personnalisé comme nouveau projet à créer.

  5. Sélectionnez Conversation avec vos données.

    Capture d’écran montrant l’option permettant de sélectionner des fonctionnalités d’application à l’aide de la liste des bibliothèques IA.

  6. Sélectionnez Personnaliser.

    Capture d’écran montrant l’option permettant de sélectionner la personnalisation des données pour le chargement.

  7. Sélectionnez JavaScript.

    Capture d’écran montrant l’option permettant de sélectionner le langage de programmation.

  8. Sélectionnez Azure OpenAI ou OpenAI.

    Capture d’écran montrant l’option permettant de sélectionner le LLM.

  9. Entrez vos informations d’identification Azure OpenAI ou OpenAI en fonction du service que vous sélectionnez. Ensuite, sélectionnez Entrée.

    Capture d’écran montrant l’emplacement où entrer la clé API d’ouverture Azure.

  10. Sélectionnez Dossier par défaut.

    Capture d’écran montrant le dossier d’application location à enregistrer.

    Pour modifier l’emplacement par défaut, procédez comme suit :

    1. Sélectionnez Parcourir.
    2. Sélectionnez l’emplacement de l’espace de travail du projet.
    3. Sélectionnez Sélectionner un dossier.
  11. Entrez un nom d’application pour votre application, puis sélectionnez la touche Entrée .

    Capture d’écran montrant l’option permettant d’entrer le nom approprié.

    Vous avez créé votre espace de travail de projet Conversation avec vos données .

    Capture d’écran montrant le chatbot ai créé et le fichier Lisez-moi est disponible.

  12. Sous EXPLORATEUR, accédez au fichier env.env.testtool.user>.

  13. Mettez à jour les valeurs suivantes :

    • SECRET_AZURE_OPENAI_API_KEY=<your-key>
    • AZURE_OPENAI_ENDPOINT=<your-endpoint>
    • AZURE_OPENAI_DEPLOYMENT_NAME=<your-deployment>

    Capture d’écran montrant les détails mis à jour dans le fichier env.

  14. Pour déboguer votre application, sélectionnez la touche F5 ou, dans le volet gauche, sélectionnez Exécuter et déboguer (Ctrl+Maj+D), puis sélectionnez Déboguer dans l’outil de test (préversion) dans la liste déroulante.

    Capture d’écran montrant la sélection de l’option débogage dans la liste des options.

L’outil de test ouvre le bot dans une page web.

Capture d’écran de la conversation avec la sortie finale de vos données.

Découvrez le code source de l’application bot

Folder Sommaire
.vscode Fichiers Visual Studio Code pour le débogage.
appPackage Modèles pour le manifeste de l’application Teams.
env Fichiers d’environnement.
infra Modèles de provisionnement de ressources Azure.
src Code source de l’application.
src/index.js Configure le serveur d’applications bot.
src/adapter.js Configure l’adaptateur de bot.
src/config.js Définit les variables d’environnement.
src/prompts/chat/skprompt.txt Définit l’invite.
src/prompts/chat/config.json Configure l’invite.
src/app/app.js Gère les logiques métier du bot RAG.
src/app/myDataSource.js Définit la source de données.
src/data/*.md Sources de données de texte brut.
teamsapp.yml Il s’agit du fichier projet principal du Kit de ressources Teams. Le fichier projet définit les propriétés et les définitions d’étape de configuration.
teamsapp.local.yml Cela remplace par des teamsapp.yml actions qui activent l’exécution et le débogage locaux.
teamsapp.testtool.yml Cela remplace par des teamsapp.yml actions qui permettent l’exécution et le débogage locaux dans l’outil de test d’application Teams.

Scénarios RAG pour Teams AI

Dans le contexte de l’IA, les bases de données vectorielles sont largement utilisées comme stockages RAG, qui stockent les données d’incorporation et fournissent une recherche de similarité vectorielle. La bibliothèque IA Teams fournit des utilitaires pour vous aider à créer des incorporations pour les entrées données.

Conseil

La bibliothèque IA Teams ne fournit pas l’implémentation de la base de données vectorielle. Vous devez donc ajouter votre propre logique pour traiter les incorporations créées.

// create OpenAIEmbeddings instance
const model = new OpenAIEmbeddings({ ... endpoint, apikey, model, ... });

// create embeddings for the given inputs
const embeddings = await model.createEmbeddings(model, inputs);

// your own logic to process embeddings

Le diagramme suivant montre comment la bibliothèque IA Teams fournit des fonctionnalités pour faciliter chaque étape du processus de récupération et de génération :

Capture d’écran montrant le scénario RAG.

  1. Gérer l’entrée : la méthode la plus simple consiste à passer l’entrée de l’utilisateur à la récupération sans aucune modification. Toutefois, si vous souhaitez personnaliser l’entrée avant la récupération, vous pouvez ajouter un gestionnaire d’activités à certaines activités entrantes.

  2. Récupérer des donnéesSource : La bibliothèque IA Teams fournit une DataSource interface pour vous permettre d’ajouter votre propre logique de récupération. Vous devez créer votre propre DataSource instance et la bibliothèque IA Teams l’appelle à la demande.

    class MyDataSource implements DataSource {
      /**
        * Name of the data source.
        */
      public readonly name = "my-datasource";
    
      /**
        * Renders the data source as a string of text.
        * @param context Turn context for the current turn of conversation with the user.
        * @param memory An interface for accessing state values.
        * @param tokenizer Tokenizer to use when rendering the data source.
        * @param maxTokens Maximum number of tokens allowed to be rendered.
        * @returns The text to inject into the prompt as a `RenderedPromptSection` object.
        */
      renderData(
        context: TurnContext,
        memory: Memory,
        tokenizer: Tokenizer,
        maxTokens: number
      ): Promise<RenderedPromptSection<string>> {
        ...
      }
    }
    
  3. Appeler l’IA avec l’invite : dans le système d’invite IA Teams, vous pouvez facilement injecter un DataSource en ajustant la augmentation.data_sources section de configuration. Cela connecte l’invite avec l’orchestrateur DataSource de bibliothèque et pour injecter le DataSource texte dans l’invite finale. Pour plus d’informations, consultez authorprompt. Par exemple, dans le fichier de l’invite config.json :

    {
        "schema": 1.1,
        ...
        "augmentation": {
            "data_sources": {
                "my-datasource": 1200
            }
        }
    }
    
  4. Générer une réponse : par défaut, la bibliothèque IA Teams répond à la réponse générée par l’IA sous forme de sms à l’utilisateur. Si vous souhaitez personnaliser la réponse, vous pouvez remplacer les actions SAY par défaut ou appeler explicitement le modèle IA pour générer vos réponses, par exemple, avec des cartes adaptatives.

Voici un ensemble minimal d’implémentations pour ajouter RAG à votre application. En général, il implémente DataSource pour injecter votre knowledge dans l’invite, afin que l’IA puisse générer une réponse basée sur le knowledge.

  • Créer un myDataSource.ts fichier pour implémenter DataSource l’interface :

    export class MyDataSource implements DataSource {
      public readonly name = "my-datasource";
      public async renderData(
        context: TurnContext,
        memory: Memory,
        tokenizer: Tokenizer,
        maxTokens: number
      ): Promise<RenderedPromptSection<string>> {
        const input = memory.getValue('temp.input') as string;
        let knowledge = "There's no knowledge found.";
    
        // hard-code knowledge
        if (input?.includes("shuttle bus")) {
          knowledge = "Company's shuttle bus may be 15 minutes late on rainy days.";
        } else if (input?.includes("cafe")) {
          knowledge = "The Cafe's available time is 9:00 to 17:00 on working days and 10:00 to 16:00 on weekends and holidays."
        }
    
        return {
          output: knowledge,
          length: knowledge.length,
          tooLong: false
        }
      }
    }
    
  • Inscrivez dans app.ts le DataSource fichier :

      // Register your data source to prompt manager
      planner.prompts.addDataSource(new MyDataSource());
    

  • Créez le prompts/qa/skprompt.txt fichier et ajoutez le texte suivant :

    The following is a conversation with an AI assistant. The assistant is helpful, creative, clever, and very friendly to answer user's question.
    
    Base your answer off the text below:
    
  • Créez le prompts/qa/config.json fichier et ajoutez le code suivant pour vous connecter à la source de données :

    {
        "schema": 1.1,
        "description": "Chat with QA Assistant",
        "type": "completion",
        "completion": {
            "model": "gpt-35-turbo",
            "completion_type": "chat",
            "include_history": true,
            "include_input": true,
            "max_input_tokens": 2800,
            "max_tokens": 1000,
            "temperature": 0.9,
            "top_p": 0.0,
            "presence_penalty": 0.6,
            "frequency_penalty": 0.0,
            "stop_sequences": []
        },
        "augmentation": {
            "data_sources": {
                "my-datasource": 1200
            }
        }
    }
    

Sélectionner des sources de données

Dans les scénarios Chat With Your Data ou RAG, Teams Toolkit fournit les types de sources de données suivants :

  • Personnaliser : vous permet de contrôler entièrement l’ingestion des données pour créer votre propre index vectoriel et l’utiliser comme source de données. Pour plus d’informations, consultez Générer votre propre ingestion de données.

    Vous pouvez également utiliser l’extension de base de données vectorielle Azure Cosmos DB ou l’extension vectorielle du serveur Azure PostgreSQL comme bases de données vectorielles, ou l’API Recherche web Bing pour obtenir le contenu web le plus récent afin d’implémenter n’importe quelle instance de source de données pour se connecter à votre propre source de données.

  • Recherche Azure AI : fournit un exemple pour ajouter vos documents au service Recherche Azure AI, puis utiliser l’index de recherche comme source de données.

  • API personnalisée : permet à votre chatbot d’appeler l’API définie dans le document de description OpenAPI pour récupérer des données de domaine à partir du service API.

  • Microsoft Graph et SharePoint : fournit un exemple d’utilisation du contenu Microsoft 365 de l’API Recherche Microsoft Graph comme source de données.

Créer votre propre ingestion de données

Pour générer votre ingestion de données, procédez comme suit :

  1. Charger vos documents sources : assurez-vous que votre document comporte un texte explicite, car le modèle d’incorporation prend uniquement du texte comme entrée.

  2. Fractionner en blocs : veillez à fractionner le document pour éviter les échecs d’appel d’API, car le modèle d’incorporation a une limitation de jeton d’entrée.

  3. Modèle d’incorporation d’appel : appelez les API du modèle d’incorporation pour créer des incorporations pour les entrées données.

  4. Stocker les incorporations : stockez les incorporations créées dans une base de données vectorielle. Incluez également des métadonnées utiles et du contenu brut pour plus de référence.

Exemple de code

  • loader.ts: texte brut comme entrée source.

    import * as fs from "node:fs";
    
    export function loadTextFile(path: string): string {
      return fs.readFileSync(path, "utf-8");
    }
    
  • splitter.ts: fractionnez le texte en blocs, avec un chevauchement.

    
    // split words by delimiters.
    const delimiters = [" ", "\t", "\r", "\n"];
    
    export function split(content: string, length: number, overlap: number): Array<string> {
      const results = new Array<string>();
      let cursor = 0, curChunk = 0;
      results.push("");
      while(cursor < content.length) {
        const curChar = content[cursor];
        if (delimiters.includes(curChar)) {
          // check chunk length
          while (curChunk < results.length && results[curChunk].length >= length) {
            curChunk ++;
          }
          for (let i = curChunk; i < results.length; i++) {
            results[i] += curChar;
          }
          if (results[results.length - 1].length >= length - overlap) {
            results.push("");
          }
        } else {
          // append
          for (let i = curChunk; i < results.length; i++) {
            results[i] += curChar;
          }
        }
        cursor ++;
      }
      while (curChunk < results.length - 1) {
        results.pop();
      }
      return results;
    }
    
    
  • embeddings.ts: utilisez la bibliothèque OpenAIEmbeddings IA Teams pour créer des incorporations.

    import { OpenAIEmbeddings } from "@microsoft/teams-ai";
    
    const embeddingClient = new OpenAIEmbeddings({
      azureApiKey: "<your-aoai-key>",
      azureEndpoint: "<your-aoai-endpoint>",
      azureDeployment: "<your-embedding-deployment, e.g., text-embedding-ada-002>"
    });
    
    export async function createEmbeddings(content: string): Promise<number[]> {
      const response = await embeddingClient.createEmbeddings(content);
      return response.output[0];
    }
    
  • searchIndex.ts: créez un index recherche Azure AI.

    import { SearchIndexClient, AzureKeyCredential, SearchIndex } from "@azure/search-documents";
    
    const endpoint = "<your-search-endpoint>";
    const apiKey = "<your-search-key>";
    const indexName = "<your-index-name>";
    
    const indexDef: SearchIndex = {
      name: indexName,
      fields: [
        {
          type: "Edm.String",
          name: "id",
          key: true,
        },
        {
          type: "Edm.String",
          name: "content",
          searchable: true,
        },
        {
          type: "Edm.String",
          name: "filepath",
          searchable: true,
          filterable: true,
        },
        {
          type: "Collection(Edm.Single)",
          name: "contentVector",
          searchable: true,
          vectorSearchDimensions: 1536,
          vectorSearchProfileName: "default"
        }
      ],
      vectorSearch: {
        algorithms: [{
          name: "default",
          kind: "hnsw"
        }],
        profiles: [{
          name: "default",
          algorithmConfigurationName: "default"
        }]
      },
      semanticSearch: {
        defaultConfigurationName: "default",
        configurations: [{
          name: "default",
          prioritizedFields: {
            contentFields: [{
              name: "content"
            }]
          }
        }]
      }
    };
    
    export async function createNewIndex(): Promise<void> {
      const client = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));
      await client.createIndex(indexDef);
    }
    
  • searchIndexer.ts: chargez les incorporations créées et d’autres champs dans l’index recherche Azure AI.

    import { AzureKeyCredential, SearchClient } from "@azure/search-documents";
    
    export interface Doc {
      id: string,
      content: string,
      filepath: string,
      contentVector: number[]
    }
    
    const endpoint = "<your-search-endpoint>";
    const apiKey = "<your-search-key>";
    const indexName = "<your-index-name>";
    const searchClient: SearchClient<Doc> = new SearchClient<Doc>(endpoint, indexName, new AzureKeyCredential(apiKey));
    
    export async function indexDoc(doc: Doc): Promise<boolean> {
      const response = await searchClient.mergeOrUploadDocuments([doc]);
      return response.results.every((result) => result.succeeded);
    }
    
  • index.ts: orchestrer les composants ci-dessus.

    import { createEmbeddings } from "./embeddings";
    import { loadTextFile } from "./loader";
    import { createNewIndex } from "./searchIndex";
    import { indexDoc } from "./searchIndexer";
    import { split } from "./splitter";
    
    async function main() {
      // Only need to call once
      await createNewIndex();
    
      // local files as source input
      const files = [`${__dirname}/data/A.md`, `${__dirname}/data/A.md`];
      for (const file of files) {
        // load file
        const fullContent = loadTextFile(file);
    
        // split into chunks
        const contents = split(fullContent, 1000, 100);
        let partIndex = 0;
        for (const content of contents) {
          partIndex ++;
          // create embeddings
          const embeddings = await createEmbeddings(content);
    
          // upload to index
          await indexDoc({
            id: `${file.replace(/[^a-z0-9]/ig, "")}___${partIndex}`,
            content: content,
            filepath: file,
            contentVector: embeddings,
          });
        }
      }
    }
    
    main().then().finally();
    

Recherche Azure AI en tant que source de données

Dans cette section, vous allez apprendre à :

Remarque

Cette approche crée une API de conversation de bout en bout appelée modèle IA. Vous pouvez également utiliser l’index créé précédemment comme source de données, et utiliser la bibliothèque IA Teams pour personnaliser la récupération et l’invite.

Vous pouvez ingérer vos documents de connaissances dans azure AI Search Service et créer un index vectoriel avec Azure OpenAI sur vos données. Après l’ingestion, vous pouvez utiliser l’index comme source de données.

  1. Préparez vos données dans stockage Blob Azure.

    Capture d’écran montrant la configuration de l’assistant dans Azure OpenAI Studio.

  2. Dans Azure OpenAI Studio, sélectionnez Ajouter une source de données.

  3. Mettez à jour les champs obligatoires.

    Capture d’écran montrant l’option permettant d’ajouter une source de données.

  4. Sélectionnez Suivant.

    La page Gestion des données s’affiche .

  5. Mettez à jour les champs obligatoires.

  6. Sélectionnez Suivant.

    Capture d’écran montrant l’option permettant de sélectionner ajouter une source de données.

  7. Mettez à jour les champs obligatoires. Sélectionnez Suivant.

    Capture d’écran montrant l’option permettant d’ajouter la gestion des données.

  8. Sélectionnez Enregistrer et fermer.

    Capture d’écran montrant l’option de révision et de fin.

Utiliser la source de données d’index Recherche IA Azure

Après avoir ingéré des données dans Recherche Azure AI, vous pouvez implémenter les vôtres DataSource pour récupérer les données de l’index de recherche.

const { AzureKeyCredential, SearchClient } = require("@azure/search-documents");
const { DataSource, Memory, OpenAIEmbeddings, Tokenizer } = require("@microsoft/teams-ai");
const { TurnContext } = require("botbuilder");

// Define the interface for document
class Doc {
  constructor(id, content, filepath) {
    this.id = id;
    this.content = content; // searchable
    this.filepath = filepath;
  }
}

// Azure OpenAI configuration
const aoaiEndpoint = "<your-aoai-endpoint>";
const aoaiApiKey = "<your-aoai-key>";
const aoaiDeployment = "<your-embedding-deployment, e.g., text-embedding-ada-002>";

// Azure AI Search configuration
const searchEndpoint = "<your-search-endpoint>";
const searchApiKey = "<your-search-apikey>";
const searchIndexName = "<your-index-name>";

// Define MyDataSource class implementing DataSource interface
class MyDataSource extends DataSource {
  constructor() {
    super();
    this.name = "my-datasource";
    this.embeddingClient = new OpenAIEmbeddings({
      azureEndpoint: aoaiEndpoint,
      azureApiKey: aoaiApiKey,
      azureDeployment: aoaiDeployment
    });
    this.searchClient = new SearchClient(searchEndpoint, searchIndexName, new AzureKeyCredential(searchApiKey));
  }

  async renderData(context, memory, tokenizer, maxTokens) {
    // use user input as query
    const input = memory.getValue("temp.input");

    // generate embeddings
    const embeddings = (await this.embeddingClient.createEmbeddings(input)).output[0];

    // query Azure AI Search
    const response = await this.searchClient.search(input, {
      select: [ "id", "content", "filepath" ],
      searchFields: ["rawContent"],
      vectorSearchOptions: {
        queries: [{
          kind: "vector",
          fields: [ "contentVector" ],
          vector: embeddings,
          kNearestNeighborsCount: 3
        }]
      },
      queryType: "semantic",
      top: 3,
      semanticSearchOptions: {
        // your semantic configuration name
        configurationName: "default",
      }
    });

    // Add documents until you run out of tokens
    let length = 0, output = '';
    for await (const result of response.results) {
      // Start a new doc
      let doc = `${result.document.content}\n\n`;
      let docLength = tokenizer.encode(doc).length;
      const remainingTokens = maxTokens - (length + docLength);
      if (remainingTokens <= 0) {
          break;
      }

      // Append doc to output
      output += doc;
      length += docLength;
    }
    return { output, length, tooLong: length > maxTokens };
  }
}

Ajouter d’autres API pour l’API personnalisée en tant que source de données

Suivez ces étapes pour étendre le copilote personnalisé à partir du modèle d’API personnalisée avec d’autres API.

  1. Mettez à jour ./appPackage/apiSpecificationFile/openapi.*.

    Copiez la partie correspondante de l’API que vous souhaitez ajouter à partir de votre spécification et ajoutez à ./appPackage/apiSpecificationFile/openapi.*.

  2. Mettez à jour ./src/prompts/chat/actions.json.

    Mettez à jour les informations et les propriétés nécessaires pour le chemin, la requête et le corps de l’API dans l’objet suivant :

    {
      "name": "${{YOUR-API-NAME}}",
      "description": "${{YOUR-API-DESCRIPTION}}",
      "parameters": {
        "type": "object",
        "properties": {
          "query": {
            "type": "object",
            "properties": {
              "${{YOUR-PROPERTY-NAME}}": {
                "type": "${{YOUR-PROPERTY-TYPE}}",
                "description": "${{YOUR-PROPERTY-DESCRIPTION}}",
              }
              // You can add more query properties here
            }
          },
          "path": {
            // Same as query properties
          },
          "body": {
            // Same as query properties
          }
        }
      }
    }
    
  3. Mettez à jour ./src/adaptiveCards.

    Créez un fichier avec un nom ${{YOUR-API-NAME}}.json et renseignez la carte adaptative pour la réponse d’API de votre API.

  4. Mettez à jour le./src/app/app.js fichier.

    Ajoutez le code suivant avant module.exports = app;:

    app.ai.action(${{YOUR-API-NAME}}, async (context: TurnContext, state: ApplicationTurnState, parameter: any) => {
      const client = await api.getClient();
    
      const path = client.paths[${{YOUR-API-PATH}}];
      if (path && path.${{YOUR-API-METHOD}}) {
        const result = await path.${{YOUR-API-METHOD}}(parameter.path, parameter.body, {
          params: parameter.query,
        });
        const card = generateAdaptiveCard("../adaptiveCards/${{YOUR-API-NAME}}.json", result);
        await context.sendActivity({ attachments: [card] });
      } else {
        await context.sendActivity("no result");
      }
      return "result";
    });
    

Microsoft 365 comme source de données

Découvrez comment utiliser l’API Recherche Microsoft Graph pour interroger du contenu Microsoft 365 en tant que source de données pour l’application RAG. Pour en savoir plus sur l’API Recherche Microsoft Graph, vous pouvez consulter utiliser l’API Recherche Microsoft pour rechercher du contenu OneDrive et SharePoint.

Prérequis : vous devez créer un client d’API Graph et lui accorder l’étendue Files.Read.All d’autorisation pour accéder aux fichiers, dossiers, pages et actualités SharePoint et OneDrive.

Ingestion de données

L’API Recherche Microsoft Graph, qui peut rechercher du contenu SharePoint, est disponible. Par conséquent, vous devez uniquement vous assurer que votre document est chargé sur SharePoint ou OneDrive, sans aucune ingestion de données supplémentaire requise.

Remarque

SharePoint Server indexe un fichier uniquement si son extension de fichier est répertoriée sur la page Gérer les types de fichiers. Pour obtenir la liste complète des extensions de fichier prises en charge, reportez-vous aux extensions de nom de fichier indexées par défaut et aux types de fichiers analysés dans SharePoint Server et SharePoint dans Microsoft 365.

Implémentation de la source de données

Voici un exemple de recherche de fichiers texte dans SharePoint et OneDrive :

import {
  DataSource,
  Memory,
  RenderedPromptSection,
  Tokenizer,
} from "@microsoft/teams-ai";
import { TurnContext } from "botbuilder";
import { Client, ResponseType } from "@microsoft/microsoft-graph-client";

export class GraphApiSearchDataSource implements DataSource {
  public readonly name = "my-datasource";
  public readonly description =
    "Searches the graph for documents related to the input";
  public client: Client;

  constructor(client: Client) {
    this.client = client;
  }

  public async renderData(
    context: TurnContext,
    memory: Memory,
    tokenizer: Tokenizer,
    maxTokens: number
  ): Promise<RenderedPromptSection<string>> {
    const input = memory.getValue("temp.input") as string;
    const contentResults = [];
    const response = await this.client.api("/search/query").post({
      requests: [
        {
          entityTypes: ["driveItem"],
          query: {
            // Search for markdown files in the user's OneDrive and SharePoint
            // The supported file types are listed here:
            // https://learn.microsoft.com/sharepoint/technical-reference/default-crawled-file-name-extensions-and-parsed-file-types
            queryString: `${input} filetype:txt`,
          },
          // This parameter is required only when searching with application permissions
          // https://learn.microsoft.com/graph/search-concept-searchall
          // region: "US",
        },
      ],
    });
    for (const value of response?.value ?? []) {
      for (const hitsContainer of value?.hitsContainers ?? []) {
        contentResults.push(...(hitsContainer?.hits ?? []));
      }
    }

    // Add documents until you run out of tokens
    let length = 0,
      output = "";
    for (const result of contentResults) {
      const rawContent = await this.downloadSharepointFile(
        result.resource.webUrl
      );
      if (!rawContent) {
        continue;
      }
      let doc = `${rawContent}\n\n`;
      let docLength = tokenizer.encode(doc).length;
      const remainingTokens = maxTokens - (length + docLength);
      if (remainingTokens <= 0) {
        break;
      }

      // Append do to output
      output += doc;
      length += docLength;
    }
    return { output, length, tooLong: length > maxTokens };
  }

  // Download the file from SharePoint
  // https://docs.microsoft.com/en-us/graph/api/driveitem-get-content
  private async downloadSharepointFile(
    contentUrl: string
  ): Promise<string | undefined> {
    const encodedUrl = this.encodeSharepointContentUrl(contentUrl);
    const fileContentResponse = await this.client
      .api(`/shares/${encodedUrl}/driveItem/content`)
      .responseType(ResponseType.TEXT)
      .get();

    return fileContentResponse;
  }

  private encodeSharepointContentUrl(webUrl: string): string {
    const byteData = Buffer.from(webUrl, "utf-8");
    const base64String = byteData.toString("base64");
    return (
      "u!" + base64String.replace("=", "").replace("/", "_").replace("+", "_")
    );
  }
}

Voir aussi

Bibliothèque d’IA Teams