Harjoitus – Ota käyttöön vektori- ja GPT-haut
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.
Koodin toteuttaminen upotusten luomiseksi ja vektorihaun suorittaminen
Tässä tehtävässä lisäät koodin, joka lataa tietoja tietokantaan, luo tiedostojen upotuksia ja luo vektoriindeksin.
Siirry tiedostoon 6-ohjattu projekti/node.js/Kokoelmat/products.js
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.
Siirry tiedostoon ./node.js/SearchComponents/embeddings.js
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.
Siirry tiedostoon ./node.js/Blobs/loadAndVectorize.js
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.
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.
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.
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ä.
Siirry ./node.js/SearchComponents/searches.js -tiedostoon.
Koska loit vektoriindeksin tuotteiden kokoelmaan, valmistellaan vektorihaku erityisesti kyseistä kokoelmaa varten.
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.
Siirry tiedostoon ./node.js/SearchComponents/vectorSearch.js
Seuraavaksi päivität funktion, joka suorittaa vektorihaun.
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.
Siirry tiedostoon ./node.js/SearchComponents/searches.js
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.
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.
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.