λ Όλ¬Έ λ¦¬λ© λ³΄μ‘° μμ€ν β AI κΈ°λ° PDF λ²μ + ν/κ·Έλ¦Ό/μμ ν΄μ€
λ Όλ¬Έ PDFλ₯Ό μ λ‘λνλ©΄ Docling AIκ° λ¬Έμ ꡬ쑰λ₯Ό μ λ° νμ±νκ³ , Gemini/OpenAIλ₯Ό ν΅ν΄ λ²μκ³Ό μκ°μ μμ(νΒ·κ·Έλ¦ΌΒ·μμ) ν΄μ€μ μ 곡ν©λλ€.
| κ΅¬λΆ | κΈ°μ |
|---|---|
| Backend | Python 3.10+, FastAPI, SQLAlchemy (async), PostgreSQL |
| Frontend | React 18, Vite, pdfjs-dist |
| AI νμ± | Docling (Heron AI λ μ΄μμ λͺ¨λΈ) |
| LLM | Google Gemini / OpenAI GPT |
| μ€ν λ¦¬μ§ | AWS S3 / MinIO (S3 νΈν) |
| ν¨ν€μ§ κ΄λ¦¬ | uv (κΆμ₯) / pip |
git clone https://github.com/<your-username>/openpaper.git
cd openpaperuv λ₯Ό μ¬μ©νλ©΄ κ°μνκ²½ μμ± + μμ‘΄μ± μ€μΉλ₯Ό ν λ²μ μ²λ¦¬ν μ μμ΅λλ€.
# uvκ° μλ€λ©΄ λ¨Όμ μ€μΉ (ν μ€)
curl -LsSf https://astral.sh/uv/install.sh | sh
# κ°μνκ²½ μμ± + μμ‘΄μ± λκΈ°ν (ν λ²μ μλ£!)
uv sync
# κ°λ° λꡬ(ruff, pytest λ±)κΉμ§ ν¬ν¨νλ €λ©΄:
uv sync --extra devpipμ μ¬μ©νλ κ²½μ°:
python -m venv .venv source .venv/bin/activate pip install -e ".[dev]"
cd frontend
npm install
cd ..cp .env.example .env.env νμΌμ μ΄κ³ μλ νμ νλͺ©λ€μ μ€μ κ°μΌλ‘ μ±μ λ£μ΅λλ€:
| λ³μ | μ€λͺ | νμ |
|---|---|---|
OPENPAPER_DATABASE_URL |
PostgreSQL μ°κ²° URL | β |
OPENPAPER_S3_ACCESS_KEY |
AWS/MinIO μ‘μΈμ€ ν€ | β |
OPENPAPER_S3_SECRET_KEY |
AWS/MinIO μν¬λ¦Ώ ν€ | β |
OPENPAPER_GEMINI_API_KEY |
Google AI Studioμμ λ°κΈ | β |
OPENPAPER_S3_ENDPOINT_URL |
MinIO λ± μ»€μ€ν μλν¬μΈνΈ (AWS S3 κΈ°λ³Έμ΄λ©΄ λΉμλκΈ°) | μ ν |
OPENPAPER_PARSER_BACKEND |
docling (AI νμ, κΆμ₯) λλ pymupdf |
μ ν |
OPENPAPER_TRANSLATOR_BACKEND |
huggingface (λ‘컬 NLLB) λλ llm (Gemini/OpenAI) |
μ ν |
# PostgreSQLμ΄ μ€ν μ€μ΄μ΄μΌ ν©λλ€.
# DB μμ± (μ΄λ―Έ μλ€λ©΄ μλ΅)
createdb openpaper
# ν
μ΄λΈ μλ μμ± λͺ¨λλ‘ μλ² μμ (μ²μ ν λ²λ§)
OPENPAPER_DEV_CREATE_TABLES=true uv run uvicorn app.main:app --reloadμ΄νμλ
OPENPAPER_DEV_CREATE_TABLES=false(κΈ°λ³Έκ°)λ‘ λκ³ , μ€ν€λ§ λ³κ²½ μalembic upgrade headλ₯Ό μ¬μ©ν©λλ€.
cd frontend
npm run build
cd ..uv run uvicorn app.main:app --reloadλΈλΌμ°μ μμ http://localhost:8000 μΌλ‘ μ μν©λλ€.
openpaper/
βββ app/ # λ°±μλ (FastAPI)
β βββ adapters/ # μΈλΆ μλΉμ€ μ΄λν° (Docling, Gemini, S3 λ±)
β βββ api/ # API λΌμ°νΈ (command, query λΆλ¦¬)
β βββ core/services/ # λΉμ¦λμ€ λ‘μ§
β βββ db/ # DB μΈμ
λ° base λͺ¨λΈ
β βββ models/ # SQLAlchemy ORM λͺ¨λΈ
β βββ ports/ # μΆμ ν¬νΈ μΈν°νμ΄μ€ (ν₯μ¬κ³ λ )
β βββ schemas/ # Pydantic μλ΅ μ€ν€λ§
β βββ workers/ # λΉλκΈ° Job μ²λ¦¬ μ컀
β βββ config.py # νκ²½ λ³μ μ€μ (pydantic-settings)
β βββ main.py # FastAPI μνΈλ¦¬ν¬μΈνΈ
βββ frontend/ # νλ‘ νΈμλ (React + Vite)
β βββ src/
β βββ components/ # React μ»΄ν¬λνΈ
β βββ styles/ # CSS
β βββ api.js # λ°±μλ API λνΌ
βββ tests/ # ν
μ€νΈ
βββ alembic/ # DB λ§μ΄κ·Έλ μ΄μ
βββ pyproject.toml # Python μμ‘΄μ± μ μ
βββ .env.example # νκ²½ λ³μ ν
νλ¦Ώ
βββ README.md
μ’μΈ‘μ PDF μλ¬Έ, μ°μΈ‘μ λ²μλ³Έμ λλν νμν©λλ€. λλΈν΄λ¦μΌλ‘ μλ¬Έβλ²μ κ° μμΉλ₯Ό λκΈ°νν μ μμ΅λλ€.
Gemini/OpenAI λλ HuggingFace NLLB λ‘컬 λͺ¨λΈλ‘ λ Όλ¬Έμ λ²μν©λλ€.
PDF μμ νμλλ μμλ³ μ€λ²λ μ΄(ν=νλ, κ·Έλ¦Ό=μ΄λ‘, μμ=μ£Όν©)λ₯Ό ν΄λ¦νλ©΄ AIκ° ν΄λΉ μμλ₯Ό λΆμνμ¬ νκ΅μ΄λ‘ μμΈ ν΄μ€μ μ 곡ν©λλ€.
1οΈβ£ μ 체 μμ€ν
μν€ν
μ²

