A FastAPI service that processes song requests for WXYC radio. It parses natural language messages using Groq AI, delegates search to library-metadata-lookup, and posts enriched results to Slack.
- Smart Song Parsing: Uses Groq AI to extract structured metadata from natural language song requests
- Library and Discogs Search: Delegates to library-metadata-lookup for library catalog search and Discogs cross-referencing
- Slack Integration: Posts enriched song data to Slack with embedded artwork
- Fast API: Built with FastAPI for high performance and automatic API documentation
- Python 3.12 or higher
- pip (Python package installer) or use the included
pyproject.tomlfor modern package management
git clone <repository-url>
cd request-o-maticpython -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activateOption A: Using requirements.txt
pip install -r requirements.txtOption B: Using pyproject.toml (Recommended)
pip install -e .Option C: With development dependencies
pip install -e ".[dev]"Copy the example environment file and update with your values:
cp .env.example .envThen edit .env with your actual configuration:
# Required
GROQ_API_KEY=your_groq_api_key_here
LOOKUP_SERVICE_URL=https://library-metadata-lookup-staging.up.railway.app/api/v1
# Optional - Slack Integration
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
# Optional - Telemetry
POSTHOG_API_KEY=your_posthog_project_api_key
POSTHOG_HOST=https://us.i.posthog.com
# Application Configuration
LOG_LEVEL=INFO
PORT=8000
# Feature Flags
ENABLE_SLACK_INTEGRATION=true- GROQ_API_KEY: Sign up at Groq (not Grok) to get an API key
- SLACK_WEBHOOK_URL: Create an incoming webhook in your Slack workspace's App Settings
- POSTHOG_API_KEY: Optional - Get your project API key from PostHog for telemetry tracking
python main.pyuvicorn main:app --reload --host 0.0.0.0 --port 8000The --reload flag enables auto-reloading during development.
The application will start on http://localhost:8000
- Interactive API Documentation: http://localhost:8000/docs (Swagger UI - Try out endpoints here!)
- Read-Only Docs: http://localhost:8000/redoc (ReDoc - Beautiful documentation)
- Health Check: http://localhost:8000/health (Detailed service status)
Note: All API endpoints (except /health) are versioned under /api/v1/ prefix.
# Build the image
docker build -t request-o-matic .
# Run the container
docker run -p 8000:8000 \
-e GROQ_API_KEY=your_groq_api_key \
-e LOOKUP_SERVICE_URL=https://library-metadata-lookup-staging.up.railway.app/api/v1 \
-e SLACK_WEBHOOK_URL=your_slack_webhook \
request-o-maticAll endpoints except /health are prefixed with /api/v1:
GET /health- Health check with service status details (groq, lookup, slack)POST /api/v1/parse- Parse a natural language song request into structured metadataPOST /api/v1/request- Full request workflow: parse -> delegate search to lookup service -> post to Slack
Parse a message:
curl -X POST "http://localhost:8000/api/v1/parse" \
-H "Content-Type: application/json" \
-d '{"message": "Play la paradoja by Juana Molina"}'Full request workflow:
curl -X POST "http://localhost:8000/api/v1/request" \
-H "Content-Type: application/json" \
-d '{"message": "Play la paradoja by Juana Molina"}'Health check:
curl "http://localhost:8000/health"Run all tests (excluding integration):
pytestRun unit tests only:
pytest tests/unit/Run integration tests:
pytest tests/integration/ -m integrationRun with coverage:
pytest --cov=. --cov-report=htmlThe project is configured with modern Python tooling via pyproject.toml:
Format code:
black .Lint code:
ruff check .Fix linting issues automatically:
ruff check --fix .Type checking:
mypy .Run all quality checks:
black . && ruff check --fix . && mypy . && pytest- Create a feature branch
- Make your changes
- Run tests and linters
- Submit a pull request
The project uses:
- Pydantic Settings for type-safe configuration
- FastAPI dependency injection for clean architecture
- Async/await throughout for performance
- Comprehensive logging with structured output
- Custom exceptions for better error handling
Ensure your .env file exists in the project root and contains:
GROQ_API_KEY=your_actual_key_here
If port 8000 is already in use, specify a different port:
uvicorn main:app --port 8001If Slack integration fails:
- Verify your webhook URL is correct
- Check that your Slack app has proper permissions
- The app will attempt to fetch a webhook from Railway if
SLACK_WEBHOOK_URLis not set
| Variable | Required | Default | Description |
|---|---|---|---|
GROQ_API_KEY |
Yes | - | API key for Groq AI service |
LOOKUP_SERVICE_URL |
Yes | - | Base URL of library-metadata-lookup service |
SLACK_WEBHOOK_URL |
No | - | Slack incoming webhook URL (fetches from Railway if not set) |
SLACK_WEBHOOK_KEY_URL |
No | - | Railway endpoint to fetch Slack webhook key |
PORT |
No | 8000 | Port for the application to listen on |
HOST |
No | 0.0.0.0 | Host to bind the server to |
LOG_LEVEL |
No | INFO | Logging level (DEBUG, INFO, WARNING, ERROR) |
ENABLE_SLACK_INTEGRATION |
No | true | Enable/disable Slack notifications |
ENABLE_TELEMETRY |
No | true | Enable/disable PostHog telemetry |
POSTHOG_API_KEY |
No | - | PostHog project API key for telemetry tracking |
POSTHOG_HOST |
No | https://us.i.posthog.com | PostHog host URL |
SENTRY_DSN |
No | - | Sentry DSN for error tracking |
- Service Delegation: All library search and Discogs cross-referencing is delegated to library-metadata-lookup via HTTP
- Dependency Injection: FastAPI's dependency injection system manages service lifecycle and makes testing easier
- Centralized Configuration: Pydantic Settings for type-safe, validated configuration
- Async Throughout: All I/O operations use async/await for optimal performance
- Custom Exceptions: Domain-specific exceptions for better error handling and debugging
- Error Tracking: Sentry integration for production error monitoring with breadcrumbs for debugging
Services are managed through FastAPI's lifespan context manager:
- HTTP clients are reused across requests
- Resources are properly cleaned up at shutdown
- Hosted on Railway
mainbranch auto-deploys to stagingprodbranch auto-deploys to production