Improve EPUB restoration, book terminology and Calibre QA workflow

This commit is contained in:
Kai Tan
2026-10-08 07:25:27 +08:00
parent 40491e6386
commit caf9d8f4bb
35 changed files with 1439 additions and 959 deletions
+21 -3
View File
@@ -7,6 +7,7 @@ from pathlib import Path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from src.translation.translator_engine import Translator
from src.translation.glossary import prepare_glossary
from src.translation.llm_client import LLMClient
from src.translation.manifest_manager import ManifestManager
from src.preprocessing.profiler import BookProfiler
@@ -60,6 +61,7 @@ async def run_translate(args):
logger.error("OPENAI_API_KEY not found in env or config.")
sys.exit(1)
llm = None
try:
# Load Manifest
manager = ManifestManager(manifest_path)
@@ -74,23 +76,34 @@ async def run_translate(args):
requests_per_minute=llm_conf.get("requests_per_minute", 60),
concurrent_requests=llm_conf.get("concurrent_requests", 5),
timeout=llm_conf.get("timeout", 180),
max_output_tokens=llm_conf.get("max_output_tokens", 16000),
chunk_dir=work["chunks"]
)
# Profile
profiler = BookProfiler(llm)
profiler = BookProfiler(llm, cache_path=work["root"] / "profile.json")
profile = await profiler.analyze(manager.entries)
logger.info(f"Book Profile: {profile.title} ({profile.genre})")
# Translate
target_chunk_size = trans_conf.get("chunk_size", 4000)
concurrent_reqs = llm_conf.get("concurrent_requests", 5)
translator = Translator(llm, chunk_size=target_chunk_size, max_concurrent=concurrent_reqs)
glossary = await prepare_glossary(
manager.entries, llm, work["root"] / "glossary.json",
override=getattr(args, 'glossary', None) or trans_conf.get("glossary_path"),
auto=trans_conf.get("auto_glossary", True),
chunk_chars=trans_conf.get("glossary_scan_chars", 24000))
translator = Translator(llm, chunk_size=target_chunk_size, max_concurrent=concurrent_reqs,
glossary=glossary, validation_retries=trans_conf.get("validation_retries", 2),
on_chunk_complete=manager.save)
await translator.translate(manager.entries, profile)
# Save final state
manager.save()
await llm.close()
if any(not e.translated_text or e.validation_errors for e in manager.entries):
raise ValueError("Translation incomplete; inspect manifest validation_errors and resume")
logger.info("Translation complete.")
@@ -101,10 +114,15 @@ async def run_translate(args):
logger.critical(f"Unexpected error: {e}")
sys.exit(1)
finally:
if llm:
await llm.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Step 2: Translation")
parser.add_argument("--input-epub", help="Path to original EPUB (to derive book name)")
parser.add_argument("--book-name", help="Book name (folder name in work/)")
parser.add_argument("--glossary", help="Per-book JSON terminology file")
parser.add_argument("--model", default=None, help="LLM Model (overrides config)")
args = parser.parse_args()