Skip to content

Commit ea56d13

Browse files
author
JeffiN11
committed
feat: AI-powered task API with Ollama auto-prioritization
0 parents  commit ea56d13

24 files changed

Lines changed: 662 additions & 0 deletions

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DATABASE_URL=postgresql+asyncpg://taskuser:taskpass@localhost:5432/taskdb
2+
OLLAMA_BASE_URL=http://localhost:11434
3+
OLLAMA_MODEL=llama3

.github/workflows/ci.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
name: Lint & Test
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Set up Python
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: "3.12"
22+
23+
- name: Cache pip packages
24+
uses: actions/cache@v4
25+
with:
26+
path: ~/.cache/pip
27+
key: ${{ runner.os }}-pip-${{ hashFiles('requirements*.txt') }}
28+
restore-keys: |
29+
${{ runner.os }}-pip-
30+
31+
- name: Install dependencies
32+
run: |
33+
python -m pip install --upgrade pip
34+
pip install -r requirements.txt
35+
pip install -r requirements-dev.txt
36+
pip install ruff
37+
38+
- name: Lint with Ruff
39+
run: ruff check app/ tests/
40+
41+
- name: Run tests
42+
run: pytest --tb=short -v

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
__pycache__/
2+
*.pyc
3+
*.pyo
4+
.env
5+
.venv/
6+
venv/
7+
dist/
8+
build/
9+
*.egg-info/
10+
.pytest_cache/
11+
.ruff_cache/

Dockerfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
FROM python:3.12-slim
2+
3+
WORKDIR /app
4+
5+
COPY requirements.txt .
6+
RUN pip install --no-cache-dir -r requirements.txt
7+
8+
COPY . .
9+
10+
EXPOSE 8000
11+
12+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# smart-task-api
2+
3+
An AI-powered task management REST API built with FastAPI, PostgreSQL, and Ollama (llama3). Tasks are automatically prioritized (Low / Medium / High) by a locally-running LLM the moment they are created.
4+
5+
## Tech Stack
6+
- FastAPI 0.115
7+
- PostgreSQL 16 + SQLAlchemy 2 (async)
8+
- Ollama + llama3 (local LLM)
9+
- Docker + Docker Compose
10+
- pytest + pytest-asyncio
11+
- GitHub Actions CI
12+
13+
## Quick Start
14+
15+
```bash
16+
docker compose up --build
17+
```
18+
19+
API: http://localhost:8000
20+
Docs: http://localhost:8000/docs
21+
22+
## Endpoints
23+
24+
| Method | Endpoint | Description |
25+
|--------|----------|-------------|
26+
| GET | / | Health check |
27+
| POST | /tasks/ | Create task (AI prioritizes async) |
28+
| GET | /tasks/ | List tasks |
29+
| GET | /tasks/{id} | Get task |
30+
| PATCH | /tasks/{id} | Update task |
31+
| DELETE | /tasks/{id} | Delete task |
32+
| POST | /tasks/{id}/reprioritize | Force AI re-prioritization |
33+
34+
## Run Tests
35+
36+
```bash
37+
pip install -r requirements.txt -r requirements-dev.txt
38+
pytest -v
39+
```

app/__init__.py

Whitespace-only changes.

app/db/__init__.py

Whitespace-only changes.

app/db/database.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import os
2+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
3+
from sqlalchemy.orm import DeclarativeBase
4+
5+
DATABASE_URL = os.getenv(
6+
"DATABASE_URL",
7+
"postgresql+asyncpg://taskuser:taskpass@localhost:5432/taskdb",
8+
)
9+
10+
engine = create_async_engine(DATABASE_URL, echo=False)
11+
12+
AsyncSessionLocal = async_sessionmaker(
13+
engine, class_=AsyncSession, expire_on_commit=False
14+
)
15+
16+
17+
class Base(DeclarativeBase):
18+
pass
19+
20+
21+
async def get_db():
22+
async with AsyncSessionLocal() as session:
23+
try:
24+
yield session
25+
finally:
26+
await session.close()

app/main.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from fastapi import FastAPI
2+
from fastapi.middleware.cors import CORSMiddleware
3+
from contextlib import asynccontextmanager
4+
5+
from app.db.database import engine, Base
6+
from app.routers import tasks
7+
8+
9+
@asynccontextmanager
10+
async def lifespan(app: FastAPI):
11+
async with engine.begin() as conn:
12+
await conn.run_sync(Base.metadata.create_all)
13+
yield
14+
15+
16+
app = FastAPI(
17+
title="Smart Task API",
18+
description="AI-powered task manager that auto-prioritizes tasks using a local LLM (Ollama).",
19+
version="2.0.0",
20+
lifespan=lifespan,
21+
)
22+
23+
app.add_middleware(
24+
CORSMiddleware,
25+
allow_origins=["*"],
26+
allow_methods=["*"],
27+
allow_headers=["*"],
28+
)
29+
30+
app.include_router(tasks.router, prefix="/tasks", tags=["Tasks"])
31+
32+
33+
@app.get("/", tags=["Health"])
34+
async def root():
35+
return {"status": "ok", "message": "Smart Task API is running"}
36+
37+
38+
@app.get("/health", tags=["Health"])
39+
async def health():
40+
return {"status": "healthy"}

app/models/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)