Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@ This repository contains JavaScript code samples used in Azure AI Search documen
| [azure-function-search](azure-function-search/readme.md) | This sample is an Azure Function that sends query requests to an Azure AI Search service. You can substitute this code to replace the contents of the `api` folder in the C# sample [azure-search-static-web-app](https://github.com/Azure-Samples/azure-search-static-web-app). |
| [bulk-insert](bulk-insert/readme.md) | This sample shows you how to create and load an index using the push APIs and sample data. You can substitute this code to replace the contents of the `bulk-insert` folder in the C# sample [azure-search-static-web-app](https://github.com/Azure-Samples/azure-search-static-web-app) |
| [quickstart-keyword-search](quickstart-keyword-search/README.md) | "Day One" introduction to the fundamental tasks of working with a search index: create, load, and query. This sample is a Node.js console app. The index is modeled on a subset of the Hotels dataset, reduced for readability and comprehension. |
| [quickstart-agentic-retrieval-js](quickstart-agentic-retrieval-js/README.md) | JavaScript code that demonstrates agentic retrieval in Azure AI Search, including creating a knowledge source, knowledge base, and using an LLM for query planning and answer synthesis. |
| [quickstart-agentic-retrieval-ts](quickstart-agentic-retrieval-ts/README.md) | TypeScript version of the agentic retrieval sample. |
| [quickstart-semantic-ranking-js](quickstart-semantic-ranking-js/README.md) | JavaScript code that demonstrates how to use semantic ranking in Azure AI Search to improve search relevance using machine reading comprehension. |
| [quickstart-semantic-ranking-ts](quickstart-semantic-ranking-ts/README.md) | TypeScript code that demonstrates how to use semantic ranking in Azure AI Search to improve search relevance using machine reading comprehension. |
| [quickstart-semantic-ranking-ts](quickstart-semantic-ranking-ts/README.md) | TypeScript version of the semantic ranking sample. |
| [quickstart-vector-js](quickstart-vector-js/README.md) | JavaScript code that demonstrates vector search in Azure AI Search, including creating vector indexes and performing vector, hybrid, and semantic hybrid queries. |
| [quickstart-vector-ts](quickstart-vector-ts/README.md) | TypeScript version of the vector search sample. |
34 changes: 34 additions & 0 deletions quickstart-agentic-retrieval-js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
page_type: sample
languages:
- javascript
name: "Quickstart: Agentic retrieval in Azure AI Search using JavaScript"
description: |
Learn how to set up an agentic retrieval pipeline in Azure AI Search using JavaScript.
products:
- azure
- azure-cognitive-search
urlFragment: javascript-quickstart-agentic-retrieval
---

# Quickstart: Agentic retrieval in Azure AI Search using JavaScript

