Compartir a través de


Creación de un bot rag en Teams

Los bots de chat avanzados de Q&A son aplicaciones eficaces creadas con la ayuda de modelos de lenguaje grande (LLM). Los bots de chat responden a preguntas mediante la extracción de información de orígenes específicos mediante un método denominado generación de Retrieval-Augmented (RAG). La arquitectura rag tiene dos flujos principales:

  • Ingesta de datos: una canalización para ingerir datos de un origen e indexarlos. Esto suele ocurrir sin conexión.

  • Recuperación y generación: la cadena RAG, que toma la consulta del usuario en tiempo de ejecución y recupera los datos pertinentes del índice, los pasa al modelo.

Microsoft Teams le permite crear un bot conversacional con RAG para crear una experiencia mejorada con el fin de maximizar la productividad. Teams Toolkit proporciona una serie de plantillas de aplicación listas para usar en la categoría Chat con sus datos que combina las funcionalidades de búsqueda de Azure AI, Microsoft 365 SharePoint y API personalizada como orígenes de datos y LLM diferentes para crear una experiencia de búsqueda conversacional en Teams.

Requisitos previos

Instalar Para usar...
Visual Studio Code Entornos de compilación de JavaScript, TypeScript o Python. Use la versión más reciente.
Kit de herramientas de Teams Microsoft Visual Studio Code extensión que crea un scaffolding de proyecto para la aplicación. Use la versión más reciente.
Node.js Entorno de tiempo de ejecución de JavaScript de back-end. Para obtener más información, vea Node.js tabla de compatibilidad de versiones para el tipo de proyecto.
Microsoft Teams Microsoft Teams para colaborar con todos los usuarios con los que trabaje a través de aplicaciones para chat, reuniones y llamadas en un solo lugar.
Azure OpenAI En primer lugar, cree la clave de API de OpenAI para usar el transformador preentrenado generativo (GPT) de OpenAI. Si desea hospedar la aplicación o acceder a los recursos en Azure, debe crear un servicio Azure OpenAI.

Creación de un nuevo proyecto básico de bot de chat de IA

  1. Abra Visual Studio Code.

  2. Seleccione el icono Kit de herramientas de Teams en la barra de actividad de Visual Studio Code.

  3. Seleccione Crear una nueva aplicación.

    Captura de pantalla que muestra la ubicación del vínculo Crear nuevo proyecto en la barra lateral del kit de herramientas de Teams.

  4. Seleccione Agente de motor personalizado.

    Captura de pantalla que muestra la opción para seleccionar el agente de motor personalizado como el nuevo proyecto que se va a crear.

  5. Seleccione Chatear con sus datos.

    Captura de pantalla que muestra la opción para seleccionar las características de la aplicación mediante la lista de bibliotecas de inteligencia artificial.

  6. Seleccione Personalizar.

    Captura de pantalla que muestra la opción para seleccionar la personalización de datos para la carga.

  7. Seleccione JavaScript.

    Captura de pantalla que muestra la opción para seleccionar el lenguaje de programación.

  8. Seleccione Azure OpenAI o OpenAI.

    Captura de pantalla que muestra la opción para seleccionar el LLM.

  9. Escriba las credenciales de Azure OpenAI o OpenAI en función del servicio que seleccione. Seleccione Introducir.

    Captura de pantalla que muestra la ubicación para escribir la clave de API abierta de Azure.

  10. Seleccione Carpeta predeterminada.

    Captura de pantalla que muestra la carpeta de la aplicación de ubicación que se va a guardar.

    Para cambiar la ubicación predeterminada, siga estos pasos:

    1. Seleccione Examinar.
    2. Seleccione la ubicación del área de trabajo del proyecto.
    3. Seleccione Seleccionar carpeta.
  11. Escriba un nombre de aplicación para la aplicación y, a continuación, seleccione la tecla Entrar .

    Captura de pantalla que muestra la opción para escribir el nombre adecuado.

    Ha creado correctamente el área de trabajo del proyecto Chat con los datos .

    Captura de pantalla que muestra que el bot de chat de ai creado y el archivo léame están disponibles.

  12. En EXPLORER, vaya al archivo env.env.testtool.user>.

  13. Actualice los valores siguientes:

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

    Captura de pantalla que muestra los detalles actualizados en el archivo env.

  14. Para depurar la aplicación, seleccione la tecla F5 o en el panel izquierdo, seleccione Ejecutar y depurar (Ctrl+Mayús+D) y, a continuación, seleccione Depurar en la herramienta de prueba (versión preliminar) en la lista desplegable.

    Captura de pantalla que muestra la selección de la opción de depuración de la lista de opciones.

La herramienta de prueba abre el bot en una página web.

En pantalla se muestra el chat con la salida final de los datos.

Realice un recorrido por el código fuente de la aplicación bot.

