Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
name: CI

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
paths:
- '**/*.py'
- 'requirements.txt'
- '.github/workflows/ci.yml'

jobs:
lint-test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Syntax check
run: |
python -m py_compile $(git ls-files '*.py' | tr '\n' ' ')

- name: Import smoke
run: |
python - << 'PY'
from importlib import import_module
import_module('main')
print('Import OK')
PY

35 changes: 35 additions & 0 deletions .github/workflows/docker.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
name: Docker Build & Push (Backend)

on:
push:
branches: [ main ]
paths:
- '**'
- '!README.md'

jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository }}:backend-latest
ghcr.io/${{ github.repository }}:backend-${{ github.sha }}

20 changes: 20 additions & 0 deletions Dockerfile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

# System dependencies for pdf2image
RUN apt-get update && apt-get install -y --no-install-recommends \
poppler-utils \
&& rm -rf /var/lib/apt/lists/*

COPY Backend/requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY Backend/ ./

EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

55 changes: 55 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
# Noteflow Backend (FastAPI)

## Overview
- FastAPI backend for Noteflow
- OCR pipeline supports images, PDF, DOC/DOCX, HWP (via utilities and system tools)

## Run (local)
```
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8080 --reload
```

Env (optional):
- `SECRET_KEY`, `ACCESS_TOKEN_EXPIRE_MINUTES`
- Database URLs if you connect a DB (current code uses provided models)

## OCR system tools (optional but recommended)
- PyMuPDF (Python) used by default for PDF text extraction
- Optional fallbacks/tools:
- Poppler (`pdftoppm`) for `pdf2image`
- LibreOffice (`soffice`) for .doc → .pdf
- `hwp5txt` for .hwp text extraction
- If missing, the API still returns 200 with `warnings` explaining limitations.

## API Highlights
- `POST /api/v1/files/ocr` — OCR and create note (accepts file + optional `folder_id`, `langs`, `max_pages`)
- `POST /api/v1/files/upload` — Upload files to folder
- `POST /api/v1/files/audio` — STT from audio, create/append to note

## CI (GitHub Actions)
- This folder includes `.github/workflows/ci.yml` to lint/smoke-test on push/PR.
- Python 3.11, `pip install -r requirements.txt`, syntax check and import smoke.

## Docker (optional; for later)
- Dockerfile included. Build & run locally:
```
docker build -t noteflow-backend .
docker run --rm -p 8080:8080 noteflow-backend
```
- GitHub Actions container build:
- `.github/workflows/docker.yml` pushes to GHCR:
- `ghcr.io/<owner>/<repo>:backend-latest`
- `ghcr.io/<owner>/<repo>:backend-<sha>`
- Deployment example (SSH) once you’re ready:
```
docker login ghcr.io -u <USER> -p <TOKEN>
docker pull ghcr.io/<owner>/<repo>:backend-latest
docker run -d --name backend --restart=always -p 8080:8080 ghcr.io/<owner>/<repo>:backend-latest
```

## Notes
- If you split this folder into its own repository root, the included `.github/workflows/*.yml` files will work as-is.
- OCR uses model-first path (EasyOCR + TrOCR) and falls back to tesseract when available.
22 changes: 16 additions & 6 deletions requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,21 +3,31 @@ uvicorn
pydantic
sqlalchemy
mysql-connector-python
dotenv
python-dotenv
google-auth
requests
python-jose[cryptography]
bcrypt

torch==2.3.0+cu121
torchaudio==2.3.0+cu121
torchvision==0.18.0+cu121
--extra-index-url https://download.pytorch.org/whl/cu121
# PyTorch (MacOS: CPU/MPS 빌드 자동 설치됨)
torch==2.3.0
torchvision==0.18.0
torchaudio==2.3.0

transformers>=4.40.0
accelerate
sentencepiece
protobuf
python-multipart
easyocr
whisper
whisper
pytesseract
pdf2image
PyMuPDF
python-docx

langchain>=0.2.0
langchain-community
langchain-core
langchain-openai
langchain-ollama
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
name: CI

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
paths:
- '**/*.py'
- 'requirements.txt'
- '.github/workflows/ci.yml'

