Skip to content

Commit c6dae20

Browse files
authored
Merge pull request #78 from diberry/diberry/0709-semantic-reranker-2
Fixes for semantic ranker
2 parents 744447c + 527473d commit c6dae20

16 files changed

+49
-253
lines changed

quickstart-semantic-ranking-js/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ Semantic ranking uses machine reading comprehension from Microsoft to rescore se
2727
- Copy `sample.env` to `.env`
2828
- Update the values with your Azure AI Search service details:
2929
```
30-
SEARCH_ENDPOINT=https://your-service-name.search.windows.net
30+
AZURE_SEARCH_ENDPOINT=https://your-service-name.search.windows.net
3131
INDEX_NAME=hotels-sample-index
32+
AZURE_SEARCH_API_KEY=your-api-key
3233
```
3334
3435
4. **Get your search service endpoint and API key**
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Azure AI Search Service Configuration
2-
SEARCH_ENDPOINT=PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
3-
INDEX_NAME=hotels-sample-index
2+
AZURE_SEARCH_ENDPOINT=PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
3+
AZURE_SEARCH_INDEX_NAME=hotels-sample-index
44
SEMANTIC_CONFIGURATION_NAME=semantic-config
55

quickstart-semantic-ranking-js/src/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { DefaultAzureCredential } from "@azure/identity";
55

66
// Configuration - use environment variables
77
export const searchEndpoint = process.env.AZURE_SEARCH_ENDPOINT || "PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE";
8-
export const searchApiKey = process.env.AZURE_SEARCH_API_KEY || "PUT-YOUR-SEARCH-SERVICE-ADMIN-API-KEY-HERE";
98
export const indexName = process.env.AZURE_SEARCH_INDEX_NAME || "hotels-sample-index";
9+
export const semanticConfigurationName = process.env.SEMANTIC_CONFIGURATION_NAME || "semantic-config";
1010

1111
// Create credential
1212
export const credential = new DefaultAzureCredential();

quickstart-semantic-ranking-js/src/getIndexSettings.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,6 @@ if(index.semanticSearch && index.semanticSearch.configurations) {
2323
console.log(`Configuration name: ${config.name}`);
2424
console.log(`Title field: ${config.prioritizedFields.titleField?.name}`);
2525
}
26+
} else {
27+
console.log("No semantic configuration exists for this index.");
2628
}

quickstart-semantic-ranking-js/src/semanticAnswer.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
import { SearchClient } from "@azure/search-documents";
2-
import { credential, searchEndpoint, indexName } from "./config.js";
2+
import { credential, searchEndpoint, indexName, semanticConfigurationName } from "./config.js";
33

44
const searchClient = new SearchClient(
55
searchEndpoint,
66
indexName,
77
credential
88
);
99

