Upload 4 files
Browse files- KAIRO_Checklist_Config.json +28 -0
- README.md +4 -4
- app.py +41 -108
- requirements.txt +3 -4
KAIRO_Checklist_Config.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"checklist_korean": [
|
| 3 |
+
"λ§μΆ€λ² (Orthography)",
|
| 4 |
+
"λμ΄μ°κΈ° (Spacing Rules)",
|
| 5 |
+
"λ¬Έλ² μ€λ₯ (Grammatical Errors)",
|
| 6 |
+
"νμ€μ΄ κ·μ μλ° (Standard Language Regulation)",
|
| 7 |
+
"μΈλμ΄ νκΈ°λ² μλ° (Loanword Orthography)",
|
| 8 |
+
"λ¬Έμ₯ ꡬ쑰 μ€λ₯ (Sentence Structure Error)",
|
| 9 |
+
"μ΄ν μ μ μ± (Lexical Appropriateness)",
|
| 10 |
+
"μ€λ³΅μ΄/κ΅°λλκΈ° μ κ±° (Redundancy Elimination)",
|
| 11 |
+
"μ€νμ (Typographical Errors)",
|
| 12 |
+
"λ¬Έμ₯ λΆνΈ μ¬μ© (Punctuation Usage)",
|
| 13 |
+
"μ΄λ² μ€λ₯ (Usage Error)",
|
| 14 |
+
"λ
Όλ¦¬μ μΌκ΄μ± (Logical Coherence)",
|
| 15 |
+
"νμμ μ€λ₯ (Formatting Consistency)"
|
| 16 |
+
],
|
| 17 |
+
"checklist_english": [
|
| 18 |
+
"Spelling (μ² μ μ€λ₯)",
|
| 19 |
+
"Grammar (λ¬Έλ² μ€λ₯)",
|
| 20 |
+
"Capitalization (λμλ¬Έμ μ€λ₯)",
|
| 21 |
+
"Subject-Verb Agreement (μ£Όμ΄-λμ¬ μΌμΉ)",
|
| 22 |
+
"Article Usage (κ΄μ¬μ μ μ μ±)",
|
| 23 |
+
"Tense Consistency (μμ μΌκ΄μ±)",
|
| 24 |
+
"Word Choice (μ΄ν μ ν)",
|
| 25 |
+
"Redundancy (μ€λ³΅ νν)",
|
| 26 |
+
"Tone (문체 λ° μΌκ΄μ±)"
|
| 27 |
+
]
|
| 28 |
+
}
|
README.md
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
---
|
| 2 |
title: "KAIRO.ai"
|
| 3 |
emoji: "π§ "
|
|
@@ -9,7 +10,6 @@ app_file: app.py
|
|
| 9 |
pinned: false
|
| 10 |
---
|
| 11 |
|
| 12 |
-
# KAIRO.ai
|
| 13 |
-
|
| 14 |
-
-
|
| 15 |
-
- μ΅μ ν보 μλ μ ν
|
|
|
|
| 1 |
+
|
| 2 |
---
|
| 3 |
title: "KAIRO.ai"
|
| 4 |
emoji: "π§ "
|
|
|
|
| 10 |
pinned: false
|
| 11 |
---
|
| 12 |
|
| 13 |
+
# KAIRO.ai
|
| 14 |
+
|
| 15 |
+
AI κΈ°λ° PNG μ΄λ―Έμ§ κ΅μ (OCR + GPT-4 Turbo + PPT μμ±) μμ€ν
μ
λλ€.
|
|
|
app.py
CHANGED
|
@@ -1,119 +1,52 @@
|
|
| 1 |
|
| 2 |
import streamlit as st
|
| 3 |
from PIL import Image
|
| 4 |
-
import pytesseract
|
| 5 |
-
import easyocr
|
| 6 |
-
from paddleocr import PaddleOCR
|
| 7 |
-
import numpy as np
|
| 8 |
-
from pptx import Presentation
|
| 9 |
-
from pptx.util import Inches, Pt
|
| 10 |
-
import os
|
| 11 |
import io
|
| 12 |
-
import tempfile
|
| 13 |
-
import zipfile
|
| 14 |
-
from difflib import SequenceMatcher
|
| 15 |
|
| 16 |
-
st.set_page_config(layout="
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
st.
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
def run_tesseract(img):
|
| 48 |
-
return pytesseract.image_to_string(img, lang="kor+eng")
|
| 49 |
-
|
| 50 |
-
def run_easyocr(img):
|
| 51 |
-
reader = easyocr.Reader(['ko', 'en'], gpu=False)
|
| 52 |
-
result = reader.readtext(np.array(img), detail=0)
|
| 53 |
-
return "\n".join(result)
|
| 54 |
-
|
| 55 |
-
def run_paddleocr(img):
|
| 56 |
-
ocr = PaddleOCR(use_angle_cls=True, lang='korean')
|
| 57 |
-
result = ocr.ocr(np.array(img), cls=True)
|
| 58 |
-
return "\n".join([line[1][0] for block in result for line in block])
|
| 59 |
-
|
| 60 |
-
def create_ppt(results):
|
| 61 |
-
prs = Presentation()
|
| 62 |
-
for idx, (img, all_texts, best_text, best_engine) in enumerate(results):
|
| 63 |
-
slide = prs.slides.add_slide(prs.slide_layouts[5])
|
| 64 |
-
title = slide.shapes.title
|
| 65 |
-
title.text = f"νμΌ {idx+1} (μ΅μ μμ§: {best_engine})"
|
| 66 |
-
|
| 67 |
-
left = Inches(0.5)
|
| 68 |
-
top = Inches(1.0)
|
| 69 |
-
width = Inches(8.5)
|
| 70 |
-
height = Inches(5.5)
|
| 71 |
-
txBox = slide.shapes.add_textbox(left, top, width, height)
|
| 72 |
-
tf = txBox.text_frame
|
| 73 |
-
for engine, text in all_texts.items():
|
| 74 |
-
p = tf.add_paragraph()
|
| 75 |
-
p.text = f"[{engine}]\n{text}\n"
|
| 76 |
-
p.font.size = Pt(14)
|
| 77 |
-
p = tf.add_paragraph()
|
| 78 |
-
p.text = f"[μ΅μ’
μ ν κ²°κ³Ό]\n{best_text}"
|
| 79 |
-
p.font.size = Pt(16)
|
| 80 |
-
return prs
|
| 81 |
|
| 82 |
if uploaded_files:
|
| 83 |
-
|
| 84 |
-
for file in uploaded_files:
|
| 85 |
-
images = extract_images(file)
|
| 86 |
-
for img in images:
|
| 87 |
-
ocr_texts = {}
|
| 88 |
-
if "Tesseract" in ocr_engines:
|
| 89 |
-
ocr_texts["Tesseract"] = run_tesseract(img)
|
| 90 |
-
if "EasyOCR" in ocr_engines:
|
| 91 |
-
ocr_texts["EasyOCR"] = run_easyocr(img)
|
| 92 |
-
if "PaddleOCR" in ocr_engines:
|
| 93 |
-
ocr_texts["PaddleOCR"] = run_paddleocr(img)
|
| 94 |
-
|
| 95 |
-
st.image(img, caption="μ
λ‘λ μ΄λ―Έμ§", use_column_width=True)
|
| 96 |
-
|
| 97 |
-
# λΉκ΅ κΈ°μ€: 첫 μμ§μ κΈ°μ€μΌλ‘ μ μ¬λ κ³μ°
|
| 98 |
-
base_engine = list(ocr_texts.keys())[0]
|
| 99 |
-
base_text = normalize(ocr_texts[base_engine])
|
| 100 |
-
scores = {engine: score_similarity(base_text, normalize(txt)) for engine, txt in ocr_texts.items()}
|
| 101 |
-
best_engine = max(scores, key=scores.get)
|
| 102 |
-
best_text = ocr_texts[best_engine]
|
| 103 |
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
|
| 112 |
-
|
| 113 |
-
|
|
|
|
| 114 |
|
| 115 |
-
|
| 116 |
-
ppt_path = "/mnt/data/KAIRO_OCR_μ΅μ κ²°κ³Ό.pptx"
|
| 117 |
-
ppt.save(ppt_path)
|
| 118 |
-
with open(ppt_path, "rb") as f:
|
| 119 |
-
st.download_button("π₯ PPT λ€μ΄λ‘λ", data=f.read(), file_name="KAIRO_OCR_μ΅μ κ²°κ³Ό.pptx")
|
|
|
|
| 1 |
|
| 2 |
import streamlit as st
|
| 3 |
from PIL import Image
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
import io
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
+
st.set_page_config(page_title="KAIRO.ai", layout="wide")
|
| 7 |
+
|
| 8 |
+
# λ€ν¬λͺ¨λ ν κΈ (μ°μΈ‘ μλ¨)
|
| 9 |
+
col1, col2 = st.columns([8, 1])
|
| 10 |
+
with col2:
|
| 11 |
+
dark_mode = st.toggle("π", help="λ€ν¬ λͺ¨λ μ ν")
|
| 12 |
+
|
| 13 |
+
# μ€μ μ λ ¬ νμ΄ν, νλ
|
| 14 |
+
st.markdown(
|
| 15 |
+
"<h1 style='text-align: center; font-size: 3em;'>π§ KAIRO.ai</h1>",
|
| 16 |
+
unsafe_allow_html=True
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
# λ€ν¬λͺ¨λ μ€νμΌ μ μ©
|
| 20 |
+
if dark_mode:
|
| 21 |
+
st.markdown("""
|
| 22 |
+
<style>
|
| 23 |
+
html, body, .stApp {
|
| 24 |
+
background-color: #1e1e1e;
|
| 25 |
+
color: #f0f0f0;
|
| 26 |
+
}
|
| 27 |
+
</style>
|
| 28 |
+
""", unsafe_allow_html=True)
|
| 29 |
+
|
| 30 |
+
ocr_engines = st.multiselect("π§ OCR μμ§ μ ν (μ€λ³΅ κ°λ₯)", ["Tesseract", "EasyOCR", "PaddleOCR"], default=["Tesseract"])
|
| 31 |
+
checklist = st.multiselect("π κ²μ νλͺ© μ ν", ["μ€νμ", "λμ΄μ°κΈ°", "λ¬Έλ²", "μ΄ν"], default=["μ€νμ", "λμ΄μ°κΈ°"])
|
| 32 |
+
uploaded_files = st.file_uploader("π PNG μ
λ‘λ (μ ν μμ)", type=["png"], accept_multiple_files=True)
|
| 33 |
+
api_key = st.text_input("π OpenAI API Key", type="password")
|
| 34 |
+
|
| 35 |
+
st.markdown("---")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
if uploaded_files:
|
| 38 |
+
st.success(f"{len(uploaded_files)}μ₯ μ
λ‘λ μλ£ β
")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
+
estimated_tokens_per_file = 400
|
| 41 |
+
total_tokens = estimated_tokens_per_file * len(uploaded_files)
|
| 42 |
+
cost_estimate = total_tokens * 0.01 / 1000
|
| 43 |
|
| 44 |
+
st.markdown("### π° μμ λΉμ© μλ΄ (GPT-4 Turbo κΈ°μ€)")
|
| 45 |
+
st.markdown(f"- μμ ν ν° μ: **{total_tokens} tokens**")
|
| 46 |
+
st.markdown(f"- μμ λΉμ©: **${cost_estimate:.4f}**")
|
| 47 |
|
| 48 |
+
st.info("π OCR μ€ν μ€...")
|
| 49 |
+
st.info("π GPT κ΅μ μ§ν μ€...")
|
| 50 |
+
st.info("π PPT μμ± μ€...")
|
| 51 |
|
| 52 |
+
st.warning("β» μ΄ κΈ°λ₯μ λ°λͺ¨μ©μ΄λ©° μ€μ OCR/GPT μ°λμ λ€μ λ²μ μμ μλν©λλ€.")
|
|
|
|
|
|
|
|
|
|
|
|
requirements.txt
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
|
|
| 1 |
streamlit
|
| 2 |
pytesseract
|
| 3 |
-
easyocr
|
| 4 |
-
paddleocr
|
| 5 |
-
python-pptx
|
| 6 |
Pillow
|
| 7 |
-
|
|
|
|
|
|
| 1 |
+
|
| 2 |
streamlit
|
| 3 |
pytesseract
|
|
|
|
|
|
|
|
|
|
| 4 |
Pillow
|
| 5 |
+
python-pptx
|
| 6 |
+
openai
|