jobs:
lint-test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Syntax check
run: |
python -m py_compile $(git ls-files '*.py' | tr '\n' ' ')

- name: Import smoke
run: |
python - << 'PY'
from importlib import import_module
import_module('main')
print('Import OK')
PY

35 changes: 35 additions & 0 deletions .github/workflows/docker.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
name: Docker Build & Push (Backend)

on:
push:
branches: [ main ]
paths:
- '**'
- '!README.md'

jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository }}:backend-latest
ghcr.io/${{ github.repository }}:backend-${{ github.sha }}

20 changes: 20 additions & 0 deletions Dockerfile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

# System dependencies for pdf2image
RUN apt-get update && apt-get install -y --no-install-recommends \
poppler-utils \
&& rm -rf /var/lib/apt/lists/*

COPY Backend/requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY Backend/ ./

EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

55 changes: 55 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
# Noteflow Backend (FastAPI)

## Overview
- FastAPI backend for Noteflow
- OCR pipeline supports images, PDF, DOC/DOCX, HWP (via utilities and system tools)

## Run (local)
```
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8080 --reload
```

Env (optional):
- `SECRET_KEY`, `ACCESS_TOKEN_EXPIRE_MINUTES`
- Database URLs if you connect a DB (current code uses provided models)

## OCR system tools (optional but recommended)
- PyMuPDF (Python) used by default for PDF text extraction
- Optional fallbacks/tools:
- Poppler (`pdftoppm`) for `pdf2image`
- LibreOffice (`soffice`) for .doc → .pdf
- `hwp5txt` for .hwp text extraction
- If missing, the API still returns 200 with `warnings` explaining limitations.

## API Highlights
- `POST /api/v1/files/ocr` — OCR and create note (accepts file + optional `folder_id`, `langs`, `max_pages`)
- `POST /api/v1/files/upload` — Upload files to folder
- `POST /api/v1/files/audio` — STT from audio, create/append to note

## CI (GitHub Actions)
- This folder includes `.github/workflows/ci.yml` to lint/smoke-test on push/PR.
- Python 3.11, `pip install -r requirements.txt`, syntax check and import smoke.

## Docker (optional; for later)
- Dockerfile included. Build & run locally:
```
docker build -t noteflow-backend .
docker run --rm -p 8080:8080 noteflow-backend
```
- GitHub Actions container build:
- `.github/workflows/docker.yml` pushes to GHCR:
- `ghcr.io/<owner>/<repo>:backend-latest`
- `ghcr.io/<owner>/<repo>:backend-<sha>`
- Deployment example (SSH) once you’re ready:
```
docker login ghcr.io -u <USER> -p <TOKEN>
docker pull ghcr.io/<owner>/<repo>:backend-latest
docker run -d --name backend --restart=always -p 8080:8080 ghcr.io/<owner>/<repo>:backend-latest
```

## Notes
- If you split this folder into its own repository root, the included `.github/workflows/*.yml` files will work as-is.
- OCR uses model-first path (EasyOCR + TrOCR) and falls back to tesseract when available.
22 changes: 16 additions & 6 deletions requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,21 +3,31 @@ uvicorn
pydantic
sqlalchemy
mysql-connector-python
dotenv
python-dotenv
google-auth
requests
python-jose[cryptography]
bcrypt

torch==2.3.0+cu121
torchaudio==2.3.0+cu121
torchvision==0.18.0+cu121
--extra-index-url https://download.pytorch.org/whl/cu121
# PyTorch (MacOS: CPU/MPS 빌드 자동 설치됨)
torch==2.3.0
torchvision==0.18.0
torchaudio==2.3.0

transformers>=4.40.0
accelerate
sentencepiece
protobuf
python-multipart
easyocr
whisper
whisper
pytesseract
pdf2image
PyMuPDF
python-docx

langchain>=0.2.0
langchain-community
langchain-core
langchain-openai
langchain-ollama
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
name: CI

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
paths:
- '**/*.py'
- 'requirements.txt'
- '.github/workflows/ci.yml'

