bilalsxadad1231231 commited on
Commit
bf78a48
·
0 Parent(s):

Initial commit: AI Todo App Backend for Hugging Face Spaces

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .dockerignore +75 -0
  2. .env +16 -0
  3. DEPLOYMENT.md +117 -0
  4. Dockerfile +40 -0
  5. README.md +110 -0
  6. alembic.ini +41 -0
  7. alembic/env.py +59 -0
  8. app/__init__.py +1 -0
  9. app/__pycache__/__init__.cpython-312.pyc +0 -0
  10. app/__pycache__/main.cpython-312.pyc +0 -0
  11. app/api/__init__.py +1 -0
  12. app/api/__pycache__/__init__.cpython-312.pyc +0 -0
  13. app/api/v1/__init__.py +1 -0
  14. app/api/v1/__pycache__/__init__.cpython-312.pyc +0 -0
  15. app/api/v1/__pycache__/api.cpython-312.pyc +0 -0
  16. app/api/v1/api.py +8 -0
  17. app/api/v1/endpoints/__init__.py +1 -0
  18. app/api/v1/endpoints/__pycache__/__init__.cpython-312.pyc +0 -0
  19. app/api/v1/endpoints/__pycache__/subtasks.cpython-312.pyc +0 -0
  20. app/api/v1/endpoints/__pycache__/todos.cpython-312.pyc +0 -0
  21. app/api/v1/endpoints/__pycache__/translation.cpython-312.pyc +0 -0
  22. app/api/v1/endpoints/subtasks.py +62 -0
  23. app/api/v1/endpoints/todos.py +75 -0
  24. app/api/v1/endpoints/translation.py +67 -0
  25. app/core/__init__.py +1 -0
  26. app/core/__pycache__/__init__.cpython-312.pyc +0 -0
  27. app/core/__pycache__/config.cpython-312.pyc +0 -0
  28. app/core/__pycache__/database.cpython-312.pyc +0 -0
  29. app/core/config.py +28 -0
  30. app/core/database.py +27 -0
  31. app/main.py +39 -0
  32. app/models/__init__.py +1 -0
  33. app/models/__pycache__/__init__.cpython-312.pyc +0 -0
  34. app/models/__pycache__/subtask.cpython-312.pyc +0 -0
  35. app/models/__pycache__/todo.cpython-312.pyc +0 -0
  36. app/models/subtask.py +31 -0
  37. app/models/todo.py +18 -0
  38. app/schemas/__init__.py +1 -0
  39. app/schemas/__pycache__/__init__.cpython-312.pyc +0 -0
  40. app/schemas/__pycache__/subtask.cpython-312.pyc +0 -0
  41. app/schemas/__pycache__/todo.cpython-312.pyc +0 -0
  42. app/schemas/__pycache__/translation.cpython-312.pyc +0 -0
  43. app/schemas/subtask.py +31 -0
  44. app/schemas/todo.py +44 -0
  45. app/schemas/translation.py +23 -0
  46. app/services/__init__.py +1 -0
  47. app/services/__pycache__/__init__.cpython-312.pyc +0 -0
  48. app/services/__pycache__/ai_service.cpython-312.pyc +0 -0
  49. app/services/__pycache__/todo_service.cpython-312.pyc +0 -0
  50. app/services/__pycache__/translation_service.cpython-312.pyc +0 -0
