Skip to content

Commit 29e354f

Browse files
committed
edits with dac
1 parent c200d76 commit 29e354f

File tree

6 files changed

+473
-490
lines changed

6 files changed

+473
-490
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// This is a RAG (Retrieval Augmented Generation) implementation that:
2+
// 1. Takes a user query about hotels
3+
// 2. Searches a hotel database using Azure AI Search
4+
// 3. Formats the search results for the LLM
5+
// 4. Sends the query and formatted results to Azure OpenAI
6+
// 5. Returns a grounded response based only on the retrieved information
7+
8+
import { SearchClient } from "@azure/search-documents";
9+
import { AzureOpenAI } from "openai";
10+
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
11+
12+
function getClients() {
13+
14+
const credential = new DefaultAzureCredential();
15+
16+
// Search
17+
const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT;
18+
const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME;
19+
20+
const searchClient = new SearchClient(
21+
azureSearchEndpoint,
22+
azureSearchIndexName,
23+
credential
24+
);
25+
26+
27+
// OpenAI
28+
const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT;
29+
const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION;
30+
const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL;
31+
32+
const scope = "https://cognitiveservices.azure.com/.default";
33+
const azureADTokenProvider = getBearerTokenProvider(credential, scope);
34+
const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
35+
const openaiClient = new AzureOpenAI(options);
36+
37+
return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
38+
}
39+
40+
async function queryAISearchForSources(
41+
searchClient,
42+
query
43+
) {
44+
console.log(`Searching for: "${query}"\n`);
45+
46+
const selectedFields = ["HotelName", "Description", "Address", "Rooms", "Tags"];
47+
const searchResults = await searchClient.search(query, {
48+
top: 5,
49+
select: selectedFields,
50+
queryType: "semantic",
51+
semanticSearchOptions: {},
52+
});
53+
54+
return searchResults;
55+
}
56+
async function queryOpenAIForResponse(
57+
openaiClient,
58+
query,
59+
sourcesFormatted,
60+
modelName
61+
){
62+
63+
const GROUNDED_PROMPT = `
64+
You are a friendly assistant that recommends hotels based on activities and amenities.
65+
Answer the query using only the sources provided below in a friendly and concise bulleted manner.
66+
Answer ONLY with the facts listed in the list of sources below.
67+
If there isn't enough information below, say you don't know.
68+
Do not generate answers that don't use the sources below.
69+
70+
Query: {query}
71+
Sources: {sources}
72+
`;
73+
74+
return openaiClient.chat.completions.create({
75+
model: modelName,
76+
messages: [
77+
{
78+
role: "user",
79+
content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
80+
}
81+
],
82+
temperature: 0.7,
83+
max_tokens: 800,
84+
});
85+
}
86+
87+
async function main() {
88+
89+
const { openaiClient, searchClient, modelName } = getClients();
90+
91+
const query = `
92+
Can you recommend a few hotels that offer complimentary breakfast?
93+
Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
94+
`;
95+
96+
const sourcesResult = await queryAISearchForSources(searchClient, query);
97+
let sourcesFormatted = "";
98+
99+
for await (const result of sourcesResult.results) {
100+
// Explicitly typing result to ensure compatibility
101+
sourcesFormatted += JSON.stringify(result.document) + "\n";
102+
}
103+
104+
const response = await queryOpenAIForResponse(openaiClient, query, sourcesFormatted.trim(), modelName);
105+
106+
// Print the response from the chat model
107+
const content = response.choices[0].message.content;
108+
if (content) {
109+
console.log(content);
110+
} else {
111+
console.log("No content available in the response.");
112+
}
113+
}
114+
115+
main().catch((error) => {
116+
console.error("An error occurred:", error);
117+
process.exit(1);
118+
});
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// This is a RAG (Retrieval Augmented Generation) implementation that:
2+
// 1. Takes a user query about hotels
3+
// 2. Searches a hotel database using Azure AI Search
4+
// 3. Formats the search results for the LLM
5+
// 4. Sends the query and formatted results to Azure OpenAI
6+
// 5. Returns a grounded response based only on the retrieved information
7+
8+
import { SearchClient, SearchDocumentsResult } from "@azure/search-documents";
9+
import { AzureOpenAI } from "openai";
10+
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
11+
12+
function getClients(): { openaiClient: AzureOpenAI; searchClient: SearchClient<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>; modelName: string } {
13+
14+
const credential = new DefaultAzureCredential();
15+
16+
// Search
17+
const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT!;
18+
const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME!;
19+
const searchClient = new SearchClient<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>(
20+
azureSearchEndpoint,
21+
azureSearchIndexName,
22+
credential
23+
);
24+
25+
// OpenAI
26+
const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT!;
27+
const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION!;
28+
const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL!;
29+
30+
const scope = "https://cognitiveservices.azure.com/.default";
31+
const azureADTokenProvider = getBearerTokenProvider(credential, scope);
32+
const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
33+
const openaiClient = new AzureOpenAI(options);
34+
35+
return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
36+
}
37+
38+
39+
async function queryAISearchForSources(
40+
searchClient: SearchClient<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>,
41+
query: string
42+
): Promise<SearchDocumentsResult<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>> {
43+
console.log(`Searching for: "${query}"\n`);
44+
45+
const selectedFields: readonly ["HotelName", "Description", "Address", "Rooms", "Tags"] = ["HotelName", "Description", "Address", "Rooms", "Tags"];
46+
const searchResults = await searchClient.search(query, {
47+
top: 5,
48+
select: selectedFields,
49+
queryType: "semantic",
50+
semanticSearchOptions: {},
51+
});
52+
53+
return searchResults;
54+
}
55+
async function queryOpenAIForResponse(
56+
openaiClient: AzureOpenAI,
57+
query: string,
58+
sourcesFormatted: string,
59+
modelName: string
60+
): Promise<{ choices: { message: { content: string | null } }[] }> {
61+
62+
const GROUNDED_PROMPT = `
63+
You are a friendly assistant that recommends hotels based on activities and amenities.
64+
Answer the query using only the sources provided below in a friendly and concise bulleted manner.
65+
Answer ONLY with the facts listed in the list of sources below.
66+
If there isn't enough information below, say you don't know.
67+
Do not generate answers that don't use the sources below.
68+
69+
Query: {query}
70+
Sources: {sources}
71+
`;
72+
73+
return openaiClient.chat.completions.create({
74+
model: modelName,
75+
messages: [
76+
{
77+
role: "user",
78+
content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
79+
}
80+
],
81+
temperature: 0.7,
82+
max_tokens: 800,
83+
});
84+
}
85+
86+
async function main(): Promise<void> {
87+
88+
const { openaiClient, searchClient, modelName } = getClients();
89+
90+
const query = `
91+
Can you recommend a few hotels that offer complimentary breakfast?
92+
Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
93+
`;
94+
95+
const sourcesResult = await queryAISearchForSources(searchClient, query);
96+
let sourcesFormatted = "";
97+
98+
for await (const result of sourcesResult.results) {
99+
// Explicitly typing result to ensure compatibility
100+
sourcesFormatted += JSON.stringify(result.document) + "\n";
101+
}
102+
103+
const response = await queryOpenAIForResponse(openaiClient, query, sourcesFormatted.trim(), modelName);
104+
105+
// Print the response from the chat model
106+
const content = response.choices[0].message.content;
107+
if (content) {
108+
console.log(content);
109+
} else {
110+
console.log("No content available in the response.");
111+
}
112+
}
113+
114+
main().catch((error) => {
115+
console.error("An error occurred:", error);
116+
process.exit(1);
117+
});
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// This is a RAG (Retrieval Augmented Generation) implementation that:
2+
// 1. Takes a user query about hotels
3+
// 2. Searches a hotel database using Azure AI Search
4+
// 3. Formats the search results for the LLM
5+
// 4. Sends the query and formatted results to Azure OpenAI
6+
// 5. Returns a grounded response based only on the retrieved information
7+
8+
import { SearchClient } from "@azure/search-documents";
9+
import { AzureOpenAI } from "openai";
10+
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
11+
12+
function getClients() {
13+
14+
const credential = new DefaultAzureCredential();
15+
16+
// Search
17+
const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT;
18+
const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME;
19+
20+
const searchClient = new SearchClient(
21+
azureSearchEndpoint,
22+
azureSearchIndexName,
23+
credential
24+
);
25+
26+
27+
// OpenAI
28+
const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT;
29+
const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION;
30+
const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL;
31+
32+
const scope = "https://cognitiveservices.azure.com/.default";
33+
const azureADTokenProvider = getBearerTokenProvider(credential, scope);
34+
const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
35+
const openaiClient = new AzureOpenAI(options);
36+
37+
return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
38+
}
39+
40+
async function queryAISearchForSources(searchClient, query) {
41+
console.log(`Searching for: "${query}"\n`);
42+
const searchResults = await searchClient.search(query, {
43+
top: 5,
44+
select: ["Description", "HotelName", "Tags"]
45+
});
46+
47+
const sources = [];
48+
for await (const result of searchResults.results) {
49+
const doc = result.document;
50+
sources.push(
51+
`Hotel: ${doc.HotelName}\n` +
52+
`Description: ${doc.Description}\n` +
53+
`Tags: ${Array.isArray(doc.Tags) ? doc.Tags.join(', ') : doc.Tags}\n`
54+
);
55+
}
56+
const sourcesFormatted = sources.join("\n---\n");
57+
return sourcesFormatted;
58+
}
59+
async function queryOpenAIForResponse(openaiClient, query, sourcesFormatted, modelName) {
60+
61+
const GROUNDED_PROMPT = `
62+
You are a friendly assistant that recommends hotels based on activities and amenities.
63+
Answer the query using only the sources provided below in a friendly and concise bulleted manner.
64+
Answer ONLY with the facts listed in the list of sources below.
65+
If there isn't enough information below, say you don't know.
66+
Do not generate answers that don't use the sources below.
67+
68+
Query: {query}
69+
Sources: {sources}
70+
`;
71+
72+
return openaiClient.chat.completions.create({
73+
model: modelName,
74+
messages: [
75+
{
76+
role: "user",
77+
content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
78+
}
79+
],
80+
temperature: 0.7,
81+
max_tokens: 800,
82+
});
83+
}
84+
85+
async function main() {
86+
87+
const { openaiClient, searchClient, modelName } = getClients();
88+
89+
const query = "Can you recommend a few hotels with complimentary breakfast?";
90+
91+
const sources = await queryAISearchForSources(searchClient, query);
92+
const response = await queryOpenAIForResponse(openaiClient, query, sources, modelName);
93+
94+
// Print the response from the chat model
95+
const content = response.choices[0].message.content;
96+
if (content) {
97+
console.log(content);
98+
} else {
99+
console.log("No content available in the response.");
100+
}
101+
}
102+
103+
main().catch((error) => {
104+
console.error("An error occurred:", error);
105+
process.exit(1);
106+
});

0 commit comments

Comments
 (0)