用Python+LangChain构建PDF翻译Agent:自动分块、翻译、合并实战

在处理大量PDF翻译任务时,手动逐页操作显然不现实。本文介绍如何用Python + LangChain构建一个简易的PDF翻译Agent,实现自动分块、调用翻译API、合并结果的完整流程。

前言

PDF翻译自动化有几个典型痛点:

  • PDF结构复杂,直接全文提取容易丢失格式
  • 大模型上下文有限,长文档需要分块处理
  • 翻译后需要按原结构合并,保持可读性
  • 专业术语不一致,需要术语库支持

本文的方案适合有一定Python基础的开发者,代码可直接运行和扩展。

环境准备

  • Python 3.10+
  • 依赖库:
pip install langchain pymupdf openai requests python-dotenv
  • 一个可用的翻译API(本文以OpenAI兼容接口为例,可替换为PDFTranslator API或其他大模型API)

设计思路

整个Agent的工作流程:

读取PDF → 按页/段落分块 → 术语预处理 → 调用翻译API → 术语还原 → 合并输出 → 保存为Markdown/PDF

核心组件:

组件作用
PyMuPDF提取PDF文本和页面结构
LangChain组织翻译Chain和Prompt模板
术语库CSV维护专业术语标准译法
翻译API执行实际翻译

代码实现

Step 1:读取PDF并分块

import fitz  # PyMuPDF
from pathlib import Path

def extract_pdf_chunks(pdf_path: str, chunk_by: str = "page") -> list[dict]:
    """按页提取PDF文本块
    
    Args:
        pdf_path: PDF文件路径
        chunk_by: 分块方式,目前支持 page
        
    Returns:
        每个元素包含 page_num 和 text
    """
    doc = fitz.open(pdf_path)
    chunks = []
    for page_num in range(len(doc)):
        page = doc.load_page(page_num)
        text = page.get_text("text")
        chunks.append({
            "page_num": page_num + 1,
            "text": text.strip()
        })
    doc.close()
    return chunks

Step 2:加载术语库

import csv
from pathlib import Path

def load_glossary(csv_path: str) -> dict:
    """加载术语库
    
    CSV格式:source,target
    """
    glossary = {}
    if not Path(csv_path).exists():
        return glossary
    with open(csv_path, "r", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for row in reader:
            glossary[row["source"].strip()] = row["target"].strip()
    return glossary

Step 3:术语保护与还原

import uuid

def protect_terms(text: str, glossary: dict) -> tuple[str, dict]:
    """将术语替换为占位符,避免翻译时产生不一致"""
    placeholder_map = {}
    for source, target in glossary.items():
        placeholder = f"__TERM_{uuid.uuid4().hex[:8].upper()}__"
        placeholder_map[placeholder] = target
        text = text.replace(source, placeholder)
    return text, placeholder_map

def restore_terms(text: str, placeholder_map: dict) -> str:
    """将占位符还原为标准译法"""
    for placeholder, target in placeholder_map.items():
        text = text.replace(placeholder, target)
    return text

Step 4:LangChain翻译Chain

import os
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv

load_dotenv()

# 配置API(请替换为你的实际API地址和Key)
llm = ChatOpenAI(
    model="gpt-4o-mini",
    openai_api_base=os.getenv("OPENAI_API_BASE", "https://api.openai.com/v1"),
    openai_api_key=os.getenv("OPENAI_API_KEY"),
    temperature=0.1,
)

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一名专业翻译。请将用户提供的英文PDF段落翻译成中文,保持原意和语气。不要解释,只输出译文。"),
    ("human", "{text}")
])

translate_chain = prompt | llm

def translate_text(text: str) -> str:
    """调用LangChain Chain翻译文本"""
    if not text.strip():
        return ""
    response = translate_chain.invoke({"text": text})
    return response.content

Step 5:完整翻译流程

def translate_pdf(pdf_path: str, glossary: dict, output_path: str):
    """翻译整个PDF并保存为Markdown"""
    chunks = extract_pdf_chunks(pdf_path)
    results = []
    
    for chunk in chunks:
        print(f"Translating page {chunk['page_num']}...")
        protected_text, placeholder_map = protect_terms(chunk["text"], glossary)
        translated = translate_text(protected_text)
        restored = restore_terms(translated, placeholder_map)
        results.append({
            "page_num": chunk["page_num"],
            "translated": restored
        })
    
    # 输出为Markdown
    with open(output_path, "w", encoding="utf-8") as f:
        for r in results:
            f.write(f"## 第{r['page_num']}页\n\n")
            f.write(r["translated"])
            f.write("\n\n---\n\n")
    print(f"Done. Output saved to {output_path}")

Step 6:运行示例

if __name__ == "__main__":
    glossary = load_glossary("glossary.csv")
    translate_pdf(
        pdf_path="sample.pdf",
        glossary=glossary,
        output_path="translated_sample.md"
    )

术语库CSV示例

source,target
neural network,神经网络
machine learning,机器学习
SSL certificate,SSL证书
warranty period,保修期

进阶方向

这个基础Agent可以继续扩展:

  1. 按段落分块:对于页数少但单页内容多的文档,按段落分块比按页更精细。
  2. 上下文增强:在翻译每个块时,注入文档摘要或前面块的关键信息,提升连贯性。
  3. 双语对照输出:生成原文-译文对照格式,方便校对。
  4. 集成PDFTranslator API:如果你需要保留原始PDF排版,可以将翻译后的文本交给支持格式保留的API二次处理。
  5. 异步并发:用asyncio或线程池并行翻译多个块,提升速度。

总结

用LangChain构建PDF翻译Agent的核心价值,是把"提取-翻译-合并"的流程标准化。术语库的加入则解决了机器翻译中术语不一致的常见问题。

对于开发者来说,这套方案可以作为企业内部文档翻译 pipeline 的基础模块;对于个人用户,直接调用PDFTranslator这类保留格式的工具可能更省事。两者可以根据实际需求组合使用。

标签:PDF翻译、Python自动化、LangChain、AI翻译、开发者工具

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值