Spaces:
Sleeping
Download docs/ko/advanced/API/python.md from ryusaksun/PDFTranslate: direct link, hf CLI and curl.
- Browser
- Download file 10.1 kB
-
https://huggingface.co/spaces/ryusaksun/PDFTranslate/resolve/main/docs/ko/advanced/API/python.md
- Command line
-
hf download hf://spaces/ryusaksun/PDFTranslate/docs/ko/advanced/API/python.md
-
curl -L -o python.md https://huggingface.co/spaces/ryusaksun/PDFTranslate/resolve/main/docs/ko/advanced/API/python.md
์ด ๋ฌธ์์๋ AI ์์ฑ ์ฝํ ์ธ ๊ฐ ํฌํจ๋ ์ ์์ต๋๋ค. ์ ํ์ฑ์ ์ํด ๋ ธ๋ ฅํ๊ณ ์์ง๋ง ๋ถ์ ํํ ๋ด์ฉ์ด ์์ ์ ์์ต๋๋ค. ๋ฌธ์ ๊ฐ ๋ฐ๊ฒฌ๋๋ฉด ๋ค์์ ํตํด ์ ๊ณ ํด ์ฃผ์ธ์:
- GitHub Issues
- ์ปค๋ฎค๋ํฐ ๊ธฐ์ฌ (PR ํ์ํฉ๋๋ค!)
Python API: do_translate_async_stream
๊ฐ์
- do_translate_async_stream ์ ๋จ์ผ PDF ๋ฅผ ๋ฒ์ญํ๊ณ ์ด๋ฒคํธ (์งํ ์ํฉ/์ค๋ฅ/์๋ฃ) ์คํธ๋ฆผ์ ์์ฑํ๋ ์ ์์ค ๋น๋๊ธฐ ์ง์ ์ ์ ๋๋ค.
- ์ค์๊ฐ ์งํ ์ํฉ๊ณผ ๊ฒฐ๊ณผ์ ๋ํ ์์ ํ ์ ์ด๋ฅผ ์ํ๋ ์ฌ์ฉ์ ์ ์ UI ๋ CLI ๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ์ ํฉํฉ๋๋ค.
- ์ ํจ์ฑ์ด ๊ฒ์ฆ๋ SettingsModel ๊ณผ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์๋ฝํ๊ณ , dict ์ด๋ฒคํธ์ ๋น๋๊ธฐ ์์ฑ๊ธฐ๋ฅผ ๋ฐํํฉ๋๋ค.
์๋ช
- Import:
from pdf2zh_next.high_level import do_translate_async_stream - Call:
async for event in do_translate_async_stream(settings, file): ... - Parameters:
- settings: SettingsModel. ์ ํจํด์ผ ํฉ๋๋ค; ํจ์๋
settings.validate_settings()๋ฅผ ํธ์ถํฉ๋๋ค. - file: str | pathlib.Path. ๋ฒ์ญํ ๋จ์ผ PDF ํ์ผ์ ๋๋ค. ์กด์ฌํด์ผ ํฉ๋๋ค.
- settings: SettingsModel. ์ ํจํด์ผ ํฉ๋๋ค; ํจ์๋
์ฐธ๊ณ :
settings.basic.input_files๋ ์ด ํจ์์์ ๋ฌด์๋ฉ๋๋ค; ์ฃผ์ด์งfile๋ง ๋ฒ์ญ๋ฉ๋๋ค.settings.basic.debug๊ฐ True ์ธ ๊ฒฝ์ฐ, ๋ฒ์ญ์ ๋ฉ์ธ ํ๋ก์ธ์ค์์ ์คํ๋ฉ๋๋ค; ๊ทธ๋ ์ง ์์ผ๋ฉด ํ์ ํ๋ก์ธ์ค์์ ์คํ๋ฉ๋๋ค. ๋ ๊ฒฝ์ฐ ๋ชจ๋ ์ด๋ฒคํธ ์คํค๋ง๋ ๋์ผํฉ๋๋ค.
์ด๋ฒคํธ ์คํธ๋ฆผ ๊ณ์ฝ
๋น๋๊ธฐ ์์ฑ์๋ ๋ค์๊ณผ ๊ฐ์ ์ ํ์ JSON ํ์ dict ์ด๋ฒคํธ๋ฅผ ์์ฑํฉ๋๋ค:
๋จ๊ณ ์์ฝ ์ด๋ฒคํธ:
stage_summary(์ ํ ์ฌํญ, ์ฒ์ ๋ํ๋ ์ ์์)- ํ๋
type: "stage_summary"stages: ์์ ์์ ๋ถํฌ๋ฅผ ์ค๋ช ํ๋ ๊ฐ์ฒด{ "name": str, "percent": float }์ ๋ชฉ๋กpart_index: ์ด ์์ฝ ์ด๋ฒคํธ์ ๊ฒฝ์ฐ 0 ์ผ ์ ์์total_parts: ์ ์ฒด ๋ถ๋ถ ์ (>= 1)
- ํ๋
์งํ ์ํฉ ์ด๋ฒคํธ:
progress_start,progress_update,progress_end- ๊ณตํต ํ๋
type: ์ ์ค ํ๋stage: ์ฌ๋์ด ์ฝ์ ์ ์๋ ๋จ๊ณ ์ด๋ฆ (์: "PDF ๊ตฌ๋ฌธ ๋ถ์ ๋ฐ ์ค๊ฐ ํํ ์์ฑ", "๋จ๋ฝ ๋ฒ์ญ", "PDF ์ ์ฅ")stage_progress: ํ์ฌ ๋จ๊ณ ๋ด ์งํ๋ฅ ์ ๋ํ๋ด๋ [0, 100] ๋ฒ์์ floatoverall_progress: ์ ์ฒด ์งํ๋ฅ ์ ๋ํ๋ด๋ [0, 100] ๋ฒ์์ floatpart_index: ํ์ฌ ๋ถ๋ถ ์ธ๋ฑ์ค (์ผ๋ฐ์ ์ผ๋ก ์งํ ์ํฉ ์ด๋ฒคํธ์ ๊ฒฝ์ฐ 1 ๋ถํฐ ์์)total_parts: ์ ์ฒด ๋ถ๋ถ ์ (>= 1). ํฐ ๋ฌธ์๋ ์๋์ผ๋ก ๋ถํ ๋ ์ ์์.stage_current: ๋จ๊ณ ๋ด ํ์ฌ ๋จ๊ณstage_total: ๋จ๊ณ ๋ด ์ ์ฒด ๋จ๊ณ ์
- ๊ณตํต ํ๋
์๋ฃ ์ด๋ฒคํธ:
finish- ํ๋
type: "finish"translate_result: ์ต์ข ์ถ๋ ฅ์ ์ ๊ณตํ๋ ๊ฐ์ฒด (์ฐธ๊ณ : ์ฌ์ ์ด ์๋ ํด๋์ค ์ธ์คํด์ค)original_pdf_path: ์ ๋ ฅ PDF ๊ฒฝ๋กmono_pdf_path: ๋จ์ผ ์ธ์ด ๋ฒ์ญ PDF ๊ฒฝ๋ก (๋๋ None)dual_pdf_path: ์ด์ค ์ธ์ด ๋ฒ์ญ PDF ๊ฒฝ๋ก (๋๋ None)no_watermark_mono_pdf_path: ์ํฐ๋งํฌ๊ฐ ์๋ ๋จ์ผ ์ธ์ด ์ถ๋ ฅ ๊ฒฝ๋ก (์์ฑ๋ ๊ฒฝ์ฐ), ๊ทธ๋ ์ง ์์ผ๋ฉด Noneno_watermark_dual_pdf_path: ์ํฐ๋งํฌ๊ฐ ์๋ ์ด์ค ์ธ์ด ์ถ๋ ฅ ๊ฒฝ๋ก (์์ฑ๋ ๊ฒฝ์ฐ), ๊ทธ๋ ์ง ์์ผ๋ฉด Noneauto_extracted_glossary_path: ์๋ ์ถ์ถ ์ฉ์ด์ง CSV ๊ฒฝ๋ก (๋๋ None)total_seconds: ๊ฒฝ๊ณผ ์๊ฐ (์ด, float)peak_memory_usage: ๋ฒ์ญ ์ค ๋๋ต์ ์ธ ์ต๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ (float; ๊ตฌํ์ ๋ฐ๋ฅธ ๋จ์)
- ํ๋
์ค๋ฅ ์ด๋ฒคํธ:
error- ํ๋
type: "error"error: ์ฌ๋์ด ์ฝ์ ์ ์๋ ์ค๋ฅ ๋ฉ์์งerror_type:BabeldocError,SubprocessError,IPCError,SubprocessCrashError๋ฑ ์ค ํ๋details: ์ ํ์ ์ธ๋ถ ์ ๋ณด (์: ์๋ณธ ์ค๋ฅ ๋๋ ํธ๋ ์ด์ค๋ฐฑ)
- ํ๋
์ค์ํ ๋์:
- ์ ํ์ ์ผ๋ก
stage_summary๊ฐ ์งํ๋ฅ ์ด ์์๋๊ธฐ ์ ์ ๋ฐ์ํ ์ ์์ต๋๋ค. - ํน์ ์คํจ ์, ์์ฑ๊ธฐ๋ ๋จผ์
error์ด๋ฒคํธ๋ฅผ yield ํ ๋ค์TranslationError์์ ํ์๋ ์์ธ๋ฅผ ๋ฐ์์ํต๋๋ค. ์ค๋ฅ ์ด๋ฒคํธ๋ฅผ ํ์ธํ๊ณ ์์ธ๋ฅผ catch ํ ์ค๋น๋ฅผ ๋ชจ๋ ํด์ผ ํฉ๋๋ค. progress_update์ด๋ฒคํธ๋ ๋์ผํ ๊ฐ์ผ๋ก ๋ฐ๋ณต๋ ์ ์์ต๋๋ค; ํ์ํ๋ค๋ฉด ์๋น์๋ ๋๋ฐ์ด์ฑ์ ํด์ผ ํฉ๋๋ค.finish์ด๋ฒคํธ๋ฅผ ์์ ํ๋ฉด ์คํธ๋ฆผ ์๋น๋ฅผ ์ค์งํ์ธ์.
์ต์ ์ฌ์ฉ ์์ (๋น๋๊ธฐ)
import asyncio
from pathlib import Path
from pdf2zh_next.high_level import do_translate_async_stream
# Assume you already have a valid SettingsModel instance named `settings`
# and a PDF file path
async def translate_one(settings, pdf_path: str | Path):
try:
async for event in do_translate_async_stream(settings, pdf_path):
etype = event.get("type")
if etype == "stage_summary":
# Optional pre-flight summary of stages
stages = event.get("stages", [])
print("Stage summary:", ", ".join(f"{s['name']}:{s['percent']:.2f}" for s in stages))
elif etype in {"progress_start", "progress_update", "progress_end"}:
stage = event.get("stage")
stage_prog = event.get("stage_progress") # 0..100
overall = event.get("overall_progress") # 0..100
part_i = event.get("part_index")
part_n = event.get("total_parts")
print(f"[{etype}] {stage} | stage {stage_prog:.1f}% | overall {overall:.1f}% (part {part_i}/{part_n})")
elif etype == "error":
# You will also get a raised exception after this yield
print("[error]", event.get("error"), event.get("error_type"))
elif etype == "finish":
result = event["translate_result"]
print("Done in", getattr(result, "total_seconds", None), "s")
print("Mono:", getattr(result, "mono_pdf_path", None))
print("Dual:", getattr(result, "dual_pdf_path", None))
print("No-watermark Mono:", getattr(result, "no_watermark_mono_pdf_path", None))
print("No-watermark Dual:", getattr(result, "no_watermark_dual_pdf_path", None))
print("Glossary:", getattr(result, "auto_extracted_glossary_path", None))
print("Peak memory:", getattr(result, "peak_memory_usage", None))
break
except Exception as exc:
# Catch exceptions raised by the stream after an error event
print("Translation failed:", exc)
# asyncio.run(translate_one(settings, "/path/to/file.pdf"))
์ทจ์
์์ ์ ์ทจ์ํ๋ฉด ์คํธ๋ฆผ์ ์๋นํ๋ ์์ ์ด ์ทจ์๋ฉ๋๋ค. ์ทจ์๋ ๊ธฐ๋ณธ ๋ฒ์ญ ํ๋ก์ธ์ค๋ก ์ ํ๋ฉ๋๋ค.
import asyncio
from pdf2zh_next.high_level import do_translate_async_stream
async def cancellable(settings, pdf):
task = asyncio.create_task(_consume(settings, pdf))
await asyncio.sleep(1.0) # let it start
task.cancel()
try:
await task
except asyncio.CancelledError:
print("Cancelled")
async def _consume(settings, pdf):
async for event in do_translate_async_stream(settings, pdf):
if event["type"] == "finish":
break
์ด๋ฒคํธ ๋ชจ์ ์์
๋จ๊ณ ์์ฝ ์ด๋ฒคํธ (์์):
{
"type": "stage_summary",
"stages": [
{"name": "Parse PDF and Create Intermediate Representation", "percent": 0.1086},
{"name": "DetectScannedFile", "percent": 0.0188},
{"name": "Parse Page Layout", "percent": 0.1079}
// ... more stages ...
],
"part_index": 0,
"total_parts": 1
}
Progress event (์์):
{
"type": "progress_update",
"stage": "Translate Paragraphs",
"stage_progress": 2.04,
"stage_current": 1,
"stage_total": 49,
"overall_progress": 53.44,
"part_index": 1,
"total_parts": 1
}
Finish event (์์):
{
"type": "finish",
"translate_result": {
"original_pdf_path": "pdf2zh_files/<session>/table.pdf",
"mono_pdf_path": "pdf2zh_files/<session>/table.zh-CN.mono.pdf",
"dual_pdf_path": "pdf2zh_files/<session>/table.zh-CN.dual.pdf",
"no_watermark_mono_pdf_path": "pdf2zh_files/<session>/table.no_watermark.zh-CN.mono.pdf",
"no_watermark_dual_pdf_path": "pdf2zh_files/<session>/table.no_watermark.zh-CN.dual.pdf",
"auto_extracted_glossary_path": "pdf2zh_files/<session>/table.zh-CN.glossary.csv",
"total_seconds": 42.83,
"peak_memory_usage": 4651.55
}
}
Error event (example):
{
"type": "error",
"error": "Babeldoc translation error: <message>",
"error_type": "BabeldocError",
"details": "<optional original error or traceback>"
}
์ฐธ๊ณ ์ฌํญ ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก
- ํญ์ ์์ฑ๊ธฐ์์ ๋ฐ์ํ๋ ์ค๋ฅ ์ด๋ฒคํธ์ ์์ธ๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํ์ญ์์ค.
- ๋ถํ์ํ ์์
์ ํผํ๊ธฐ ์ํด
finish์ด๋ฒคํธ์์ ๋ฃจํ๋ฅผ ์ค๋จํ์ญ์์ค. - ํธ์ถํ๊ธฐ ์ ์
file์ด ์กด์ฌํ๊ณsettings.validate_settings()๊ฐ ํต๊ณผํ๋์ง ํ์ธํ์ญ์์ค. - ๋ํ ๋ฌธ์๋ ๋ถํ ๋ ์ ์์ต๋๋ค.
part_index/total_parts์overall_progress๋ฅผ ์ฌ์ฉํ์ฌ UI ๋ฅผ ๊ตฌ๋ํ์ญ์์ค. - UI ๊ฐ ๋ฐ๋ณต์ ์ด๊ณ ๋์ผํ ์
๋ฐ์ดํธ์ ๋ฏผ๊ฐํ ๊ฒฝ์ฐ
progress_update์ด๋ฒคํธ๋ฅผ ๋๋ฐ์ด์คํ์ญ์์ค. report_interval(SettingsModel):progress_update์ด๋ฒคํธ์ ๋ฐ์ ๋น๋๋ง ์ ์ดํฉ๋๋ค.stage_summary,progress_start,progress_end๋๋finish์๋ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค. ๊ธฐ๋ณธ๊ฐ์ 0.1 ์ด์ด๋ฉฐ ํ์ฉ๋๋ ์ต์๊ฐ์ 0.05 ์ด์ ๋๋ค. ์งํ๋ฅ ๋ชจ๋ํฐ ๋ก์ง์ ๋ฐ๋ผ,stage_total <= 3์ผ ๋ ์ ๋ฐ์ดํธ๋report_interval์ ์ํด ์ ํ๋์ง ์์ต๋๋ค.