jobs:
lint-test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Syntax check
run: |
python -m py_compile $(git ls-files '*.py' | tr '\n' ' ')

- name: Import smoke
run: |
python - << 'PY'
from importlib import import_module
import_module('main')
print('Import OK')
PY

35 changes: 35 additions & 0 deletions .github/workflows/docker.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
name: Docker Build & Push (Backend)

on:
push:
branches: [ main ]
paths:
- '**'
- '!README.md'

jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository }}:backend-latest
ghcr.io/${{ github.repository }}:backend-${{ github.sha }}

20 changes: 20 additions & 0 deletions Dockerfile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

# System dependencies for pdf2image
RUN apt-get update && apt-get install -y --no-install-recommends \
poppler-utils \
&& rm -rf /var/lib/apt/lists/*

COPY Backend/requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY Backend/ ./

EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

55 changes: 55 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
# Noteflow Backend (FastAPI)

## Overview
- FastAPI backend for Noteflow
- OCR pipeline supports images, PDF, DOC/DOCX, HWP (via utilities and system tools)

## Run (local)
```
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8080 --reload
```

Env (optional):
- `SECRET_KEY`, `ACCESS_TOKEN_EXPIRE_MINUTES`
- Database URLs if you connect a DB (current code uses provided models)

## OCR system tools (optional but recommended)
- PyMuPDF (Python) used by default for PDF text extraction
- Optional fallbacks/tools:
- Poppler (`pdftoppm`) for `pdf2image`
- LibreOffice (`soffice`) for .doc → .pdf
- `hwp5txt` for .hwp text extraction
- If missing, the API still returns 200 with `warnings` explaining limitations.

## API Highlights
- `POST /api/v1/files/ocr` — OCR and create note (accepts file + optional `folder_id`, `langs`, `max_pages`)
- `POST /api/v1/files/upload` — Upload files to folder
- `POST /api/v1/files/audio` — STT from audio, create/append to note

## CI (GitHub Actions)
- This folder includes `.github/workflows/ci.yml` to lint/smoke-test on push/PR.
- Python 3.11, `pip install -r requirements.txt`, syntax check and import smoke.

## Docker (optional; for later)
- Dockerfile included. Build & run locally:
```
docker build -t noteflow-backend .
docker run --rm -p 8080:8080 noteflow-backend
```
- GitHub Actions container build:
- `.github/workflows/docker.yml` pushes to GHCR:
- `ghcr.io/<owner>/<repo>:backend-latest`
- `ghcr.io/<owner>/<repo>:backend-<sha>`
- Deployment example (SSH) once you’re ready:
```
docker login ghcr.io -u <USER> -p <TOKEN>
docker pull ghcr.io/<owner>/<repo>:backend-latest
docker run -d --name backend --restart=always -p 8080:8080 ghcr.io/<owner>/<repo>:backend-latest
```

## Notes
- If you split this folder into its own repository root, the included `.github/workflows/*.yml` files will work as-is.
- OCR uses model-first path (EasyOCR + TrOCR) and falls back to tesseract when available.
22 changes: 16 additions & 6 deletions requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,21 +3,31 @@ uvicorn
pydantic
sqlalchemy
mysql-connector-python
dotenv
python-dotenv
google-auth
requests
python-jose[cryptography]
bcrypt

torch==2.3.0+cu121
torchaudio==2.3.0+cu121
torchvision==0.18.0+cu121
--extra-index-url https://download.pytorch.org/whl/cu121
# PyTorch (MacOS: CPU/MPS 빌드 자동 설치됨)
torch==2.3.0
torchvision==0.18.0
torchaudio==2.3.0

transformers>=4.40.0
accelerate
sentencepiece
protobuf
python-multipart
easyocr
whisper
whisper
pytesseract
pdf2image
PyMuPDF
python-docx

langchain>=0.2.0
langchain-community
langchain-core
langchain-openai
langchain-ollama
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
name: CI

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
paths:
- '**/*.py'
- 'requirements.txt'
- '.github/workflows/ci.yml'

