【文献翻译】关于文献翻译的思考以及简单的工作流程

2026-04-11 14:001阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐
问题描述:

这两天一直在思考怎么将PDF英文文献翻译成好理解、好阅读、好查阅的中文形式,研究了一下将整个流程整理一下。

总体流程

对于一个PDF,直接对译为中文PDF在很多时候是不合适的,主要问题在于中英文表述相同意义下的字数不同,以及对公式处理不佳。考虑这一点,找到一个合适的中间格式来转可能更好。

显然markdown完美符合这个中间格式的要求,换句话说我们第一步就要将PDF转成markdown,然后因为markdown纯文本的格式,直接按段落分丢给LLM翻译就行了

而且markdown本身就有极佳的可读性,也可以借助mdbook等SSG工具转换成网页从而在各个端都能访问阅读

用流程图描述就是这样

graph LR Start[原始 PDF 文件] --> CoreProcess subgraph CoreProcess [核心处理流程] direction LR Step1[PDF 转换为 Markdown] Step2[按段落分割纯文本,调用 LLM 进行翻译] Result[中文 Markdown 文件] Step1 --> Step2 --> Result end CoreProcess --> Final[生成网页, 实现多端访问]

PDF 2 MD

那么第一问题来了,怎么将PDF转换为md

考虑到公式、表格、图片三个要素的存在,转换方式一定是要完美保持这三个东西的,这个可以借助一些专门的OCR模型来做

我试了好几个,最后选择的是MonkeyOCR,相较于Deepseek OCR、PaddleVL OCR等几个模型,这个主要的好处是不费劲,速度和效果和Deepseek OCR差不多,比PaddleVL OCR好配置。

但是本地用这些OCR模型对显存的要求还是蛮高的,尽管模型本身只有3B参数,但是实际上跑下来大概需要12-16G显存才能运行,我使用一块V100才勉强压下来

但是也有其他方式来进行PDF转换,不少OCR提供商都有DEMO or 官方网站来进行转换,比如:dots.ocr,MinerU.

我用dots.ocr为例,上传文献之后就可以直接得到OCR后的结果,下载即可

dots.ocr DEMO1904×1710 523 KB

下载后解压完得到如下的文件:

结果803×345 23.6 KB

自己拼接一下就行了,可以人工来做或者用Codex之类的vibe一个小脚本,甚至直接让Codex给你拼接也行

en 2 zh

其实转MD是最麻烦的一步,后面都好搞,翻译用LLM来做就行,整体思路就是分段然后一段段丢给大模型

比如10自然段为一个整体,每次翻译后写入文本,然后叠起来

用Codex Vibe了一个脚本(pwsh)

