Skip to content

Pseudo-Lab/TableMagnifier

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

22 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

TableMagnifier

TableMagnifier

PseudoLab Discord Community Stars Badge Forks Badge Pull Requests Badge Issues Badge GitHub contributors

TableMagnifier Repository์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค! ํ•œ๊ตญ์–ด TableQA์— ๋Œ€ํ•œ ์‹ ๋ขฐ๋„ ๋†’์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ํ‰๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿš€ {{TableMagnifier}} โ€” ๊ฐ€์งœ์—ฐ๊ตฌ์†Œ 11๊ธฐ NLx Crew ์†Œ์† ํ”„๋กœ์ ํŠธ

โ€œํ•จ๊ป˜ ๋งŒ๋“œ๋Š” ์šฐ์—ฐํ•œ ํ˜๋ช…(Serendipity Revolution)โ€ ์ง„์‹คํ•จ๊ณผ ์‹ ๋ขฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ AI/DS ํ˜์‹  ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ ๊ธฐ์ˆ  ์‹คํ—˜์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๐ŸŒŸ ํ”„๋กœ์ ํŠธ ๋ชฉํ‘œ (Project Vision)

"์ด๋ก ์—์„œ ์‹ค์ „๊นŒ์ง€, ํ•จ๊ป˜ ์„ฑ์žฅํ•˜๋Š” AI ์‹คํ—˜์‹ค"

  • ๊ฐœ์ธ ์„ฑ์žฅ๊ณผ ์ง‘๋‹จ ์ง€ํ˜œ์˜ ์‹œ๋„ˆ์ง€ ์ฐฝ์ถœ
  • ์˜คํ”ˆ์†Œ์Šค ์ •์‹ ์„ ๋ฐ”ํƒ•์œผ๋กœ ํ•œ ์ง€์‹ ๊ณต์œ  ๋ฌธํ™”
  • ์‹คํŒจ๋ฅผ ์„ฑ๊ณต์˜ ๋””๋”ค๋Œ๋กœ ๋งŒ๋“œ๋Š” ์‹คํ—˜์  ์ ‘๊ทผ
  • ๋…ผ๋ฌธ ๋ฆฌ๋ทฐ ํ”„๋กœ์ ํŠธ โ€” ์ตœ์‹  AI ๋…ผ๋ฌธ ๋ถ„์„, ํ† ๋ก , ์‹คํ—˜ ์žฌํ˜„
  • ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ โ€” AIยท๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ฐœ๋ฐœ ๋ฐ ๊ฐœ์„ 
  • ์ปจํผ๋Ÿฐ์Šค ๋…ผ๋ฌธ ํˆฌ๊ณ  โ€” ์ตœ์‹  ์—ฐ๊ตฌ ์ˆ˜ํ–‰ ๋ฐ ๊ตญ์ œ ํ•™ํšŒ ์ œ์ถœ ์ค€๋น„

๐Ÿง‘ ํŒ€ ์†Œ๊ฐœ (Dynamic Team)

์—ญํ•  ์ด๋ฆ„ ๊ธฐ์ˆ  ์Šคํƒ ๋ฐฐ์ง€ ์ฃผ์š” ๊ด€์‹ฌ ๋ถ„์•ผ
Project Manager ๋ฐ•์„ธ์—ฐ Python PyTorch VLM, Image Captioning, SLT
Member ์ตœ์žฌํ˜ Python PyTorch LLM, RAG, Agent
Member ์ด๋ช…์ง„ Python PyTorch LLM, SLT
Member ๊น€์ง„์•„ Python PyTorch NLP, Data Science
Member ์„œ์„ํ˜„ Python PyTorch VLM, Data Statistics
Member ์ž„์˜ˆ์› Python PyTorch Compiler, Ontology

๐Ÿš€ ํ”„๋กœ์ ํŠธ ๋กœ๋“œ๋งต (Project Roadmap)

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
Loading

๐Ÿ’ป ์ฃผ์ฐจ๋ณ„ ํ™œ๋™ (Activity History)

์ฃผ์ฐจ ๋‚ ์งœ ํ™œ๋™ ๊ฒฐ๊ณผ๋ฌผ ์œ ํ˜• ๋น„๊ณ 
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 ์˜คํ”„๋ผ์ธ