jobs:
lint-test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Syntax check
run: |
python -m py_compile $(git ls-files '*.py' | tr '\n' ' ')

- name: Import smoke
run: |
python - << 'PY'
from importlib import import_module
import_module('main')
print('Import OK')
PY

35 changes: 35 additions & 0 deletions .github/workflows/docker.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
name: Docker Build & Push (Backend)

on:
push:
branches: [ main ]
paths:
- '**'
- '!README.md'

jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository }}:backend-latest
ghcr.io/${{ github.repository }}:backend-${{ github.sha }}

20 changes: 20 additions & 0 deletions Dockerfile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

# System dependencies for pdf2image
RUN apt-get update && apt-get install -y --no-install-recommends \
poppler-utils \
&& rm -rf /var/lib/apt/lists/*

COPY Backend/requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY Backend/ ./

EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

55 changes: 55 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
# Noteflow Backend (FastAPI)

## Overview
- FastAPI backend for Noteflow
- OCR pipeline supports images, PDF, DOC/DOCX, HWP (via utilities and system tools)

## Run (local)
```
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8080 --reload
```

Env (optional):
- `SECRET_KEY`, `ACCESS_TOKEN_EXPIRE_MINUTES`
- Database URLs if you connect a DB (current code uses provided models)

## OCR system tools (optional but recommended)
- PyMuPDF (Python) used by default for PDF text extraction
- Optional fallbacks/tools:
- Poppler (`pdftoppm`) for `pdf2image`
- LibreOffice (`soffice`) for .doc → .pdf
- `hwp5txt` for .hwp text extraction
- If missing, the API still returns 200 with `warnings` explaining limitations.

## API Highlights
- `POST /api/v1/files/ocr` — OCR and create note (accepts file + optional `folder_id`, `langs`, `max_pages`)
- `POST /api/v1/files/upload` — Upload files to folder
- `POST /api/v1/files/audio` — STT from audio, create/append to note

## CI (GitHub Actions)
- This folder includes `.github/workflows/ci.yml` to lint/smoke-test on push/PR.
- Python 3.11, `pip install -r requirements.txt`, syntax check and import smoke.

## Docker (optional; for later)
- Dockerfile included. Build & run locally:
```
docker build -t noteflow-backend .
docker run --rm -p 8080:8080 noteflow-backend
```
- GitHub Actions container build:
- `.github/workflows/docker.yml` pushes to GHCR:
- `ghcr.io/<owner>/<repo>:backend-latest`
- `ghcr.io/<owner>/<repo>:backend-<sha>`
- Deployment example (SSH) once you’re ready:
```
docker login ghcr.io -u <USER> -p <TOKEN>
docker pull ghcr.io/<owner>/<repo>:backend-latest
docker run -d --name backend --restart=always -p 8080:8080 ghcr.io/<owner>/<repo>:backend-latest
```

## Notes
- If you split this folder into its own repository root, the included `.github/workflows/*.yml` files will work as-is.
- OCR uses model-first path (EasyOCR + TrOCR) and falls back to tesseract when available.
22 changes: 16 additions & 6 deletions requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,21 +3,31 @@ uvicorn
pydantic
sqlalchemy
mysql-connector-python
dotenv
python-dotenv
google-auth
requests
python-jose[cryptography]
bcrypt

torch==2.3.0+cu121
torchaudio==2.3.0+cu121
torchvision==0.18.0+cu121
--extra-index-url https://download.pytorch.org/whl/cu121
# PyTorch (MacOS: CPU/MPS 빌드 자동 설치됨)
torch==2.3.0
torchvision==0.18.0
torchaudio==2.3.0

transformers>=4.40.0
accelerate
sentencepiece
protobuf
python-multipart
easyocr
whisper
whisper
pytesseract
pdf2image
PyMuPDF
python-docx

langchain>=0.2.0
langchain-community
langchain-core
langchain-openai
langchain-ollama
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
name: CI

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
paths:
- '**/*.py'
- 'requirements.txt'
- '.github/workflows/ci.yml'

