A hotel search and booking platform that uses LLMs and speech transcription to convert voice queries into structured search filters.
The application integrates Google Gemini, Anthropic Claude, and Speechmatics speech recognition. Users can search using filters or speak their requirements, which are processed through LLMs to extract search parameters.
WebSocket-based audio streaming sends user speech to Speechmatics for transcription, then to an LLM for extraction of search parameters including location, price range, amenities, and dates.
Proximity-based searches using PostgreSQL with PostGIS extensions. Supports filtering by hotel ratings, property types, amenities, and price ranges.
CopilotKit integration provides functions for finding nearby places and calculating distances between locations.
Hotel pages display room types, rate plans, amenities, and user reviews. Database schema maintains relationships between hotels, rooms, rate plans, and bookings.
Stores recent searches for authenticated users.
- Framework: FastAPI with Python 3.13
- Database: PostgreSQL with PostGIS for geographic queries
- ORM: SQLAlchemy with GeoAlchemy2
- AI Services:
- Google Gemini (via langchain-google-genai)
- Anthropic Claude (via langchain-anthropic)
- OpenAI (via langchain-openai)
- Speechmatics for real-time speech transcription
- Authentication: JWT-based authentication with OAuth2
- Maps & Location: Google Maps API for geocoding and place autocomplete
- Deployment: Docker, Gunicorn with uvicorn workers
- Framework: Next.js 15 with React 19
- Language: TypeScript
- Styling: Tailwind CSS
- UI Components: Radix UI primitives
- State Management: Zustand
- Maps: @vis.gl/react-google-maps
- Audio Visualization: Audiomotion Analyzer
- Forms: React Hook Form with Zod validation
- HTTP Client: Axios
haven/
├── backend/ # FastAPI backend application
│ ├── app/
│ │ ├── router/ # API route handlers
│ │ │ ├── auth/ # Authentication endpoints
│ │ │ ├── hotel_search/ # Hotel search functionality
│ │ │ ├── voice_search_exp/ # Voice search WebSocket
│ │ │ ├── booking/ # Booking management
│ │ │ └── cpkit.py # CopilotKit integration
│ │ ├── services/ # Business logic layer
│ │ │ ├── ai/ # LLM integration (prompts, schemas)
│ │ │ ├── transcription/ # Speech-to-text services
│ │ │ ├── maps/ # Google Maps integration
│ │ │ ├── tools/ # AI agent tools
│ │ │ └── crud/ # Database operations
│ │ ├── models.py # SQLAlchemy database models
│ │ ├── schemas.py # Pydantic request/response schemas
│ │ ├── database.py # Database connection setup
│ │ └── main.py # FastAPI application entry point
│ ├── requirements.txt
│ └── pyproject.toml
│
└── haven/ # Next.js frontend application
├── src/
│ ├── app/ # Next.js app router pages
│ │ ├── page.tsx # Landing page
│ │ ├── hotels/ # Search results page
│ │ ├── hotel/[id]/ # Hotel detail page
│ │ ├── booking/ # Booking flow
│ │ └── profile/ # User profile
│ ├── components/ # React components
│ │ ├── auth/ # Authentication UI
│ │ ├── search/ # Search bar and filters
│ │ ├── voice-search/ # Voice input UI
│ │ ├── booking/ # Booking components
│ │ ├── chat/ # AI assistant chat
│ │ └── ui/ # Shared UI components
│ ├── hooks/ # Custom React hooks
│ ├── store/ # Zustand state stores
│ ├── context/ # React context providers
│ └── lib/ # Utility functions
└── package.json
- Python 3.13+
- Node.js 20+
- PostgreSQL with PostGIS extension
- API keys for:
- Google Maps API
- Speechmatics API
- At least one LLM provider (Google Gemini, Anthropic Claude, or OpenAI)
- Navigate to the backend directory:
cd backend- Create a virtual environment and activate it:
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate- Install dependencies:
pip install -r requirements.txt- Create a
.envfile in the backend directory with the following variables:
DATABASE_URL=postgresql://user:password@localhost:5432/haven
BASE_FRONTEND_URL=http://localhost:3000
BASE_FRONTEND_DOMAIN=localhost
SECRET_KEY=your-secret-key-here
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
# API Keys
GOOGLE_MAPS_API_KEY=your-google-maps-key
SPEECHMATICS_API_KEY=your-speechmatics-key
GOOGLE_API_KEY=your-gemini-key # For Gemini
ANTHROPIC_API_KEY=your-claude-key # For Claude
OPENAI_API_KEY=your-openai-key # For OpenAI
# Optional: Parent URL for health checks
PARENT_URL=http://localhost:3000-
Run database migrations and seed initial data (if applicable).
-
Start the development server:
uvicorn app.main:app --reloadThe API will be available at http://localhost:8000.
- Navigate to the haven frontend directory:
cd haven- Install dependencies:
npm install- Create a
.envfile in the haven directory:
NEXT_PUBLIC_API_URL=http://localhost:8000
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=your-google-maps-key- Start the development server:
npm run devThe application will be available at http://localhost:3000.
POST /auth/register- Create new user accountPOST /auth/login- User authentication
POST /search/hotels- Search hotels with filtersGET /search/suggestions- Get location suggestions
WS /ws/audio/{language}- WebSocket endpoint for real-time voice search
GET /hotel/{hotel_id}- Get hotel informationGET /hotel/{hotel_id}/rooms- Get available rooms and rates
POST /booking- Create new bookingGET /booking/user/{user_id}- Get user bookings
POST /copilotkit_remote- AI assistant actions endpoint
The application uses a normalized relational schema with the following entities:
- PlatformUser: User accounts and authentication
- Hotel: Hotel properties with geographic coordinates
- HotelAmenity: Hotel amenities
- RoomType: Room configurations
- RatePlan: Pricing and payment options
- Booking: User reservations
- UserReview: Hotel reviews and ratings
- City/Country: Location taxonomy
Geographic queries use PostGIS geography types for proximity searches.
The backend uses a layered architecture separating routing, business logic, and data access. The services directory contains business logic including AI model interactions, speech processing, and database operations.
- Client establishes WebSocket connection with language parameter
- Audio streams from browser to backend
- Backend forwards audio to Speechmatics for transcription
- Transcript is sent to LLM for filter extraction
- Filters are processed and database query is executed
- Results are sent back through WebSocket
LangChain handles model orchestration across different LLM providers. The services/ai module contains prompts and schemas used to extract structured search filters from text.
Zustand stores handle global state for authentication, search filters, and booking. React Context is used for authentication status.