|
# Rexa Search
|
|
|
|
A classic Google-style search engine (2005-2010 era) powered by Exa API and OpenRouter. Features AI-powered search with markdown formatting, web search, and image search with thumbnail display, complete with a REST API and 24-hour result caching.
|
|
|
|
## Features
|
|
|
|
- Classic Google interface (2005-2010 era)
|
|
- **AI Search** - Perform Exa web/image search, format with OpenRouter in markdown with syntax highlighting (default option)
|
|
- Web search with Exa API
|
|
- Image search with thumbnail grid layout
|
|
- 24-hour caching for entire search pipeline (Exa results + OpenRouter formatted answers)
|
|
- Progressive Web App (PWA) support
|
|
- Fully responsive design
|
|
- REST API for programmatic access
|
|
- Installable Python package
|
|
- SQLite-based caching with dataset library
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
pip install rexa-search
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Set the required API keys as environment variables:
|
|
|
|
```bash
|
|
export EXA_API_KEY=your_exa_api_key_here
|
|
export OPENROUTER_API_KEY=your_openrouter_api_key_here
|
|
```
|
|
|
|
### API Keys
|
|
|
|
- **EXA_API_KEY**: For web and image search (https://dashboard.exa.ai/api-keys)
|
|
- **OPENROUTER_API_KEY**: For AI answer formatting with markdown and syntax highlighting (https://openrouter.ai/keys)
|
|
- **OPENROUTER_MODEL**: Optional, defaults to `x-ai/grok-code-fast-1`
|
|
|
|
## Usage
|
|
|
|
### Start the Server
|
|
|
|
```bash
|
|
rexa-search
|
|
```
|
|
|
|
Or using Python module:
|
|
|
|
```bash
|
|
python -m rexa
|
|
```
|
|
|
|
The server will start on port 8088 by default.
|
|
|
|
### Using Make
|
|
|
|
```bash
|
|
make install
|
|
make run
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### Web Interface
|
|
|
|
- `GET /` - Homepage (AI search is default)
|
|
- `GET /ai?q=query` - AI search with markdown formatting and syntax highlighting
|
|
- `GET /search?q=query&num=10` - Web search results page
|
|
- `GET /images?q=query&num=20` - Image search results page
|
|
|
|
### REST API
|
|
|
|
- `GET /api/ai?q=query&num=10` - AI search with markdown formatted answer (JSON)
|
|
- Returns: `html_answer`, `markdown_answer`, `search_results`, `search_type`, `cached`
|
|
- Auto-detects web vs image search based on query keywords
|
|
- `GET /api/search?q=query&num=10` - Web search (JSON)
|
|
- `GET /api/images?q=query&num=20` - Image search (JSON)
|
|
- `GET /api/mixed?q=query&num=10` - Combined web and images (JSON)
|
|
|
|
### Response Format
|
|
|
|
AI Search:
|
|
```json
|
|
{
|
|
"html_answer": "<p>Formatted HTML with syntax highlighting</p>",
|
|
"markdown_answer": "# Answer in **markdown** format",
|
|
"search_results": [...],
|
|
"search_type": "web" | "images",
|
|
"cached": false,
|
|
"fallback": false
|
|
}
|
|
```
|
|
|
|
**Features:**
|
|
- Query type auto-detection (web vs images based on keywords)
|
|
- Markdown formatting with OpenRouter (x-ai/grok-code-fast-1)
|
|
- Syntax highlighting for code blocks
|
|
- Fallback to markdown-formatted Exa results if OpenRouter fails
|
|
- Entire pipeline cached for 24 hours
|
|
|
|
Web Search:
|
|
```json
|
|
{
|
|
"results": [
|
|
{
|
|
"title": "Page Title",
|
|
"url": "https://example.com",
|
|
"image": "https://example.com/image.jpg",
|
|
"favicon": "https://example.com/favicon.ico",
|
|
"text": "Page content snippet...",
|
|
"highlights": ["Important text..."],
|
|
"published_date": "2025-01-01",
|
|
"author": "Author Name"
|
|
}
|
|
],
|
|
"cached": false
|
|
}
|
|
```
|
|
|
|
Mixed Search:
|
|
```json
|
|
{
|
|
"web": [...],
|
|
"images": [...]
|
|
}
|
|
```
|
|
|
|
## Caching
|
|
|
|
All API requests are cached for 24 hours in a local SQLite database (`cache.db` in the working directory). This reduces API calls and improves performance.
|
|
|
|
**Cached data includes:**
|
|
- AI search results (Exa web/images search + OpenRouter formatted markdown answer)
|
|
- Web search results
|
|
- Image search results
|
|
- Mixed search results
|
|
|
|
**Cache structure:**
|
|
```python
|
|
{
|
|
"html_answer": "<p>Rendered HTML...</p>",
|
|
"markdown_answer": "# Markdown response...",
|
|
"search_results": [...],
|
|
"search_type": "web" | "images",
|
|
"fallback": false
|
|
}
|
|
```
|
|
|
|
## Development
|
|
|
|
### Setup Development Environment
|
|
|
|
```bash
|
|
git clone https://github.com/retoor/rexa-search.git
|
|
cd rexa-search
|
|
make install
|
|
```
|
|
|
|
### Run with Auto-Reload
|
|
|
|
```bash
|
|
make dev
|
|
```
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
rexa/
|
|
├── rexa/
|
|
│ ├── main.py # Application entry point
|
|
│ ├── api/
|
|
│ │ ├── router.py # FastAPI routes
|
|
│ │ └── endpoints.py # Search endpoints
|
|
│ ├── core/
|
|
│ │ ├── config.py # Configuration
|
|
│ │ ├── cache.py # 24h caching logic
|
|
│ │ └── exa_client.py # Exa API wrapper
|
|
│ ├── templates/
|
|
│ │ ├── base.html
|
|
│ │ ├── home.html
|
|
│ │ ├── results_web.html
|
|
│ │ └── results_images.html
|
|
│ └── static/
|
|
│ ├── css/
|
|
│ │ └── style.css
|
|
│ └── js/
|
|
├── setup.py
|
|
├── pyproject.toml
|
|
├── Makefile
|
|
└── README.md
|
|
```
|
|
|
|
## Configuration Options
|
|
|
|
Environment variables:
|
|
|
|
- `EXA_API_KEY` - Your Exa API key (required)
|
|
- `PORT` - Server port (default: 8088)
|
|
- `HOST` - Server host (default: 0.0.0.0)
|
|
- `CACHE_TTL_HOURS` - Cache time-to-live in hours (default: 24)
|
|
|
|
## License
|
|
|
|
MIT License - See LICENSE file for details.
|
|
|
|
## Author
|
|
|
|
retoor <retoor@molodetz.nl>
|
|
|
|
## Acknowledgments
|
|
|
|
- Powered by Exa API - https://exa.ai
|
|
- Classic Google design inspiration
|