A production-ready Docker application that processes JSON problem descriptions and generates Python solutions using Google's Gemini AI. The application reads coding problems from JSON files, generates Python code solutions, executes them, and validates the output against expected results.
- Reads JSON Files: Processes all
.jsonfiles from the input directory - AI Code Generation: Uses Gemini AI to generate Python solutions for each problem
- Code Execution: Runs the generated code with test inputs
- Validation: Compares actual output with expected results
- Solution Storage: Saves all generated solutions to files
- Rate Limiting: Implements intelligent delays to avoid API limits
- Error Handling: Robust retry logic for API failures
main.py: Main application orchestrating the entire workflowjsonLoader.py: JSON file parsing and loading utilitydockerfile: Multi-stage production Docker imagedocker-compose.yml: Container orchestration configuration
# Builder stage: Install dependencies
FROM python:3.11-slim AS builder
# ... build dependencies and virtual environment
# Production stage: Minimal runtime image
FROM python:3.11-slim AS production
# ... copy only necessary files and run as non-root user- β
Non-root execution: Runs as
appuserfor security - β Read-only filesystem: Container filesystem is read-only
- β No new privileges: Security option prevents privilege escalation
- β Resource limits: Memory (1GB) and CPU (0.5 cores) constraints
- β Health monitoring: Built-in health checks
- β Minimal image size: Multi-stage build reduces final image size
- β Dependency isolation: Virtual environment for clean dependencies
- β Log management: Structured logging with rotation (10MB max, 3 files)
- β
Restart policy:
on-failure- restarts only on errors, not after completion
json-ai-code-generator/
βββ π³ Docker Configuration
β βββ dockerfile # Multi-stage production Docker image
β βββ docker-compose.yml # Container orchestration
β βββ .dockerignore # Docker build exclusions
βββ π― Application Code
β βββ main.py # Main processing application
β βββ jsonLoader.py # JSON file parsing utility
β βββ requirements.txt # Python dependencies
βββ π Deployment Scripts
β βββ deploy.ps1 # Windows PowerShell deployment
β βββ deploy.sh # Linux/macOS Bash deployment
β βββ Makefile # Linux/macOS Make commands
βββ βοΈ Configuration
β βββ .env.example # Environment variables template
β βββ .gitignore # Git exclusions
βββ π Input/Output
β βββ json/ # Input JSON problem files
β βββ solutions/ # Generated Python solutions
βββ π Documentation
βββ README.md # This file
# Copy environment template
cp .env.example .env
# Edit .env file and add your Gemini API key
# GEMINI_API_KEY=your_actual_api_key_hereCreate JSON files in the json/ directory with this format:
{
"query": "Write a Python program that reads an integer and prints 'YES' if it's even, 'NO' if it's odd.",
"test_input": 7,
"test_output": "NO"
}# Deploy and run
.\deploy.ps1
# Monitor progress
.\deploy.ps1 -Action logs
# Check status
.\deploy.ps1 -Action status# Make script executable
chmod +x deploy.sh
# Deploy and run
./deploy.sh
# Monitor progress
./deploy.sh logs
# Check status
./deploy.sh status# Deploy and run
make deploy
# Monitor progress
make logs
# Check status
make status- Docker & Docker Compose: Ensure both are installed and running
- Gemini API Key: Get your API key from Google AI Studio
- Environment File: Configure
.envwith your API key
git clone <repository-url>
cd json-ai-code-generator
cp .env.example .env
# Edit .env and add GEMINI_API_KEY=your_key_here# Add your JSON problem files to the json/ directory
# Each file should contain: query, test_input, test_outputWindows:
# Full deployment
.\deploy.ps1
# Alternative: Manual Docker commands
docker build -t json-processor:latest .
docker-compose up -dLinux/macOS:
# Using deployment script
./deploy.sh
# Using Make
make deploy
# Alternative: Manual Docker commands
docker build -t json-processor:latest .
docker-compose up -d# Real-time logs
docker-compose logs -f
# Check container status
docker-compose ps
# View health status
docker inspect json-processor-prod --format='{{.State.Health.Status}}'# Generated solutions will be in ./solutions/ directory
ls -la solutions/
# Example files:
# solution_1.py, solution_2.py, etc.| Feature | Development | Production |
|---|---|---|
| Restart Policy | no |
on-failure |
| Resource Limits | None | 1GB RAM, 0.5 CPU |
| Security | Basic | Non-root, read-only filesystem |
| Logging | Console | Structured with rotation |
| Health Checks | Disabled | Enabled (30s intervals) |
| Volume Mounts | Read-write | Read-only for inputs |
| Variable | Required | Description | Example |
|---|---|---|---|
GEMINI_API_KEY |
β | Google Gemini API key | AIza... |
OPENAI_API_KEY |
β | OpenAI API key (if using OpenAI) | sk-... |
OPENROUTER_API_KEY |
β | OpenRouter API key (if using OpenRouter) | sk-or-... |
PYTHONUNBUFFERED |
β | Disable Python buffering | 1 |
PYTHONDONTWRITEBYTECODE |
β | Don't create .pyc files | 1 |
The application supports multiple AI providers. By default, it uses Google Gemini, but you can easily switch to OpenAI or OpenRouter.
# In main.py - Current configuration
llm = ChatOpenAI(
api_key=os.getenv("GEMINI_API_KEY"),
base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
model="gemini-2.5-flash",
)# In .env file
OPENAI_API_KEY=sk-your-openai-api-key-here# Replace the LLM configuration in main.py
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
model="gpt-5", # or "gpt-5", "gpt-5-mini", etc.
temperature=0.1,
)# Add to requirements.txt (if not already present)
openai>=1.0.0# In .env file
OPENROUTER_API_KEY=sk-or-your-openrouter-api-key-here# Replace the LLM configuration in main.py
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
api_key=os.getenv("OPENROUTER_API_KEY"),
base_url="https://openrouter.ai/api/v1",
model="anthropic/claude-sonnet-4.5", # or other available models
temperature=0.1,
extra_headers={
"HTTP-Referer": "https://your-site.com", # Optional
"X-Title": "JSON AI Code Generator", # Optional
}
)# Add to requirements.txt (if not already present)
openai>=1.0.0gpt-5- Most capable, higher costgpt-5-mini- Fast, small and capablegpt-4o- Capable last gen multimodal model
anthropic/claude-sonnet-4.5- Excellent for codingmeta-llama/llama-3.1-70b-instruct- Open source, good performancegoogle/gemini-2.5-pro- Google's model via OpenRouterz-ai/glm-4.6- Open source, top of oss benchmarksmistralai/mixtral-8x7b-instruct- Good balance of speed/quality
# main.py - Support multiple providers
import os
from langchain_openai import ChatOpenAI
def get_llm_provider():
"""Select LLM provider based on available API keys"""
if os.getenv("OPENAI_API_KEY"):
return ChatOpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
model="gpt-5",
temperature=0.1,
)
elif os.getenv("OPENROUTER_API_KEY"):
return ChatOpenAI(
api_key=os.getenv("OPENROUTER_API_KEY"),
base_url="https://openrouter.ai/api/v1",
model="z-ai/glm-4.6",
temperature=0.1,
)
elif os.getenv("GEMINI_API_KEY"):
return ChatOpenAI(
api_key=os.getenv("GEMINI_API_KEY"),
base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
model="gemini-2.5-flash",
)
else:
raise ValueError("No API key found. Please set one of: OPENAI_API_KEY, OPENROUTER_API_KEY, GEMINI_API_KEY")
# Use the function
llm = get_llm_provider()# .env file - Set your preferred provider
AI_PROVIDER=openai
OPENAI_API_KEY=sk-your-key-here
# Or
AI_PROVIDER=openrouter
OPENROUTER_API_KEY=sk-or-your-key-here
# Or
AI_PROVIDER=gemini
GEMINI_API_KEY=your-key-here# main.py - Environment-based selection
import os
from langchain_openai import ChatOpenAI
def create_llm():
provider = os.getenv("AI_PROVIDER", "gemini").lower()
if provider == "openai":
return ChatOpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
model=os.getenv("OPENAI_MODEL", "gpt-5"),
temperature=float(os.getenv("AI_TEMPERATURE", "0.1")),
)
elif provider == "openrouter":
return ChatOpenAI(
api_key=os.getenv("OPENROUTER_API_KEY"),
base_url="https://openrouter.ai/api/v1",
model=os.getenv("OPENROUTER_MODEL", "z-ai/glm-4.6"),
temperature=float(os.getenv("AI_TEMPERATURE", "0.1")),
)
elif provider == "gemini":
return ChatOpenAI(
api_key=os.getenv("GEMINI_API_KEY"),
base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
model=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"),
)
else:
raise ValueError(f"Unsupported AI provider: {provider}")
llm = create_llm()Different providers have different rate limits. You may need to adjust the delays:
# In main.py, adjust these values based on your provider:
# For OpenAI (adjust based on your tier)
retry_delay = 60 # Longer delay for OpenAI
time.sleep(10) # Shorter delay between problems
# For OpenRouter (varies by model)
retry_delay = 30 # Standard delay
time.sleep(15) # Medium delay between problems
# For Gemini (current default)
retry_delay = 30 # Standard delay
time.sleep(20) # Longer delay between problems| Provider | Model | Cost (approx) | Speed | Quality |
|---|---|---|---|---|
| OpenAI | gpt-5 | $$$ | Medium | Excellent |
| OpenAI | gpt-5-mini | $ | Fast | Good |
| OpenRouter | claude-4.5-sonnet | $$ | Medium | Excellent |
| OpenRouter | llama-3.1-70b | $ | Fast | Good |
| Gemini | gemini-2.5-flash | $ | Fast | Good |
After modifying the configuration:
# Rebuild and deploy with new AI provider
docker build -t json-processor:latest .
docker-compose up -d
# Monitor logs to ensure new provider works
docker-compose logs -fEach JSON file should contain:
{
"query": "Problem description for the AI",
"test_input": "Input data for testing (string, number, or array)",
"test_output": "Expected output for validation"
}Examples:
{
"query": "Write a program to check if a number is prime",
"test_input": 17,
"test_output": "YES"
}{
"query": "Write a program to reverse a string",
"test_input": "hello",
"test_output": "olleh"
}-
API Rate Limiting
- Symptom:
503 - model is overloadederrors - Solution: App has built-in retry logic with 30s delays
- Symptom:
-
No JSON Files Found
- Symptom:
Found 0 problems to process - Solution: Add
.jsonfiles to thejson/directory
- Symptom:
-
Container Exits Immediately
- Symptom: Container status shows
Exited (0) - Solution: This is normal! Container completes and exits cleanly
- Symptom: Container status shows
-
Permission Errors
- Symptom: Cannot write to solutions directory
- Solution: Check Docker volume mount permissions
# Check container logs
docker-compose logs --tail=100
# Access container shell (if running)
docker exec -it json-processor-prod /bin/bash
# Check Docker system resources
docker system df
# Clean up Docker resources
docker system prune -f# In main.py, adjust these values:
retry_delay = 30 # Seconds between retries
time.sleep(20) # Seconds between problems
max_retries = 3 # Maximum retry attempts# In docker-compose.yml:
deploy:
resources:
limits:
memory: 1G # Adjust based on needs
cpus: '0.5' # Adjust based on needs| Action | Windows PowerShell | Linux/macOS Bash | Linux/macOS Make |
|---|---|---|---|
| Deploy | .\deploy.ps1 |
./deploy.sh |
make deploy |
| Status | .\deploy.ps1 -Action status |
./deploy.sh status |
make status |
| Logs | .\deploy.ps1 -Action logs |
./deploy.sh logs |
make logs |
| Stop | .\deploy.ps1 -Action stop |
./deploy.sh stop |
make stop |
| Restart | .\deploy.ps1 -Action stop && .\deploy.ps1 |
./deploy.sh stop && ./deploy.sh |
make restart |
# Build image
docker build -t json-processor:latest .
# Run container
docker-compose up -d
# View logs
docker-compose logs -f
# Stop container
docker-compose down
# Remove everything
docker-compose down --volumes --remove-orphans- π Non-root execution: Container runs as unprivileged
appuser - π Read-only filesystem: Container filesystem is read-only for security
- π« No new privileges: Prevents privilege escalation attacks
- π― Minimal attack surface: Multi-stage build with minimal runtime dependencies
- π Resource constraints: Memory and CPU limits prevent resource exhaustion
- π₯ Health monitoring: Regular health checks ensure container integrity
- π Resource Usage: Built-in CPU and memory monitoring
- π₯ Health Checks: Automated health status verification
- π Structured Logging: JSON-formatted logs with rotation
- π Progress Tracking: Real-time progress indicators
β οΈ Error Handling: Comprehensive error reporting and retry logic
- Fork the repository
- Create a feature branch
- Make your changes
- Test with Docker deployment
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.