.dockerignore ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # Virtual environments
25
+ env/
26
+ venv/
27
+ ENV/
28
+ env.bak/
29
+ venv.bak/
30
+
31
+ # IDE
32
+ .vscode/
33
+ .idea/
34
+ *.swp
35
+ *.swo
36
+ *~
37
+
38
+ # OS
39
+ .DS_Store
40
+ .DS_Store?
41
+ ._*
42
+ .Spotlight-V100
43
+ .Trashes
44
+ ehthumbs.db
45
+ Thumbs.db
46
+
47
+ # Git
48
+ .git/
49
+ .gitignore
50
+
51
+ # Database
52
+ *.db
53
+ *.sqlite
54
+ *.sqlite3
55
+
56
+ # Logs
57
+ *.log
58
+
59
+ # Environment files
60
+ .env
61
+ .env.local
62
+ .env.production
63
+
64
+ # Test files
65
+ .pytest_cache/
66
+ .coverage
67
+ htmlcov/
68
+
69
+ # Documentation
70
+ README.md
71
+ *.md
72
+
73
+ # Docker
74
+ Dockerfile
75
+ .dockerignore
.env ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Database
2
+ DATABASE_URL=sqlite:///./todo_app.db
3
+ # For production use PostgreSQL:
4
+ # DATABASE_URL=postgresql://user:password@localhost/todo_app
5
+
6
+ # Groq Configuration
7
+ GROQ_API_KEY=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
8
+ GROQ_MODEL_NAME=llama3-8b-8192
9
+
10
+ # API Configuration
11
+ API_V1_STR=/api/v1
12
+ PROJECT_NAME=AI Todo App
13
+ DEBUG=True
14
+
15
+ # CORS
16
+ BACKEND_CORS_ORIGINS=["http://localhost:3000", "https://yourdomain.vercel.app"]
DEPLOYMENT.md ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Deployment Guide
2
+
3
+ ## Hugging Face Spaces Deployment
4
+
5
+ ### 1. Create a Hugging Face Space
6
+
7
+ 1. Go to [Hugging Face Spaces](https://huggingface.co/spaces)
8
+ 2. Click "Create new Space"
9
+ 3. Choose "Docker" as the SDK
10
+ 4. Set the Space name and visibility
11
+ 5. Click "Create Space"
12
+
13
+ ### 2. Configure Environment Variables
14
+
15
+ In your Hugging Face Space settings, add these environment variables:
16
+
17
+ ```
18
+ DATABASE_URL=sqlite:///./todo_app.db
19
+ GROQ_API_KEY=your_actual_groq_api_key
20
+ GROQ_MODEL_NAME=llama3-8b-8192
21
+ API_V1_STR=/api/v1
22
+ PROJECT_NAME=AI Todo App
23
+ DEBUG=False
24
+ BACKEND_CORS_ORIGINS=["https://your-frontend-domain.com"]
25
+ ```
26
+
27
+ ### 3. Update Dockerfile for HF Spaces
28
+
29
+ The Dockerfile is already optimized for Hugging Face Spaces. Make sure to:
30
+
31
+ 1. Set `DEBUG=False` in production
32
+ 2. Configure proper CORS origins
33
+ 3. Set your actual Groq API key
34
+
35
+ ### 4. Build and Deploy
36
+
37
+ The Space will automatically build and deploy when you push to the repository.
38
+
39
+ ## Local Development
40
+
41
+ ### Using Docker Compose
42
+
43
+ ```bash
44
+ # Build and run
45
+ docker-compose up --build
46
+
47
+ # Run in background
48
+ docker-compose up -d
49
+
50
+ # View logs
51
+ docker-compose logs -f
52
+
53
+ # Stop
54
+ docker-compose down
55
+ ```
56
+
57
+ ### Using Docker directly
58
+
59
+ ```bash
60
+ # Build image
61
+ docker build -t todo-ai-app .
62
+
63
+ # Run container
64
+ docker run -p 8000:8000 -e GROQ_API_KEY=your_key todo-ai-app
65
+ ```
66
+
67
+ ## Environment Variables
68
+
69
+ | Variable | Description | Required | Default |
70
+ |----------|-------------|----------|---------|
71
+ | `DATABASE_URL` | Database connection string | No | `sqlite:///./todo_app.db` |
72
+ | `GROQ_API_KEY` | Groq API key for AI features | Yes | - |
73
+ | `GROQ_MODEL_NAME` | Groq model to use | No | `llama3-8b-8192` |
74
+ | `API_V1_STR` | API version prefix | No | `/api/v1` |
75
+ | `PROJECT_NAME` | Application name | No | `AI Todo App` |
76
+ | `DEBUG` | Debug mode | No | `True` |
77
+ | `BACKEND_CORS_ORIGINS` | CORS allowed origins | No | `["http://localhost:3000"]` |
78
+
79
+ ## Health Check
80
+
81
+ The application includes a health check endpoint at `/health` that returns:
82
+
83
+ ```json
84
+ {
85
+ "status": "healthy"
86
+ }
87
+ ```
88
+
89
+ ## API Documentation
90
+
91
+ Once deployed, you can access:
92
+ - API Documentation: `https://your-space.hf.space/docs`
93
+ - Health Check: `https://your-space.hf.space/health`
94
+ - Root endpoint: `https://your-space.hf.space/`
95
+
96
+ **Note**: The application runs on port 7860, which is the standard port for Hugging Face Spaces.
97
+
98
+ ## Troubleshooting
99
+
100
+ ### Common Issues
101
+
102
+ 1. **Port binding**: Make sure port 8000 is exposed
103
+ 2. **Environment variables**: Ensure all required env vars are set
104
+ 3. **Database**: SQLite database will be created automatically
105
+ 4. **CORS**: Update CORS origins for your frontend domain
106
+
107
+ ### Logs
108
+
109
+ Check application logs for debugging:
110
+
111
+ ```bash
112
+ # Docker Compose
113
+ docker-compose logs app
114
+
115
+ # Docker
116
+ docker logs <container_id>
117
+ ```
Dockerfile ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use Python 3.11 slim image for smaller size
2
+ FROM python:3.11-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Set environment variables
8
+ ENV PYTHONDONTWRITEBYTECODE=1 \
9
+ PYTHONUNBUFFERED=1 \
10
+ PYTHONPATH=/app
11
+
12
+ # Install system dependencies
13
+ RUN apt-get update && apt-get install -y \
14
+ gcc \
15
+ && rm -rf /var/lib/apt/lists/*
16
+
17
+ # Copy requirements first for better caching
18
+ COPY requirements.txt .
19
+
20
+ # Install Python dependencies
21
+ RUN pip install --no-cache-dir --upgrade pip && \
22
+ pip install --no-cache-dir -r requirements.txt
23
+
24
+ # Copy application code
25
+ COPY . .
26
+
27
+ # Create a non-root user for security
28
+ RUN useradd --create-home --shell /bin/bash app && \
29
+ chown -R app:app /app
30
+ USER app
31
+
32
+ # Expose port
33
+ EXPOSE 7860
34
+
35
+ # Health check
36
+ HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
37
+ CMD python -c "import requests; requests.get('http://localhost:7860/health')" || exit 1
38
+
39
+ # Run the application
40
+ CMD ["python", "run.py"]
README.md ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: AI Todo App Backend
3
+ emoji: 🤖
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ ---
10
+
11
+ # AI Todo App Backend
12
+
13
+ A FastAPI-based backend application for an AI-powered todo management system with Groq AI integration.
14
+
15
+ ## Features
16
+
17
+ - **FastAPI REST API** with automatic documentation
18
+ - **SQLite Database** with SQLAlchemy ORM
19
+ - **Groq AI Integration** for intelligent todo management
20
+ - **CORS Support** for frontend integration
21
+ - **Health Check Endpoints** for monitoring
22
+ - **Docker Containerization** for easy deployment
23
+
24
+ ## API Endpoints
25
+
26
+ - **GET /** - Root endpoint with app info
27
+ - **GET /health** - Health check endpoint
28
+ - **GET /docs** - Interactive API documentation (Swagger UI)
29
+ - **GET /api/v1/** - API v1 endpoints
30
+
31
+ ## Environment Variables
32
+
33
+ | Variable | Description | Required | Default |
34
+ |----------|-------------|----------|---------|
35
+ | `DATABASE_URL` | Database connection string | No | `sqlite:///./todo_app.db` |
36
+ | `GROQ_API_KEY` | Groq API key for AI features | Yes | - |
37
+ | `GROQ_MODEL_NAME` | Groq model to use | No | `llama3-8b-8192` |
38
+ | `API_V1_STR` | API version prefix | No | `/api/v1` |
39
+ | `PROJECT_NAME` | Application name | No | `AI Todo App` |
40
+ | `DEBUG` | Debug mode | No | `True` |
41
+ | `BACKEND_CORS_ORIGINS` | CORS allowed origins | No | `["http://localhost:3000"]` |
42
+
43
+ ## Local Development
44
+
45
+ ### Using Docker Compose
46
+
47
+ ```bash
48
+ # Build and run
49
+ docker-compose up --build
50
+
51
+ # Run in background
52
+ docker-compose up -d
53
+
54
+ # View logs
55
+ docker-compose logs -f
56
+
57
+ # Stop
58
+ docker-compose down
59
+ ```
60
+
61
+ ### Using Docker directly
62
+
63
+ ```bash
64
+ # Build image
65
+ docker build -t todo-ai-app .
66
+
67
+ # Run container
68
+ docker run -p 7860:7860 -e GROQ_API_KEY=your_key todo-ai-app
69
+ ```
70
+
71
+ ## Deployment
72
+
73
+ This application is deployed on Hugging Face Spaces and runs on port 7860.
74
+
75
+ ### Access Points
76
+
77
+ - **Application**: https://huggingface.co/spaces/Muhammadbilal10101/todo-ai
78
+ - **API Documentation**: https://huggingface.co/spaces/Muhammadbilal10101/todo-ai/docs
79
+ - **Health Check**: https://huggingface.co/spaces/Muhammadbilal10101/todo-ai/health
80
+
81
+ ## Technology Stack
82
+
83
+ - **FastAPI** - Modern, fast web framework for building APIs
84
+ - **SQLAlchemy** - SQL toolkit and ORM
85
+ - **Alembic** - Database migration tool
86
+ - **Pydantic** - Data validation using Python type annotations
87
+ - **Groq** - Fast AI inference API
88
+ - **Docker** - Containerization platform
89
+ - **SQLite** - Lightweight database
90
+
91
+ ## Project Structure
92
+
93
+ ```
94
+ backend/
95
+ ├── app/
96
+ │ ├── api/ # API routes
97
+ │ ├── core/ # Core configuration
98
+ │ ├── models/ # Database models
99
+ │ ├── schemas/ # Pydantic schemas
100
+ │ └── services/ # Business logic
101
+ ├── alembic/ # Database migrations
102
+ ├── Dockerfile # Docker configuration
103
+ ├── docker-compose.yml # Local development
104
+ ├── requirements.txt # Python dependencies
105
+ └── run.py # Application entry point
106
+ ```
107
+
108
+ ## License
109
+
110
+ MIT License - see LICENSE file for details.
alembic.ini ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [alembic]
2
+ script_location = alembic
3
+ prepend_sys_path = .
4
+ version_path_separator = os
5
+ sqlalchemy.url = sqlite:///./todo_app.db
6
+
7
+ [post_write_hooks]
8
+
9
+ [loggers]
10
+ keys = root,sqlalchemy,alembic
11
+
12
+ [handlers]
13
+ keys = console
14
+
15
+ [formatters]
16
+ keys = generic
17
+
18
+ [logger_root]
19
+ level = WARN
20
+ handlers = console
21
+ qualname =
22
+
23
+ [logger_sqlalchemy]
24
+ level = WARN
25
+ handlers =
26
+ qualname = sqlalchemy.engine
27
+
28
+ [logger_alembic]
29
+ level = INFO
30
+ handlers =
31
+ qualname = alembic
32
+
33
+ [handler_console]
34
+ class = StreamHandler
35
+ args = (sys.stderr,)
36
+ level = NOTSET
37
+ formatter = generic
38
+
39
+ [formatter_generic]
40
+ format = %(levelname)-5.5s [%(name)s] %(message)s
41
+ datefmt = %H:%M:%S
alembic/env.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from logging.config import fileConfig
2
+ from sqlalchemy import engine_from_config, pool
3
+ from alembic import context
4
+ import os
5
+ import sys
6
+
7
+ # Add your project directory to Python path
8
+ sys.path.append(os.path.dirname(os.path.dirname(__file__)))
9
+
10
+ from app.core.config import settings
11
+ from app.core.database import Base
12
+ from app.models import todo, subtask # Import all models
13
+
14
+ # Alembic Config object
15
+ config = context.config
16
+
17
+ # Set SQLAlchemy URL from settings
18
+ config.set_main_option("sqlalchemy.url", settings.DATABASE_URL)
19
+
20
+ # Interpret the config file for Python logging
21
+ if config.config_file_name is not None:
22
+ fileConfig(config.config_file_name)
23
+
24
+ # Target metadata for 'autogenerate' support
25
+ target_metadata = Base.metadata
26
+
27
+ def run_migrations_offline() -> None:
28
+ """Run migrations in 'offline' mode."""
29
+ url = config.get_main_option("sqlalchemy.url")
30
+ context.configure(
31
+ url=url,
32
+ target_metadata=target_metadata,
33
+ literal_binds=True,
34
+ dialect_opts={"paramstyle": "named"},
35
+ )
36
+
37
+ with context.begin_transaction():
38
+ context.run_migrations()
39
+
40
+ def run_migrations_online() -> None:
41
+ """Run migrations in 'online' mode."""
42
+ connectable = engine_from_config(
43
+ config.get_section(config.config_ini_section, {}),
44
+ prefix="sqlalchemy.",
45
+ poolclass=pool.NullPool,
46
+ )
47
+
48
+ with connectable.connect() as connection:
49
+ context.configure(
50
+ connection=connection, target_metadata=target_metadata
51
+ )
52
+
53
+ with context.begin_transaction():
54
+ context.run_migrations()
55
+
56
+ if context.is_offline_mode():
57
+ run_migrations_offline()
58
+ else:
59
+ run_migrations_online()
app/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # AI Todo App Backend
app/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (174 Bytes). View file
 
app/__pycache__/main.cpython-312.pyc ADDED
Binary file (1.75 kB). View file
 
app/api/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # API endpoints
app/api/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (178 Bytes). View file
 
app/api/v1/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # API v1 endpoints
app/api/v1/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (181 Bytes). View file
 
app/api/v1/__pycache__/api.cpython-312.pyc ADDED
Binary file (676 Bytes). View file
 
app/api/v1/api.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter
2
+ from .endpoints import todos, subtasks, translation
3
+
4
+ api_router = APIRouter()
5
+
6
+ api_router.include_router(todos.router, prefix="/todos", tags=["todos"])
7
+ api_router.include_router(subtasks.router, prefix="", tags=["subtasks"])
8
+ api_router.include_router(translation.router, prefix="/todos", tags=["translation"])
app/api/v1/endpoints/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # API endpoint modules
app/api/v1/endpoints/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (191 Bytes). View file
 
app/api/v1/endpoints/__pycache__/subtasks.cpython-312.pyc ADDED
Binary file (2.92 kB). View file
 
app/api/v1/endpoints/__pycache__/todos.cpython-312.pyc ADDED
Binary file (3.7 kB). View file
 
app/api/v1/endpoints/__pycache__/translation.cpython-312.pyc ADDED
Binary file (3.16 kB). View file
 
app/api/v1/endpoints/subtasks.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, Depends, HTTPException, status
2
+ from sqlalchemy.orm import Session
3
+ from typing import List
4
+ from ....core.database import get_db
5
+ from ....schemas.subtask import Subtask, SubtaskGenerateRequest, SubtaskUpdate
6
+ from ....services.todo_service import TodoService
7
+
8
+ router = APIRouter()
9
+
10
+ @router.post("/todos/{todo_id}/generate", response_model=List[Subtask])
11
+ async def generate_subtasks(
12
+ todo_id: int,
13
+ request: SubtaskGenerateRequest,
14
+ db: Session = Depends(get_db)
15
+ ):
16
+ """Generate AI subtasks for a todo"""
17
+ todo_service = TodoService(db)
18
+
19
+ try:
20
+ subtasks = await todo_service.generate_subtasks(
21
+ todo_id=todo_id,
22
+ max_subtasks=request.max_subtasks
23
+ )
24
+ return subtasks
25
+ except ValueError as e:
26
+ raise HTTPException(
27
+ status_code=status.HTTP_404_NOT_FOUND,
28
+ detail=str(e)
29
+ )
30
+ except Exception as e:
31
+ raise HTTPException(
32
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
33
+ detail=f"Failed to generate subtasks: {str(e)}"
34
+ )
35
+
36
+ @router.get("/todos/{todo_id}/subtasks", response_model=List[Subtask])
37
+ def get_todo_subtasks(todo_id: int, db: Session = Depends(get_db)):
38
+ """Get all subtasks for a todo"""
39
+ todo_service = TodoService(db)
40
+ todo = todo_service.get_todo(todo_id)
41
+ if not todo:
42
+ raise HTTPException(
43
+ status_code=status.HTTP_404_NOT_FOUND,
44
+ detail="Todo not found"
45
+ )
46
+ return todo.subtasks
47
+
48
+ @router.put("/subtasks/{subtask_id}", response_model=Subtask)
49
+ def update_subtask(
50
+ subtask_id: int,
51
+ subtask_update: SubtaskUpdate,
52
+ db: Session = Depends(get_db)
53
+ ):
54
+ """Update a subtask"""
55
+ todo_service = TodoService(db)
56
+ updated_subtask = todo_service.update_subtask(subtask_id, subtask_update)
57
+ if not updated_subtask:
58
+ raise HTTPException(
59
+ status_code=status.HTTP_404_NOT_FOUND,
60
+ detail="Subtask not found"
61
+ )
62
+ return updated_subtask
app/api/v1/endpoints/todos.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, Depends, HTTPException, status
2
+ from sqlalchemy.orm import Session
3
+ from typing import List
4
+ from ....core.database import get_db
5
+ from ....schemas.todo import Todo, TodoCreate, TodoUpdate, TodoWithRelations
6
+ from ....services.todo_service import TodoService
7
+
8
+ router = APIRouter()
9
+
10
+ @router.get("/", response_model=List[TodoWithRelations])
11
+ def get_todos(
12
+ skip: int = 0,
13
+ limit: int = 100,
14
+ db: Session = Depends(get_db)
15
+ ):
16
+ """Get all todos with subtasks and translations"""
17
+ todo_service = TodoService(db)
18
+ return todo_service.get_todos(skip=skip, limit=limit)
19
+
20
+ @router.get("/{todo_id}", response_model=TodoWithRelations)
21
+ def get_todo(todo_id: int, db: Session = Depends(get_db)):
22
+ """Get a specific todo with subtasks and translations"""
23
+ todo_service = TodoService(db)
24
+ todo = todo_service.get_todo(todo_id)
25
+ if not todo:
26
+ raise HTTPException(
27
+ status_code=status.HTTP_404_NOT_FOUND,
28
+ detail="Todo not found"
29
+ )
30
+ return todo
31
+
32
+ @router.post("/", response_model=TodoWithRelations, status_code=status.HTTP_201_CREATED)
33
+ def create_todo(todo: TodoCreate, db: Session = Depends(get_db)):
34
+ """Create a new todo"""
35
+ todo_service = TodoService(db)
36
+ return todo_service.create_todo(todo)
37
+
38
+ @router.put("/{todo_id}", response_model=TodoWithRelations)
39
+ def update_todo(
40
+ todo_id: int,
41
+ todo_update: TodoUpdate,
42
+ db: Session = Depends(get_db)
43
+ ):
44
+ """Update an existing todo"""
45
+ todo_service = TodoService(db)
46
+ updated_todo = todo_service.update_todo(todo_id, todo_update)
47
+ if not updated_todo:
48
+ raise HTTPException(
49
+ status_code=status.HTTP_404_NOT_FOUND,
50
+ detail="Todo not found"
51
+ )
52
+ return updated_todo
53
+
54
+ @router.delete("/{todo_id}", status_code=status.HTTP_204_NO_CONTENT)
55
+ def delete_todo(todo_id: int, db: Session = Depends(get_db)):
56
+ """Delete a todo"""
57
+ todo_service = TodoService(db)
58
+ success = todo_service.delete_todo(todo_id)
59
+ if not success:
60
+ raise HTTPException(
61
+ status_code=status.HTTP_404_NOT_FOUND,
62
+ detail="Todo not found"
63
+ )
64
+
65
+ @router.patch("/{todo_id}/toggle", response_model=TodoWithRelations)
66
+ def toggle_todo_completion(todo_id: int, db: Session = Depends(get_db)):
67
+ """Toggle todo completion status"""
68
+ todo_service = TodoService(db)
69
+ updated_todo = todo_service.toggle_todo_completion(todo_id)
70
+ if not updated_todo:
71
+ raise HTTPException(
72
+ status_code=status.HTTP_404_NOT_FOUND,
73
+ detail="Todo not found"
74
+ )
75
+ return updated_todo
app/api/v1/endpoints/translation.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, Depends, HTTPException, status
2
+ from sqlalchemy.orm import Session
3
+ from typing import List
4
+ from ....core.database import get_db
5
+ from ....schemas.translation import Translation, TranslationRequest, TodoTranslationRequest
6
+ from ....services.todo_service import TodoService
7
+
8
+ router = APIRouter()
9
+
10
+ @router.post("/{todo_id}/translate", response_model=Translation)
11
+ async def translate_todo(
12
+ todo_id: int,
13
+ request: TodoTranslationRequest,
14
+ db: Session = Depends(get_db)
15
+ ):
16
+ """Translate a todo to target language"""
17
+ todo_service = TodoService(db)
18
+
19
+ try:
20
+ translation = await todo_service.translate_todo(
21
+ todo_id=todo_id,
22
+ target_language=request.target_language
23
+ )
24
+ if not translation:
25
+ raise HTTPException(
26
+ status_code=status.HTTP_404_NOT_FOUND,
27
+ detail="Todo not found"
28
+ )
29
+ return translation
30
+ except Exception as e:
31
+ raise HTTPException(
32
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
33
+ detail=str(e)
34
+ )
35
+
36
+ @router.get("/{todo_id}/translations", response_model=List[Translation])
37
+ def get_todo_translations(todo_id: int, db: Session = Depends(get_db)):
38
+ """Get all translations for a todo"""
39
+ todo_service = TodoService(db)
40
+ todo = todo_service.get_todo(todo_id)
41
+ if not todo:
42
+ raise HTTPException(
43
+ status_code=status.HTTP_404_NOT_FOUND,
44
+ detail="Todo not found"
45
+ )
46
+ return todo_service.get_todo_translations(todo_id)
47
+
48
+ @router.post("/translate", response_model=dict)
49
+ async def translate_text(request: TranslationRequest):
50
+ """Translate any text to target language"""
51
+ from ....services.translation_service import translation_service
52
+
53
+ try:
54
+ translated_text = await translation_service.translate_text(
55
+ text=request.text,
56
+ target_language=request.target_language
57
+ )
58
+ return {
59
+ "original_text": request.text,
60
+ "translated_text": translated_text,
61
+ "target_language": request.target_language
62
+ }
63
+ except Exception as e:
64
+ raise HTTPException(
65
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
66
+ detail=str(e)
67
+ )
app/core/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Core configuration and database setup
app/core/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (179 Bytes). View file
 
app/core/__pycache__/config.cpython-312.pyc ADDED
Binary file (1.17 kB). View file
 
app/core/__pycache__/database.cpython-312.pyc ADDED
Binary file (1.07 kB). View file
 
app/core/config.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic_settings import BaseSettings
2
+ from typing import List
3
+ import os
4
+
5
+ class Settings(BaseSettings):
6
+ # API Settings
7
+ API_V1_STR: str = "/api/v1"
8
+ PROJECT_NAME: str = "AI Todo App"
9
+ DEBUG: bool = True
10
+
11
+ # Database
12
+ DATABASE_URL: str = "sqlite:///./todo_app.db"
13
+
14
+ # Groq Configuration
15
+ GROQ_API_KEY: str
16
+ GROQ_MODEL_NAME: str = "llama3-8b-8192"
17
+
18
+ # CORS
19
+ BACKEND_CORS_ORIGINS: List[str] = [
20
+ "http://localhost:3000",
21
+ "http://127.0.0.1:3000",
22
+ ]
23
+
24
+ class Config:
25
+ env_file = ".env"
26
+ case_sensitive = True
27
+
28
+ settings = Settings()
app/core/database.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import create_engine
2
+ from sqlalchemy.ext.declarative import declarative_base
3
+ from sqlalchemy.orm import sessionmaker
4
+ from .config import settings
5
+
6
+ # Create engine
7
+ if settings.DATABASE_URL.startswith("sqlite"):
8
+ engine = create_engine(
9
+ settings.DATABASE_URL,
10
+ connect_args={"check_same_thread": False}
11
+ )
12
+ else:
13
+ engine = create_engine(settings.DATABASE_URL)
14
+
15
+ # Create session
16
+ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
17
+
18
+ # Base class for models
19
+ Base = declarative_base()
20
+
21
+ # Dependency to get database session
22
+ def get_db():
23
+ db = SessionLocal()
24
+ try:
25
+ yield db
26
+ finally:
27
+ db.close()
app/main.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from .core.config import settings
4
+ from .core.database import engine, Base
5
+ from .api.v1.api import api_router
6
+
7
+ # Create database tables
8
+ Base.metadata.create_all(bind=engine)
9
+
10
+ # Create FastAPI app
11
+ app = FastAPI(
12
+ title=settings.PROJECT_NAME,
13
+ openapi_url=f"{settings.API_V1_STR}/openapi.json",
14
+ debug=settings.DEBUG
15
+ )
16
+
17
+ # Add CORS middleware
18
+ app.add_middleware(
19
+ CORSMiddleware,
20
+ allow_origins=settings.BACKEND_CORS_ORIGINS,
21
+ allow_credentials=True,
22
+ allow_methods=["*"],
23
+ allow_headers=["*"],
24
+ )
25
+
26
+ # Include API router
27
+ app.include_router(api_router, prefix=settings.API_V1_STR)
28
+
29
+ @app.get("/")
30
+ async def root():
31
+ return {"message": "AI Todo App API", "version": "1.0.0"}
32
+
33
+ @app.get("/health")
34
+ async def health_check():
35
+ return {"status": "healthy"}
36
+
37
+ if __name__ == "__main__":
38
+ import uvicorn
39
+ uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=True)
app/models/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Database models
app/models/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (181 Bytes). View file
 
app/models/__pycache__/subtask.cpython-312.pyc ADDED
Binary file (2 kB). View file
 
app/models/__pycache__/todo.cpython-312.pyc ADDED
Binary file (1.38 kB). View file
 
app/models/subtask.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, ForeignKey
2
+ from sqlalchemy.orm import relationship
3
+ from sqlalchemy.sql import func
4
+ from ..core.database import Base
5
+
6
+ class Subtask(Base):
7
+ __tablename__ = "subtasks"
8
+
9
+ id = Column(Integer, primary_key=True, index=True)
10
+ todo_id = Column(Integer, ForeignKey("todos.id"), nullable=False)
11
+ title = Column(String(255), nullable=False)
12
+ description = Column(Text, nullable=True)
13
+ completed = Column(Boolean, default=False, nullable=False)
14
+ order_index = Column(Integer, default=0)
15
+ created_at = Column(DateTime(timezone=True), server_default=func.now())
16
+
17
+ # Relationships
18
+ todo = relationship("Todo", back_populates="subtasks")
19
+
20
+ class Translation(Base):
21
+ __tablename__ = "translations"
22
+
23
+ id = Column(Integer, primary_key=True, index=True)
24
+ todo_id = Column(Integer, ForeignKey("todos.id"), nullable=False)
25
+ language = Column(String(50), nullable=False)
26
+ translated_title = Column(String(500), nullable=False)
27
+ translated_description = Column(Text, nullable=True)
28
+ created_at = Column(DateTime(timezone=True), server_default=func.now())
29
+
30
+ # Relationships
31
+ todo = relationship("Todo", back_populates="translations")
app/models/todo.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime
2
+ from sqlalchemy.orm import relationship
3
+ from sqlalchemy.sql import func
4
+ from ..core.database import Base
5
+
6
+ class Todo(Base):
7
+ __tablename__ = "todos"
8
+
9
+ id = Column(Integer, primary_key=True, index=True)
10
+ title = Column(String(255), nullable=False, index=True)
11
+ description = Column(Text, nullable=True)
12
+ completed = Column(Boolean, default=False, nullable=False)
13
+ created_at = Column(DateTime(timezone=True), server_default=func.now())
14
+ updated_at = Column(DateTime(timezone=True), onupdate=func.now())
15
+
16
+ # Relationships
17
+ subtasks = relationship("Subtask", back_populates="todo", cascade="all, delete-orphan")
18
+ translations = relationship("Translation", back_populates="todo", cascade="all, delete-orphan")
app/schemas/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Pydantic schemas for request/response models
app/schemas/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (182 Bytes). View file
 
app/schemas/__pycache__/subtask.cpython-312.pyc ADDED
Binary file (2.14 kB). View file
 
app/schemas/__pycache__/todo.cpython-312.pyc ADDED
Binary file (2.18 kB). View file
 
app/schemas/__pycache__/translation.cpython-312.pyc ADDED
Binary file (1.82 kB). View file
 
app/schemas/subtask.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel, Field
2
+ from typing import Optional
3
+ from datetime import datetime
4
+
5
+ class SubtaskBase(BaseModel):
6
+ title: str = Field(..., min_length=1, max_length=255)
7
+ description: Optional[str] = None
8
+
9
+ class SubtaskCreate(SubtaskBase):
10
+ todo_id: int
11
+ order_index: Optional[int] = 0
12
+
13
+ class SubtaskUpdate(BaseModel):
14
+ title: Optional[str] = Field(None, min_length=1, max_length=255)
15
+ description: Optional[str] = None
16
+ completed: Optional[bool] = None
17
+ order_index: Optional[int] = None
18
+
19
+ class Subtask(SubtaskBase):
20
+ id: int
21
+ todo_id: int
22
+ completed: bool
23
+ order_index: int
24
+ created_at: datetime
25
+
26
+ class Config:
27
+ from_attributes = True
28
+
29
+ class SubtaskGenerateRequest(BaseModel):
30
+ todo_id: int
31
+ max_subtasks: Optional[int] = Field(default=5, ge=1, le=10)
app/schemas/todo.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel, Field
2
+ from typing import Optional, List, TYPE_CHECKING
3
+ from datetime import datetime
4
+
5
+ if TYPE_CHECKING:
6
+ from .subtask import Subtask
7
+ from .translation import Translation
8
+
9
+ # Base Todo schema
10
+ class TodoBase(BaseModel):
11
+ title: str = Field(..., min_length=1, max_length=255)
12
+ description: Optional[str] = None
13
+
14
+ # Schema for creating Todo
15
+ class TodoCreate(TodoBase):
16
+ pass
17
+
18
+ # Schema for updating Todo
19
+ class TodoUpdate(BaseModel):
20
+ title: Optional[str] = Field(None, min_length=1, max_length=255)
21
+ description: Optional[str] = None
22
+ completed: Optional[bool] = None
23
+
24
+ # Schema for Todo response
25
+ class Todo(TodoBase):
26
+ id: int
27
+ completed: bool
28
+ created_at: datetime
29
+ updated_at: Optional[datetime]
30
+
31
+ class Config:
32
+ from_attributes = True
33
+
34
+ # Schema for Todo with relations
35
+ class TodoWithRelations(Todo):
36
+ subtasks: List["Subtask"] = []
37
+ translations: List["Translation"] = []
38
+
39
+ # Import the actual classes to resolve forward references
40
+ from .subtask import Subtask
41
+ from .translation import Translation
42
+
43
+ # Rebuild the model to resolve forward references
44
+ TodoWithRelations.model_rebuild()
app/schemas/translation.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel, Field
2
+ from typing import Optional
3
+ from datetime import datetime
4
+
5
+ class TranslationBase(BaseModel):
6
+ language: str = Field(..., min_length=2, max_length=50)
7
+ translated_title: str = Field(..., min_length=1, max_length=500)
8
+ translated_description: Optional[str] = None
9
+
10
+ class Translation(TranslationBase):
11
+ id: int
12
+ todo_id: int
13
+ created_at: datetime
14
+
15
+ class Config:
16
+ from_attributes = True
17
+
18
+ class TranslationRequest(BaseModel):
19
+ text: str = Field(..., min_length=1)
20
+ target_language: str = Field(..., min_length=2, max_length=50)
21
+
22
+ class TodoTranslationRequest(BaseModel):
23
+ target_language: str = Field(..., min_length=2, max_length=50)
app/services/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Business logic services
app/services/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (183 Bytes). View file
 
app/services/__pycache__/ai_service.cpython-312.pyc ADDED
Binary file (9.56 kB). View file
 
app/services/__pycache__/todo_service.cpython-312.pyc ADDED
Binary file (8.91 kB). View file
 
app/services/__pycache__/translation_service.cpython-312.pyc ADDED
Binary file (4.22 kB). View file