FastAPI κΈ°λ°μ λͺ¨λ리μ λ°±μλ, λΉλκΈ° ν(ARQ), μΈλΆ AI νμ λ° LLMμ νμ©ν νμ΄νλΌμΈ ꡬμ±λμ λλ€.
2οΈβ£ λΉλκΈ° μμ
(Job) μν μ μ΄λ

λν λ¬Έμλ₯Ό μ²λ¦¬ν λ νμλΆν° κ²°κ³Ό λ°ν(RUNNING β DONE/FAILED)κΉμ§μ μν λ³νλ₯Ό λνλ λλ€.
1οΈβ£ AI ν΄μ€ (μκ°μ μμ λΆμ)

PDFμμ λ Όλ¬Έμ 볡μ‘ν κ·Έλ¦Όμ΄λ νλ₯Ό ν΄λ¦νλ©΄ μ°μΈ‘ νμμ AIκ° λ¬Έλ§₯μ λ§μΆ° νκ΅μ΄λ‘ μ€λͺ ν΄μ€λλ€.
2οΈβ£ λμΌ ν¨λ κΈ°λ° AI λ²μ

μλ¬Έκ³Ό λ²μλ³Έμ΄ 1:1λ‘ λ§€μΉλλ©°, λ§μ°μ€ λλΈν΄λ¦μΌλ‘ μμͺ½ μ€ν¬λ‘€ μμΉκ° λκΈ°νλ©λλ€.
# μλ² μ€ν (ν« λ¦¬λ‘λ)
uv run uvicorn app.main:app --reload
# νλ‘ νΈμλ κ°λ° μλ²
cd frontend && npm run dev
# λ¦°νΈ
uv run ruff check app/
# ν
μ€νΈ
uv run pytest tests/ -v
# DB λ§μ΄κ·Έλ μ΄μ
uv run alembic upgrade head- Python: 3.10 μ΄μ
- Node.js: 18 μ΄μ
- PostgreSQL: 14 μ΄μ
- GPU (μ ν): Docling AI νμ μ¬μ© μ CUDA μ§μ GPU κΆμ₯ (VRAM 6GB+)
MIT License