Folder Contenido
.vscode Visual Studio Code archivos para la depuración.
appPackage Plantillas para el manifiesto de aplicación de Teams.
env Archivos de entorno.
infra Plantillas para aprovisionar recursos de Azure.
src Código fuente de la aplicación.
src/index.js Configura el servidor de aplicaciones de bot.
src/adapter.js Configura el adaptador del bot.
src/config.js Define las variables de entorno.
src/prompts/chat/skprompt.txt Define el símbolo del sistema.
src/prompts/chat/config.json Configura el símbolo del sistema.
src/app/app.js Controla las lógicas de negocios para el bot RAG.
src/app/myDataSource.js Define el origen de datos.
src/data/*.md Orígenes de datos de texto sin formato.
teamsapp.yml Este es el archivo de proyecto principal del kit de herramientas de Teams. El archivo de proyecto define las propiedades y las definiciones de la fase de configuración.
teamsapp.local.yml Esto invalida teamsapp.yml con acciones que habilitan la ejecución y depuración locales.
teamsapp.testtool.yml Esto invalida teamsapp.yml con acciones que habilitan la ejecución y depuración locales en la herramienta de prueba de aplicaciones de Teams.

Escenarios de RAG para la inteligencia artificial de Teams

En el contexto de IA, las bases de datos vectoriales se usan ampliamente como almacenamientos RAG, que almacenan datos de incrustaciones y proporcionan búsqueda de similitud vectorial. La biblioteca de inteligencia artificial de Teams proporciona utilidades para ayudar a crear inserciones para las entradas especificadas.

Sugerencia

La biblioteca de inteligencia artificial de Teams no proporciona la implementación de la base de datos vectorial, por lo que debe agregar su propia lógica para procesar las incrustaciones creadas.

// 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

En el diagrama siguiente se muestra cómo la biblioteca de inteligencia artificial de Teams proporciona funcionalidades para facilitar cada paso del proceso de recuperación y generación:

Captura de pantalla que muestra el escenario de RAG.

  1. Controlar la entrada: la manera más directa es pasar la entrada del usuario a la recuperación sin ningún cambio. Sin embargo, si desea personalizar la entrada antes de la recuperación, puede agregar un controlador de actividad a determinadas actividades entrantes.

  2. Recuperar DataSource: la biblioteca de IA de Teams proporciona DataSource una interfaz que le permite agregar su propia lógica de recuperación. Debe crear su propia DataSource instancia y la biblioteca de inteligencia artificial de Teams la llama a petición.

    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. Llame a IA con aviso: en el sistema de avisos de IA de Teams, puede insertar fácilmente un DataSource mediante el ajuste de la augmentation.data_sources sección de configuración. Esto conecta el símbolo del sistema con el DataSource orquestador y la biblioteca para insertar el DataSource texto en el símbolo del sistema final. Para obtener más información, consulte authorprompt. Por ejemplo, en el archivo del símbolo del config.json sistema:

    {
        "schema": 1.1,
        ...
        "augmentation": {
            "data_sources": {
                "my-datasource": 1200
            }
        }
    }
    
  4. Respuesta de compilación: de forma predeterminada, la biblioteca de inteligencia artificial de Teams responde a la respuesta generada por IA como un mensaje de texto para el usuario. Si desea personalizar la respuesta, puede invalidar las acciones SAY predeterminadas o llamar explícitamente al modelo de inteligencia artificial para compilar las respuestas, por ejemplo, con tarjetas adaptables.

Este es un conjunto mínimo de implementaciones para agregar RAG a la aplicación. En general, implementa DataSource para insertar knowledge en el símbolo del sistema, de modo que la inteligencia artificial pueda generar una respuesta basada en knowledge.

  • Cree myDataSource.ts un archivo para implementar DataSource la interfaz:

    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
        }
      }
    }
    
  • Registre el DataSource archivo en app.ts :

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

  • Cree el prompts/qa/skprompt.txt archivo y agregue el texto siguiente:

    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:
    
  • Cree el prompts/qa/config.json archivo y agregue el código siguiente para conectarse con el origen de datos:

    {
        "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
            }
        }
    }
    

Selección de orígenes de datos

En los escenarios Chat with Your Data o RAG, Teams Toolkit proporciona los siguientes tipos de orígenes de datos:

  • Personalizar: permite controlar completamente la ingesta de datos para compilar su propio índice vectorial y usarlo como origen de datos. Para obtener más información, consulte Compilación de su propia ingesta de datos.

    También puede usar la extensión de base de datos vectorial de Azure Cosmos DB o la extensión vector del servidor de Azure PostgreSQL como bases de datos vectoriales, o Bing Web Search API para obtener el contenido web más reciente para implementar cualquier instancia de origen de datos para conectarse con su propio origen de datos.

  • Azure AI Search: proporciona un ejemplo para agregar los documentos a Azure AI Search Service y, a continuación, usar el índice de búsqueda como origen de datos.

  • API personalizada: permite que el bot de chat invoque la API definida en el documento de descripción de OpenAPI para recuperar datos de dominio del servicio de API.

  • Microsoft Graph y SharePoint: proporciona un ejemplo para usar el contenido de Microsoft 365 de Microsoft Graph Search API como origen de datos.

Creación de su propia ingesta de datos

Para compilar la ingesta de datos, siga estos pasos:

  1. Cargar los documentos de origen: asegúrese de que el documento tiene un texto significativo, ya que el modelo de inserción solo toma texto como entrada.

  2. Dividir en fragmentos: asegúrese de dividir el documento para evitar errores de llamada api, ya que el modelo de inserción tiene una limitación de token de entrada.

  3. Modelo de inserción de llamadas: llame a las API del modelo de inserción para crear inserciones para las entradas especificadas.

  4. Almacenar incrustaciones: almacene las incrustaciones creadas en una base de datos vectorial. Incluya también metadatos útiles y contenido sin procesar para seguir haciendo referencia.

Código de ejemplo

  • loader.ts: texto sin formato como entrada de origen.

    import * as fs from "node:fs";
    
    export function loadTextFile(path: string): string {
      return fs.readFileSync(path, "utf-8");
    }
    
  • splitter.ts: divida el texto en fragmentos, con una superposición.

    
    // 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: use la biblioteca OpenAIEmbeddings de inteligencia artificial de Teams para crear inserciones.

    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: cree un índice de Azure AI Search.

    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: cargue las incrustaciones creadas y otros campos en azure AI Search Index.

    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: organice los componentes anteriores.

    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();
    

Azure AI Search como origen de datos

En esta sección aprenderá a:

Nota:

Este enfoque crea una API de chat de un extremo a otro denominada modelo de inteligencia artificial. También puede usar el índice creado anteriormente como origen de datos y usar la biblioteca de inteligencia artificial de Teams para personalizar la recuperación y la solicitud.

Puede ingerir los documentos de conocimiento en Azure AI Search Service y crear un índice vectorial con Azure OpenAI en los datos. Después de la ingesta, puede usar el índice como origen de datos.

  1. Prepare los datos en Azure Blob Storage.

    Captura de pantalla que muestra asistente configuración en Azure OpenAI Studio.

  2. En Azure OpenAI Studio, seleccione Agregar un origen de datos.

  3. Actualice los campos necesarios.

    Captura de pantalla que muestra la opción para agregar el origen de datos.

  4. Seleccione Siguiente.

    Aparece la página Administración de datos .

  5. Actualice los campos necesarios.

  6. Seleccione Siguiente.

    Captura de pantalla que muestra la opción para seleccionar Agregar origen de datos.

  7. Actualice los campos necesarios. Seleccione Siguiente.

    Captura de pantalla que muestra la opción para agregar la administración de datos.

  8. Seleccione Guardar y cerrar.

    Captura de pantalla que muestra la opción para revisar y finalizar.

Uso del origen de datos del índice de Azure AI Search

Después de ingerir datos en Azure AI Search, puede implementar los suyos propios DataSource para recuperar datos del índice de búsqueda.

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 };
  }
}

Adición de más API para Custom API como origen de datos

Siga estos pasos para ampliar el agente de motor personalizado desde la plantilla de API personalizada con más API.

  1. Actualice ./appPackage/apiSpecificationFile/openapi.*.

    Copie la parte correspondiente de la API que desea agregar desde la especificación y anexe a ./appPackage/apiSpecificationFile/openapi.*.

  2. Actualice ./src/prompts/chat/actions.json.

    Actualice la información y las propiedades necesarias para la ruta de acceso, la consulta y el cuerpo de la API en el objeto siguiente:

    {
      "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. Actualice ./src/adaptiveCards.

    Cree un nuevo archivo con el nombre ${{YOUR-API-NAME}}.json y rellene la tarjeta adaptable para la respuesta de api de la API.

  4. Actualice el./src/app/app.js archivo.

    Agregue el código siguiente antes de 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 como origen de datos

Aprenda a usar Microsoft Graph Search API para consultar contenido de Microsoft 365 como origen de datos de la aplicación RAG. Para obtener más información sobre Microsoft Graph Search API, puede hacer referencia a usar Microsoft Search API para buscar contenido de OneDrive y SharePoint.

Requisito previo: debe crear un cliente Graph API y concederle el ámbito de Files.Read.All permiso para acceder a archivos, carpetas, páginas y noticias de SharePoint y OneDrive.

Ingesta de datos

La API de búsqueda de Microsoft Graph, que puede buscar contenido de SharePoint, está disponible. Por lo tanto, solo debe asegurarse de que el documento se carga en SharePoint o OneDrive, sin necesidad de ingesta de datos adicional.

Nota:

El servidor de SharePoint indexa un archivo solo si su extensión de archivo aparece en la página Administrar tipos de archivo. Para obtener una lista completa de las extensiones de archivo admitidas, consulte las extensiones de nombre de archivo indizadas predeterminadas y los tipos de archivo analizados en SharePoint Server y SharePoint en Microsoft 365.

Implementación del origen de datos

A continuación se muestra un ejemplo de búsqueda de archivos de texto en SharePoint y 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("+", "_")
    );
  }
}

Recursos adicionales

Biblioteca de IA de Teams