基于Java和通义千问(Qwen) API的学术论文PDF翻译系统,可将英文PDF论文翻译为中文Markdown文档。
- PDF文本提取: 使用Apache PDFBox从PDF中提取纯文本
- 智能分段: 针对学术论文优化的分段策略,保持章节结构和上下文连贯性
- 批量翻译: 调用通义千问API进行批量翻译
- 格式保留: 输出学术论文格式的Markdown,保留标题、章节、段落等结构
- 错误处理: 完善的重试机制和错误处理
- 进度跟踪: 实时显示翻译进度和详细日志
- 中文日志: 全中文日志输出,更易读易懂
- 字符统计: 统计原文和译文的字符数量,直观了解翻译规模
- 精简类名: 日志中只显示类名,不显示完整包路径,输出更简洁
- Java 17 或更高版本
- Maven 3.6+
- 通义千问API密钥
访问阿里云百炼平台申请通义千问API密钥。
在 ~/.zshrc 或 ~/.bash_profile 中添加:
export QWEN_API_KEY="your-api-key-here"然后执行:
source ~/.zshrc
# 或
source ~/.bash_profile# 快速编译(跳过测试)
mvn clean package -DskipTests
# 查看详细编译说明,请参考下文"编译项目"章节# 方式1: 指定PDF文件路径(推荐)
java -jar target/aitranslation-1.0-SNAPSHOT.jar /path/to/your-paper.pdf
# 方式2: 使用相对路径
java -jar target/aitranslation-1.0-SNAPSHOT.jar ./papers/paper.pdf
# 方式3: 使用环境变量指定
export PDF_FILE_PATH="/path/to/paper.pdf"
java -jar target/aitranslation-1.0-SNAPSHOT.jar翻译结果将保存在 output/{文件名}_translated.md
更多PDF路径指定方式请查看: PDF_USAGE.md
运行程序后,您将看到清晰的中文日志输出:
=================================================================
AI PDF 学术论文翻译系统启动中...
=================================================================
步骤 1/6: 正在加载配置...
配置加载成功
翻译配置: 分段token限制=3000, 重叠token数=200
步骤 2/6: 正在确定PDF文件路径...
PDF文件路径: /path/to/paper.pdf
步骤 3/6: 正在提取PDF内容...
PDF提取完成: 15 页, 24580 个字符, 86 个分段, 预估 7234 tokens
步骤 4/6: 正在初始化翻译服务...
步骤 5/6: 正在开始翻译过程...
根据文档长度,这可能需要几分钟时间...
开始翻译文档: paper.pdf,共 86 个分段
正在优化分段...
分段完成: 86 个原始分段优化为 32 个
正在为分段添加上下文...
正在翻译 32 个分段...
正在翻译分段 1/32 (类型: TITLE, 预估tokens: 45)
分段 1/32 翻译成功
...(省略中间翻译过程)
正在翻译分段 32/32 (类型: PARAGRAPH, 预估tokens: 1543)
分段 32/32 翻译成功
翻译完成。成功率: 32/32 (100.00%)
步骤 6/6: 正在保存翻译结果...
翻译结果已保存至: /path/to/output/paper_translated.md
=================================================================
翻译完成!
=================================================================
统计信息:
总分段数: 32
已翻译: 32
失败: 0
成功率: 100.00%
原文字符数: 24580
译文字符数: 18932
耗时: 245.67 秒
=================================================================
输出文件: ./output/paper_translated.md
=================================================================
更多日志输出详情请查看: LOG_OUTPUT_SAMPLE.md
可以通过环境变量自定义配置:
| 环境变量 | 说明 | 默认值 |
|---|---|---|
QWEN_API_KEY |
通义千问API密钥(必填) | - |
QWEN_MODEL |
使用的模型名称 | qwen3-max |
PDF_FILE_PATH |
PDF文件路径(必填) | - |
QWEN_MAX_TOKENS |
每次请求的最大token数 | 4000 |
QWEN_TEMPERATURE |
温度参数(0-2) | 0.3 |
QWEN_MAX_RETRIES |
最大重试次数 | 3 |
SEGMENT_TOKEN_LIMIT |
分段token限制 | 3000 |
SEGMENT_OVERLAP_TOKENS |
段落重叠token数 | 200 |
OUTPUT_DIRECTORY |
输出目录 | ./output |
示例:
export QWEN_MODEL=qwen-plus
export SEGMENT_TOKEN_LIMIT=2000
java -jar target/aitranslation-1.0-SNAPSHOT.jar┌─────────────────────────────────────────────────────────────────┐
│ AITranslationApplication │
│ (主程序入口) │
└───────────────────────────┬─────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Config │ │ Services │ │ Models │
│ 配置管理层 │ │ 业务服务层 │ │ 数据模型层 │
└───────────────┘ └───────┬───────┘ └───────────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ PDFExtractor │ │ Translation │ │ Markdown │
│ Service │ │ Service │ │ Formatter │
│ PDF文本提取 │ │ 翻译服务 │ │ 格式化服务 │
└───────┬───────┘ └───────┬───────┘ └───────────────┘
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ SegmentStrategy│ │ QwenApiClient│
│ 分段策略 │ │ API客户端 │
└───────────────┘ └───────┬───────┘
│
▼
┌───────────────┐
│ Qwen API │
│ 通义千问API │
└───────────────┘
1. PDF加载阶段
┌─────────┐ ┌──────────────┐ ┌─────────────┐
│ PDF文件 │ ──▶ │ PDFExtractor │ ──▶ │ PDFDocument │
└─────────┘ └──────────────┘ └─────────────┘
│
├─ 文本提取 (PDFBox)
├─ 元数据提取
└─ 结构识别
2. 分段优化阶段
┌─────────────┐ ┌──────────────────┐ ┌──────────────┐
│ PDFDocument │ ──▶ │ AcademicSegment │ ──▶ │ Optimized │
│ (原始) │ │ Strategy │ │ Segments │
└─────────────┘ └──────────────────┘ └──────────────┘
│
├─ 章节识别
├─ Token估算
├─ 智能分段 (3000 tokens)
└─ 上下文添加 (200 tokens重叠)
3. 翻译阶段
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Optimized │ ──▶ │ QwenApiClient │ ──▶ │ Translated │
│ Segments │ │ │ │ Segments │
└──────────────┘ └──────────────┘ └──────────────┘
│
├─ 构建Prompt
├─ 调用API
├─ 重试机制 (指数退避)
└─ 结果解析
4. 格式化输出
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Translated │ ──▶ │ Markdown │ ──▶ │ .md File │
│ Segments │ │ Formatter │ │ (输出) │
└──────────────┘ └──────────────┘ └──────────────┘
│
├─ 标题层级处理
├─ 段落格式化
└─ 元数据添加
- AITranslationApplication: 应用程序主入口,协调整体流程
- PDFExtractorService: PDF文本提取和结构识别
- TranslationService: 翻译流程编排
- AcademicSegmentStrategy: 学术论文智能分段策略
- MarkdownFormatter: Markdown格式化输出
- QwenApiClient: 通义千问API客户端封装
- AppConfig: 应用配置管理
- TranslationConfig: 翻译配置管理
- PDFDocument: PDF文档模型
- TextSegment: 文本分段模型
- TranslationResult: 翻译结果模型
- 异常处理: PDFProcessException, TranslationException, ConfigurationException
- 日志系统: SLF4J + Logback
- 工具类: 文本处理、重试机制等
输入: PDF原始文本段落
│
├─ 识别章节结构 (Abstract, Introduction, etc.)
│ │
│ ├─ 正则匹配常见章节标题
│ ├─ 识别编号章节 (1., 1.1, etc.)
│ └─ 判断文本类型 (标题/段落/引用)
│
├─ Token估算
│ │
│ ├─ 英文: ~4字符/token
│ ├─ 中文: ~1.5字符/token
│ └─ 数字: ~4字符/token
│
├─ 分段处理
│ │
│ ├─ 限制: 3000 tokens/段
│ ├─ 重叠: 200 tokens上下文
│ └─ 特殊处理: 标题独立分段
│
└─ 输出: 优化后的分段列表
// 角色设定
You are a professional academic translator.
// 上下文信息
Context: [前后段落摘要]
// 文本类型
Text Type: PARAGRAPH/SECTION/TITLE/...
// 待翻译文本
Text to translate:[原始文本]
// 翻译要求
Requirements:
1. Maintain academic writing style
2. Preserve structure and formatting
3. Keep technical terms in English when appropriate
4. Ensure accuracy and fluency
5. Keep formulas in LaTeX format
API调用失败
│
├─ 判断是否可重试
│ │
│ ├─ 网络错误 → 可重试
│ ├─ 超时错误 → 可重试
│ ├─ 限流错误 → 可重试
│ └─ 其他错误 → 不可重试
│
├─ 可重试
│ │
│ ├─ 第1次重试: 延迟 2s
│ ├─ 第2次重试: 延迟 4s
│ └─ 第3次重试: 延迟 8s
│
└─ 仍失败 → 记录错误,继续下一段
获取API密钥
访问阿里云百炼平台:
- 注册/登录阿里云账号
- 开通通义千问服务
- 创建API-KEY
- 充值(按需付费)
配置环境变量
# 编辑配置文件
vim ~/.zshrc
# 添加以下内容
export QWEN_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxx"
# 重新加载配置
source ~/.zshrc
# 验证配置
echo $QWEN_API_KEY# 进入项目目录
cd /path/to/aitranslation
# 方式1: 标准编译(包含测试)
mvn clean package
# 方式2: 跳过测试快速编译
mvn clean package -DskipTests
# 方式3: 仅编译不打包
mvn clean compile
# 方式4: 清理构建缓存
mvn clean编译说明
Maven会自动完成以下步骤:
- 下载依赖包(首次运行时)
- 编译Java源代码
- 运行测试(如果未使用-DskipTests)
- 打包成可执行JAR文件
- 生成依赖项(dependency-reduced-pom.xml)
编译产物
编译成功后会在 target/ 目录生成以下文件:
target/
├── aitranslation-1.0-SNAPSHOT.jar # 主JAR包(包含所有依赖,可直接运行)
├── original-aitranslation-1.0-SNAPSHOT.jar # 原始JAR包(不含依赖)
├── classes/ # 编译后的类文件
├── generated-sources/ # 生成的源代码
└── maven-status/ # Maven状态信息
验证编译
# 查看JAR包信息
java -jar target/aitranslation-1.0-SNAPSHOT.jar --version 2>/dev/null || echo "JAR已成功构建"
# 查看JAR包内容
jar tf target/aitranslation-1.0-SNAPSHOT.jar | head -20
# 查看JAR包大小
ls -lh target/aitranslation-1.0-SNAPSHOT.jar常见编译问题
如果编译失败,请检查:
- Java版本是否为17或更高:
java -version - Maven版本是否为3.6+:
mvn -version - 网络连接是否正常(需下载依赖)
- 本地Maven仓库是否有权限:
~/.m2/repository
将您要翻译的PDF文件放在任意位置,记下文件路径。
# 通过命令行参数指定PDF文件(推荐)
java -jar target/aitranslation-1.0-SNAPSHOT.jar /path/to/your-paper.pdf
# 或通过环境变量指定
export PDF_FILE_PATH="/path/to/your-paper.pdf"
java -jar target/aitranslation-1.0-SNAPSHOT.jar
# 查看输出
# 翻译结果: output/your-paper_translated.md
# 日志文件: logs/translation.log, logs/error.log完整配置示例
# 必填配置
export QWEN_API_KEY="sk-your-api-key-here"
# 模型配置
export QWEN_MODEL="qwen3-max" # qwen3-max, qwen-plus, qwen-turbo
export QWEN_MAX_TOKENS="4000" # 每次请求最大token数
export QWEN_TEMPERATURE="0.3" # 温度参数 (0-2, 越低越确定性)
export QWEN_MAX_RETRIES="3" # 最大重试次数
# 分段配置
export SEGMENT_TOKEN_LIMIT="3000" # 分段token限制
export SEGMENT_OVERLAP_TOKENS="200" # 段落重叠token数
# 输出配置
export OUTPUT_DIRECTORY="./output" # 输出目录
# 运行
java -jar target/aitranslation-1.0-SNAPSHOT.jar快速配置脚本
创建 run.sh:
#!/bin/bash
# 设置API密钥
export QWEN_API_KEY="sk-your-api-key-here"
# 模型选择 (根据需求选择)
export QWEN_MODEL="qwen3-max" # 最高质量,较慢
# export QWEN_MODEL="qwen-plus" # 平衡质量和速度
# export QWEN_MODEL="qwen-turbo" # 最快,质量略低
# 分段配置
export SEGMENT_TOKEN_LIMIT="3000"
export SEGMENT_OVERLAP_TOKENS="200"
# 运行翻译
java -jar target/aitranslation-1.0-SNAPSHOT.jar "$@"使用:
chmod +x run.sh
./run.sh针对不同文档类型的配置
# 短文档 (< 10页)
export SEGMENT_TOKEN_LIMIT="5000" # 较大分段,减少API调用
export QWEN_MODEL="qwen3-max" # 使用高质量模型
# 长文档 (> 50页)
export SEGMENT_TOKEN_LIMIT="2000" # 较小分段,提高并行度
export QWEN_MODEL="qwen-plus" # 使用较快模型
# 包含大量公式的论文
export QWEN_TEMPERATURE="0.1" # 降低温度,提高公式准确性
export SEGMENT_OVERLAP_TOKENS="300" # 增加重叠,保持上下文虽然当前版本主要通过环境变量配置,但可以扩展支持命令行参数:
# 示例:未来可支持的命令行参数
java -jar target/aitranslation-1.0-SNAPSHOT.jar \
--input papers/sample.pdf \
--output output/sample_translated.md \
--model qwen3-max \
--temperature 0.3 \
--segment-limit 3000如果需要翻译多个PDF,可以创建批处理脚本:
batch_translate.sh
#!/bin/bash
# API配置
export QWEN_API_KEY="sk-your-api-key-here"
export QWEN_MODEL="qwen3-max"
# PDF文件目录
PDF_DIR="./papers"
OUTPUT_DIR="./output"
# 创建输出目录
mkdir -p "$OUTPUT_DIR"
mkdir -p "logs"
# 遍历所有PDF文件
for pdf in "$PDF_DIR"/*.pdf; do
if [ -f "$pdf" ]; then
filename=$(basename "$pdf" .pdf)
echo "========================================="
echo "Translating: $filename"
echo "========================================="
# 通过命令行参数运行翻译
java -jar target/aitranslation-1.0-SNAPSHOT.jar "$pdf"
echo "Completed: $filename"
echo ""
fi
done
echo "All translations completed!"创建 Dockerfile:
FROM openjdk:17-slim
# 设置工作目录
WORKDIR /app
# 复制JAR文件
COPY target/aitranslation-1.0-SNAPSHOT.jar /app/translator.jar
# 创建输出目录
RUN mkdir -p /app/output /app/logs
# 设置环境变量
ENV QWEN_API_KEY=""
ENV QWEN_MODEL="qwen3-max"
ENV OUTPUT_DIRECTORY="/app/output"
# 运行应用
ENTRYPOINT ["java", "-jar", "translator.jar"]使用:
# 构建镜像
docker build -t pdf-translator .
# 运行容器
docker run -v $(pwd)/papers:/app/papers \
-v $(pwd)/output:/app/output \
-e QWEN_API_KEY="sk-your-key" \
pdf-translatorsrc/main/java/org/wstt/aitranslation/
├── AITranslationApplication.java # 主程序入口
├── config/ # 配置类
│ ├── AppConfig.java # 应用配置(API、模型等)
│ └── TranslationConfig.java # 翻译配置(分段策略等)
├── model/ # 数据模型
│ ├── PDFDocument.java # PDF文档模型
│ ├── TextSegment.java # 文本分段模型
│ └── TranslationResult.java # 翻译结果模型
├── service/ # 业务服务
│ ├── PDFExtractorService.java # PDF提取服务
│ ├── TranslationService.java # 翻译编排服务
│ ├── SegmentStrategy.java # 分段策略接口
│ ├── AcademicSegmentStrategy.java # 学术论文分段实现
│ └── MarkdownFormatter.java # Markdown格式化服务
├── client/ # API客户端
│ └── QwenApiClient.java # 通义千问API客户端
└── exception/ # 异常类
├── PDFProcessException.java # PDF处理异常
├── TranslationException.java # 翻译异常
└── ConfigurationException.java # 配置异常
aitranslation/
├── pom.xml # Maven配置文件
├── README.md # 项目文档
├── .gitignore # Git忽略文件
├── src/
│ ├── main/
│ │ ├── java/ # Java源代码
│ │ └── resources/ # 资源文件
│ │ └── logback.xml # 日志配置
│ └── test/ # 测试代码
├── target/ # 编译输出
│ ├── aitranslation-1.0-SNAPSHOT.jar # 可执行JAR
│ └── classes/ # 编译后的类文件
├── output/ # 翻译结果输出目录
└── logs/ # 日志目录
├── translation.log # 完整日志
└── error.log # 错误日志
| 技术 | 版本 | 用途 |
|---|---|---|
| Java | 17 | 编程语言 |
| Maven | 3.6+ | 项目构建和依赖管理 |
| Apache PDFBox | 3.0.1 | PDF文本提取和解析 |
| Dashscope SDK | 2.16.4 | 通义千问API官方SDK |
| SLF4J | 2.0.9 | 日志门面 |
| Logback | 1.4.14 | 日志实现 |
| Jackson | 2.16.1 | JSON处理 |
| SnakeYAML | 2.2 | YAML配置解析 |
| Apache Commons Lang3 | 3.14.0 | 工具类库 |
- 分层架构: 表示层、业务层、数据层、基础设施层清晰分离
- 策略模式: 分段策略可扩展,支持不同文档类型
- 依赖注入: 通过构造函数注入依赖,便于测试
- 异常处理: 自定义异常体系,统一的错误处理
- 日志系统: 分级日志,文件和控制台双输出
- 配置管理: 支持环境变量和默认值,灵活配置
翻译后的Markdown文档包含:
- 一级标题:文档标题
- 二级标题:主要章节(Abstract, Introduction等)
- 三级标题:子章节
- 普通段落:翻译后的正文
- 元数据:作者、标题等信息
- API费用: 使用通义千问API会产生费用,请注意控制使用量
- Token限制: qwen-max模型最大支持30k tokens,分段策略已优化
- 翻译质量: 学术论文翻译质量取决于模型能力,建议人工校对
- ARM64兼容: 项目已针对ARM64架构优化,完全兼容Apple Silicon
- 全中文输出: 所有日志信息使用中文显示,易于理解
- 精简类名: 只显示类名(如
AITranslationApplication),不显示完整包路径 - 分级日志: INFO、DEBUG、WARN、ERROR 四个级别
- 多端输出: 控制台实时显示 + 文件持久化存储
- 颜色标识: 控制台输出使用不同颜色区分日志级别
{时间戳} [{线程名}] {级别} {类名} - {消息}
示例:
20:00:00.123 [main] INFO AITranslationApplication - 步骤 1/6: 正在加载配置...
20:00:01.456 [main] INFO TranslationService - 开始翻译文档: paper.pdf,共 86 个分段
程序运行时会在以下位置生成日志:
| 日志文件 | 说明 | 级别 |
|---|---|---|
| 控制台输出 | 实时日志,带颜色标识 | INFO及以上 |
logs/translation.log |
完整日志,包含调试信息 | DEBUG |
logs/error.log |
仅错误日志 | ERROR |
# 实时查看完整日志
tail -f logs/translation.log
# 查看错误日志
cat logs/error.log
# 查看最近100行日志
tail -n 100 logs/translation.log翻译完成后会显示以下统计信息:
| 指标 | 说明 |
|---|---|
| 总分段数 | 优化后的分段总数 |
| 已翻译 | 成功翻译的分段数 |
| 失败 | 翻译失败的分段数 |
| 成功率 | 翻译成功率百分比 |
| 原文字符数 | PDF中提取的英文字符总数 |
| 译文字符数 | 翻译后的中文字符总数(不含空格) |
| 耗时 | 总翻译时间(秒) |
详细日志输出示例请查看: LOG_OUTPUT_SAMPLE.md
A: 三种方式:
- 命令行参数(推荐):
java -jar target/aitranslation-1.0-SNAPSHOT.jar /path/to/paper.pdf - 环境变量:
export PDF_FILE_PATH="/path/to/paper.pdf" - 默认文件:将PDF放入
src/main/resources/目录
详细说明请查看:PDF_USAGE.md
A: 检查:
- API密钥是否正确设置
- 网络连接是否正常
- API账户是否有足够余额
- 查看
logs/error.log获取详细错误信息
A: 可以考虑:
- 使用更快的模型(如qwen-plus)
- 减小segment token限制以支持并行翻译
- 升级网络连接
mvn testmvn cleanmvn compileMIT License
欢迎提交Issue和Pull Request!
- PDF_USAGE.md - PDF文件路径指定完整指南
- LOG_OUTPUT_SAMPLE.md - 日志输出格式和示例