Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Intelligens AI-ügynök létrehozása TypeScript és Azure DocumentDB használatával. Ez a rövid útmutató egy kétügynök-architektúrát mutat be, amely szemantikai szállodakeresést végez, és személyre szabott javaslatokat hoz létre.
Important
Ez a minta a LangChaint használja, amely egy népszerű keretrendszer az AI-alkalmazások létrehozásához. A LangChain absztrakciókat biztosít az ügynökök, eszközök és kérések számára, amelyek leegyszerűsítik az ügynökök fejlesztését.
Prerequisites
Az Azure Developer CLI használatával létrehozhatja a szükséges Azure-erőforrásokat a azd mintaadattár parancsainak futtatásával. További információ: Infrastruktúra üzembe helyezése az Azure Developer CLI-vel.
Azure-erőforrások
Azure OpenAI a Microsoft Foundry Models erőforrásban (klasszikus) a következő modelltelepítésekkel a Microsoft Azure AI Foundryben:
-
gpt-4oüzembe helyezés (szintetizátorügynök) – Ajánlott: 50 000 token/perc (TPM) kapacitás -
gpt-4o-miniüzembe helyezés (Planner-ügynök) – Ajánlott: 30 000 token/perc (TPM) kapacitás -
text-embedding-3-smallüzembe helyezés (beágyazások) – Ajánlott: 10 000 token/perc (TPM) kapacitás -
Jogkivonatkvóták: Konfiguráljon elegendő TPM-et minden üzembe helyezéshez a sebességkorlátozás elkerülése érdekében
- Lásd: Azure OpenAI-kvóták kezelése a kvótakezeléshez
- Ha 429-et tapasztal, növelje a TPM-kvótát, vagy csökkentse a kérelmek gyakoriságát
-
Azure DocumentDB (MongoDB-kompatibilitással) fürt vektorkeresési támogatással:
-
A fürtréteg követelményei az előnyben részesített vektorindex-algoritmus alapján:
- IVF (invertált fájlindex): M10 vagy újabb (alapértelmezett algoritmus)
- HNSW (Hierarchikus navigálható kisvilág): M30 vagy újabb (gráfalapú)
- DiskANN: M40 vagy újabb (nagy léptékűre optimalizálva)
-
Tűzfalkonfiguráció: KÖTELEZŐ. Megfelelő tűzfalkonfiguráció nélkül a csatlakozási kísérletek meghiúsulnak.
- Adja hozzá az ügyfél IP-címét a fürt tűzfalszabályaihoz. További információ: Hozzáférés engedélyezése az IP-címről.
- A jelszó nélküli hitelesítéshez győződjön meg arról, hogy a szerepköralapú hozzáférés-vezérlés (RBAC) engedélyezve van.
-
A fürtréteg követelményei az előnyben részesített vektorindex-algoritmus alapján:
Fejlesztői eszközök
- Azure Developer CLI az erőforrás-kiépítéshez
- Node.js LTS
- TypeScript 5.0 vagy újabb
- Azure CLI hitelesítéshez
- Visual Studio Code a DocumentDB kiterjesztéssel az adatbázis-kezeléshez (nem kötelező)
Agentic RAG alkalmazás-architektúra Node.js-hez
A minta egy kétügynök-architektúrát használ, amelyben minden ügynöknek van egy adott szerepköre.
Ez a minta LangChain ügynök-keretrendszerét használja az OpenAI SDK-val. A LangChain függvényhívási absztrakciókat alkalmaz az eszközintegrációhoz, és lineáris munkafolyamatot követ az ügynökök és a keresőeszköz között. A végrehajtás állapot nélküli, beszélgetési előzmények nélkül, így alkalmas egyfordulós lekérdezési és válaszhelyzetekhez.
A Node.js mintakód lekérése
A gyors kezdés követéséhez klónozza vagy töltse le az Azure DocumentDB mintákat a helyi gépére.
Lépjen be a projektkönyvtárba:
cd ai/vector-search-agent-typescript
Azure-erőforrások üzembe helyezése az Azure Developer CLI-vel
Az Azure Developer CLI (azd) használatával kiépíteni a szükséges Azure OpenAI- és DocumentDB-erőforrásokat.
Jelentkezzen be az Azure-ba:
azd auth loginAz infrastruktúra kiépítése és üzembe helyezése:
azd upAmikor a rendszer kéri, válassza ki az előfizetést és egy helyet (például
swedencentralvagyeastus2).Az üzembe helyezés befejezése
azdután a szükséges környezeti változókat adja ki. Másolja őket a.envfájlba (lásd : Környezeti változók konfigurálása).
Jótanács
Futtassa a azd env get-values bármikor az aktuális környezeti értékek megtekintéséhez.
Környezeti változók konfigurálása
Ha manuálisan hozta létre az Azure-erőforrásokat, vagy saját meglévő erőforrásait szeretné használni, konfigurálnia kell az alkalmazás környezeti változóit az Azure OpenAI-hoz és az Azure DocumentDB-hez való csatlakozáshoz. Ha azd up használta, akkor kihagyhatja ezt a lépést, mivel a szükséges környezeti változók automatikusan be vannak állítva a azd környezetben, és elérhetők a azd env get-values segítségével.
Hozzon létre egy .env fájlt a projekt gyökérkönyvtárában a környezeti változók konfigurálásához. Létrehozhat egy másolatot a .env.sample fájlról az adattárból.
Szerkessze a .env fájlt, és cserélje le a helyőrző értékeket.
Ez a gyorsindítás egy kétügynökös architektúrát (tervező + szintetizátor) használ három modelltelepítéssel (két csevegőmodell + beágyazások). A környezeti változók minden modelltelepítéshez konfigurálva vannak.
-
AZURE_OPENAI_PLANNER_MODEL: A gpt-4o-mini modell neve -
AZURE_OPENAI_SYNTH_MODEL: A(z) gpt-4o modell neve -
AZURE_OPENAI_EMBEDDING_MODEL: text-embedding-3-small modell neve
Két hitelesítési módszer közül választhat: jelszó nélküli hitelesítés az Azure Identity használatával (ajánlott), vagy hagyományos kapcsolati sztring és API-kulcs.
1. lehetőség: Jelszó nélküli hitelesítés
Használjon jelszó nélküli hitelesítést az Azure OpenAI-val és az Azure DocumentDB-vel is. Beállítás USE_PASSWORDLESS=true, AZURE_OPENAI_ENDPOINT, és AZURE_DOCUMENTDB_CLUSTER.
# Enable passwordless authentication
USE_PASSWORDLESS=true
# Azure OpenAI Configuration (passwordless)
AZURE_OPENAI_ENDPOINT=your-openai-endpoint
AZURE_OPENAI_PLANNER_MODEL=gpt-4o-mini
AZURE_OPENAI_PLANNER_API_VERSION=2024-08-01-preview
AZURE_OPENAI_SYNTH_MODEL=gpt-4o
AZURE_OPENAI_SYNTH_API_VERSION=2024-08-01-preview
AZURE_OPENAI_EMBEDDING_MODEL=text-embedding-3-small
AZURE_OPENAI_EMBEDDING_API_VERSION=2023-05-15
# Azure DocumentDB (passwordless)
AZURE_DOCUMENTDB_CLUSTER=your-mongo-cluster-name
AZURE_DOCUMENTDB_DATABASENAME=Hotels
AZURE_DOCUMENTDB_COLLECTION=hotel_data
# Data Configuration
DATA_FILE_WITHOUT_VECTORS=../data/Hotels.json
# Vector Index Configuration
VECTOR_INDEX_ALGORITHM=vector-ivf
EMBEDDING_DIMENSIONS=1536
A jelszó nélküli hitelesítés előfeltételei:
Győződjön meg arról, hogy bejelentkezett az Azure-ba:
az loginAdja meg identitásának a következő szerepköröket:
-
Cognitive Services OpenAI Useraz Azure OpenAI-erőforráson -
DocumentDB Account ContributorésCosmos DB Account Reader Roleaz Azure DocumentDB-erőforráson
A szerepkörök hozzárendelésével kapcsolatos további információkért lásd: Azure-szerepkörök hozzárendelése az Azure Portal használatával.
-
A jelszó nélküli hitelesítés működése
Amikor USE_PASSWORDLESS=true az alkalmazás az Azure Identity SDK-ból szerez be DefaultAzureCredential egy OAuth-jogkivonatot. Az Azure DocumentDB-kapcsolatok esetében OIDC-jogkivonat-visszahívást használ, amely közvetlenül a MongoDB-illesztőnek továbbítja a hozzáférési jogkivonatot. Ez azt jelenti, hogy a konfigurációs fájlok nem tárolnak jelszavakat vagy kapcsolati sztringeket.
A hitelesítési folyamat:
-
DefaultAzureCredentiala rendelkezésre álló hitelesítő adatokat (Azure CLI, felügyelt identitás, környezeti változók) sorrendben ellenőrzi. - Az Azure OpenAI esetében a token automatikusan átadásra kerül a LangChain
AzureChatOpenAIésAzureOpenAIEmbeddingsklienseknek. - Az Azure DocumentDB esetében a token visszahívási függvény lekéri a hozzáférési tokent, és azt a
MONGODB-OIDChitelesítési mechanizmuson keresztül biztosítja a MongoDB-ügyfélnek.
import { AzureOpenAIEmbeddings, AzureChatOpenAI } from "@langchain/openai";
import { MongoClient, OIDCCallbackParams } from 'mongodb';
import { AccessToken, DefaultAzureCredential, TokenCredential, getBearerTokenProvider } from '@azure/identity';
/*
This file contains utility functions to create Azure OpenAI clients for embeddings, planning, and synthesis.
It supports two modes of authentication:
1. API Key based authentication using AZURE_OPENAI_API_KEY and AZURE_OPENAI_ENDPOINTenvironment variables.
2. Passwordless authentication using DefaultAzureCredential from Azure Identity library.
*/
// Azure Identity configuration
const OPENAI_SCOPE = 'https://cognitiveservices.azure.com/.default';
const DOCUMENT_DB_SCOPE = 'https://ossrdbms-aad.database.windows.net/.default';
// Azure identity credential (used for passwordless auth)
const CREDENTIAL = new DefaultAzureCredential();
function requireEnvVars(names: string[]) {
const missing = names.filter((name) => {
const value = process.env[name];
return !value || value.trim().length === 0;
});
if (missing.length > 0) {
throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
}
}
// Token callback for MongoDB OIDC authentication
async function azureIdentityTokenCallback(
params: OIDCCallbackParams,
credential: TokenCredential
): Promise<{ accessToken: string; expiresInSeconds: number }> {
const tokenResponse: AccessToken | null = await credential.getToken([DOCUMENT_DB_SCOPE]);
return {
accessToken: tokenResponse?.token || '',
expiresInSeconds: (tokenResponse?.expiresOnTimestamp || 0) - Math.floor(Date.now() / 1000)
};
2. lehetőség: Kapcsolati sztring és API-kulcs hitelesítése
Használjon kulcsalapú hitelesítést a USE_PASSWORDLESS=false beállításával (vagy kihagyásával), és adja meg a AZURE_OPENAI_API_KEY és AZURE_DOCUMENTDB_CONNECTION_STRING értékeket a .env fájlban.
# Disable passwordless authentication
USE_PASSWORDLESS=false
# Azure OpenAI Configuration (API key)
AZURE_OPENAI_ENDPOINT=your-openai-endpoint
AZURE_OPENAI_API_KEY=your-azure-openai-api-key
AZURE_OPENAI_PLANNER_MODEL=gpt-4o-mini
AZURE_OPENAI_PLANNER_API_VERSION=2024-08-01-preview
AZURE_OPENAI_SYNTH_MODEL=gpt-4o
AZURE_OPENAI_SYNTH_API_VERSION=2024-08-01-preview
AZURE_OPENAI_EMBEDDING_MODEL=text-embedding-3-small
AZURE_OPENAI_EMBEDDING_API_VERSION=2023-05-15
# Azure DocumentDB (connection string)
AZURE_DOCUMENTDB_CLUSTER=your-mongo-cluster-name
AZURE_DOCUMENTDB_CONNECTION_STRING=mongodb+srv://username:password@cluster.mongocluster.cosmos.azure.com/
AZURE_DOCUMENTDB_DATABASENAME=Hotels
AZURE_DOCUMENTDB_COLLECTION=hotel_data
# Data Configuration
DATA_FILE_WITHOUT_VECTORS=../data/Hotels.json
# Vector Index Configuration
VECTOR_INDEX_ALGORITHM=vector-ivf
EMBEDDING_DIMENSIONS=1536
A projekt szerkezete
A projekt egy szabványos Node.js/TypeScript-projektelrendezést követ. A címtárszerkezetnek a következő struktúrához hasonlóan kell kinéznie:
vector-search-agent-typescript/
├── src/
│ ├── agent.ts # Main agent application
│ ├── upload-documents.ts # Data upload utility
│ ├── cleanup.ts # Database cleanup utility
│ ├── vector-store.ts # Vector store and tool implementation
│ ├── utils/
│ │ ├── clients.ts # Azure OpenAI and DocumentDB client setup
│ │ ├── prompts.ts # System prompts and tool definitions
│ │ ├── types.ts # TypeScript type definitions
│ │ └── mongo.ts # MongoDB utility functions
│ └── scripts/ # Additional utility scripts
├── .env # Environment variable configuration
├── package.json # npm dependencies and scripts
└── tsconfig.json # TypeScript configuration
Az ügynöki RAG-alkalmazás Node.js kódjának megismerése
Ez a szakasz az AI-ügynök munkafolyamatának alapvető összetevőit ismerteti. Kiemeli, hogy az ügynökök hogyan dolgozzák fel a kéréseket, hogyan csatlakoztatják az eszközök az AI-t az adatbázishoz, és hogy a kérések hogyan irányítja az AI viselkedését.
Node.js Agentic RAG-alkalmazás
A src/agent.ts fájl egy AI-alapú szállodaajánlási rendszert vezényl.
Az alkalmazás két Azure-szolgáltatást használ:
- A lekérdezéseket megértő és javaslatokat generáló AI-modelleket használó Azure OpenAI
- Azure DocumentDB, amely szállodai adatokat tárol, és vektoros hasonlósági keresést végez
Node.js Ügynök és eszközösszetevők
A három összetevő együttműködve dolgozza fel a szálloda keresési kérését:
- Planner-ügynök – Értelmezi a kérést, és eldönti, hogyan kell keresni
- Vektorkereső eszköz – A Planner-ügynök által leírthoz hasonló szállodák keresése
- Szintetizátorügynök – Hasznos javaslatot ír a keresési eredmények alapján
Ügynök alapú RAG alkalmazás munkafolyamata
Az alkalmazás két lépésben dolgozza fel a szálloda keresési kérését:
- Tervezés: A munkafolyamat meghívja a planner-ügynököt, amely elemzi a felhasználó lekérdezését (például "futó nyomvonalak közelében lévő szállodák"), és megkeresi az adatbázisban az egyező szállodákat.
- Szintetizáló: A munkafolyamat meghívja a szintetizátor-ügynököt, amely áttekinti a keresési eredményeket, és személyre szabott javaslatot ír, amely ismerteti, hogy mely szállodák felelnek meg a legjobban a kérésnek.
// Authentication
const clients = process.env.USE_PASSWORDLESS === 'true' || process.env.USE_PASSWORDLESS === '1' ? createClientsPasswordless() : createClients();
const { embeddingClient, plannerClient, synthClient, dbConfig } = clients;
console.log(`DEBUG mode is ${process.env.DEBUG === 'true' ? 'ON' : 'OFF'}`);
console.log(`DEBUG_CALLBACKS length: ${DEBUG_CALLBACKS.length}`);
// Get vector store (get docs, create embeddings, insert docs)
const store = await getExistingStore(
embeddingClient,
dbConfig);
const query = process.env.QUERY || "quintessential lodging near running trails, eateries, retail";
const nearestNeighbors = parseInt(process.env.NEAREST_NEIGHBORS || '5', 10);
//Run planner agent
const hotelContext = await runPlannerAgent(plannerClient, embeddingClient, query, store, nearestNeighbors);
if (process.env.DEBUG === 'true') console.log(hotelContext);
//Run synth agent
const finalAnswer = await runSynthesizerAgent(synthClient, query, hotelContext);
// Get final recommendation (data + AI)
console.log('\n--- FINAL ANSWER ---');
console.log(finalAnswer);
Node.js ügynökök tervezése és szintetizálása
A src/agent.ts forrásfájl implementálja azokat a tervező- és szintetizátorügynököket, amelyek együttműködve dolgozzák fel a szállodai keresési kéréseket.
Planner-ügynök
A planner-ügynök az a döntéshozó , amely meghatározza a szállodák keresésének módját.
A planner-ügynök megkapja a felhasználó természetes nyelvi lekérdezését, és elküldi azt egy AI-modellnek a LangChain ügynök-keretrendszerével, valamint az általa használható elérhető eszközökkel. Az AI úgy dönt, hogy meghívja a vektorkereső eszközt, és keresési paramétereket biztosít. A LangChain automatikusan kezeli az eszköz végrehajtását, és visszaadja a megfelelő szállodákat. A keresési logika keménykódolása helyett az AI értelmezi a felhasználó által kívánt adatokat, és kiválasztja a keresés módját, így a rendszer rugalmassá válik a különböző típusú lekérdezésekhez.
async function runPlannerAgent(
plannerClient: any,
embeddingClient: any,
userQuery: string,
store: AzureDocumentDBVectorStore,
nearestNeighbors = 5
): Promise<string> {
console.log('\n--- PLANNER ---');
const userMessage = `Use the "${TOOL_NAME}" tool with nearestNeighbors=${nearestNeighbors} and query="${userQuery}". Do not answer directly; call the tool.`;
const contextSchema = z.object({
store: z.any(),
embeddingClient: z.any()
});
const agent = createAgent({
model: plannerClient,
systemPrompt: PLANNER_SYSTEM_PROMPT,
tools: [getHotelsToMatchSearchQuery],
contextSchema,
});
const agentResult = await agent.invoke(
{ messages: [{ role: 'user', content: userMessage }] },
// @ts-ignore
{ context: { store, embeddingClient }, callbacks: DEBUG_CALLBACKS }
);
const plannerMessages = agentResult.messages || [];
const searchResultsAsText = extractPlannerToolOutput(plannerMessages);
return searchResultsAsText;
}
Szintetizátorügynök
A szintetizátorügynök az az író, aki hasznos javaslatokat hoz létre.
A szintetizátorügynök megkapja az eredeti felhasználói lekérdezést a szálloda keresési eredményeivel együtt. Mindent elküld egy AI-modellnek a javaslatok megírására vonatkozó útmutatással. Természetes nyelvi választ ad vissza, amely összehasonlítja a szállodákat, és elmagyarázza a legjobb lehetőségeket. Ez a megközelítés azért fontos, mert a nyers keresési eredmények nem felhasználóbarátak. A szintetizátor beszélgetési javaslattá alakítja az adatbázisrekordokat, amely elmagyarázza, hogy egyes szállodák miért felelnek meg a felhasználó igényeinek.
async function runSynthesizerAgent(synthClient: any, userQuery: string, hotelContext: string): Promise<string> {
console.log('\n--- SYNTHESIZER ---');
let conciseContext = hotelContext;
console.log(`Context size is ${conciseContext.length} characters`);
const agent = createAgent({
model: synthClient,
systemPrompt: SYNTHESIZER_SYSTEM_PROMPT,
});
const agentResult = await agent.invoke({
messages: [{
role: 'user',
content: createSynthesizerUserPrompt(userQuery, conciseContext)
}]
});
const synthMessages = agentResult.messages;
const finalAnswer = synthMessages[synthMessages.length - 1].content;
console.log(`Output: ${finalAnswer.length} characters of final recommendation`);
return finalAnswer as string;
}
Ügynökeszközök vektortár-kereséshez
A src/vector-store.ts forrásfájl határozza meg a planner-ügynök által használt vektorkeresési eszközt.
Az eszközfájl egy keresőeszközt határoz meg, amelyet az AI-ügynök használhat a szállodák kereséséhez. Az ügynök így csatlakozik az adatbázishoz. Az AI nem keres közvetlenül az adatbázisban. Kéri a keresőeszköz használatát, és az eszköz végrehajtja a tényleges keresést.
Node.js függvény eszközdefinícióként
A LangChain függvénye tool egy szokásos TypeScript-függvényből hoz létre egy eszközt. Az eszközdefiníció tartalmazza a nevet, a leírást és a sémát (a Zod használata az ellenőrzéshez). Ez a definíció tudatja az AI-t az eszköz meglétéről és helyes használatáról.
export const getHotelsToMatchSearchQuery = tool(
async ({ query, nearestNeighbors }, config): Promise<string> => {
try {
const store = config.context.store as AzureDocumentDBVectorStore;
const embeddingClient = config.context.embeddingClient as AzureOpenAIEmbeddings;
// Create query embedding and perform search
const queryVector = await embeddingClient.embedQuery(query);
const results = await store.similaritySearchVectorWithScore(queryVector, nearestNeighbors);
console.log(`Found ${results.length} documents from vector store`);
// Format results for synthesizer
const formatted = results.map(([doc, score]) => {
const md = doc.metadata as Partial<HotelForVectorStore>;
console.log(`Hotel: ${md.HotelName ?? 'N/A'}, Score: ${score}`);
return formatHotelForSynthesizer(md, score);
}).join('\n\n');
return formatted;
} catch (error) {
console.error('Error in getHotelsToMatchSearchQuery tool:', error);
return 'Error occurred while searching for hotels.';
}
},
{
name: TOOL_NAME,
description: TOOL_DESCRIPTION,
schema: z.object({
query: z.string(),
nearestNeighbors: z.number().optional().default(5),
}),
}
);
Node.js Eszközvégrehajtás az Azure DocumentDB vektorkereséssel
Amikor az AI meghívja az eszközt, a függvény törzse fut. Beágyazást hoz létre úgy, hogy a szöveges lekérdezést numerikus vektorsá alakítja az Azure OpenAI beágyazási modelljével. Ezután megkeresi az adatbázist úgy, hogy elküldi a vektort az Azure DocumentDB-nek, amely hasonló, hasonló leírást jelentő vektorokkal rendelkező szállodákat talál. Végül úgy formázhatja az eredményeket, hogy az adatbázisrekordokat olvasható szöveggé alakítja, amelyet a szintetizátorügynök megérthet.
Az implementáció a LangChain-eket AzureDocumentDBVectorStore használja az Azure DocumentDB-vel való zökkenőmentes integrációhoz.
Miért érdemes ezt a mintát használni?
Az eszköz az ügynöktől való elválasztása rugalmasságot biztosít. Az AI dönti el, hogy mikor és mire keressen, míg az eszköz kezeli a keresés módját. Az ügynöklogika módosítása nélkül további eszközöket is hozzáadhat.
Az ügynök utasításokat ad az AI viselkedésének irányításához.
A src/utils/prompts.ts forrásfájl rendszerkéréseket és eszközdefiníciókat tartalmaz az ügynökök számára.
A parancssori fájl meghatározza az AI-modelleknek adott utasításokat és kontextust mind a tervező, mind a szintetizáló ügynökök számára. Ezek a kérések útmutatást adnak az AI viselkedéséhez, és biztosítják, hogy megértse a munkafolyamatban betöltött szerepét.
Az AI-válaszok minősége nagymértékben függ az egyértelmű utasításoktól. Ezek a kérések határokat határoznak meg, definiálják a kimeneti formátumot, és a felhasználó döntési céljára összpontosítják az AI-t. Ezeket a kéréseket testreszabhatja úgy, hogy kód módosítása nélkül módosítsa az ügynökök viselkedését.
export const PLANNER_SYSTEM_PROMPT = `You are a hotel search planner. Transform the user's request into a clear, detailed search query for a vector database.
CRITICAL REQUIREMENT: You MUST ALWAYS call the "${TOOL_NAME}" tool. This is MANDATORY for every request.
Use a tool call with:
- query (string)
- nearestNeighbors (number 1-20)
QUERY REFINEMENT RULES:
- If vague (e.g., "nice hotel"), add specific attributes: "hotel with high ratings and good amenities"
- If minimal (e.g., "cheap"), expand: "budget hotel with good value"
- Preserve specific details from user (location, amenities, business/leisure)
- Keep natural language - this is for semantic search
- Don't just echo the input - improve it for better search results
- nearestNeighbors: Use 3-5 for specific requests, 10-15 for broader requests, max 20
EXAMPLES:
User: "cheap hotel" → {"tool": "${TOOL_NAME}", "args": {"query": "budget-friendly hotel with good value and affordable rates", "nearestNeighbors": 10}}
User: "hotel near downtown with parking" → {"tool": "${TOOL_NAME}", "args": {"query": "hotel near downtown with good parking and wifi", "nearestNeighbors": 5}}
User: "nice place to stay" → {"tool": "${TOOL_NAME}", "args": {"query": "hotel with high ratings, good reviews, and quality amenities", "nearestNeighbors": 10}}
Do not answer the user directly. Always call the tool.`;
// ============================================================================
// Synthesizer Prompts
// ============================================================================
export const SYNTHESIZER_SYSTEM_PROMPT = `You are an expert hotel recommendation assistant using vector search results.
Only use the TOP 3 results provided. Do not request additional searches or call other tools.
GOAL: Provide a concise comparative recommendation to help the user choose between the top 3 options.
REQUIREMENTS:
- Compare only the top 3 results across the most important attributes: rating, score, location, price-level (if available), and key tags (parking, wifi, pool).
- Identify the main tradeoffs in one short sentence per tradeoff.
- Give a single clear recommendation with one short justification sentence.
- Provide up to two alternative picks (one sentence each) explaining when they are preferable.
FORMAT CONSTRAINTS:
- Plain text only (no markdown).
- Keep the entire response under 220 words.
- Use simple bullets (•) or numbered lists and short sentences (preferably <25 words per sentence).
- Preserve hotel names exactly as provided in the tool summary.
Do not add extra commentary, marketing language, or follow-up questions. If information is missing and necessary to choose, state it in one sentence and still provide the best recommendation based on available data.`;
Adatok előkészítése és feltöltése az Azure DocumentDB-be Node.js
A minta egy JSON-fájlból származó szállodai adatokat használ. Az adattár két verziót tartalmaz:
-
Hotels.json- Szállodai adatok vektoros beágyazások nélkül (ezt a mintát használja) -
Hotels_Vector.json- Szállodai adatok előre kiszámított beágyazásokkal (más minták által használt)
A feltöltés működése
A upload-documents.ts szkript három lépést hajt végre:
-
Adatok betöltése – Beolvassa a szálloda rekordjait a
Hotels.jsonfájlból. -
Beágyazások létrehozása – A szkript minden szállodában elküldi a
Descriptionmezőt az Azure OpenAI-modellnektext-embedding-3-small, hogy létrehoz egy 1536 dimenziós vektorbeágyazást. Ez a szövegleírást numerikus ábrázolássá alakítja, amely rögzíti annak szemantikai jelentését. - Beszúrás és indexelés – A szkript beszúrja a dokumentumokat (beágyazásukkal) az Azure DocumentDB-gyűjteménybe, és létrehoz egy vektorindexet a konfigurált algoritmus (IVF, HNSW vagy DiskANN) használatával.
import { createClientsPasswordless, createClients } from './utils/clients.js';
import { getStore } from './vector-store.js';
/**
* Upload documents to Azure DocumentDB MongoDB Vector Store
*/
async function uploadDocuments() {
try {
console.log('Starting document upload...\n');
// Get clients based on authentication mode
const usePasswordless = process.env.USE_PASSWORDLESS === 'true' || process.env.USE_PASSWORDLESS === '1';
console.log(`Authentication mode: ${usePasswordless ? 'Passwordless (Azure AD)' : 'API Key'}`);
console.log('\nEnvironment variables check:');
console.log(` DATA_FILE_WITHOUT_VECTORS: ${process.env.DATA_FILE_WITHOUT_VECTORS}`);
console.log(` AZURE_DOCUMENTDB_DATABASENAME: ${process.env.AZURE_DOCUMENTDB_DATABASENAME}`);
console.log(` AZURE_DOCUMENTDB_COLLECTION: ${process.env.AZURE_DOCUMENTDB_COLLECTION}`);
console.log(` AZURE_DOCUMENTDB_CLUSTER: ${process.env.AZURE_DOCUMENTDB_CLUSTER}`);
console.log(` AZURE_OPENAI_EMBEDDING_MODEL: ${process.env.AZURE_OPENAI_EMBEDDING_MODEL}`);
const requiredEnvVars = [
'DATA_FILE_WITHOUT_VECTORS',
'AZURE_DOCUMENTDB_DATABASENAME',
'AZURE_DOCUMENTDB_COLLECTION',
'AZURE_DOCUMENTDB_CLUSTER',
'AZURE_OPENAI_EMBEDDING_MODEL',
];
const missingEnvVars = requiredEnvVars.filter((name) => {
const value = process.env[name];
return !value || value.trim().length === 0;
});
if (missingEnvVars.length > 0) {
throw new Error(`Missing required environment variables: ${missingEnvVars.join(', ')}`);
}
const clients = usePasswordless ? createClientsPasswordless() : createClients();
const { embeddingClient, dbConfig } = clients;
console.log('\ndbConfig properties:');
console.log(` instance: ${dbConfig.instance}`);
console.log(` databaseName: ${dbConfig.databaseName}`);
console.log(` collectionName: ${dbConfig.collectionName}`);
// Check for data file path
const dataFilePath = process.env.DATA_FILE_WITHOUT_VECTORS!;
console.log(`\nReading data from: ${dataFilePath}`);
console.log(`Database: ${dbConfig.databaseName}`);
console.log(`Collection: ${dbConfig.collectionName}`);
console.log(`Vector algorithm: ${process.env.VECTOR_INDEX_ALGORITHM || 'vector-ivf'}\n`);
// Upload documents using existing getStore function
const startTime = Date.now();
const store = await getStore(dataFilePath, embeddingClient, dbConfig);
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
console.log(`\n✓ Upload completed in ${duration} seconds`);
// Close connection
await store.close();
console.log('✓ Connection closed');
// Force exit to ensure process terminates (Azure credential timers may still be active)
process.exit(0);
} catch (error: any) {
console.error('\n✗ Upload failed:', error?.message || error);
console.error('\nFull error:', error);
process.exit(1);
}
}
// Run the upload
uploadDocuments();
Vektorindex létrehozása
A vektorindex lehetővé teszi a gyors hasonlóság keresését. Az index létrehozásakor az Azure DocumentDB rendszerezi a beágyazási vektorokat, hogy a "leíráshoz hasonló szállodák keresése" lekérdezések hatékonyan megválaszolhatók legyenek minden dokumentum vizsgálata nélkül.
A választott indextípus befolyásolja a teljesítményt:
| Algorithm | Klaszterszint | A következőkre alkalmas |
|---|---|---|
| IVF | M10+ | Kis- és közepes adathalmazok, alacsonyabb költség |
| HNSW | M30+ | Magas visszahívás, gyors lekérdezések |
| DiskANN | M40+ | Nagy méretű adathalmazok, milliárdos vektorok |
import {
AzureDocumentDBVectorStore,
AzureDocumentDBSimilarityType,
AzureDocumentDBConfig
} from "@langchain/azure-cosmosdb";
import type { AzureOpenAIEmbeddings } from "@langchain/openai";
import { readFileSync } from 'fs';
import { Document } from '@langchain/core/documents';
import { HotelsData, Hotel } from './utils/types.js';
import { TOOL_NAME, TOOL_DESCRIPTION } from './utils/prompts.js';
import { z } from 'zod';
import { tool } from "langchain";
import { MongoClient } from 'mongodb';
import { BaseMessage } from "@langchain/core/messages";
type HotelForVectorStore = Omit<Hotel, 'Description_fr' | 'Location' | 'Rooms'>;
// Helper function for similarity type
function getSimilarityType(similarity: string) {
switch (similarity.toUpperCase()) {
case 'COS': return AzureDocumentDBSimilarityType.COS;
case 'L2': return AzureDocumentDBSimilarityType.L2;
case 'IP': return AzureDocumentDBSimilarityType.IP;
default: return AzureDocumentDBSimilarityType.COS;
}
}
// Consolidated vector index configuration
function getVectorIndexOptions() {
const algorithm = process.env.VECTOR_INDEX_ALGORITHM || 'vector-ivf';
const dimensions = parseInt(process.env.EMBEDDING_DIMENSIONS || '1536');
const similarity = getSimilarityType(process.env.VECTOR_SIMILARITY || 'COS');
const baseOptions = { dimensions, similarity };
switch (algorithm) {
case 'vector-hnsw':
return {
kind: 'vector-hnsw' as const,
m: parseInt(process.env.HNSW_M || '16'),
efConstruction: parseInt(process.env.HNSW_EF_CONSTRUCTION || '64'),
...baseOptions
};
case 'vector-diskann':
return {
kind: 'vector-diskann' as const,
...baseOptions
};
case 'vector-ivf':
default:
Futtassa az agentikus RAG alkalmazást a Node.js használatával.
Telepítse a függőségeket:
npm installAz ügynök futtatása előtt töltse fel a szálloda adatait beágyazásokkal. A
upload-documents.tsparancs betölti a szállodákat a JSON-fájlból, beágyazásokat hoz létre minden szállodához az Azure DocumentDB használatávaltext-embedding-3-small, dokumentumokat szúr be az Azure DocumentDB-be, és létrehoz egy vektorindexet.npm run uploadFuttassa a szállodai ajánlási ügynököt a
agent.tsparancs használatával. Az ügynök meghívja a tervezőügynököt, a vektorkeresést és a szintetizátor-ügynököt. A kimenet hasonlósági pontszámokat és a szintetizátorügynök javaslatokkal végzett összehasonlító elemzését tartalmazza.npm startDEBUG mode is OFF DEBUG_CALLBACKS length: 0 Connected to existing vector store: Hotels.hotel_data --- PLANNER --- Found 5 documents from vector store Hotel: Nordick's Valley Motel, Score: 0.49866509437561035 Hotel: White Mountain Lodge & Suites, Score: 0.48731985688209534 Hotel: Trails End Motel, Score: 0.47985398769378662 Hotel: Country Comfort Inn, Score: 0.47431993484497070 Hotel: Lakefront Captain Inn, Score: 0.45787304639816284 --- SYNTHESIZER --- Context size is 3233 characters Output: 812 characters of final recommendation --- FINAL ANSWER --- 1. COMPARISON SUMMARY: • Nordick's Valley Motel has the highest rating (4.5) and offers free parking, air conditioning, and continental breakfast. It is located in Washington D.C., near historic attractions and trails. • White Mountain Lodge & Suites is a resort with unique amenities like a pool, restaurant, and meditation gardens, but has the lowest rating (2.4). It is located in Denver, surrounded by forest trails. • Trails End Motel is budget-friendly with a moderate rating (3.2), free parking, free wifi, and a restaurant. It is close to downtown Scottsdale and eateries. Key tradeoffs: - Nordick's Valley Motel excels in rating and proximity to historic attractions but lacks a pool or free wifi. - White Mountain Lodge & Suites offers resort-style amenities and forest trails but has the lowest rating. - Trails End Motel balances affordability and essential amenities but has fewer unique features compared to the others. 2. BEST OVERALL: Nordick's Valley Motel is the best choice for its high rating, proximity to trails and attractions, and free parking. 3. ALTERNATIVE PICKS: • Choose White Mountain Lodge & Suites if you prioritize resort amenities and forest trails over rating. • Choose Trails End Motel if affordability and proximity to downtown Scottsdale are your main concerns.
Adatok megtekintése és kezelése a Visual Studio Code-ban
Válassza ki a DocumentDB bővítményt a Visual Studio Code-ban az Azure DocumentDB-fiókhoz való csatlakozáshoz.
Az adatok és indexek megtekintése a Hotels adatbázisban.
Erőforrások tisztítása
Ha korábban erőforrásokhoz használt azd up, az összes Azure erőforrást eltávolíthatja a következőkkel:
azd down
Ha manuálisan hozta létre az erőforrásokat, és el szeretné távolítani az összes erőforrást, törölje az erőforráscsoportot a többletköltségek elkerülése érdekében.
Ha újra fel szeretné használni az erőforrásokat, a törlési paranccsal törölheti a tesztadatbázist, amikor elkészült. Futtassa a következő parancsot:
npm run cleanup