TableMagnifier Repository์ ์ค์ ๊ฒ์ ํ์ํฉ๋๋ค! ํ๊ตญ์ด TableQA์ ๋ํ ์ ๋ขฐ๋ ๋์ ๋ฐ์ดํฐ๋ฅผ ๊ตฌ์ถํ๊ณ ํ๊ฐํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค.
๐ {{TableMagnifier}} โ ๊ฐ์ง์ฐ๊ตฌ์ 11๊ธฐ NLx Crew ์์ ํ๋ก์ ํธ
โํจ๊ป ๋ง๋๋ ์ฐ์ฐํ ํ๋ช (Serendipity Revolution)โ ์ง์คํจ๊ณผ ์ ๋ขฐ๋ฅผ ๋ฐํ์ผ๋ก AI/DS ํ์ ์ปค๋ฎค๋ํฐ์ ๊ธฐ์ ์คํ์ ์งํํฉ๋๋ค.
"์ด๋ก ์์ ์ค์ ๊น์ง, ํจ๊ป ์ฑ์ฅํ๋ AI ์คํ์ค"
- ๊ฐ์ธ ์ฑ์ฅ๊ณผ ์ง๋จ ์งํ์ ์๋์ง ์ฐฝ์ถ
- ์คํ์์ค ์ ์ ์ ๋ฐํ์ผ๋ก ํ ์ง์ ๊ณต์ ๋ฌธํ
- ์คํจ๋ฅผ ์ฑ๊ณต์ ๋๋ค๋๋ก ๋ง๋๋ ์คํ์ ์ ๊ทผ
- ๋ ผ๋ฌธ ๋ฆฌ๋ทฐ ํ๋ก์ ํธ โ ์ต์ AI ๋ ผ๋ฌธ ๋ถ์, ํ ๋ก , ์คํ ์ฌํ
- ์คํ์์ค ํ๋ก์ ํธ โ AIยท๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ๋ฐ ๋ฐ ๊ฐ์
- ์ปจํผ๋ฐ์ค ๋ ผ๋ฌธ ํฌ๊ณ โ ์ต์ ์ฐ๊ตฌ ์ํ ๋ฐ ๊ตญ์ ํํ ์ ์ถ ์ค๋น
gantt
title 2025 TableMagnifier Roadmap
section ํต์ฌ ๋ง์ผ์คํค
๋ฐ์ดํฐ ๊ตฌ์ฑ ๋
ผ์ :a1, 2025-09-09, 28d
๊ตฌ์ถ ๋ฐ ์ฆ๊ฐ :a2, after a1, 35d
ํ๊ฐ ์ ์ฉ :a3, after a2, 35d
๋
ผ๋ฌธ ์์ฑ :a4, after a3, 21d
section ๋ถ๊ฐ ํ๋
๋งค์ง์ปฌ์ํฌ :2025-09-21, 7d
๋งค์ง์ปฌ์ํฌ :2025-10-26, 7d
| ์ฃผ์ฐจ | ๋ ์ง | ํ๋ | ๊ฒฐ๊ณผ๋ฌผ ์ ํ | ๋น๊ณ |
|---|---|---|---|---|
| 1 | 9/9 | Introduction | ์จ๋ผ์ธ | |
| 2 | 9/16 | ๋ ผ๋ฌธ ๋ฆฌ๋ทฐ (๋ฐฐ์ 1๊ถ, ๊ฐ๋ณ 1๊ถ) | ๋ ผ๋ฌธ ๋ฆฌ๋ทฐ ๋ฌธ์ | ์จ๋ผ์ธ |
| 9/23 | Magical Week | ์คํ๋ผ์ธ | ||
| 3 | 9/30 | ๋ ผ๋ฌธ ๋ฆฌ๋ทฐ (๋ฐฐ์ 1๊ถ, ๊ฐ๋ณ 1๊ถ) | ๋ ผ๋ฌธ ๋ฆฌ๋ทฐ ๋ฌธ์ | ์จ๋ผ์ธ |
| 4 | 10/14 | Dataset ๊ตฌ์ฑ ๋ ผ์ | ์จ๋ผ์ธ | |
| 5 | 10/21 | Raw-data Collection | ์จ๋ผ์ธ | |
| 10/28 | Magical Week | ์คํ๋ผ์ธ | ||
| 6 | 11/4 | Data refinement / Augmentation | ์จ๋ผ์ธ | |
| 7 | 11/11 | Data refinement / Augmentation | ์ต์ข ๋ฐ์ดํฐ์ | ์จ๋ผ์ธ |
| 8 | 11/18 | Paper Remind / Evaluation Idea Discussion | ์คํ๋ผ์ธ | |
| 9 | 11/25 | Pipleine setting | ์จ๋ผ์ธ | |
| 10 | 12/2 | Evaluation (Basic) | ์์ด๋์ด ๊ตฌํ, ๊ฒฐ๊ณผ๋ฌผ | ์จ๋ผ์ธ |
| 11 | 12/9 | Evaluation (Advanced) | ์์ด๋์ด ๊ตฌํ, ๊ฒฐ๊ณผ๋ฌผ | ์จ๋ผ์ธ |
| 12 | 12/16 | Evaluation (Advanced) | ์์ด๋์ด ๊ตฌํ, ๊ฒฐ๊ณผ๋ฌผ | ์จ๋ผ์ธ |
| 13 | 12/23 | Evaluation (Advanced) | ์์ด๋์ด ๊ตฌํ, ๊ฒฐ๊ณผ๋ฌผ | ์จ๋ผ์ธ |
| 14 | 12/30 | Github ๊ด๋ฆฌ, Paper Writing | ์จ๋ผ์ธ | |
| 15 | 1/6 | Github ๊ด๋ฆฌ, Paper Writing | ์จ๋ผ์ธ | |
| 16 | 1/13 | ํ๊ณ ๋ฐ ์์นด์ด๋น, ํฌ๊ณ ์ค๋น | Paper | ์คํ๋ผ์ธ |
- ๋น๋๋ก ์ฐธ์ฌ โ ํ๋ก์ ํธ ๊ธฐํยท์ด์ ์ฃผ๋
- ๋ฌ๋๋ก ์ฐธ์ฌ โ ์ฐ๊ตฌยท๊ฐ๋ฐยทํ ์คํธ ๋ฑ ์คํ
- ์ฒญ๊ฐ ์ฐธ์ฌ โ ๊ณต๊ฐ ์ธ์ ์ฐธ์ฌ ๊ฐ๋ฅ
โ๏ธ์ฐธ์ฌ ๋งํฌ: ๊ฐ์ง์ฐ๊ตฌ์ ๋์ค์ฝ๋ โ๏ธ์ปค๋ฎค๋์ผ์ด์ ์ฑ๋: ์นด์นด์คํก
๋๊ตฌ๋ ์ฒญ๊ฐ์ ํตํด ๋ชจ์์ ์ฐธ์ฌํ์ค ์ ์์ต๋๋ค.
- ํน๋ณํ ์ ์ฒญ ์์ด ์ ๊ธฐ ๋ชจ์ ์๊ฐ์ ๋ง์ถ์ด ๋์ค์ฝ๋ #Room-CS ์ฑ๋๋ก ์ ์ฅ
- Magical Week ์ค ํ์ฌ์ ์ฐธ๊ฐ {{ ... }}
์ด ํ๋ก์ ํธ๋ ๊ฐ์ง์ฐ๊ตฌ์ Open Academy๋ก ์งํ๋ฉ๋๋ค. ์ฌ๋ฌ๋ถ์ ์ฐธ์ฌ์ ๊ธฐ์ฌ๊ฐ '์ฐ์ฐํ ํ๋ช (Serendipity Revolution)'์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ๋ชจ๋์๊ฒ ๊น์ ๊ฐ์ฌ๋ฅผ ์ ํฉ๋๋ค.
TableMagnifier๋ ํ๊ตญ์ด ํ ์ด๋ธ ์ด๋ฏธ์ง๋ฅผ ๋ถ์ํ์ฌ ๊ตฌ์กฐํ๋ ํฉ์ฑ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๊ณ , ์ด๋ฅผ ๊ฒ์ฆ ๋ฐ ์์ ํ ์ ์๋ ๋๊ตฌ์ ๋๋ค. LangGraph๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ๋ฉํฐ ์์ด์ ํธ ์ํฌํ๋ก์ฐ๋ฅผ ํตํด ์ด๋ฏธ์ง์์ HTML ํ ์ด๋ธ ๊ตฌ์กฐ๋ฅผ ์ถ์ถํ๊ณ , ์ด๋ฅผ ๋ฐํ์ผ๋ก ์๋ก์ด ํฉ์ฑ ๋ฐ์ดํฐ๋ฅผ ์์ฑํฉ๋๋ค.
- ์ด๋ฏธ์ง to HTML ๋ณํ: ํ ์ด๋ธ ์ด๋ฏธ์ง๋ฅผ HTML ๊ตฌ์กฐ๋ก ๋ณํํฉ๋๋ค.
- ํฉ์ฑ ๋ฐ์ดํฐ ์์ฑ: ์๋ณธ ํ ์ด๋ธ์ ๊ตฌ์กฐ๋ฅผ ์ ์งํ๋ฉด์ ์๋ก์ด ํฉ์ฑ ๋ฐ์ดํฐ๋ฅผ ์์ฑํฉ๋๋ค.
- ์๊ฐ ๊ฒ์ฆ ๋ฐ ์์ (Self-Reflection): ์์ฑ๋ ํฉ์ฑ ๋ฐ์ดํฐ๊ฐ ์๋ณธ ๊ตฌ์กฐ์ ์ผ์นํ๋์ง ๊ฒ์ฆํ๊ณ , ํ์์ ์๋์ผ๋ก ์์ ํฉ๋๋ค.
- QA ๋ฐ์ดํฐ ์์ฑ: ์์ฑ๋ ํฉ์ฑ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก RAG ํ์ต์ฉ QA ์์ ์์ฑํฉ๋๋ค.
- API ํค ํ๋ง: ์ฌ๋ฌ Gemini API ํค๋ฅผ ์๋ ๋กํ ์ด์ ํ์ฌ ๋ฌด๋ฃ ํ ๋น๋์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํฉ๋๋ค.
- ์น ๊ธฐ๋ฐ ๊ฒ์ฆ ๋๊ตฌ: ์์ฑ๋ ๋ฐ์ดํฐ๋ฅผ ์น ์ธํฐํ์ด์ค์์ ์๊ฐ์ ์ผ๋ก ํ์ธํ๊ณ ์ง์ ์์ ํ ์ ์์ต๋๋ค.
TableMagnifier/
โโโ generate_synthetic_table/ # ํต์ฌ ๋ก์ง (LangGraph ์ํฌํ๋ก์ฐ)
โ โโโ flow.py # ๊ทธ๋ํ ์ ์ ๋ฐ ๋
ธ๋ ๊ตฌํ
โ โโโ runner.py # ์คํ ์ ํธ๋ฆฌํฐ
โ โโโ cli.py # CLI ์ง์
์
โ โโโ llm_factory.py # LLM ํฉํ ๋ฆฌ (OpenAI, Gemini, Gemini Pool, vLLM)
โ โโโ validators.py # ๋ฐ์ดํฐ ๊ฒ์ฆ ๋ก์ง
โ โโโ html_to_image.py # HTML โ ์ด๋ฏธ์ง ๋ณํ
โ โโโ prompts/ # LLM ํ๋กฌํํธ ํ
ํ๋ฆฟ
โ
โโโ polling_gemini/ # Gemini API ํค ํ๋ง ์์คํ
โ โโโ api_pool.py # API ํค ๋กํ
์ด์
๋งค๋์
โ โโโ langgraph_integration.py # LangChain/LangGraph ํธํ ๋ํผ
โ โโโ README.md # ์ฌ์ฉ ๊ฐ์ด๋
โ
โโโ annotate_tools/ # ์น ๊ธฐ๋ฐ ๊ฒ์ฆ ๋๊ตฌ
โ โโโ server.py # FastAPI ๋ฐฑ์๋
โ โโโ App.tsx # React ํ๋ก ํธ์๋
โ โโโ components/ # UI ์ปดํฌ๋ํธ
โ
โโโ apis/ # API ํค ์ค์
โ โโโ gemini_keys.yaml # Gemini API ํค ๋ชฉ๋ก (gemini_pool์ฉ)
โ
โโโ tests/ # ํ
์คํธ ์ฝ๋
โโโ main.py # CLI ์ง์
์
โโโ pyproject.toml # ํ๋ก์ ํธ ์์กด์ฑ
โโโ README.md # ์ค๋ช
์
flowchart TD
START((START)) --> RouteStart{์
๋ ฅ ํ์
ํ์ธ}
RouteStart -->|HTML ํ์ผ| LoadHTML[load_html_input]
RouteStart -->|์ด๋ฏธ์ง + openai/gemini/gemini_pool| DirectGen[generate_synthetic_table_from_image]
RouteStart -->|์ด๋ฏธ์ง + ๊ธฐํ ๋ชจ๋ธ| PyMuPDF[pymupdf_parse]
LoadHTML --> Analyze[analyze_table]
PyMuPDF --> Validate[validate_parsed_table]
Validate -->|์ ํจ| Analyze
Validate -->|๋ฌดํจ| ImageToHTML[image_to_html]
ImageToHTML --> Analyze
Analyze --> GenSynthetic[generate_synthetic_table]
GenSynthetic --> SelfReflection[self_reflection]
DirectGen --> SelfReflection
SelfReflection --> RouteReflection{๊ฒ์ฆ ๊ฒฐ๊ณผ}
RouteReflection -->|ํต๊ณผ ๋๋ ์ต๋ ์๋| Parse[parse_synthetic_table]
RouteReflection -->|์์ ํ์| Revise[revise_synthetic_table]
Revise --> SelfReflection
Parse --> GenerateQA[generate_qa]
GenerateQA --> END((END))
- Python 3.10 ์ด์
- Node.js (๊ฒ์ฆ ๋๊ตฌ ์คํ ์ ํ์)
- OpenAI API Key ๋๋ Google Gemini API Key
git clone https://github.com/Pseudo-Lab/TableMagnifier.git
cd TableMagnifier
# uv ์ฌ์ฉ (๊ถ์ฅ)
uv sync
# ๋๋ pip ์ฌ์ฉ
python3 -m venv .venv
source .venv/bin/activate
pip install -e ..env ํ์ผ์ ์์ฑํ๊ณ API ํค๋ฅผ ์
๋ ฅํ์ธ์.
OPENAI_API_KEY=sk-...
# ๋๋
GOOGLE_API_KEY=AIza...์ฌ๋ฌ ๊ฐ์ Gemini API ํค๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌด๋ฃ ํ ๋น๋์ ํจ์จ์ ์ผ๋ก ํ์ฉํ๋ ค๋ฉด apis/gemini_keys.yaml ํ์ผ์ ์์ฑํ์ธ์:
api_keys:
- name: key1
key: AIza...your-first-key
enabled: true
- name: key2
key: AIza...your-second-key
enabled: true
# ๋ ๋ง์ ํค ์ถ๊ฐ ๊ฐ๋ฅ
settings:
model: gemini-2.5-flash
temperature: 0.2
max_retries: 3
retry_delay: 2### backend
cd pipeline_ui/backend && uv run python main.py
### frontend
cd pipeline_ui/frontend && npm run dev์ด๋ฏธ์ง ํ์ผ ๋๋ HTML ํ์ผ์ ์ ๋ ฅ์ผ๋ก ๋ฐ์ ํฉ์ฑ ๋ฐ์ดํฐ๋ฅผ ์์ฑํฉ๋๋ค.
# OpenAI ์ฌ์ฉ (๊ธฐ๋ณธ)
uv run python -m generate_synthetic_table.cli path/to/table_image.png --save-json output.json
# Gemini ๋ชจ๋ธ ์ฌ์ฉ (๋จ์ผ API ํค)
uv run python -m generate_synthetic_table.cli path/to/table_image.png \
--provider gemini --model gemini-1.5-flash --save-json output.json
# Gemini Pool ์ฌ์ฉ (๋ค์ค API ํค ์๋ ๋กํ
์ด์
) โญ ๊ถ์ฅ
uv run python -m generate_synthetic_table.cli path/to/table_image.png \
--provider gemini_pool --save-json output.json
# ์ปค์คํ
์ค์ ํ์ผ ์ฌ์ฉ
uv run python -m generate_synthetic_table.cli path/to/table_image.png \
--provider gemini_pool --config-path /path/to/gemini_keys.yaml์ต์ ์ค๋ช :
| ์ต์ | ์ค๋ช | ๊ธฐ๋ณธ๊ฐ |
|---|---|---|
image |
์ ๋ ฅ ์ด๋ฏธ์ง ๋๋ HTML ํ์ผ ๊ฒฝ๋ก | (ํ์) |
--provider |
LLM ์ ๊ณต์ (openai, gemini, gemini_pool, vllm) |
openai |
--model |
์ฌ์ฉํ ๋ชจ๋ธ๋ช | gpt-4.1-mini |
--temperature |
์์ฑ ๋ค์์ฑ ์กฐ์ | 0.2 |
--config-path |
gemini_pool์ฉ ์ค์ ํ์ผ ๊ฒฝ๋ก | apis/gemini_keys.yaml |
--save-json |
๊ฒฐ๊ณผ JSON ์ ์ฅ ๊ฒฝ๋ก | (์ ํ) |
$ uv run python -m generate_synthetic_table.cli ./image.png --provider gemini_pool
# ์ถ๋ ฅ ๋ก๊ทธ
2025-12-15 10:47:42 - polling_gemini.api_pool - INFO - ์ด 6๊ฐ์ API ํค๋ฅผ ๋ก๋ํ์ต๋๋ค.
2025-12-15 10:47:42 - polling_gemini.api_pool - INFO - API ํค 'key1' ์ฌ์ฉ ์ค (๋ชจ๋ธ: gemini-2.5-flash)
2025-12-15 10:47:42 - generate_synthetic_table.flow - INFO - Entering node: generate_synthetic_table_from_image
2025-12-15 10:47:53 - generate_synthetic_table.flow - INFO - Entering node: self_reflection
2025-12-15 10:48:14 - generate_synthetic_table.flow - INFO - Entering node: revise_synthetic_table
2025-12-15 10:48:27 - generate_synthetic_table.flow - INFO - Entering node: self_reflection
2025-12-15 10:48:33 - generate_synthetic_table.flow - INFO - Entering node: parse_synthetic_table
2025-12-15 10:48:38 - generate_synthetic_table.flow - INFO - Entering node: generate_qa
# ๊ฒฐ๊ณผ JSON
{
"image_path": "./image.png",
"synthetic_json": [
{"๊ฒฝ๊ณผ๊ธฐ๊ฐ": "1๋
", "๋ฉ์
๋ณดํ๋ฃ ๋๊ณ": 600000, "ํด์งํ๊ธ๊ธ": 0, "ํ๊ธ๋ฅ ": 0},
{"๊ฒฝ๊ณผ๊ธฐ๊ฐ": "3๋
", "๋ฉ์
๋ณดํ๋ฃ ๋๊ณ": 1800000, "ํด์งํ๊ธ๊ธ": 540000, "ํ๊ธ๋ฅ ": 30},
{"๊ฒฝ๊ณผ๊ธฐ๊ฐ": "5๋
", "๋ฉ์
๋ณดํ๋ฃ ๋๊ณ": 3000000, "ํด์งํ๊ธ๊ธ": 1650000, "ํ๊ธ๋ฅ ": 55},
...
]
}์์ฑ๋ output.json์ ์น ์ธํฐํ์ด์ค์์ ํ์ธํ๊ณ ์์ ํ ์ ์์ต๋๋ค.
์๋ฒ ์คํ:
python annotate_tools/server.py --file output.jsonํด๋ผ์ด์ธํธ ์คํ (๋ณ๋ ํฐ๋ฏธ๋):
cd annotate_tools
npm install
npm run dev๋ธ๋ผ์ฐ์ ์์ http://localhost:5173์ผ๋ก ์ ์ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ํ์ธํ์ธ์.
polling_gemini๋ ์ฌ๋ฌ Gemini API ํค๋ฅผ ์๋์ผ๋ก ๋กํ
์ด์
ํ๋ ํ๋ง ์์คํ
์
๋๋ค. ๋ฌด๋ฃ ํ ๋น๋์ด ์์ง๋๋ฉด ์๋์ผ๋ก ๋ค์ ํค๋ก ์ ํ๋ฉ๋๋ค.
from polling_gemini import create_gemini_chat_model, invoke_gemini
# LangChain ํธํ ๋ชจ๋ธ๋ก ์ฌ์ฉ
model = create_gemini_chat_model()
response = model.invoke([HumanMessage(content="์๋
ํ์ธ์!")])
# ๊ฐ๋จํ ํจ์ ํธ์ถ
response = invoke_gemini("ํ
์ด๋ธ ๋ฐ์ดํฐ๋ฅผ ๋ถ์ํด์ฃผ์ธ์.")from polling_gemini import create_gemini_chat_model
from langgraph.graph import StateGraph
model = create_gemini_chat_model()
def my_node(state):
response = model.invoke([HumanMessage(content=state["query"])])
return {"response": response.content}
graph = StateGraph(...)
graph.add_node("process", my_node)generate_synthetic_table/flow.py์์ LangGraph์ ๋
ธ๋์ ์ฃ์ง๋ฅผ ์์ ํ์ฌ ์ํฌํ๋ก์ฐ๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
generate_synthetic_table/prompts/ ๋๋ ํ ๋ฆฌ์ ํ
์คํธ ํ์ผ์ ์์ ํ์ฌ LLM์ ๋์์ ์ ์ดํ ์ ์์ต๋๋ค.
generate_synthetic_table/llm_factory.py์ get_llm() ํจ์๋ฅผ ์์ ํ์ฌ ์๋ก์ด LLM provider๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
This project is licensed under the MIT License.