jobs:
lint-test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Syntax check
run: |
python -m py_compile $(git ls-files '*.py' | tr '\n' ' ')

- name: Import smoke
run: |
python - << 'PY'
from importlib import import_module
import_module('main')
print('Import OK')
PY

35 changes: 35 additions & 0 deletions .github/workflows/docker.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
name: Docker Build & Push (Backend)

on:
push:
branches: [ main ]
paths:
- '**'
- '!README.md'

jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository }}:backend-latest
ghcr.io/${{ github.repository }}:backend-${{ github.sha }}

20 changes: 20 additions & 0 deletions Dockerfile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

# System dependencies for pdf2image
RUN apt-get update && apt-get install -y --no-install-recommends \
poppler-utils \
&& rm -rf /var/lib/apt/lists/*

COPY Backend/requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY Backend/ ./

EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

55 changes: 55 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
# Noteflow Backend (FastAPI)

## Overview
- FastAPI backend for Noteflow
- OCR pipeline supports images, PDF, DOC/DOCX, HWP (via utilities and system tools)

## Run (local)
```
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8080 --reload
```

Env (optional):
- `SECRET_KEY`, `ACCESS_TOKEN_EXPIRE_MINUTES`
- Database URLs if you connect a DB (current code uses provided models)

## OCR system tools (optional but recommended)
- PyMuPDF (Python) used by default for PDF text extraction
- Optional fallbacks/tools:
- Poppler (`pdftoppm`) for `pdf2image`
- LibreOffice (`soffice`) for .doc → .pdf
- `hwp5txt` for .hwp text extraction
- If missing, the API still returns 200 with `warnings` explaining limitations.

## API Highlights
- `POST /api/v1/files/ocr` — OCR and create note (accepts file + optional `folder_id`, `langs`, `max_pages`)
- `POST /api/v1/files/upload` — Upload files to folder
- `POST /api/v1/files/audio` — STT from audio, create/append to note

## CI (GitHub Actions)
- This folder includes `.github/workflows/ci.yml` to lint/smoke-test on push/PR.
- Python 3.11, `pip install -r requirements.txt`, syntax check and import smoke.

## Docker (optional; for later)
- Dockerfile included. Build & run locally:
```
docker build -t noteflow-backend .
docker run --rm -p 8080:8080 noteflow-backend
```
- GitHub Actions container build:
- `.github/workflows/docker.yml` pushes to GHCR:
- `ghcr.io/<owner>/<repo>:backend-latest`
- `ghcr.io/<owner>/<repo>:backend-<sha>`
- Deployment example (SSH) once you’re ready:
```
docker login ghcr.io -u <USER> -p <TOKEN>
docker pull ghcr.io/<owner>/<repo>:backend-latest
docker run -d --name backend --restart=always -p 8080:8080 ghcr.io/<owner>/<repo>:backend-latest
```

## Notes
- If you split this folder into its own repository root, the included `.github/workflows/*.yml` files will work as-is.
- OCR uses model-first path (EasyOCR + TrOCR) and falls back to tesseract when available.
22 changes: 16 additions & 6 deletions requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,21 +3,31 @@ uvicorn
pydantic
sqlalchemy
mysql-connector-python
dotenv
python-dotenv
google-auth
requests
python-jose[cryptography]
bcrypt

torch==2.3.0+cu121
torchaudio==2.3.0+cu121
torchvision==0.18.0+cu121
--extra-index-url https://download.pytorch.org/whl/cu121
# PyTorch (MacOS: CPU/MPS 빌드 자동 설치됨)
torch==2.3.0
torchvision==0.18.0
torchaudio==2.3.0

transformers>=4.40.0
accelerate
sentencepiece
protobuf
python-multipart
easyocr
whisper
whisper
pytesseract
pdf2image
PyMuPDF
python-docx

langchain>=0.2.0
langchain-community
langchain-core
langchain-openai
langchain-ollama
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
name: CI

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
paths:
- '**/*.py'
- 'requirements.txt'
- '.github/workflows/ci.yml'

