Skip to content

Commit d73aa05

Browse files
committed
Add car rental agent documentation with semantic search capabilities
1 parent e6cb9f8 commit d73aa05

File tree

1 file changed

+126
-13
lines changed

1 file changed

+126
-13
lines changed

docs/04_explore/README.md

Lines changed: 126 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -281,26 +281,139 @@
281281

282282
</details>
283283

284-
The car rental policy search uses the same semantic search approach as the hotel policies. The policies are stored in JSON format with embeddings for efficient semantic search.
284+
### Expand to see the complete car_rental_plugins.py file
285+
<details>
286+
<summary> Click to expand/collapse</summary>
287+
288+
```python
289+
from typing import Annotated, Any
290+
from semantic_kernel.functions import kernel_function
291+
import os
292+
from openai import AzureOpenAI
293+
import json
294+
from scipy import spatial
285295

286-
The Car_Rental_Tools class now includes a method to search policies.
296+
# Constants for Azure OpenAI
297+
AZURE_OPENAI_API_KEY = os.getenv("AZURE_OPENAI_API_KEY")
298+
AZURE_OPENAI_ENDPOINT = os.getenv("AZURE_OPENAI_ENDPOINT")
299+
AZURE_OPENAI_EMB_DEPLOYMENT = os.getenv("AZURE_OPENAI_EMB_DEPLOYMENT")
300+
AZURE_OPENAI_EMB_ENDPOINT = os.getenv("AZURE_OPENAI_EMB_ENDPOINT", AZURE_OPENAI_ENDPOINT)
301+
AZURE_OPENAI_EMB_API_KEY = os.getenv("AZURE_OPENAI_EMB_API_KEY", AZURE_OPENAI_API_KEY)
302+
AZURE_OPENAI_CHAT_DEPLOYMENT = os.getenv("AZURE_OPENAI_CHAT_DEPLOYMENT")
303+
304+
# Azure OpenAI client setup
305+
embedding_client = AzureOpenAI(
306+
api_key=AZURE_OPENAI_EMB_API_KEY,
307+
azure_endpoint=AZURE_OPENAI_EMB_ENDPOINT,
308+
api_version="2023-12-01-preview"
309+
)
310+
311+
def get_embedding(text: str, model: str = AZURE_OPENAI_EMB_DEPLOYMENT) -> list[float]:
312+
"""Generate text embeddings using Azure OpenAI."""
313+
text = text.replace("\n", " ")
314+
return embedding_client.embeddings.create(input=[text], model=model).data[0].embedding
315+
316+
class SearchClient:
317+
"""Client for performing semantic search on a knowledge base."""
318+
def __init__(self, emb_map_file_path: str):
319+
with open(emb_map_file_path) as file:
320+
self.chunks_emb = json.load(file)
321+
322+
def find_article(self, question: str, topk: int = 3) -> str:
323+
"""Find relevant articles based on cosine similarity."""
324+
input_vector = get_embedding(question)
325+
cosine_list = [
326+
(item['id'], item['policy_text'], 1 - spatial.distance.cosine(input_vector, item['policy_text_embedding']))
327+
for item in self.chunks_emb
328+
]
329+
cosine_list.sort(key=lambda x: x[2], reverse=True)
330+
cosine_list = cosine_list[:topk]
331+
332+
return "\n".join(f"{chunk_id}\n{content}" for chunk_id, content, _ in cosine_list)
287333

288-
The embedding generation script needs to be run once to prepare the policy data.
334+
# Initialize the search client
335+
search_client = SearchClient("./data/car_rental_policy.json")
289336

290-
You can expand the policy database by adding more entries to the JSON file.
337+
# Kernel functions
338+
class Car_Rental_Tools:
339+
"""Tools for car rental agent to perform various rental operations"""
340+
341+
agent_name = "car_rental_agent" # Name of the agent
291342

292-
After implementing these changes:
343+
@kernel_function(
344+
description="Search for available rental cars",
345+
name="search_cars"
346+
)
347+
async def search_cars(self, location: str, pickup_date: str, return_date: str) -> str:
348+
# Mock implementation - replace with actual car rental API
349+
return f"Found available cars in {location} from {pickup_date} to {return_date}: \n" \
350+
"1. Economy - Toyota Corolla ($45/day)\n" \
351+
"2. SUV - Honda CR-V ($65/day)\n" \
352+
"3. Luxury - BMW 5 Series ($95/day)"
293353

294-
- The car rental agent will be available alongside the hotel and flight agents
295-
- The agent can be triggered through intent detection
296-
- The agent will have access to car rental specific tools through its plugin
297-
- The agent will maintain its own context and persona while handling customer interactions
354+
@kernel_function(
355+
description="Get rental car details",
356+
name="get_car_details"
357+
)
358+
async def get_car_details(self, car_id: str) -> str:
359+
# Mock implementation
360+
car_details = {
361+
"1": "Toyota Corolla: 4 doors, 5 seats, automatic transmission, GPS, bluetooth",
362+
"2": "Honda CR-V: 5 doors, 5 seats, automatic transmission, GPS, bluetooth, roof rack",
363+
"3": "BMW 5 Series: 4 doors, 5 seats, automatic transmission, GPS, bluetooth, leather seats"
364+
}
365+
return car_details.get(car_id, "Car not found")
298366

299-
Test the new agent with various car rental scenarios.
300367

301-
Future steps to try on your own.
302-
- Expand the Car_Rental_Tools class with additional functions as needed.
303-
- Replace mock implementations with actual car rental API integrations
368+
@kernel_function(
369+
name="search_rental_policies",
370+
description="Search car rental and insurance policies for relevant information."
371+
)
372+
async def search_rental_policies(self,
373+
search_query: Annotated[str, "The search query about rental or insurance policies."]
374+
) -> str:
375+
return search_client.find_article(search_query)
376+
```
377+
378+
</details>
379+
380+
### Summarizing Adding a New Car Rental Agent with Semantic Search
381+
382+
This exercise demonstrates how to extend the voice agent system by adding a completely new domain-specific agent for car rentals, complete with semantic search capabilities for policy information.
383+
384+
#### Files Created:
385+
- `car_rental_agent_profile.yaml` - Defines the agent's persona and responsibilities
386+
- `car_rental_plugins.py` - Contains tools for car searching, details, and policy lookups
387+
- `car_rental_policy.json` - Stores policy data with embeddings for semantic search
388+
- `scripts/generate_car_rental_policy_embeddings.py` - Script to generate policy embeddings
389+
390+
#### Files Updated:
391+
- `rtmt.py` - Modified to register and initialize the new car rental agent
392+
- `utility.py` - Updated to include car rental in intent detection system messages
393+
394+
#### Key Components:
395+
1. **Agent Profile**: Defines the car rental agent's persona and scope
396+
2. **Tool Integration**: Custom tools for searching cars, viewing details, and accessing policies
397+
3. **SearchClient Class**: Implements vector similarity search using cosine distance
398+
4. **Intent Detection**: Updates to route car rental queries to the specialized agent
399+
400+
#### Integration Benefits:
401+
- Demonstrates the extensibility of the multi-agent architecture
402+
- Adds a completely new domain (car rentals) to the existing hotel and flight agents
403+
- Semantic search provides accurate policy information retrieval
404+
- Maintains consistent agent experience while expanding capabilities
405+
406+
#### Testing:
407+
After implementation, test with queries about:
408+
- Insurance coverage options and costs
409+
- Rental requirements and age restrictions
410+
- Deductibles and additional coverage options
411+
412+
#### Future Enhancements:
413+
- Expand the policy database with more detailed entries
414+
- Add domain-specific tools to the Car_Rental_Tools class
415+
- Implement actual API integrations to replace mock implementations
416+
- Create more sophisticated embedding strategies for better matching
304417

305418
### Exercise 2: debug/fix/commit flow
306419
- scenario which 'fails' from a functionality standpoint -> use observability (tracing in AI Foundry), figure out the problem, change system-prompt/etc., run test suite (local run of Evaluations), then PR

0 commit comments

Comments
 (0)