param( [Parameter(Mandatory = $true)] [Alias("i")] [string]$InFile, [Parameter(Mandatory = $true)] [Alias("o")] [string]$Output, [Alias("b")] [int]$BatchSize = 10 ) $ErrorActionPreference = "Stop" function Load-DotEnv { param( [string]$Path = ".env" ) if (-not (Test-Path -Path $Path -PathType Leaf)) { Write-Host "Warning: .env file not found, relying on system environment variables" return } Get-Content -Path $Path | ForEach-Object { $line = $_.Trim() if ([string]::IsNullOrWhiteSpace($line)) { return } if ($line.StartsWith("#")) { return } $idx = $line.IndexOf("=") if ($idx -lt 1) { return } $key = $line.Substring(0, $idx).Trim() $value = $line.Substring($idx + 1).Trim() if (-not [string]::IsNullOrWhiteSpace($key)) { [System.Environment]::SetEnvironmentVariable($key, $value, "Process") } } } function Split-IntoParagraphs { param( [string]$Text ) # 统一换行符为 `\n` $normalized = $Text -replace "`r`n", "`n" # 按两个换行拆分 $rawParagraphs = $normalized -split "`n`n" $paragraphs = @() foreach ($p in $rawParagraphs) { $trimmed = $p.Trim() if (-not [string]::IsNullOrWhiteSpace($trimmed)) { $paragraphs += $trimmed } } return ,$paragraphs } function Initialize-OutputFile { param( [string]$OutputPath ) # 创建或截断输出文件 [System.IO.File]::Create($OutputPath).Dispose() } function Append-TranslationBatch { param( [string]$TranslatedBatch, [string]$OutputPath ) # 统一将批次中的换行符规范为 CRLF $normalized = $TranslatedBatch.Replace("`r`n", "`n").Replace("`n", "`r`n") # 末尾加两个 CRLF 分隔批次 Add-Content -Path $OutputPath -Value ($normalized + "`r`n`r`n") } function Translate-Text { param( [string]$Text, [string]$Model, [string]$BaseUrl, [string]$ApiKey ) # 系统提示:说明翻译要求 $systemPrompt = @" 你是一个专业的翻译助手,请将英文文本翻译成中文。保持原文的技术术语和格式不变,只翻译自然语言部分。翻译对象是markdown格式,如果有不符合md格式(比如代码块没有用对应的格式)的请你修正,英文的参考文献请保持不翻译,你只能输出翻译后的文本,不能输出其他内容。 "@ $userPrompt = "请翻译以下英文文本为中文:`n`n$Text" $body = @{ model = $Model temperature = 0.3 max_tokens = 8000 messages = @( @{ role = "system" content = $systemPrompt }, @{ role = "user" content = $userPrompt } ) } $uri = ($BaseUrl.TrimEnd("/") + "/chat/completions") try { $response = Invoke-RestMethod ` -Method Post ` -Uri $uri ` -Headers @{ Authorization = "Bearer $ApiKey" } ` -ContentType "application/json" ` -Body ($body | ConvertTo-Json -Depth 10) ` -TimeoutSec (5 * 60) } catch { throw "API request failed: $($_.Exception.Message)" } if (-not $response -or -not $response.choices -or $response.choices.Count -eq 0) { throw "received empty response from API" } $content = $response.choices[0].message.content if (-not $content) { throw "API response does not contain message.content" } return $content.Trim() } try { # 1. 加载 .env(若存在) Load-DotEnv $apiKey = $env:TR_API_KEY $baseUrl = $env:TR_API_BASE_URL $model = $env:TR_MODEL if ([string]::IsNullOrWhiteSpace($apiKey) -or [string]::IsNullOrWhiteSpace($baseUrl) -or [string]::IsNullOrWhiteSpace($model)) { Write-Error "error: TR_API_KEY, TR_API_BASE_URL, and TR_MODEL must be set in .env or environment" exit 1 } Write-Host "Input file: $InFile" Write-Host "Output file: $Output" Write-Host "Batch size: $BatchSize" # 2. 读取输入文件 Write-Host "Reading file..." if (-not (Test-Path -Path $InFile -PathType Leaf)) { Write-Error ("error reading input file {0}: file not found" -f $InFile) exit 1 } $content = Get-Content -Path $InFile -Raw # 3. 切分段落 Write-Host "Splitting into paragraphs..." $paragraphs = Split-IntoParagraphs -Text $content $paragraphCount = $paragraphs.Count Write-Host "Found $paragraphCount paragraphs" # 4. 初始化输出文件 Initialize-OutputFile -OutputPath $Output if ($paragraphCount -eq 0) { Write-Host "No paragraphs found, nothing to translate." exit 0 } # 5. 批量调用 API $successfulBatches = 0 $totalBatches = [int][math]::Ceiling($paragraphCount / [double]$BatchSize) for ($i = 0; $i -lt $paragraphCount; $i += $BatchSize) { $end = [math]::Min($i + $BatchSize, $paragraphCount) $batchNum = [int]([math]::Floor($i / $BatchSize) + 1) $range = $i..($end - 1) $batch = $paragraphs[$range] Write-Host ("Translating batch {0}/{1} (paragraphs {2}-{3})..." -f ` $batchNum, $totalBatches, ($i + 1), $end) $batchText = $batch -join "`n`n" # 翻译请求,失败时等待 30 秒重试一次 $maxAttempts = 2 $attempt = 1 $translatedBatch = $null $translateSuccess = $false while (-not $translateSuccess -and $attempt -le $maxAttempts) { try { $translatedBatch = Translate-Text -Text $batchText -Model $model -BaseUrl $baseUrl -ApiKey $apiKey $translateSuccess = $true } catch { if ($attempt -lt $maxAttempts) { Write-Warning ("Error translating batch {0} (attempt {1}/{2}): {3}. Retrying after 30 seconds..." -f ` $batchNum, $attempt, $maxAttempts, $_.Exception.Message) Start-Sleep -Seconds 30 $attempt++ } else { Write-Warning ("Error translating batch {0} (attempt {1}/{2}): {3}. Skipping." -f ` $batchNum, $attempt, $maxAttempts, $_.Exception.Message) break } } } if (-not $translateSuccess) { continue } try { Append-TranslationBatch -TranslatedBatch $translatedBatch -OutputPath $Output $successfulBatches++ Write-Host "Batch $batchNum translated and written to file." } catch { Write-Warning "Error writing batch $batchNum to file: $($_.Exception.Message). Skipping." continue } } # 6. 总结 if ($successfulBatches -gt 0) { Write-Host "" Write-Host "Translation complete! Successfully translated $successfulBatches/$totalBatches batches." Write-Host "Result saved to $Output" } else { Write-Host "" Write-Host "Translation failed. Please check your API key, network connection, and error logs." } exit 0 } catch { Write-Error $_.Exception.Message exit 1 }

需要在同文件夹下放置一个.env,记录

TR_API_KEY=xxx TR_API_BASE_URL=https://xxxxxxxx/v1 TR_MODEL=xxx

然后

./translator.ps1 -i <input> -o <output> -b <batch>

即可

关于翻译用的模型,建议使用指令模型而不是思考模型,这个地方盲目的用GPT、Gemini效果未必比国产模型好,就我个人的体感来说,比较建议Qwen 3.5 Plus、Qwen 3 Max或者Kimi K2 0905,相较于GPT 5.4、Gemini 3.1效果不差

利用MarkText、Typora、VS Code等工具可以将MD转换为PDF

MD 2 Page

这个就我本人来说不是很想细说,佬友们应该有不少md转换为blog的思路,也有很多现成的工具,例如mdbook、astro、hugo、hexo、vitepress、jekyll等等等,然后利用netlify、vercel、cf page、gh page等等静态网站托管服务跑起来即可

End

以上是我目前走文献翻译的流程,希望能够给大家参考

网友解答:
--【壹】--:

当然是批量翻译,一百多万份pdf用mineru两周跑完上传到oss,然后再进行清洗、提取数据。如果全交给AI成本太高了


--【贰】--:

感谢分享,


--【叁】--: tutu_pink:

PDF2zh

感觉PDF2zh就不错,一直在用


--【肆】--:

感谢分享


--【伍】--:

佬友有没有试过这个幻觉翻译,作者是知乎的,他用的方案好像是转latex,我自己用下来感觉显示效果很不错:https://hjfy.top/


--【陆】--:

我也在用MATH,感觉还是得用API以及绕不开的清洗。


--【柒】--:

很有帮助


--【捌】--:

这个主要还是看什么类型的pdf。不过mineru出现脑补的情况没遇到过。我这边实际调研用起来doc2x和mineru不相上下,mineru免费当然是不二之选。doc2x也只适合少量的任务,不管是成本还是速度都不如mineru


--【玖】--:

是这样的,市面上大部分转换方案都没有比较完美的。主要是不规则的表格以及各种公式。所以需要根据工具和个人需求来清洗、修复文档。


--【拾】--:

如果文献有上传到 arXiv 的话,可以下载 TeX 源码后让 AI 翻译源码然后编译 PDF,效果非常完美。


--【拾壹】--: cc:

mineru

看你的需求是批量翻译还是一份翻译了。如果是一份翻译的话,我们就把 PDF 文件直接丢给多模态的 AI 模型,比如说比较强劲的,一定是要国内性能比较好的,比如说 gemini 然后你直接把文件丢给他。 它就会自动,你就告诉它,你自动识别文件内容和排版,然后重新整理翻译后返回。你如果想让它返回 Markdown 的话,就返回 Markdown 如果想让它返回 Word 的话,就直接告诉它基于 Python 来对这个文件进行排版,生成 Word。
如果是批量翻译的话,没得选,就只能是。 mineru 它的免费额额度还是很给力的,好像每天 2000 页,还是每个月 2000 页来着。


--【拾贰】--:

我自己用的感觉不如doc2X

mineru有时候会自己脑补


--【拾叁】--:

1、pdf转md文档首选必须是mineru,试过市面上免费的和付费的(国外的没试过)工具都没有这个转换出来的效果好。无论是数学公式还是表格方面,都很不错。
2、转换md文档之后还需要清洗文档,比如某些公式、表格还是有问题
3、翻译文本的时候不能单纯按段落分割,最好是使用DeepSeek和gemini这种上下文大的,一定要结合上下文翻译,不然中英文互译涉及专业术语会有问题
4、翻译的提示词要反复优化,不同类型的pdf文档来区分,这样翻译效果会更好,专业性更强

做pdf中英文互译基本踩过坑,还有别的不足佬友们可以指点一下


--【拾肆】--:

感谢指导!

确实,mineru 2.5的质量非常之高,不仅仅是模型本身,mineru的工作流设计在开源方案里是比较好的一档,但是自己部署OCR模型的话mineru的工作流相较于MonkeyOCR和DeepseekOCR的工作流有点难改(但是相较于paddle就好搞多了),我平时读的文献有一部分是需要自己改一下layout识别模型的参数的,比较简单的工作流好改一点

清洗文档有点疼,很多OCR模型总会搞一点有自己特点的输出,尤其是跨页代码的情况下,比如MonkeyOCR 3B Pro有时候会输出连续百个w,Mineru有时会不解析表格中的公式

至于直接喂整体上下文在有些情况下有点贵,同时考虑到国内用国外模型很多都带着一些上下文产生污染,可以走一些别的路子,比如利用GalTransl这样工具提取一个术语表带在上下文里

不过我主要是用来翻译后读文献的,十几页的文献我觉得这样足够了,毕竟主要目的是能读懂文献而不是做翻译


--【拾伍】--:

PDF2zh这个我感觉挺好用的

标签:人工智能
问题描述:

这两天一直在思考怎么将PDF英文文献翻译成好理解、好阅读、好查阅的中文形式,研究了一下将整个流程整理一下。

总体流程

对于一个PDF,直接对译为中文PDF在很多时候是不合适的,主要问题在于中英文表述相同意义下的字数不同,以及对公式处理不佳。考虑这一点,找到一个合适的中间格式来转可能更好。

显然markdown完美符合这个中间格式的要求,换句话说我们第一步就要将PDF转成markdown,然后因为markdown纯文本的格式,直接按段落分丢给LLM翻译就行了

而且markdown本身就有极佳的可读性,也可以借助mdbook等SSG工具转换成网页从而在各个端都能访问阅读

用流程图描述就是这样

graph LR Start[原始 PDF 文件] --> CoreProcess subgraph CoreProcess [核心处理流程] direction LR Step1[PDF 转换为 Markdown] Step2[按段落分割纯文本,调用 LLM 进行翻译] Result[中文 Markdown 文件] Step1 --> Step2 --> Result end CoreProcess --> Final[生成网页, 实现多端访问]

PDF 2 MD

那么第一问题来了,怎么将PDF转换为md

考虑到公式、表格、图片三个要素的存在,转换方式一定是要完美保持这三个东西的,这个可以借助一些专门的OCR模型来做

我试了好几个,最后选择的是MonkeyOCR,相较于Deepseek OCR、PaddleVL OCR等几个模型,这个主要的好处是不费劲,速度和效果和Deepseek OCR差不多,比PaddleVL OCR好配置。

但是本地用这些OCR模型对显存的要求还是蛮高的,尽管模型本身只有3B参数,但是实际上跑下来大概需要12-16G显存才能运行,我使用一块V100才勉强压下来

但是也有其他方式来进行PDF转换,不少OCR提供商都有DEMO or 官方网站来进行转换,比如:dots.ocr,MinerU.

我用dots.ocr为例,上传文献之后就可以直接得到OCR后的结果,下载即可

dots.ocr DEMO1904×1710 523 KB

下载后解压完得到如下的文件:

结果803×345 23.6 KB

自己拼接一下就行了,可以人工来做或者用Codex之类的vibe一个小脚本,甚至直接让Codex给你拼接也行

en 2 zh

其实转MD是最麻烦的一步,后面都好搞,翻译用LLM来做就行,整体思路就是分段然后一段段丢给大模型

比如10自然段为一个整体,每次翻译后写入文本,然后叠起来

用Codex Vibe了一个脚本(pwsh)

param( [Parameter(Mandatory = $true)] [Alias("i")] [string]$InFile, [Parameter(Mandatory = $true)] [Alias("o")] [string]$Output, [Alias("b")] [int]$BatchSize = 10 ) $ErrorActionPreference = "Stop" function Load-DotEnv { param( [string]$Path = ".env" ) if (-not (Test-Path -Path $Path -PathType Leaf)) { Write-Host "Warning: .env file not found, relying on system environment variables" return } Get-Content -Path $Path | ForEach-Object { $line = $_.Trim() if ([string]::IsNullOrWhiteSpace($line)) { return } if ($line.StartsWith("#")) { return } $idx = $line.IndexOf("=") if ($idx -lt 1) { return } $key = $line.Substring(0, $idx).Trim() $value = $line.Substring($idx + 1).Trim() if (-not [string]::IsNullOrWhiteSpace($key)) { [System.Environment]::SetEnvironmentVariable($key, $value, "Process") } } } function Split-IntoParagraphs { param( [string]$Text ) # 统一换行符为 `\n` $normalized = $Text -replace "`r`n", "`n" # 按两个换行拆分 $rawParagraphs = $normalized -split "`n`n" $paragraphs = @() foreach ($p in $rawParagraphs) { $trimmed = $p.Trim() if (-not [string]::IsNullOrWhiteSpace($trimmed)) { $paragraphs += $trimmed } } return ,$paragraphs } function Initialize-OutputFile { param( [string]$OutputPath ) # 创建或截断输出文件 [System.IO.File]::Create($OutputPath).Dispose() } function Append-TranslationBatch { param( [string]$TranslatedBatch, [string]$OutputPath ) # 统一将批次中的换行符规范为 CRLF $normalized = $TranslatedBatch.Replace("`r`n", "`n").Replace("`n", "`r`n") # 末尾加两个 CRLF 分隔批次 Add-Content -Path $OutputPath -Value ($normalized + "`r`n`r`n") } function Translate-Text { param( [string]$Text, [string]$Model, [string]$BaseUrl, [string]$ApiKey ) # 系统提示:说明翻译要求 $systemPrompt = @" 你是一个专业的翻译助手,请将英文文本翻译成中文。保持原文的技术术语和格式不变,只翻译自然语言部分。翻译对象是markdown格式,如果有不符合md格式(比如代码块没有用对应的格式)的请你修正,英文的参考文献请保持不翻译,你只能输出翻译后的文本,不能输出其他内容。 "@ $userPrompt = "请翻译以下英文文本为中文:`n`n$Text" $body = @{ model = $Model temperature = 0.3 max_tokens = 8000 messages = @( @{ role = "system" content = $systemPrompt }, @{ role = "user" content = $userPrompt } ) } $uri = ($BaseUrl.TrimEnd("/") + "/chat/completions") try { $response = Invoke-RestMethod ` -Method Post ` -Uri $uri ` -Headers @{ Authorization = "Bearer $ApiKey" } ` -ContentType "application/json" ` -Body ($body | ConvertTo-Json -Depth 10) ` -TimeoutSec (5 * 60) } catch { throw "API request failed: $($_.Exception.Message)" } if (-not $response -or -not $response.choices -or $response.choices.Count -eq 0) { throw "received empty response from API" } $content = $response.choices[0].message.content if (-not $content) { throw "API response does not contain message.content" } return $content.Trim() } try { # 1. 加载 .env(若存在) Load-DotEnv $apiKey = $env:TR_API_KEY $baseUrl = $env:TR_API_BASE_URL $model = $env:TR_MODEL if ([string]::IsNullOrWhiteSpace($apiKey) -or [string]::IsNullOrWhiteSpace($baseUrl) -or [string]::IsNullOrWhiteSpace($model)) { Write-Error "error: TR_API_KEY, TR_API_BASE_URL, and TR_MODEL must be set in .env or environment" exit 1 } Write-Host "Input file: $InFile" Write-Host "Output file: $Output" Write-Host "Batch size: $BatchSize" # 2. 读取输入文件 Write-Host "Reading file..." if (-not (Test-Path -Path $InFile -PathType Leaf)) { Write-Error ("error reading input file {0}: file not found" -f $InFile) exit 1 } $content = Get-Content -Path $InFile -Raw # 3. 切分段落 Write-Host "Splitting into paragraphs..." $paragraphs = Split-IntoParagraphs -Text $content $paragraphCount = $paragraphs.Count Write-Host "Found $paragraphCount paragraphs" # 4. 初始化输出文件 Initialize-OutputFile -OutputPath $Output if ($paragraphCount -eq 0) { Write-Host "No paragraphs found, nothing to translate." exit 0 } # 5. 批量调用 API $successfulBatches = 0 $totalBatches = [int][math]::Ceiling($paragraphCount / [double]$BatchSize) for ($i = 0; $i -lt $paragraphCount; $i += $BatchSize) { $end = [math]::Min($i + $BatchSize, $paragraphCount) $batchNum = [int]([math]::Floor($i / $BatchSize) + 1) $range = $i..($end - 1) $batch = $paragraphs[$range] Write-Host ("Translating batch {0}/{1} (paragraphs {2}-{3})..." -f ` $batchNum, $totalBatches, ($i + 1), $end) $batchText = $batch -join "`n`n" # 翻译请求,失败时等待 30 秒重试一次 $maxAttempts = 2 $attempt = 1 $translatedBatch = $null $translateSuccess = $false while (-not $translateSuccess -and $attempt -le $maxAttempts) { try { $translatedBatch = Translate-Text -Text $batchText -Model $model -BaseUrl $baseUrl -ApiKey $apiKey $translateSuccess = $true } catch { if ($attempt -lt $maxAttempts) { Write-Warning ("Error translating batch {0} (attempt {1}/{2}): {3}. Retrying after 30 seconds..." -f ` $batchNum, $attempt, $maxAttempts, $_.Exception.Message) Start-Sleep -Seconds 30 $attempt++ } else { Write-Warning ("Error translating batch {0} (attempt {1}/{2}): {3}. Skipping." -f ` $batchNum, $attempt, $maxAttempts, $_.Exception.Message) break } } } if (-not $translateSuccess) { continue } try { Append-TranslationBatch -TranslatedBatch $translatedBatch -OutputPath $Output $successfulBatches++ Write-Host "Batch $batchNum translated and written to file." } catch { Write-Warning "Error writing batch $batchNum to file: $($_.Exception.Message). Skipping." continue } } # 6. 总结 if ($successfulBatches -gt 0) { Write-Host "" Write-Host "Translation complete! Successfully translated $successfulBatches/$totalBatches batches." Write-Host "Result saved to $Output" } else { Write-Host "" Write-Host "Translation failed. Please check your API key, network connection, and error logs." } exit 0 } catch { Write-Error $_.Exception.Message exit 1 }

需要在同文件夹下放置一个.env,记录

TR_API_KEY=xxx TR_API_BASE_URL=https://xxxxxxxx/v1 TR_MODEL=xxx

然后

./translator.ps1 -i <input> -o <output> -b <batch>

即可

关于翻译用的模型,建议使用指令模型而不是思考模型,这个地方盲目的用GPT、Gemini效果未必比国产模型好,就我个人的体感来说,比较建议Qwen 3.5 Plus、Qwen 3 Max或者Kimi K2 0905,相较于GPT 5.4、Gemini 3.1效果不差

利用MarkText、Typora、VS Code等工具可以将MD转换为PDF

MD 2 Page

这个就我本人来说不是很想细说,佬友们应该有不少md转换为blog的思路,也有很多现成的工具,例如mdbook、astro、hugo、hexo、vitepress、jekyll等等等,然后利用netlify、vercel、cf page、gh page等等静态网站托管服务跑起来即可

End

以上是我目前走文献翻译的流程,希望能够给大家参考

网友解答:
--【壹】--:

当然是批量翻译,一百多万份pdf用mineru两周跑完上传到oss,然后再进行清洗、提取数据。如果全交给AI成本太高了


--【贰】--:

感谢分享,


--【叁】--: tutu_pink:

PDF2zh

感觉PDF2zh就不错,一直在用


--【肆】--:

感谢分享


--【伍】--:

佬友有没有试过这个幻觉翻译,作者是知乎的,他用的方案好像是转latex,我自己用下来感觉显示效果很不错:https://hjfy.top/


--【陆】--:

我也在用MATH,感觉还是得用API以及绕不开的清洗。


--【柒】--:

很有帮助


--【捌】--:

这个主要还是看什么类型的pdf。不过mineru出现脑补的情况没遇到过。我这边实际调研用起来doc2x和mineru不相上下,mineru免费当然是不二之选。doc2x也只适合少量的任务,不管是成本还是速度都不如mineru


--【玖】--:

是这样的,市面上大部分转换方案都没有比较完美的。主要是不规则的表格以及各种公式。所以需要根据工具和个人需求来清洗、修复文档。


--【拾】--:

如果文献有上传到 arXiv 的话,可以下载 TeX 源码后让 AI 翻译源码然后编译 PDF,效果非常完美。


--【拾壹】--: cc:

mineru

看你的需求是批量翻译还是一份翻译了。如果是一份翻译的话,我们就把 PDF 文件直接丢给多模态的 AI 模型,比如说比较强劲的,一定是要国内性能比较好的,比如说 gemini 然后你直接把文件丢给他。 它就会自动,你就告诉它,你自动识别文件内容和排版,然后重新整理翻译后返回。你如果想让它返回 Markdown 的话,就返回 Markdown 如果想让它返回 Word 的话,就直接告诉它基于 Python 来对这个文件进行排版,生成 Word。
如果是批量翻译的话,没得选,就只能是。 mineru 它的免费额额度还是很给力的,好像每天 2000 页,还是每个月 2000 页来着。


--【拾贰】--:

我自己用的感觉不如doc2X

mineru有时候会自己脑补


--【拾叁】--:

1、pdf转md文档首选必须是mineru,试过市面上免费的和付费的(国外的没试过)工具都没有这个转换出来的效果好。无论是数学公式还是表格方面,都很不错。
2、转换md文档之后还需要清洗文档,比如某些公式、表格还是有问题
3、翻译文本的时候不能单纯按段落分割,最好是使用DeepSeek和gemini这种上下文大的,一定要结合上下文翻译,不然中英文互译涉及专业术语会有问题
4、翻译的提示词要反复优化,不同类型的pdf文档来区分,这样翻译效果会更好,专业性更强

做pdf中英文互译基本踩过坑,还有别的不足佬友们可以指点一下


--【拾肆】--:

感谢指导!

确实,mineru 2.5的质量非常之高,不仅仅是模型本身,mineru的工作流设计在开源方案里是比较好的一档,但是自己部署OCR模型的话mineru的工作流相较于MonkeyOCR和DeepseekOCR的工作流有点难改(但是相较于paddle就好搞多了),我平时读的文献有一部分是需要自己改一下layout识别模型的参数的,比较简单的工作流好改一点

清洗文档有点疼,很多OCR模型总会搞一点有自己特点的输出,尤其是跨页代码的情况下,比如MonkeyOCR 3B Pro有时候会输出连续百个w,Mineru有时会不解析表格中的公式

至于直接喂整体上下文在有些情况下有点贵,同时考虑到国内用国外模型很多都带着一些上下文产生污染,可以走一些别的路子,比如利用GalTransl这样工具提取一个术语表带在上下文里

不过我主要是用来翻译后读文献的,十几页的文献我觉得这样足够了,毕竟主要目的是能读懂文献而不是做翻译


--【拾伍】--:

PDF2zh这个我感觉挺好用的

标签:人工智能