jobs:
lint-test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Syntax check
run: |
python -m py_compile $(git ls-files '*.py' | tr '\n' ' ')

- name: Import smoke
run: |
python - << 'PY'
from importlib import import_module
import_module('main')
print('Import OK')
PY

35 changes: 35 additions & 0 deletions .github/workflows/docker.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
name: Docker Build & Push (Backend)

on:
push:
branches: [ main ]
paths:
- '**'
- '!README.md'

jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository }}:backend-latest
ghcr.io/${{ github.repository }}:backend-${{ github.sha }}

20 changes: 20 additions & 0 deletions Dockerfile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

# System dependencies for pdf2image
RUN apt-get update && apt-get install -y --no-install-recommends \
poppler-utils \
&& rm -rf /var/lib/apt/lists/*

COPY Backend/requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY Backend/ ./

EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

55 changes: 55 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
# Noteflow Backend (FastAPI)

## Overview
- FastAPI backend for Noteflow
- OCR pipeline supports images, PDF, DOC/DOCX, HWP (via utilities and system tools)

## Run (local)
```
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8080 --reload
```

Env (optional):
- `SECRET_KEY`, `ACCESS_TOKEN_EXPIRE_MINUTES`
- Database URLs if you connect a DB (current code uses provided models)

## OCR system tools (optional but recommended)
- PyMuPDF (Python) used by default for PDF text extraction
- Optional fallbacks/tools:
- Poppler (`pdftoppm`) for `pdf2image`
- LibreOffice (`soffice`) for .doc → .pdf
- `hwp5txt` for .hwp text extraction
- If missing, the API still returns 200 with `warnings` explaining limitations.

## API Highlights
- `POST /api/v1/files/ocr` — OCR and create note (accepts file + optional `folder_id`, `langs`, `max_pages`)
- `POST /api/v1/files/upload` — Upload files to folder
- `POST /api/v1/files/audio` — STT from audio, create/append to note

## CI (GitHub Actions)
- This folder includes `.github/workflows/ci.yml` to lint/smoke-test on push/PR.
- Python 3.11, `pip install -r requirements.txt`, syntax check and import smoke.

## Docker (optional; for later)
- Dockerfile included. Build & run locally:
```
docker build -t noteflow-backend .
docker run --rm -p 8080:8080 noteflow-backend
```
- GitHub Actions container build:
- `.github/workflows/docker.yml` pushes to GHCR:
- `ghcr.io/<owner>/<repo>:backend-latest`
- `ghcr.io/<owner>/<repo>:backend-<sha>`
- Deployment example (SSH) once you’re ready:
```
docker login ghcr.io -u <USER> -p <TOKEN>
docker pull ghcr.io/<owner>/<repo>:backend-latest
docker run -d --name backend --restart=always -p 8080:8080 ghcr.io/<owner>/<repo>:backend-latest
```

## Notes
- If you split this folder into its own repository root, the included `.github/workflows/*.yml` files will work as-is.
- OCR uses model-first path (EasyOCR + TrOCR) and falls back to tesseract when available.
22 changes: 16 additions & 6 deletions requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,21 +3,31 @@ uvicorn
pydantic
sqlalchemy
mysql-connector-python
dotenv
python-dotenv
google-auth
requests
python-jose[cryptography]
bcrypt

torch==2.3.0+cu121
torchaudio==2.3.0+cu121
torchvision==0.18.0+cu121
--extra-index-url https://download.pytorch.org/whl/cu121
# PyTorch (MacOS: CPU/MPS 빌드 자동 설치됨)
torch==2.3.0
torchvision==0.18.0
torchaudio==2.3.0

transformers>=4.40.0
accelerate
sentencepiece
protobuf
python-multipart
easyocr
whisper
whisper
pytesseract
pdf2image
PyMuPDF
python-docx

langchain>=0.2.0
langchain-community
langchain-core
langchain-openai
langchain-ollama
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
name: CI

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
paths:
- '**/*.py'
- 'requirements.txt'
- '.github/workflows/ci.yml'