![Quickstart sample MIT license badge](https://img.shields.io/badge/license-MIT-green.svg)

This sample demonstrates the fundamentals of agentic retrieval using Azure AI Search. You create a search index, a knowledge source that targets the index, and a knowledge base that integrates an LLM for query planning and answer synthesis.

## What's in this sample

| File | Description |
|------|-------------|
| `package.json` | Project file that defines dependencies |
| `sample.env` | Environment variable template for configuration |
| `src/index.js` | Main script that demonstrates the complete agentic retrieval workflow |

## Documentation

This sample accompanies [Quickstart: Agentic retrieval using JavaScript](https://learn.microsoft.com/azure/search/search-get-started-agentic-retrieval?pivots=javascript). Follow the documentation for prerequisites, setup instructions, and detailed explanations.

## Next step

You can learn more about Azure AI Search on the [official documentation site](https://learn.microsoft.com/azure/search).
20 changes: 20 additions & 0 deletions quickstart-agentic-retrieval-js/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "quickstart-agentic-retrieval-js",
"version": "1.0.0",
"main": "src/index.js",
"type": "module",
"scripts": {
"start": "node -r dotenv/config src/index.js"
},
"keywords": ["azure", "search", "knowledge-retrieval", "agentic-retrieval", "javascript"],
"author": "",
"license": "ISC",
"description": "Azure AI Search agentic retrieval quickstart in JavaScript",
"dependencies": {
"@azure/identity": "^4.10.0",
"@azure/search-documents": "^12.3.0-beta.1"
},
"devDependencies": {
"dotenv": "^16.5.0"
}
}
7 changes: 7 additions & 0 deletions quickstart-agentic-retrieval-js/sample.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Azure AI Search Configuration
AZURE_SEARCH_ENDPOINT=https://your-search-service.search.windows.net

# Azure OpenAI Configuration
AZURE_OPENAI_ENDPOINT=https://your-openai-resource.openai.azure.com
AZURE_OPENAI_EMBEDDING_DEPLOYMENT=text-embedding-3-large
AZURE_OPENAI_GPT_DEPLOYMENT=gpt-5-mini
321 changes: 321 additions & 0 deletions quickstart-agentic-retrieval-js/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
import "dotenv/config";
import { DefaultAzureCredential } from "@azure/identity";
import {
SearchIndexClient,
SearchClient,
KnowledgeRetrievalClient,
SearchIndexingBufferedSender,
} from "@azure/search-documents";

export const documentKeyRetriever = (document) => {
return document.id;
};

export const WAIT_TIME = 4000;
export function delay(timeInMs) {
return new Promise((resolve) => setTimeout(resolve, timeInMs));
}

const index = {
name: "earth_at_night",
fields: [
{
name: "id",
type: "Edm.String",
key: true,
filterable: true,
sortable: true,
facetable: true,
},
{
name: "page_chunk",
type: "Edm.String",
searchable: true,
filterable: false,
sortable: false,
facetable: false,
},
{
name: "page_embedding_text_3_large",
type: "Collection(Edm.Single)",
searchable: true,
filterable: false,
sortable: false,
facetable: false,
vectorSearchDimensions: 3072,
vectorSearchProfileName: "hnsw_text_3_large",
},
{
name: "page_number",
type: "Edm.Int32",
filterable: true,
sortable: true,
facetable: true,
},
],
vectorSearch: {
profiles: [
{
name: "hnsw_text_3_large",
algorithmConfigurationName: "alg",
vectorizerName: "azure_openai_text_3_large",
},
],
algorithms: [
{
name: "alg",
kind: "hnsw",
},
],
vectorizers: [
{
vectorizerName: "azure_openai_text_3_large",
kind: "azureOpenAI",
parameters: {
resourceUrl: process.env.AZURE_OPENAI_ENDPOINT,
deploymentId: process.env.AZURE_OPENAI_EMBEDDING_DEPLOYMENT,
modelName: process.env.AZURE_OPENAI_EMBEDDING_DEPLOYMENT,
},
},
],
},
semanticSearch: {
defaultConfigurationName: "semantic_config",
configurations: [
{
name: "semantic_config",
prioritizedFields: {
contentFields: [{ name: "page_chunk" }],
},
},
],
},
};

const credential = new DefaultAzureCredential();

const searchIndexClient = new SearchIndexClient(
process.env.AZURE_SEARCH_ENDPOINT,
credential
);
const searchClient = new SearchClient(
process.env.AZURE_SEARCH_ENDPOINT,
"earth_at_night",
credential
);

await searchIndexClient.createOrUpdateIndex(index);

// Get documents with vectors
const response = await fetch(
"https://raw.githubusercontent.com/Azure-Samples/azure-search-sample-data/refs/heads/main/nasa-e-book/earth-at-night-json/documents.json"
);

if (!response.ok) {
throw new Error(
`Failed to fetch documents: ${response.status} ${response.statusText}`
);
}
const documents = await response.json();

const bufferedClient = new SearchIndexingBufferedSender(
searchClient,
documentKeyRetriever,
{
autoFlush: true,
}
);

await bufferedClient.uploadDocuments(documents);
await bufferedClient.flush();
await bufferedClient.dispose();

console.log(`Waiting for indexing to complete...`);
console.log(`Expected documents: ${documents.length}`);
await delay(WAIT_TIME);

let count = await searchClient.getDocumentsCount();
console.log(`Current indexed count: ${count}`);

while (count !== documents.length) {
await delay(WAIT_TIME);
count = await searchClient.getDocumentsCount();
console.log(`Current indexed count: ${count}`);
}

console.log(`✓ All ${documents.length} documents indexed successfully!`);

await searchIndexClient.createKnowledgeSource({
name: "earth-knowledge-source",
description: "Knowledge source for Earth at Night e-book content",
kind: "searchIndex",
searchIndexParameters: {
searchIndexName: "earth_at_night",
sourceDataFields: [{ name: "id" }, { name: "page_number" }],
},
});

console.log(`✅ Knowledge source 'earth-knowledge-source' created successfully.`);

await searchIndexClient.createKnowledgeBase({
name: "earth-knowledge-base",
knowledgeSources: [
{
name: "earth-knowledge-source",
},
],
models: [
{
kind: "azureOpenAI",
azureOpenAIParameters: {
resourceUrl: process.env.AZURE_OPENAI_ENDPOINT,
deploymentId: process.env.AZURE_OPENAI_GPT_DEPLOYMENT,
modelName: process.env.AZURE_OPENAI_GPT_DEPLOYMENT,
},
},
],
outputMode: "answerSynthesis",
answerInstructions:
"Provide a two sentence concise and informative answer based on the retrieved documents.",
});

console.log(`✅ Knowledge base 'earth-knowledge-base' created successfully.`);

const knowledgeRetrievalClient = new KnowledgeRetrievalClient(
process.env.AZURE_SEARCH_ENDPOINT,
"earth-knowledge-base",
credential
);

const query1 = `Why do suburban belts display larger December brightening than urban cores even though absolute light levels are higher downtown? Why is the Phoenix nighttime street grid is so sharply visible from space, whereas large stretches of the interstate between midwestern cities remain comparatively dim?`;

const retrievalRequest = {
messages: [
{
role: "user",
content: [
{
type: "text",
text: query1,
},
],
},
],
knowledgeSourceParams: [
{
kind: "searchIndex",
knowledgeSourceName: "earth-knowledge-source",
includeReferences: true,
includeReferenceSourceData: true,
alwaysQuerySource: true,
rerankerThreshold: 2.5,
},
],
includeActivity: true,
retrievalReasoningEffort: { kind: "low" },
};

const result = await knowledgeRetrievalClient.retrieveKnowledge(retrievalRequest);

console.log("\n📝 ANSWER:");
console.log("─".repeat(80));
if (result.response && result.response.length > 0) {
result.response.forEach((msg) => {
if (msg.content && msg.content.length > 0) {
msg.content.forEach((content) => {
if (content.type === "text" && "text" in content) {
console.log(content.text);
}
});
}
});
}
console.log("─".repeat(80));

if (result.activity) {
console.log("\nActivities:");
result.activity.forEach((activity) => {
console.log(`Activity Type: ${activity.type}`);
console.log(JSON.stringify(activity, null, 2));
});
}

if (result.references) {
console.log("\nReferences:");
result.references.forEach((reference) => {
console.log(`Reference Type: ${reference.type}`);
console.log(JSON.stringify(reference, null, 2));
});
}

// Follow-up query - to demonstrate conversational context
const query2 = "How do I find lava at night?";
console.log(`\n❓ Follow-up question: ${query2}`);

const retrievalRequest2 = {
messages: [
{
role: "user",
content: [
{
type: "text",
text: query2,
},
],
},
],
knowledgeSourceParams: [
{
kind: "searchIndex",
knowledgeSourceName: "earth-knowledge-source",
includeReferences: true,
includeReferenceSourceData: true,
alwaysQuerySource: true,
rerankerThreshold: 2.5,
},
],
includeActivity: true,
retrievalReasoningEffort: { kind: "low" },
};

const result2 = await knowledgeRetrievalClient.retrieveKnowledge(retrievalRequest2);

console.log("\n📝 ANSWER:");
console.log("─".repeat(80));
if (result2.response && result2.response.length > 0) {
result2.response.forEach((msg) => {
if (msg.content && msg.content.length > 0) {
msg.content.forEach((content) => {
if (content.type === "text" && "text" in content) {
console.log(content.text);
}
});
}
});
}
console.log("─".repeat(80));

if (result2.activity) {
console.log("\nActivities:");
result2.activity.forEach((activity) => {
console.log(`Activity Type: ${activity.type}`);
console.log(JSON.stringify(activity, null, 2));
});
}

if (result2.references) {
console.log("\nReferences:");
result2.references.forEach((reference) => {
console.log(`Reference Type: ${reference.type}`);
console.log(JSON.stringify(reference, null, 2));
});
}

console.log("\n✅ Quickstart completed successfully!");

// Clean up resources
await searchIndexClient.deleteKnowledgeBase("earth-knowledge-base");
await searchIndexClient.deleteKnowledgeSource("earth-knowledge-source");
await searchIndexClient.deleteIndex("earth_at_night");

console.log(`\n🗑️ Cleaned up resources.`);
Loading