An AI-powered FastAPI application that generates recipe recommendations from ingredients using OpenRouter AI services.
- Recipe Generation: Generate recipes from a list of ingredients with quantities
- Multi-Unit Support: Supports 33+ measurement units including mass (kg, g, lb, oz) and capacity (l, ml, cups, tbsp, tsp)
- Input Validation: Comprehensive validation of ingredient formats and quantities with intelligent unit recognition
- AI Integration: Uses OpenRouter API for intelligent recipe generation
- Error Handling: Robust error handling with detailed error messages
- Health Monitoring: Health check endpoint for service monitoring
- Comprehensive Testing: Full test coverage with unit and integration tests
python-recipebot-api/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI application entry point
│ ├── api/
│ │ ├── __init__.py
│ │ └── recipe_routes.py # Recipe API endpoints
│ ├── models/
│ │ ├── __init__.py
│ │ └── recipe_models.py # Pydantic models for request/response
│ ├── services/
│ │ ├── __init__.py
│ │ ├── ingredient_validator.py # Ingredient validation logic
│ │ ├── openrouter_client.py # OpenRouter API client
│ │ ├── prompt_generator.py # AI prompt generation
│ │ └── recipe_generator.py # Main recipe generation service
│ └── utils/
│ ├── __init__.py
│ ├── logger_config.py # Logging configuration
│ └── response_formatter.py # Response formatting utilities
├── templates/
│ └── recipe_prompt.txt # AI prompt template
├── tests/ # Comprehensive test suite
├── requirements.txt # Python dependencies
├── pytest.ini # Pytest configuration
├── .env.example # Environment variables example
└── README.md # This file
-
Clone the repository:
git clone <repository-url> cd python-recipebot-api
-
Create virtual environment:
# Remove any existing virtual environments first rm -rf venv .venv # Create new virtual environment python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install dependencies:
# Upgrade pip first pip install --upgrade pip # Install dependencies pip install -r requirements.txt
-
Set up environment variables:
cp .env.example .env # Edit .env and add your OpenRouter API key
If you encounter issues during installation:
# Solution: Remove and recreate virtual environment
rm -rf venv .venv
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
# Solution 1: Use virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Solution 2: Use --break-system-packages (not recommended for production)
pip install -r requirements.txt --break-system-packages
# Solution 3: Install using pipx (if available)
pipx install -r requirements.txt
# Make sure you're in the virtual environment
source venv/bin/activate
# Then install with user flag if needed
pip install --user -r requirements.txt
# Check Python version (requires Python 3.8+)
python3 --version
# If you have multiple Python versions, specify the version
python3.11 -m venv venv # or python3.10, python3.12, etc.
source venv/bin/activate
pip install -r requirements.txt
Create a .env
file with the following variables:
OPENROUTER_API_KEY=your_openrouter_api_key_here
- Sign up at OpenRouter
- Generate an API key
- Add it to your
.env
file
Make sure to activate the virtual environment first:
# Activate virtual environment
source venv/bin/activate # On Windows: venv\Scripts\activate
# Development server (with auto-reload)
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# Alternative: using the virtual environment directly
./venv/bin/uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# Production server (without auto-reload)
uvicorn app.main:app --host 0.0.0.0 --port 8000
The API will be available at http://localhost:8000
- Interactive API docs:
http://localhost:8000/docs
- ReDoc documentation:
http://localhost:8000/redoc
GET /health
Response:
{
"status": "healthy",
"service": "RecipeBot API"
}
POST /api/recipe
Request Body:
{
"ingredients": [
"2kg pork shoulder",
"1kg potatoes",
"500g onions",
"2 tbsp olive oil",
"1 tsp salt",
"500ml chicken broth"
]
}
Success Response (200):
{
"status": "success",
"recipe": {
"title": "Hearty Pork and Potato Stew",
"ingredients": [
"2kg pork shoulder",
"1kg potatoes",
"500g onions",
"2 tbsp olive oil",
"1 tsp salt",
"500ml chicken broth"
],
"instructions": [
"Cut pork shoulder into chunks",
"Dice potatoes and onions",
"Heat olive oil in a large pot",
"Brown the pork in the pot",
"Add vegetables and broth, simmer for 45 minutes"
],
"cooking_time": "45 minutes"
}
}
Error Response (400):
{
"detail": {
"status": "error",
"message": "need to provide more ingredients"
}
}
The API validates:
- Ingredient format: Each ingredient must include a quantity (numbers) and a supported unit
- List size: 1-20 ingredients maximum
- Content: Non-empty strings only
- Unit recognition: Supports 33+ measurement units for mass and capacity
Mass Units (12 units):
- Metric:
kg
,kilogram
,kilograms
,g
,gram
,grams
- Imperial:
lb
,pound
,pounds
,oz
,ounce
,ounces
Capacity Units (21 units):
- Metric:
l
,liter
,liters
,litre
,litres
,ml
,milliliter
,milliliters
,millilitre
,millilitres
- Imperial:
fl oz
,fluid ounce
,fluid ounces
- Cooking:
cup
,cups
,tbsp
,tablespoon
,tablespoons
,tsp
,teaspoon
,teaspoons
Mass measurements:
"2kg pork"
- kilograms"500g flour"
- grams"1lb beef"
- pounds"8oz cheese"
- ounces"2.5 kilograms potatoes"
- long form with decimals
Capacity measurements:
"2l milk"
- liters"500ml water"
- milliliters"1 cup sugar"
- cups (with space)"2 tbsp olive oil"
- tablespoons"1 tsp salt"
- teaspoons"16 fl oz broth"
- fluid ounces"250 milliliters cream"
- long form
Invalid ingredients:
"pork"
(no quantity)"2 invalid_unit meat"
(unsupported unit)""
(empty string)" "
(whitespace only)"2 pork"
(no unit specified)
Make sure to activate the virtual environment first:
# Activate virtual environment
source venv/bin/activate # On Windows: venv\Scripts\activate
# Run all tests
pytest
# Run with coverage
pytest --cov=app
# Run specific test file
pytest tests/test_ingredient_validator.py
# Run with verbose output
pytest -v
# Alternative: using the virtual environment directly
./venv/bin/pytest tests/ -v
# Run tests for new units functionality specifically
./venv/bin/pytest tests/test_ingredient_validator.py::TestIngredientValidator::test_validate_mass_units -v
./venv/bin/pytest tests/test_ingredient_validator.py::TestIngredientValidator::test_validate_capacity_units -v
- Unit Tests: Individual component testing
- Integration Tests: Service interaction testing
- API Tests: Endpoint testing with mocked dependencies
The enhanced ingredient validation includes comprehensive tests for all supported units:
# Test all ingredient validator functionality
./venv/bin/pytest tests/test_ingredient_validator.py -v
# Test specific unit types
./venv/bin/pytest tests/test_ingredient_validator.py::TestIngredientValidator::test_validate_mass_units -v
./venv/bin/pytest tests/test_ingredient_validator.py::TestIngredientValidator::test_validate_capacity_units -v
# Test unit extraction and categorization
./venv/bin/pytest tests/test_ingredient_validator.py::TestIngredientValidator::test_get_ingredient_unit -v
./venv/bin/pytest tests/test_ingredient_validator.py::TestIngredientValidator::test_is_mass_unit -v
./venv/bin/pytest tests/test_ingredient_validator.py::TestIngredientValidator::test_is_capacity_unit -v
Test Coverage: The ingredient validator now includes 19 test methods covering:
- ✅ Mass unit validation (kg, g, lb, oz, etc.)
- ✅ Capacity unit validation (l, ml, cups, tbsp, tsp, etc.)
- ✅ Unit extraction from ingredient strings
- ✅ Unit type categorization (mass vs capacity)
- ✅ Long-form unit names (kilogram, tablespoon, etc.)
- ✅ Invalid format detection
- ✅ Backward compatibility with existing functionality
# Clone and setup
git clone <repository-url>
cd python-recipebot-api
# Setup virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Setup environment
cp .env.example .env
# Edit .env and add your OPENROUTER_API_KEY
# Run tests
./venv/bin/pytest tests/ -v
# Start development server
./venv/bin/uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# Test the API
curl -X POST "http://localhost:8000/api/recipe" \
-H "Content-Type: application/json" \
-d '{"ingredients": ["2kg pork", "500ml broth", "1 cup rice"]}'
The project follows strict coding conventions defined in CODING_CONVENTIONS.md
:
- Naming: snake_case for variables/functions, PascalCase for classes
- File Size: Maximum 200 lines per file
- Nesting: Maximum 3 levels of nesting
- SOLID Principles: Single responsibility, dependency injection
- Type Hints: All functions have type annotations
- Documentation: Google-style docstrings
- Create feature branch:
git checkout -b feature/new-feature
- Write tests first: Follow TDD approach
- Implement feature: Follow coding conventions
- Run tests: Ensure all tests pass
- Update documentation: Update README and docstrings
- Submit PR: Include test coverage and documentation
The application follows a clean architecture pattern:
- API Layer (
app/api/
): FastAPI routes and request handling - Service Layer (
app/services/
): Business logic and external integrations - Model Layer (
app/models/
): Data models and validation - Utility Layer (
app/utils/
): Cross-cutting concerns (logging, formatting)
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
For production deployment:
- Set environment variables securely
- Use a production ASGI server (uvicorn with workers)
- Set up proper logging and monitoring
- Configure reverse proxy (nginx)
- Enable HTTPS
The application includes:
- Structured logging: JSON format for production
- Health checks:
/health
endpoint for monitoring - Error tracking: Comprehensive error logging
- Request logging: All API requests are logged
-
Installation Issues:
zsh: bad interpreter: no such file or directory error: externally-managed-environment
Solution: See the "Troubleshooting Installation" section above
-
OpenRouter API Key Error:
ValueError: OPENROUTER_API_KEY environment variable not set
Solution: Set the
OPENROUTER_API_KEY
environment variable -
Import Errors:
ModuleNotFoundError: No module named 'app'
Solution: Run from project root directory and ensure virtual environment is activated
-
Test Failures:
Failed: async def functions are not natively supported
Solution: Ensure
pytest-asyncio
is installed -
Virtual Environment Issues:
Command 'python' not found, or 'pip' not found
Solution: Ensure virtual environment is activated:
source venv/bin/activate # Linux/Mac # or venv\Scripts\activate # Windows
-
Unit Validation Issues:
Invalid ingredient format: 2 pork
Solution: Ensure ingredients include supported units:
# Test supported units ./venv/bin/python3 -c " from app.services.ingredient_validator import IngredientValidator validator = IngredientValidator() units = validator.get_supported_units() print('Supported units:', units) "
-
Server Won't Start:
ModuleNotFoundError: No module named 'uvicorn'
Solution: Ensure virtual environment is activated and dependencies are installed:
source venv/bin/activate pip install -r requirements.txt ./venv/bin/uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
Enable debug logging by setting:
export LOG_LEVEL=DEBUG
- Fork the repository
- Create a feature branch
- Follow coding conventions
- Write comprehensive tests
- Update documentation
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
For support and questions:
- Create an issue in the repository
- Check the troubleshooting section
- Review the API documentation at
/docs