๐ŸŒฑ ์ฐธ์—ฌ ์•ˆ๋‚ด (How to Engage)

  • ๋นŒ๋”๋กœ ์ฐธ์—ฌ โ€” ํ”„๋กœ์ ํŠธ ๊ธฐํšยท์šด์˜ ์ฃผ๋„
  • ๋Ÿฌ๋„ˆ๋กœ ์ฐธ์—ฌ โ€” ์—ฐ๊ตฌยท๊ฐœ๋ฐœยทํ…Œ์ŠคํŠธ ๋“ฑ ์‹คํ–‰
  • ์ฒญ๊ฐ• ์ฐธ์—ฌ โ€” ๊ณต๊ฐœ ์„ธ์…˜ ์ฐธ์—ฌ ๊ฐ€๋Šฅ

โ—๏ธ์ฐธ์—ฌ ๋งํฌ: ๊ฐ€์งœ์—ฐ๊ตฌ์†Œ ๋””์Šค์ฝ”๋“œ โ—๏ธ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜ ์ฑ„๋„: ์นด์นด์˜คํ†ก

๋ˆ„๊ตฌ๋‚˜ ์ฒญ๊ฐ•์„ ํ†ตํ•ด ๋ชจ์ž„์„ ์ฐธ์—ฌํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ํŠน๋ณ„ํ•œ ์‹ ์ฒญ ์—†์ด ์ •๊ธฐ ๋ชจ์ž„ ์‹œ๊ฐ„์— ๋งž์ถ”์–ด ๋””์Šค์ฝ”๋“œ #Room-CS ์ฑ„๋„๋กœ ์ž…์žฅ
  2. Magical Week ์ค‘ ํ–‰์‚ฌ์— ์ฐธ๊ฐ€ {{ ... }}

Acknowledgement ๐Ÿ™

์ด ํ”„๋กœ์ ํŠธ๋Š” ๊ฐ€์งœ์—ฐ๊ตฌ์†Œ Open Academy๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์˜ ์ฐธ์—ฌ์™€ ๊ธฐ์—ฌ๊ฐ€ '์šฐ์—ฐํ•œ ํ˜๋ช…(Serendipity Revolution)'์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋‘์—๊ฒŒ ๊นŠ์€ ๊ฐ์‚ฌ๋ฅผ ์ „ํ•ฉ๋‹ˆ๋‹ค.


TableMagnifier (ํ…Œ์ด๋ธ” ๋งค๊ทธ๋‹ˆํŒŒ์ด์–ด)

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                   # ์„ค๋ช…์„œ

LangGraph ์›Œํฌํ”Œ๋กœ์šฐ

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))
Loading

์„ค์น˜ ๋ฐฉ๋ฒ•

์‚ฌ์ „ ์š”๊ตฌ ์‚ฌํ•ญ

  • Python 3.10 ์ด์ƒ
  • Node.js (๊ฒ€์ฆ ๋„๊ตฌ ์‹คํ–‰ ์‹œ ํ•„์š”)
  • OpenAI API Key ๋˜๋Š” Google Gemini API Key

1. ํ”„๋กœ์ ํŠธ ํด๋ก  ๋ฐ ์˜์กด์„ฑ ์„ค์น˜

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 .

2. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •

.env ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.

OPENAI_API_KEY=sk-...
# ๋˜๋Š”
GOOGLE_API_KEY=AIza...

3. Gemini API ํ‚ค ํ’€๋ง ์„ค์ • (์„ ํƒ์‚ฌํ•ญ)

์—ฌ๋Ÿฌ ๊ฐœ์˜ 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

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

UI ์‚ฌ์šฉ๋ฐฉ๋ฒ•

### backend
cd pipeline_ui/backend && uv run python main.py

### frontend
cd pipeline_ui/frontend && npm run dev

1. ํ•ฉ์„ฑ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ (CLI)

์ด๋ฏธ์ง€ ํŒŒ์ผ ๋˜๋Š” 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},
    ...
  ]
}

2. ๊ฒ€์ฆ ๋„๊ตฌ ์‹คํ–‰ (Web UI)

์ƒ์„ฑ๋œ output.json์„ ์›น ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ํ™•์ธํ•˜๊ณ  ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„œ๋ฒ„ ์‹คํ–‰:

python annotate_tools/server.py --file output.json

ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰ (๋ณ„๋„ ํ„ฐ๋ฏธ๋„):

cd annotate_tools
npm install
npm run dev

๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:5173์œผ๋กœ ์ ‘์†ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

polling_gemini ๋ชจ๋“ˆ

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("ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•ด์ฃผ์„ธ์š”.")

LangGraph์—์„œ ์‚ฌ์šฉ

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์˜ ๋™์ž‘์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

LLM Provider ์ถ”๊ฐ€

generate_synthetic_table/llm_factory.py์˜ get_llm() ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ์ƒˆ๋กœ์šด LLM provider๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


Contributors ๐Ÿ˜ƒ

License ๐Ÿ—ž

This project is licensed under the MIT License.