Harjoitus – Ota käyttöön vektori- ja GPT-haut

Valmis

Tässä harjoituksessa otat käyttöön ja parannat sovelluksesi tekoälyvektorihakutoimintoa luomalla upotuksia, suorittamalla vektorihakuja ja integroimalla GPT-3.5:n täydennettyjä hakutuloksia varten. Päivität JavaScript-avainfunktiot, jotta voit ladata ja vektoroida tietoja, luoda vektoriindeksejä ja määrittää hakukomponentteja. Suorittamalla nämä vaiheet voit syventää ymmärrystäsi verkkosovelluksen upottamisesta, vektorihakutekniikoista ja tekoälyintegraatiosta.

Tärkeää

Muista suorittaa edellisen Ohjatun projektin valmistelu -osion vaiheet ennen tämän harjoituksen aloittamista.

Tässä tehtävässä lisäät koodin, joka lataa tietoja tietokantaan, luo tiedostojen upotuksia ja luo vektoriindeksin.

  1. Siirry tiedostoon 6-ohjattu projekti/node.js/Kokoelmat/products.js

  2. Päivitä generateProductEmbedding-funktio seuraavalla koodilla:

    // Construct a string representing the product's name and category
    const productName = "Category - " + product["categoryName"] + ", Name -" + product["name"];
    
    // If the productName exists, generate an embedding for it
    if (productName) {
        // The embedding is generated using the Embeddings module's generateEmbeddings function
        // The resulting embedding is stored in the product object under the key "productVector"
        product["productVector"] = await Embeddings.generateEmbeddings(productName, embeddingsDeployment, AzureOpenAIClient);
    }
    
    // Return the product object with the added embedding
    return product;
    

    Muista tallentaa muutokset tiedostoon. Tämä funktio valitsee kentät, joille upotus luodaan, kutsuu Azure OpenAI:tä näiden upotusten luomiseksi ja tallentaa ne tietokannan vektorisarakkeeseen.

  3. Siirry tiedostoon ./node.js/SearchComponents/embeddings.js

  4. Päivitä generateEmbeddings-funktio seuraavalla koodilla:

    // Generate embeddings from string of text.
    // This will be used to vectorize data and user input for interactions with Azure OpenAI.
    // Use the async-retry module to attempt the following code block
    // If an error occurs, it will retry up to 10 times, with an increasing timeout between each attempt
    return await retry(async bail => {
        try {
            // Call the Azure OpenAI Client's getEmbeddings function with the embeddings deployment and text
            // Await the response and store it in the response variable
            const response = await AzureOpenAIClient.embeddings.create({ input: text, model: embeddingsDeployment });
    
            // Extract the embeddings from the response data
            const embeddings = response.data[0].embedding;
            // Wait for 10 milliseconds to avoid rate limiting (change to 500 on AOAI for free tier)
            await new Promise(resolve => setTimeout(resolve, 10));
            // Return the embeddings
            return embeddings;
        } catch (err) {
            // If a 429 error (Too Many Requests) is received, rethrow the error to trigger a retry
            if (err.response && err.response.status === 429) {
                throw err;
            } else {
                // For any other error, stop retrying and throw the error
                bail(err);
            }
        }
    }, {
        retries: 10, // Maximum number of retries
        minTimeout: 1000, // Minimum timeout between retries (1 second)
        factor: 2, // Factor by which the timeout increases each time
        maxTimeout: 20000 // Maximum timeout between retries (20 seconds)
    });
    

    Tämä funktio luo upotuksia mille tahansa merkkijonolle Azure OpenAI Embeddings -funktion avulla. Nämä upotustiedostot lähetetään takaisin vektorisarakkeisiin tai käytettäviksi vektorihauissa.

    MongoDB-tiedostojen upotusprosessi Azure OpenAI:n avulla määrittää RAG:n vaiheen optimoimalla tiedot sekä noutamista että luontia varten.

  5. Siirry tiedostoon ./node.js/Blobs/loadAndVectorize.js

  6. Etsi loadAndVectorizeLocalBlobDataToMongoDBCluster-funktio .

    Tällä funktiolla on useita tarkoituksia. Se käy läpi kaikki paikalliset datatiedostot, purkaa niiden tiedostot, tarvittaessa kutsuu funktiota, jolla luodaan upotuksia kyseisiin asiakirjoihin, ja tallentaa asiakirjat tietokantaan.

  7. Lisää seuraava koodi funktion loppuun:

    // Create the vector indexes for the collection
    if (processCustomersVector && collectionName === "customers") {
        indexList = [
            ["customerTypeVectorSearchIndex", "customerTypeVector"],
            ["customerTitleVectorSearchIndex", "customerTitleVector"],
            ["customerNameVectorSearchIndex", "customerNameVector"],
            ["customerEmailAddressVectorSearchIndex", "customerEmailAddressVector"],
            ["customerPhoneNumberVectorSearchIndex", "customerPhoneNumberVector"],
            ["customerAddressesVectorSearchIndex", "customerAddressesVector"]
        ];
        await Indexes.createVectorIndexes(collection, indexList, db, collectionName);
    } else if (processProductsVector && collectionName === "products") {
        indexList = [
            ["productVectorSearchIndex", "productVector"]
        ];
        await Indexes.createVectorIndexes(collection, indexList, db, collectionName);
    } else if (processSalesOrdersVector && collectionName === "salesOrders") {
        indexList = [
            ["salesOrderDetailVectorSearchIndex", "salesOrderDetailVector"]
        ];
        await Indexes.createVectorIndexes(collection, indexList, db, collectionName);
    }
    

    Nyt luot kokoelmalle vektoriindeksit vektorisarakkeiden perusteella. Tässä koodissa valitset, mitkä vektorisarakkeet ja indeksien nimet on luotava. Muista tallentaa muutokset tiedostoon.

  8. Siirry tiedostoon ./node.js/SearchComponents/indexes.js

    Nyt kun tiedät, mitä vektorisarakkeiden ja vektoriindeksien nimiä haluat luoda, päivitämme funktion, joka luo indeksit itse. Voidaan luoda kahdenlaisia vektoriindeksejä, IVF (inverted File Index) ja HNSW (hierarkkinen Navigable Small World -indeksi). Tässä harjoituksessa luot IVF-indeksit.

  9. Päivitä createVectorIndexes-funktio seuraavalla koodilla:

    // Get the current indexes in the collection
    const collectionIndexes = await collection.indexInformation();
    
    // Iterate over each index in the indexList
    for (let [indexName, vectorColumn] of indexList) {
        // Iterate over each index in the collection
        for (let index of Object.keys(collectionIndexes)) {
            // If the index already exists in the collection, drop it
            if (index === indexName) {
                await collection.dropIndex(indexName);
                break;
            }
        }
    
        // Create a new IVF index in the collection
        // The index is created using the MongoDB command function
        // The command specifies the collection to create the index in, the name of the index, 
        // the key to index on, and the options for the CosmosDB search
        const commandResult = await db.command({
            'createIndexes': collectionName,
            'indexes': [
                {
                    'name': indexName,
                    'key': {
                        [vectorColumn]: "cosmosSearch"
                    },
                    'cosmosSearchOptions': {
                        'kind': 'vector-ivf',
                        'numLists': 1,
                        'similarity': 'COS',
                        'dimensions': 1536
                    }
                }
            ]
        });
    }
    

    Tallenna muutokset tiedostoon. Tämä funktio pudottaa indeksin ensin, jos se on jo olemassa, ja luo sitten uuden IVF-indeksin kokoelmaan annetun vektorisarakkeen ja indeksin nimen perusteella. Se luo indeksin käyttämällä MongoDB-komentofunktiota.

    Nyt voit suorittaa vektorihakuja käyttämällä luotuja upotuksia ja vektoriindeksejä. Myöhemmin parannat vektorihakutuloksia gpt-3.5:llä.

  10. Siirry ./node.js/SearchComponents/searches.js -tiedostoon.

    Koska loit vektoriindeksin tuotteiden kokoelmaan, valmistellaan vektorihaku erityisesti kyseistä kokoelmaa varten.

  11. Päivitä runVectorSearch-funktio seuraavalla koodilla:

    // Define the maximum number of results, the vector column, and the collection name
    const maxResults = 20;
    const vectorColumn = "productVector";
    const collectionName = "products";
    
    // Connect to the database and get the collection
    const db = client.db(cosmosDbMongodbDatabase);
    const collection = db.collection(collectionName);
    
    // Run the vector search and return the results
    let resultArray = [];
    const results = await VectorSearch.vectorSearch(userInput, vectorColumn, collection, embeddingsDeployment, AzureOpenAIClient, maxResults);
    for (let result of results) {
        resultArray.push(`Similarity Score: ${result.similarityScore}, category: ${result.document.categoryName}, Product: ${result.document.name}`);
    }
    return resultArray;
    

    Muista tallentaa muutoksesi. Tämä funktio käyttää käyttäjän syötteen kehotetta ja kutsuu funktion, joka luo kehotteen upotuksia ja hakee vektoriindeksistä samankaltaisia asiakirjoja. Sen jälkeen se näyttää tulokset konsolissa samankaltaisuuspisteet mukaan lukien.

  12. Siirry tiedostoon ./node.js/SearchComponents/vectorSearch.js

    Seuraavaksi päivität funktion, joka suorittaa vektorihaun.

  13. Päivitä vectorSearch-funktio seuraavalla koodilla:

    // Generate embeddings for the query using the Embeddings module
    const queryEmbedding = await Embeddings.generateEmbeddings(query, embeddingsDeployment, AzureOpenAIClient);
    
    // Define the aggregation pipeline for the MongoDB query
    // The pipeline first performs a search using the generated embeddings and the specified vector column
    // It then projects the results to include the similarity score and the original document
    const pipeline = [
        {
            '$search': {
                "cosmosSearch": {
                    "vector": queryEmbedding,
                    "path": vectorColumn,
                    "k": numResults
                },
                "returnStoredSource": true
            }
        },
        { '$project': { 'similarityScore': { '$meta': 'searchScore' }, 'document': '$$ROOT' } }
    ];
    
    // Execute the aggregation pipeline on the collection and convert the results to an array
    const results = await collection.aggregate(pipeline).toArray();
    // Return the results
    return results;
    

    Tämä funktio suorittaa vektorihaun luomalla käyttäjäkyselyn upotuksia, jolloin se voi etsiä samankaltaisia tiedostoja tietokannasta. Se luo ensin kyselyn upottamisen -funktiolla generateEmbeddings , joka muuttaa kyselytekstin vektoriksi. Seuraavaksi se määrittää MongoDB-koosteputken, joka käyttää kyselyn upotusta etsiäkseen vastaavat tiedostot määritetystä vektorisarakkeesta lajittelemalla samankaltaisuuden mukaan. Lopuksi se palauttaa tulokset, mukaan lukien kunkin asiakirjan ja sen samankaltaisuuspisteet sen mukaan, miten tarkasti se vastaa kyselyä.