10-
const configurationName = process.env.SEMANTIC_CONFIGURATION_NAME || "semantic-config";
11-
1210
const results = await searchClient.search("walking distance to live music", {
1311
queryType: "semantic",
1412
semanticSearchOptions: {
15-
configurationName: configurationName,
13+
configurationName: semanticConfigurationName,
1614
captions: {
1715
captionType: "extractive"
1816
},

quickstart-semantic-ranking-js/src/semanticQuery.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
import { SearchClient } from "@azure/search-documents";
2-
import { credential, searchEndpoint, indexName } from "./config.js";
2+
import { credential, searchEndpoint, indexName, semanticConfigurationName } from "./config.js";
33

44
const searchClient = new SearchClient(
55
searchEndpoint,
66
indexName,
77
credential
88
);
99

10-
const configurationName = process.env.SEMANTIC_CONFIGURATION_NAME || "semantic-config";
11-
1210
const results = await searchClient.search("walking distance to live music", {
1311
queryType: "semantic",
1412
semanticSearchOptions: {
15-
configurationName: configurationName
13+
configurationName: semanticConfigurationName
1614
},
1715
select: ["HotelId", "HotelName", "Description"]
1816
});

quickstart-semantic-ranking-js/src/semanticQueryReturnCaptions.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
import { SearchClient } from "@azure/search-documents";
2-
import { credential, searchEndpoint, indexName } from "./config.js";
2+
import { credential, searchEndpoint, indexName, semanticConfigurationName } from "./config.js";
33

44
const searchClient = new SearchClient(
55
searchEndpoint,
66
indexName,
77
credential
88
);
99

10-
const configurationName = process.env.SEMANTIC_CONFIGURATION_NAME || "semantic-config";
11-
12-
// Debug info
13-
console.log(`Using semantic configuration: ${configurationName}`);
10+
console.log(`Using semantic configuration: ${semanticConfigurationName}`);
1411
console.log("Search query: walking distance to live music");
1512

1613
const results = await searchClient.search("walking distance to live music", {
1714
queryType: "semantic",
1815
semanticSearchOptions: {
19-
configurationName: configurationName,
16+
configurationName: semanticConfigurationName,
2017
captions: {
2118
captionType: "extractive",
2219
highlight: true

quickstart-semantic-ranking-js/src/updateIndexSettings.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import {
22
SearchIndexClient
33
} from "@azure/search-documents";
4-
import { searchEndpoint, indexName, credential } from "./config.js";
4+
import { searchEndpoint, indexName, credential, semanticConfigurationName } from "./config.js";
55

66
try {
7-
const configurationName = process.env.SEMANTIC_CONFIGURATION_NAME || "semantic-config";
87

98
const indexClient = new SearchIndexClient(searchEndpoint, credential);
109

@@ -23,7 +22,7 @@ try {
2322
};
2423

2524
const newSemanticConfiguration = {
26-
name: configurationName,
25+
name: semanticConfigurationName,
2726
prioritizedFields: fields
2827
};
2928

@@ -32,7 +31,7 @@ try {
3231
existingIndex.semanticSearch.configurations.push(newSemanticConfiguration);
3332
} else {
3433
const configExists = existingIndex.semanticSearch?.configurations?.some(
35-
config => config.name === configurationName
34+
config => config.name === semanticConfigurationName
3635
);
3736
if (!configExists) {
3837
existingIndex.semanticSearch = {
Lines changed: 15 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Azure AI Search Semantic Ranking Quickstart - TypeScript
22

3-
This TypeScript sample demonstrates how to use semantic ranking in Azure AI Search to improve search relevance using machine reading comprehension. This is a TypeScript port of the [quickstart](https://learn.microsoft.com/azure/search/search-get-started-semantic).
3+
This TypeScript sample demonstrates how to use semantic ranking in Azure AI Search to improve search relevance using machine reading comprehension. This is a TypeScript version of the [quickstart](https://learn.microsoft.com/azure/search/search-get-started-semantic).
44

5-
The sample has been factored into a modular structure, similar to the vector search quickstart, with separate files for different operations.
5+
The sample has been factored into a modular structure, with separate files for different operations.
66

77
## What is Semantic Ranking?
88

@@ -30,6 +30,7 @@ Semantic ranking uses machine reading comprehension from Microsoft to rescore se
3030
```
3131
SEARCH_ENDPOINT=https://your-service-name.search.windows.net
3232
INDEX_NAME=hotels-sample-index
33+
AZURE_SEARCH_API_KEY=your-api-key
3334
```
3435
3536
4. **Get your search service endpoint and API key**
@@ -40,220 +41,27 @@ Semantic ranking uses machine reading comprehension from Microsoft to rescore se
4041
4142
## Run the Sample
4243
43-
### Run Complete Quickstart
44+
### Getting Index Settings
4445
```bash
45-
# Build and run the complete quickstart
46-
npm run dev
47-
48-
# Or separately:
49-
npm run build
50-
npm run start
46+
npm run get-index-settings
5147
```
5248

53-
### Run Individual Operations
54-
You can also run individual operations separately:
55-
49+
### Updating Index Settings for Semantic Search
5650
```bash
57-
# Create the search index with semantic configuration
58-
npm run create-index
59-
60-
# Upload sample documents
61-
npm run upload-docs
62-
63-
# Run BM25 text search
64-
npm run search-bm25
65-
66-
# Run semantic search with reranking
67-
npm run search-semantic
68-
69-
# Run semantic search with answers
70-
npm run search-answers
71-
72-
# Delete the index (useful for testing)
73-
npm run delete-index
74-
```
75-
76-
## What This Sample Does
77-
78-
The quickstart demonstrates the key steps for implementing semantic ranking:
79-
80-
1. **Creates a search index** with semantic configuration
81-
- Defines fields for hotel data (HotelName, Description, Category, etc.)
82-
- Sets up semantic configuration specifying:
83-
- **Title field**: HotelName (most important for ranking)
84-
- **Content fields**: Description (main content to analyze)
85-
- **Keywords fields**: Category (additional context)
86-
87-
2. **Uploads sample documents** containing hotel information with varied descriptions
88-
89-
3. **Runs different types of queries** to show the difference:
90-
- **Empty query**: Verifies the index is operational
91-
- **Text query with BM25**: Traditional keyword-based scoring
92-
- **Semantic query**: AI-powered reranking with captions
93-
- **Semantic answers**: Direct answer extraction from content
94-
95-
## Key Features Demonstrated
96-
97-
### Semantic Configuration
98-
Shows how to configure semantic search with prioritized fields:
99-
- **Title field**: The most important field for semantic ranking
100-
- **Content fields**: Fields containing the main content to be analyzed
101-
- **Keywords fields**: Fields providing additional context
102-
103-
### Query Comparison
104-
- **BM25 scoring**: Traditional keyword matching with frequency-based relevance
105-
- **Semantic reranking**: AI understanding of context and meaning
106-
- **Reranker scores**: Higher scores indicate better semantic relevance to the query
107-
108-
### Enhanced Results
109-
- **Semantic Captions**: Automatically extracted relevant snippets with highlighting
110-
- **Semantic Answers**: Direct responses to question-like queries when confidence is high
111-
112-
## Understanding the Results
113-
114-
When you run the sample, you'll see different results for the same query "restaurant on site":
115-
116-
**BM25 Results**: May prioritize documents that simply contain the words "restaurant" and "site"
117-
118-
**Semantic Results**: Will understand the intent and rank hotels that actually have dining facilities higher, even if they don't use the exact words
119-
120-
## Example Output
121-
122-
```
123-
=== Running text query (BM25 scoring) ===
124-
BM25-scored results:
125-
Score: 1.23
126-
Hotel: Sublime Palace Hotel
127-
Description: ...historic center...sites and landmarks...
128-
129-
=== Running semantic query ===
130-
Semantic-ranked results:
131-
Reranker Score: 2.45
132-
Hotel: Gastronomic Landscape Hotel
133-
Description: The Gastronomic Hotel stands out for its culinary excellence...
134-
Caption: culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services
51+
npm run update-index-settings
13552
```
13653

137-
## Project Structure
138-
139-
The sample has been refactored into a modular structure for better maintainability and reusability:
140-
141-
```
142-
quickstart-semantic-ranking-ts/
143-
├── src/
144-
│ ├── config.ts # Configuration and type definitions
145-
│ ├── createIndex.ts # Index creation with semantic configuration
146-
│ ├── uploadDocuments.ts # Document upload functionality
147-
│ ├── searchBM25.ts # BM25 text search queries
148-
│ ├── searchSemantic.ts # Semantic search with reranking
149-
│ ├── searchSemanticAnswer.ts # Semantic search with answers
150-
│ ├── main.ts # Main orchestration script
151-
│ └── semantic-ranking-quickstart.ts # Original monolithic version (for reference)
152-
├── dist/ # Compiled JavaScript (generated)
153-
├── package.json # Node.js dependencies and scripts
154-
├── tsconfig.json # TypeScript configuration
155-
├── sample.env # Environment variables template
156-
└── README.md # This file
157-
```
158-
159-
## Modular Code Overview
160-
161-
### Configuration (`config.ts`)
162-
- Centralizes environment variables and credentials
163-
- Exports the `HotelDocument` interface for type safety
164-
- Provides reusable configuration for all modules
165-
166-
### Index Creation (`createIndex.ts`)
167-
- Creates the search index with semantic configuration
168-
- Defines field mappings and analyzers
169-
- Sets up semantic prioritized fields (title, content, keywords)
170-
171-
### Document Upload (`uploadDocuments.ts`)
172-
- Uploads sample hotel documents to the index
173-
- Handles batch upload operations with error handling
174-
175-
### Search Operations
176-
- **`searchBM25.ts`**: Traditional keyword-based search with BM25 scoring
177-
- **`searchSemantic.ts`**: Semantic search with AI-powered reranking and captions
178-
- **`searchSemanticAnswer.ts`**: Semantic search with direct answer extraction
179-
180-
### Main Orchestrator (`main.ts`)
181-
- Coordinates all operations in the correct sequence
182-
- Provides validation and error handling
183-
- Can be used as the primary entry point
184-
185-
## Benefits of the Modular Structure
186-
187-
This refactored structure provides several advantages:
188-
189-
- **Modularity**: Each file has a single responsibility and can be used independently
190-
- **Reusability**: Individual operations can be imported and used in other projects
191-
- **Testability**: Each module can be tested in isolation
192-
- **Maintainability**: Changes to one operation don't affect others
193-
- **Educational**: Easier to understand each concept separately
194-
- **Flexibility**: Run only the operations you need during development
195-
196-
## Semantic Configuration Details
197-
198-
```typescript
199-
const semanticConfig = {
200-
name: "semantic-config",
201-
prioritizedFields: {
202-
titleField: { name: "HotelName" }, // Primary ranking field
203-
contentFields: [{ name: "Description" }], // Main content for analysis
204-
keywordsFields: [{ name: "Category" }] // Additional context
205-
}
206-
};
54+
### Run Semantic Queries
55+
```bash
56+
npm run get-semantic-query
20757
```
20858

209-
## Learn More
210-
211-
- [Azure AI Search Semantic Ranking Documentation](https://learn.microsoft.com/azure/search/semantic-search-overview)
212-
- [Original Python Quickstart](https://learn.microsoft.com/azure/search/search-get-started-semantic)
213-
- [Azure SDK for JavaScript Documentation](https://docs.microsoft.com/javascript/api/@azure/search-documents/)
214-
- [Semantic Search Best Practices](https://learn.microsoft.com/azure/search/semantic-how-to-query-request)
215-
216-
## Troubleshooting
217-
218-
- **Service Requirements**: Ensure your search service has semantic ranker enabled (Basic tier or higher)
219-
- **Configuration**: Verify your endpoint URL and API key are correct
220-
- **Index Conflicts**: Check that the index name doesn't conflict with existing indexes
221-
- **SDK Version**: Make sure you have the latest version of the Azure Search Documents SDK
222-
- **Field Configuration**: Ensure your semantic configuration references existing searchable fields
223-
224-
## Clean Up
225-
226-
The sample creates an index named "hotels-quickstart" by default. You can delete it easily:
227-
59+
### Get Captions with Results
22860
```bash
229-
npm run delete-index
61+
npm run get-captions
23062
```
23163

232-
Or programmatically:
233-
```typescript
234-
await indexClient.deleteIndex(indexName);
64+
### Get Semantic Answers
65+
```bash
66+
npm run get-answers
23567
```
236-
237-
## Migration from Original Structure
238-
239-
This sample has been refactored from a single-file structure to a modular one:
240-
241-
**Before** (Single File):
242-
- `semantic-ranking-quickstart.ts` - All functionality in one file
243-
244-
**After** (Modular Structure):
245-
- `config.ts` - Configuration and types
246-
- `createIndex.ts` - Index creation
247-
- `uploadDocuments.ts` - Document upload
248-
- `searchBM25.ts` - BM25 search operations
249-
- `searchSemantic.ts` - Semantic search
250-
- `searchSemanticAnswer.ts` - Semantic answers
251-
- `main.ts` - Orchestration script
252-
- `deleteIndex.ts` - Cleanup utility
253-
254-
The original single-file version is preserved as `semantic-ranking-quickstart.ts` for reference.
255-
256-
## Related Samples
257-
258-
- [Vector Search Quickstart](../quickstart-vector-ts/) - Learn about vector search capabilities
259-
- [RAG with TypeScript](../quickstart-rag-ts/) - Retrieval Augmented Generation patterns
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Azure AI Search Service Configuration
2-
SEARCH_ENDPOINT=PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
3-
INDEX_NAME=hotels-sample-index
4-
SEMANTIC_CONFIGURATION_NAME=semantic-config
2+
AZURE_SEARCH_ENDPOINT=PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
3+
AZURE_SEARCH_INDEX_NAME=hotels-sample-index
4+
SEMANTIC_CONFIGURATION_NAME=semantic-config

0 commit comments

Comments
 (0)