jobs:
lint-test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Syntax check
run: |
python -m py_compile $(git ls-files '*.py' | tr '\n' ' ')

- name: Import smoke
run: |
python - << 'PY'
from importlib import import_module
import_module('main')
print('Import OK')
PY

35 changes: 35 additions & 0 deletions .github/workflows/docker.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
name: Docker Build & Push (Backend)

on:
push:
branches: [ main ]
paths:
- '**'
- '!README.md'

jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository }}:backend-latest
ghcr.io/${{ github.repository }}:backend-${{ github.sha }}

20 changes: 20 additions & 0 deletions Dockerfile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

# System dependencies for pdf2image
RUN apt-get update && apt-get install -y --no-install-recommends \
poppler-utils \
&& rm -rf /var/lib/apt/lists/*

COPY Backend/requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY Backend/ ./

EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

55 changes: 55 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
# Noteflow Backend (FastAPI)

## Overview
- FastAPI backend for Noteflow
- OCR pipeline supports images, PDF, DOC/DOCX, HWP (via utilities and system tools)

## Run (local)
```
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8080 --reload
```

Env (optional):
- `SECRET_KEY`, `ACCESS_TOKEN_EXPIRE_MINUTES`
- Database URLs if you connect a DB (current code uses provided models)

## OCR system tools (optional but recommended)
- PyMuPDF (Python) used by default for PDF text extraction
- Optional fallbacks/tools:
- Poppler (`pdftoppm`) for `pdf2image`
- LibreOffice (`soffice`) for .doc → .pdf
- `hwp5txt` for .hwp text extraction
- If missing, the API still returns 200 with `warnings` explaining limitations.

## API Highlights
- `POST /api/v1/files/ocr` — OCR and create note (accepts file + optional `folder_id`, `langs`, `max_pages`)
- `POST /api/v1/files/upload` — Upload files to folder
- `POST /api/v1/files/audio` — STT from audio, create/append to note

## CI (GitHub Actions)
- This folder includes `.github/workflows/ci.yml` to lint/smoke-test on push/PR.
- Python 3.11, `pip install -r requirements.txt`, syntax check and import smoke.

## Docker (optional; for later)
- Dockerfile included. Build & run locally:
```
docker build -t noteflow-backend .
docker run --rm -p 8080:8080 noteflow-backend
```
- GitHub Actions container build:
- `.github/workflows/docker.yml` pushes to GHCR:
- `ghcr.io/<owner>/<repo>:backend-latest`
- `ghcr.io/<owner>/<repo>:backend-<sha>`
- Deployment example (SSH) once you’re ready:
```
docker login ghcr.io -u <USER> -p <TOKEN>
docker pull ghcr.io/<owner>/<repo>:backend-latest
docker run -d --name backend --restart=always -p 8080:8080 ghcr.io/<owner>/<repo>:backend-latest
```

## Notes
- If you split this folder into its own repository root, the included `.github/workflows/*.yml` files will work as-is.
- OCR uses model-first path (EasyOCR + TrOCR) and falls back to tesseract when available.
22 changes: 16 additions & 6 deletions requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,21 +3,31 @@ uvicorn
pydantic
sqlalchemy
mysql-connector-python
dotenv
python-dotenv
google-auth
requests
python-jose[cryptography]
bcrypt

torch==2.3.0+cu121
torchaudio==2.3.0+cu121
torchvision==0.18.0+cu121
--extra-index-url https://download.pytorch.org/whl/cu121
# PyTorch (MacOS: CPU/MPS 빌드 자동 설치됨)
torch==2.3.0
torchvision==0.18.0
torchaudio==2.3.0

transformers>=4.40.0
accelerate
sentencepiece
protobuf
python-multipart
easyocr
whisper
whisper
pytesseract
pdf2image
PyMuPDF
python-docx

langchain>=0.2.0
langchain-community
langchain-core
langchain-openai
langchain-ollama
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
name: CI

on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
paths:
- '**/*.py'
- 'requirements.txt'
- '.github/workflows/ci.yml'

