AI-Receptionist / app.py
sarmaddev's picture
edit name
1e26132
import chainlit as cl
import pandas as pd
import os
from dotenv import load_dotenv, find_dotenv
from agents import Agent, Runner, AsyncOpenAI, OpenAIChatCompletionsModel ,function_tool
from agents.run import RunConfig
from openai.types.responses import ResponseTextDeltaEvent
# @cl.on_message
# async def main(message: cl.Message):
# # Your custom logic goes here...
# # Send a response back to the user
# await cl.Message(
# content=f"Received: {message.content}",
# ).send()
CSV_PATH = "availablity.csv"
def load_data():
return pd.read_csv(CSV_PATH)
def save_data(df):
df.to_csv(CSV_PATH, index=False)
# Get availability for a given date
@function_tool
def get_availability(date: str) -> str:
"""
Returns a list of available room types for a given date.
Args:
date (str): The date to check availability for (format: YYYY-MM-DD).
Returns:
str: A formatted string listing available room types and counts,
or a message indicating no availability or invalid date.
"""
df = load_data()
day_rooms = df[df['date'] == date]
if day_rooms.empty:
return f"No availability data for {date}."
available_rooms = day_rooms[day_rooms['available'] > 0]
if available_rooms.empty:
return f"No rooms available on {date}."
result = [f"{row.room_type.title()} ({row.available} available)" for _, row in available_rooms.iterrows()]
return f"Available rooms on {date}:\n" + "\n".join(result)
# Book a room if available
@function_tool
def book_room(date: str, room_type: str, guests: int, num_rooms: int = 1) -> str:
"""
Attempts to book a specified number of rooms of the given type on a date.
Args:
date (str): The booking date (format: YYYY-MM-DD).
room_type (str): The type of room to book (e.g., 'single', 'double', 'suite').
guests (int): Number of guests for the booking.
num_rooms (int, optional): Number of rooms to book. Defaults to 1.
Returns:
str: A confirmation message if booking is successful, or an error message.
"""
df = load_data()
match = (df['date'] == date) & (df['room_type'].str.lower() == room_type.lower())
room_row = df[match]
if room_row.empty:
return f"No {room_type} room available on {date}."
idx = room_row.index[0]
if df.at[idx, 'available'] >= num_rooms:
df.at[idx, 'available'] -= num_rooms
save_data(df)
return f"✅ Booked {num_rooms} {room_type.title()} room(s) for {guests} guest(s) on {date}."
else:
return f"❌ Only {df.at[idx, 'available']} {room_type.title()} rooms left on {date}."
load_dotenv(find_dotenv())
api_key = os.getenv('OpenAI_api_key')
external_client = AsyncOpenAI(
api_key=api_key,
base_url="https://api.aimlapi.com/v1",
)
model = OpenAIChatCompletionsModel(
model="gpt-4",
openai_client=external_client
)
config = RunConfig(
model=model,
model_provider=external_client,
tracing_disabled=True
)
agent: Agent = Agent(
name="Receptionist",
instructions="You are a helpful hotel receptionist. You can help with booking rooms, checking availability regarding specific date user provides, and answering questions about the hotel.",
tools=[get_availability, book_room],
model=model
)
@cl.on_chat_start
async def on_chat_start():
cl.user_session.set("history", [])
await cl.Message("Hi! This AI powered Hotel Receptionist which can book hotel room, answer common queries and check hotel rooms availiblity from hotel's database for you!!").send()
@cl.on_message
async def handle(message: cl.Message):
history = cl.user_session.get("history")
history.append({
"role": "user",
"content": message.content
})
msg = cl.Message(content="")
# Format history as a string to avoid passing raw dictionaries
def format_history(history):
formatted = []
for entry in history:
role = entry["role"].title()
content = entry["content"]
formatted.append(f"{role}: {content}")
return "\n".join(formatted)
result = Runner.run_streamed(agent, format_history(history), run_config=config)
async for event in result.stream_events():
if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent):
response = event.data.delta
if isinstance(response, str):
await msg.stream_token(response)
elif isinstance(response, dict) and "content" in response:
await msg.stream_token(response["content"])
else:
print(f"Unexpected response format: {response}")
elif event.type == "final_response":
if hasattr(event.data, "content") and isinstance(event.data.content, str):
await msg.stream_token(event.data.content)
elif isinstance(event.data, dict) and "content" in event.data:
await msg.stream_token(event.data["content"])
else:
print(f"Unexpected final response format: {event.data}")
# Store only the content in history
history.append({
"role": "receptionist",
"content": msg.content
})
cl.user_session.set("history", history)
await msg.update()