Integroi GPT-3.5 parannettujen hakutulosten varmistamiseksi

Vektorihakutulokset voivat olla tehokkaita, mutta ne saattavat vaatia lisäkoodausta tulosten täydelliseen tulkintaan ja hyödyntämiseen. Tässä tehtävässä integroit GPT-3:n, jotta saat tarkempia ja ihmisen luettavissa olevia merkityksellisiä tietoja vektorihakutuloksista.

  1. Siirry tiedostoon ./node.js/SearchComponents/searches.js

  2. Päivitä runGPTSearch-funktio seuraavalla koodilla:

    // Define the maximum number of results, the vector column, and the collection name
    const maxResults = 20;
    const vectorColumn = "productVector";
    const collectionName = "products";
    
    // Connect to the database and get the collection
    const db = client.db(cosmosDbMongodbDatabase);
    const collection = db.collection(collectionName);
    
    // Run the vector search
    const resultsForPrompt = await VectorSearch.vectorSearch(userInput, vectorColumn, collection, embeddingsDeployment, AzureOpenAIClient, maxResults);
    
    // Generate completions based on the vector search results
    const completionsResults = await Completion.generateCompletion(resultsForPrompt, completionDeployment, AzureOpenAIClient, userInput);
    return completionsResults.choices[0].message.content;
    

    Muista tallentaa muutoksesi. RunVectorSearch-funktion tavoin tämä funktio kysyy kehotetta suoritettavaksi vektoriindeksiä vasten. Kun vektorihakutulokset on saatu, toinen funktio käsittelee tulokset GPT-3.5:llä ja tuottaa tarkempia, ihmisen luettavissa olevia merkityksellisiä tietoja.

  3. Siirry tiedostoon ./node.js/SearchComponents/completion.j

    GPT-3.5:n käyttäminen hakutulosten parantamiseen tuo RAG-prosessin täyteen ympyrään. Se muuttaa perustietojen haut yksityiskohtaisiksi, vuorovaikutteisiksi keskusteluiksi, jotka osoittavat tietokantatekniikan yhdistämisen voiman tekoälyn kanssa.

  4. Päivitä generateCompletion-funktio seuraavalla koodilla

    // Define the system prompt that sets the context for the AI
    const systemPrompt = `
    You are an intelligent assistant for the Adventure Works Bike Shop.
    You are designed to provide helpful answers to user questions about the store inventory given the information about to be provided.
        - Only answer questions related to the information provided below, provide 3 clear suggestions in a list format.
        - Write two lines of whitespace between each answer in the list.
        - Only provide answers that have products that are part of the Adventure Works Bike Shop.
        - If you're unsure of an answer, you can say "I don't know" or "I'm not sure" and recommend users search themselves.
    `;
    
    // Initialize the messages array with the system prompt and user input
    let messages = [
        {role: "system", content: systemPrompt},
        {role: "user", content: userInput},
    ];
    
    // Add each item from the prompt to the messages array
    for (let item of prompt) {
        messages.push({role: "system", content: `${item.document.categoryName} ${item.document.name}`});
    }
    
    // Call the Azure OpenAI Completion Client's getChatCompletions function with the completion deployment and messages
    // Await the response and store it in the response variable
    const response = await AzureOpenAICompletionClient.chat.completions.create({ messages: messages, model: completionDeployment });
    
    // Return the response
    return response;
    

    Tässä funktiossa on kolme kehotteiden joukkoa. Ensimmäinen on järjestelmäkehote (systemPrompt), joka määrittää tekoälyn kontekstin, eli sen, kuka on tekoälyn oletettu rooli ja mitä parametreja/sääntöjä sen tulisi noudattaa. Toinen on käyttäjän syöte (userInput), joka on esittämämme kysymys tai kehote. Kolmas on vektorihaun (kehote) tulosten matriisi samasta edellisestä kysymyksestä tai kehotteesta, jonka kysyimme. Sen jälkeen se kutsuu Azure OpenAI Chat Completions -funktiota, jonka avulla luodaan näihin kehotteeseen perustuvia viimeistelyjä.

Siirtyminen vektorihakujen suorittamisesta tulosten parantamiseen GPT-3.5-keskusteluilla korostaa RAG-menetelmää ja integroi tarkan tietohaun saumattomasti tekoälypohjaisilla keskustelukohtaisilla merkityksellisillä tiedoilla.