jobs:
lint-test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Syntax check
run: |
python -m py_compile $(git ls-files '*.py' | tr '\n' ' ')

- name: Import smoke
run: |
python - << 'PY'
from importlib import import_module
import_module('main')
print('Import OK')
PY

35 changes: 35 additions & 0 deletions .github/workflows/docker.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
name: Docker Build & Push (Backend)

on:
push:
branches: [ main ]
paths:
- '**'
- '!README.md'

jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository }}:backend-latest
ghcr.io/${{ github.repository }}:backend-${{ github.sha }}

20 changes: 20 additions & 0 deletions Dockerfile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

WORKDIR /app

# System dependencies for pdf2image
RUN apt-get update && apt-get install -y --no-install-recommends \
poppler-utils \
&& rm -rf /var/lib/apt/lists/*

COPY Backend/requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY Backend/ ./

EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

55 changes: 55 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
# Noteflow Backend (FastAPI)

## Overview
- FastAPI backend for Noteflow
- OCR pipeline supports images, PDF, DOC/DOCX, HWP (via utilities and system tools)

## Run (local)
```
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8080 --reload
```

Env (optional):
- `SECRET_KEY`, `ACCESS_TOKEN_EXPIRE_MINUTES`
- Database URLs if you connect a DB (current code uses provided models)

## OCR system tools (optional but recommended)
- PyMuPDF (Python) used by default for PDF text extraction
- Optional fallbacks/tools:
- Poppler (`pdftoppm`) for `pdf2image`
- LibreOffice (`soffice`) for .doc → .pdf
- `hwp5txt` for .hwp text extraction
- If missing, the API still returns 200 with `warnings` explaining limitations.

## API Highlights
- `POST /api/v1/files/ocr` — OCR and create note (accepts file + optional `folder_id`, `langs`, `max_pages`)
- `POST /api/v1/files/upload` — Upload files to folder
- `POST /api/v1/files/audio` — STT from audio, create/append to note

## CI (GitHub Actions)
- This folder includes `.github/workflows/ci.yml` to lint/smoke-test on push/PR.
- Python 3.11, `pip install -r requirements.txt`, syntax check and import smoke.

## Docker (optional; for later)
- Dockerfile included. Build & run locally:
```
docker build -t noteflow-backend .
docker run --rm -p 8080:8080 noteflow-backend
```
- GitHub Actions container build:
- `.github/workflows/docker.yml` pushes to GHCR:
- `ghcr.io/<owner>/<repo>:backend-latest`
- `ghcr.io/<owner>/<repo>:backend-<sha>`
- Deployment example (SSH) once you’re ready:
```
docker login ghcr.io -u <USER> -p <TOKEN>
docker pull ghcr.io/<owner>/<repo>:backend-latest
docker run -d --name backend --restart=always -p 8080:8080 ghcr.io/<owner>/<repo>:backend-latest
```

## Notes
- If you split this folder into its own repository root, the included `.github/workflows/*.yml` files will work as-is.
- OCR uses model-first path (EasyOCR + TrOCR) and falls back to tesseract when available.
22 changes: 16 additions & 6 deletions requirements.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,21 +3,31 @@ uvicorn
pydantic
sqlalchemy
mysql-connector-python
dotenv
python-dotenv
google-auth
requests
python-jose[cryptography]
bcrypt

torch==2.3.0+cu121
torchaudio==2.3.0+cu121
torchvision==0.18.0+cu121
--extra-index-url https://download.pytorch.org/whl/cu121
# PyTorch (MacOS: CPU/MPS 빌드 자동 설치됨)
torch==2.3.0
torchvision==0.18.0
torchaudio==2.3.0

transformers>=4.40.0
accelerate
sentencepiece
protobuf
python-multipart
easyocr
whisper
whisper
pytesseract
pdf2image
PyMuPDF
python-docx

langchain>=0.2.0
langchain-community
langchain-core
langchain-openai
langchain-ollama
Loading