From ed8461efa2ba601638145b7fdd7c6d2658b318ed Mon Sep 17 00:00:00 2001 From: xunbu Date: Thu, 1 Jan 2026 01:20:54 +0800 Subject: [PATCH] update --- README.md | 485 ++++++++++++++++-------------------------- README_JP.md | 483 ++++++++++++++++-------------------------- README_ZH.md | 486 ++++++++++++++++--------------------------- docutranslate/sdk.py | 114 ++++++++-- 4 files changed, 626 insertions(+), 942 deletions(-) diff --git a/README.md b/README.md index 54fb10d..64cc206 100644 --- a/README.md +++ b/README.md @@ -46,11 +46,10 @@ ## Integration Packages -For users who want to get started quickly, we provide integration packages on [GitHub Releases](https://github.com/xunbu/docutranslate/releases). simply download, unzip, and enter your AI platform API-Key to start using it. +For users who want to get started quickly, we provide integration packages on [GitHub Releases](https://github.com/xunbu/docutranslate/releases). Simply download, unzip, and enter your AI platform API-Key to start using it. -- **DocuTranslate**: Standard version. Uses the online `minerU` engine to parse PDF documents. Choose this version if you do not need local PDF parsing (Recommended). -- **DocuTranslate_full**: Full version. Includes the built-in `docling` local PDF parsing engine. Choose this version if you need to parse PDFs locally. -> Version 1.5.1 and later support calling a locally deployed mineru service. +- **DocuTranslate**: Standard version. Uses `minerU` (online or locally deployed) for PDF parsing. Supports local minerU API calls. (Recommended) +- **DocuTranslate_full**: Full version. Includes the built-in `docling` local PDF parsing engine. Choose this version if you need offline PDF parsing without minerU. ## Installation @@ -99,33 +98,13 @@ docker run -d -p 8010:8010 xunbu/docutranslate:latest ## Core Concept: Workflow -The core of the new DocuTranslate is the **Workflow**. Each workflow is a complete end-to-end translation pipeline designed for a specific file type. Instead of interacting with a massive class, you select and configure a suitable workflow based on your file type. +DocuTranslate uses a **Workflow** system - each workflow is a complete translation pipeline for a specific file type. -**The basic usage flow is as follows:** - -1. **Select Workflow**: Choose a workflow based on your input file type (e.g., PDF/Word or TXT), such as `MarkdownBasedWorkflow` or `TXTWorkflow`. -2. **Build Configuration**: Create the corresponding configuration object for the selected workflow (e.g., `MarkdownBasedWorkflowConfig`). This configuration object contains all necessary sub-configurations, such as: - * **Converter Config**: Defines how to convert the original file (e.g., PDF) to Markdown. - * **Translator Config**: Defines which LLM, API-Key, target language, etc., to use. - * **Exporter Config**: Defines specific options for the output format (e.g., HTML). -3. **Instantiate Workflow**: Create a workflow instance using the configuration object. -4. **Execute Translation**: Call the workflow's `.read_*()` and `.translate()` / `.translate_async()` methods. -5. **Export/Save Results**: Call `.export_to_*()` or `.save_as_*()` methods to get or save the translation results. - -## Available Workflows - -| Workflow | Applicable Scenarios | Input Formats | Output Formats | Core Configuration Class | -|:---|:---|:---|:---|:---| -| **`MarkdownBasedWorkflow`** | Handles rich text documents like PDF, Word, images, etc. Flow: `File -> Markdown -> Translate -> Export`. | `.pdf`, `.docx`, `.md`, `.png`, `.jpg`, etc. | `.md`, `.zip`, `.html` | `MarkdownBasedWorkflowConfig` | -| **`TXTWorkflow`** | Handles plain text documents. Flow: `txt -> Translate -> Export`. | `.txt` and other plain text formats | `.txt`, `.html` | `TXTWorkflowConfig` | -| **`JsonWorkflow`** | Handles JSON files. Flow: `json -> Translate -> Export`. | `.json` | `.json`, `.html` | `JsonWorkflowConfig` | -| **`DocxWorkflow`** | Handles docx files. Flow: `docx -> Translate -> Export`. | `.docx` | `.docx`, `.html` | `docxWorkflowConfig` | -| **`XlsxWorkflow`** | Handles xlsx files. Flow: `xlsx -> Translate -> Export`. | `.xlsx`, `.csv` | `.xlsx`, `.html` | `XlsxWorkflowConfig` | -| **`SrtWorkflow`** | Handles srt files. Flow: `srt -> Translate -> Export`. | `.srt` | `.srt`, `.html` | `SrtWorkflowConfig` | -| **`EpubWorkflow`** | Handles epub files. Flow: `epub -> Translate -> Export`. | `.epub` | `.epub`, `.html` | `EpubWorkflowConfig` | -| **`HtmlWorkflow`** | Handles html files. Flow: `html -> Translate -> Export`. | `.html`, `.htm` | `.html` | `HtmlWorkflowConfig` | - -> In the interactive interface, you can also export to PDF format. +**Basic flow:** +1. Select workflow based on file type +2. Configure the workflow (LLM, parsing engine, output format) +3. Execute translation +4. Save results ## Start Web UI and API Service @@ -154,6 +133,129 @@ docutranslate -i ## Usage Examples +### Using the Simple Client SDK (Recommended) + +The easiest way to get started is using the `Client` class, which provides a simple and intuitive API for translation: + +```python +from docutranslate.sdk import Client + +# Initialize the client with your AI platform settings +client = Client( + api_key="YOUR_OPENAI_API_KEY", # or any other AI platform API key + base_url="https://api.openai.com/v1/", + model_id="gpt-4o", + to_lang="Chinese", + concurrent=10, # Number of concurrent requests +) + +# Translate a single file (auto-detects file type) +result = client.translate("path/to/your/document.pdf") + +# Save with default format (PDF -> html by default) +print(f"Translation complete! Saved to: {result.save()}") + +# Or specify output format explicitly +# For PDF/markdown_based: +# - "markdown": Markdown with embedded base64 images (default) +# - "markdown_zip": Markdown with separate image files (ZIP archive) +# - "html": HTML format +# For docx: "docx" +# For xlsx: "xlsx" +result.save(fmt="html") # Save as HTML +result.save(fmt="markdown") # Save as Markdown with embedded images +result.save(fmt="markdown_zip") # Save as ZIP with separate images + +# Save to custom location +result.save(output_dir="./my_translations", name="my_document.html") + +# Export as base64 encoded string +base64_content = result.export(fmt="html") +print(f"Exported content length: {len(base64_content)}") + +# You can also access the underlying workflow for advanced operations +# workflow = result.workflow +``` + +**Client Features:** +- **Auto-detection**: Automatically detects file type and selects the appropriate workflow +- **Flexible Configuration**: Override any default settings per translation call +- **Multiple Output Options**: Save to disk or export as Base64 string +- **Async Support**: Use `translate_async()` for concurrent translation tasks + +#### Client SDK Parameters + +| Parameter | Type | Default | Description | +|:---|:---|:---|:---| +| **api_key** | `str` | - | AI platform API key | +| **base_url** | `str` | - | AI platform base URL (e.g., `https://api.openai.com/v1/`) | +| **model_id** | `str` | - | Model ID to use for translation | +| **to_lang** | `str` | - | Target language (e.g., `"Chinese"`, `"English"`, `"Japanese"`) | +| **concurrent** | `int` | 10 | Number of concurrent LLM requests | +| **convert_engine** | `str` | `"mineru"` | PDF parsing engine: `"mineru"`, `"docling"`, `"mineru_deploy"` | +| **mineru_deploy_base_url** | `str` | - | Local minerU API address (when `convert_engine="mineru_deploy"`) | +| **mineru_token** | `str` | - | minerU API token (when using online minerU) | +| **skip_translate** | `bool` | `False` | Skip translation, only parse document | +| **output_dir** | `str` | `"./output"` | Default output directory for `save()` | +| **chunk_size** | `int` | 3000 | Text chunk size for LLM processing | +| **temperature** | `float` | 0.3 | LLM temperature parameter | +| **timeout** | `int` | 60 | Request timeout in seconds | +| **retry** | `int` | 3 | Number of retry attempts on failure | +| **provider** | `str` | `"auto"` | AI provider type (auto, openai, azure, etc.) | +| **force_json** | `bool` | `False` | Force JSON output mode | +| **rpm** | `int` | - | Requests per minute limit | +| **tpm** | `int` | - | Tokens per minute limit | + +#### Result Methods + +| Method | Parameters | Description | +|:---|:---|:---| +| **save()** | `output_dir`, `name`, `fmt` | Save translation result to disk | +| **export()** | `fmt` | Export as Base64 encoded string | +| **supported_formats** | - | Get list of supported output formats | +| **workflow** | - | Access underlying workflow object | + +```python +import asyncio +from docutranslate.sdk import Client + +async def translate_multiple(): + client = Client( + api_key="YOUR_API_KEY", + base_url="https://api.openai.com/v1/", + model_id="gpt-4o", + to_lang="Chinese", + ) + + # Translate multiple files concurrently + files = ["doc1.pdf", "doc2.docx", "notes.txt"] + results = await asyncio.gather( + *[client.translate_async(f) for f in files] + ) + + for r in results: + print(f"Saved: {r.save()}") + +asyncio.run(translate_multiple()) +``` + +### Available Workflows (For Workflow API) + +If you prefer more control, use the Workflow API directly. Here are the available workflows: + +| Workflow | Applicable Scenarios | Input Formats | Output Formats | Core Configuration Class | +|:---|:---|:---|:---|:---| +| **`MarkdownBasedWorkflow`** | Handles rich text documents like PDF, Word, images, etc. Flow: `File -> Markdown -> Translate -> Export`. | `.pdf`, `.docx`, `.md`, `.png`, `.jpg`, etc. | `.md`, `.zip`, `.html` | `MarkdownBasedWorkflowConfig` | +| **`TXTWorkflow`** | Handles plain text documents. Flow: `txt -> Translate -> Export`. | `.txt` and other plain text formats | `.txt`, `.html` | `TXTWorkflowConfig` | +| **`JsonWorkflow`** | Handles JSON files. Flow: `json -> Translate -> Export`. | `.json` | `.json`, `.html` | `JsonWorkflowConfig` | +| **`DocxWorkflow`** | Handles docx files. Flow: `docx -> Translate -> Export`. | `.docx` | `.docx`, `.html` | `docxWorkflowConfig` | +| **`XlsxWorkflow`** | Handles xlsx files. Flow: `xlsx -> Translate -> Export`. | `.xlsx`, `.csv` | `.xlsx`, `.html` | `XlsxWorkflowConfig` | +| **`SrtWorkflow`** | Handles srt files. Flow: `srt -> Translate -> Export`. | `.srt` | `.srt`, `.html` | `SrtWorkflowConfig` | +| **`EpubWorkflow`** | Handles epub files. Flow: `epub -> Translate -> Export`. | `.epub` | `.epub`, `.html` | `EpubWorkflowConfig` | +| **`HtmlWorkflow`** | Handles html files. Flow: `html -> Translate -> Export`. | `.html`, `.htm` | `.html` | `HtmlWorkflowConfig` | + +> In the interactive interface, you can also export to PDF format. + ### Example 1: Translate a PDF File (Using `MarkdownBasedWorkflow`) This is the most common use case. We will use the `minerU` engine to convert the PDF to Markdown, and then translate it using an LLM. This example uses asynchronous execution. @@ -193,22 +295,6 @@ async def main(): translator_config=translator_config, # Pass translator config html_exporter_config=MD2HTMLExporterConfig(cdn=True) # HTML export config ) - - # Using locally deployed mineru service - # from docutranslate.converter.x2md.converter_mineru_deploy import ConverterMineruDeployConfig - # converter_config = ConverterMineruDeployConfig( - # base_url = "http://127.0.0.1:8000", - # output_dir= "./output", # Due to mineru limitations, parsed files are saved to output_dir and need periodic cleaning - # backend= "pipeline", - # start_page_id = 0, - # end_page_id = 99999, - # ) - # workflow_config = MarkdownBasedWorkflowConfig( - # convert_engine="mineru_deploy", # Specify parsing engine - # converter_config=converter_config, # Pass converter config - # translator_config=translator_config, # Pass translator config - # html_exporter_config=MD2HTMLExporterConfig(cdn=True) # HTML export config - # ) # 4. Instantiate Workflow workflow = MarkdownBasedWorkflow(config=workflow_config) @@ -237,254 +323,25 @@ if __name__ == "__main__": asyncio.run(main()) ``` -### Example 2: Translate a TXT File (Using `TXTWorkflow`) +### Other Workflows -For plain text files, the process is simpler as it doesn't require a document parsing (conversion) step. This example uses asynchronous execution. +All workflows follow the same pattern. Import the corresponding config and workflow, then configure: ```python -import asyncio -from docutranslate.workflow.txt_workflow import TXTWorkflow, TXTWorkflowConfig -from docutranslate.translator.ai_translator.txt_translator import TXTTranslatorConfig -from docutranslate.exporter.txt.txt2html_exporter import TXT2HTMLExporterConfig - - -async def main(): - # 1. Build Translator Configuration - translator_config = TXTTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="Chinese", - ) - - # 2. Build Main Workflow Configuration - workflow_config = TXTWorkflowConfig( - translator_config=translator_config, - html_exporter_config=TXT2HTMLExporterConfig(cdn=True) - ) - - # 3. Instantiate Workflow - workflow = TXTWorkflow(config=workflow_config) - - # 4. Read file and execute translation - workflow.read_path("path/to/your/notes.txt") - await workflow.translate_async() - # Or use synchronous method - # workflow.translate() - - # 5. Save results - workflow.save_as_txt(name="translated_notes.txt") - print("TXT file saved.") - - # You can also export the translated plain text - text = workflow.export_to_txt() - - -if __name__ == "__main__": - asyncio.run(main()) +# TXT: from docutranslate.workflow.txt_workflow import TXTWorkflow, TXTWorkflowConfig +# JSON: from docutranslate.workflow.json_workflow import JsonWorkflow, JsonWorkflowConfig +# DOCX: from docutranslate.workflow.docx_workflow import DocxWorkflow, DocxWorkflowConfig +# XLSX: from docutranslate.workflow.xlsx_workflow import XlsxWorkflow, XlsxWorkflowConfig +# EPUB: from docutranslate.workflow.epub_workflow import EpubWorkflow, EpubWorkflowConfig +# HTML: from docutranslate.workflow.html_workflow import HtmlWorkflow, HtmlWorkflowConfig +# SRT: from docutranslate.workflow.srt_workflow import SrtWorkflow, SrtWorkflowConfig +# ASS: from docutranslate.workflow.ass_workflow import AssWorkflow, AssWorkflowConfig ``` -### Example 3: Translate a JSON File (Using `JsonWorkflow`) - -This example uses asynchronous execution. In `JsonTranslatorConfig`, the `json_paths` item needs to specify the JSON paths to be translated (following `jsonpath-ng` syntax specifications); only values matching the JSON paths will be translated. - -```python -import asyncio - -from docutranslate.exporter.js.json2html_exporter import Json2HTMLExporterConfig -from docutranslate.translator.ai_translator.json_translator import JsonTranslatorConfig -from docutranslate.workflow.json_workflow import JsonWorkflowConfig, JsonWorkflow - - -async def main(): - # 1. Build Translator Configuration - translator_config = JsonTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="Chinese", - json_paths=["$.*", "$.name"] # Satisfies jsonpath-ng syntax, values at matching paths will be translated - ) - - # 2. Build Main Workflow Configuration - workflow_config = JsonWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Json2HTMLExporterConfig(cdn=True) - ) - - # 3. Instantiate Workflow - workflow = JsonWorkflow(config=workflow_config) - - # 4. Read file and execute translation - workflow.read_path("path/to/your/notes.json") - await workflow.translate_async() - # Or use synchronous method - # workflow.translate() - - # 5. Save results - workflow.save_as_json(name="translated_notes.json") - print("JSON file saved.") - - # You can also export the translated JSON text - text = workflow.export_to_json() - - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### Example 4: Translate a Docx File (Using `DocxWorkflow`) - -This example uses asynchronous execution. - -```python -import asyncio - -from docutranslate.exporter.docx.docx2html_exporter import Docx2HTMLExporterConfig -from docutranslate.translator.ai_translator.docx_translator import DocxTranslatorConfig -from docutranslate.workflow.docx_workflow import DocxWorkflowConfig, DocxWorkflow - - -async def main(): - # 1. Build Translator Configuration - translator_config = DocxTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="Chinese", - insert_mode="replace", # Options: "replace", "append", "prepend" - separator="\n", # Separator used for "append", "prepend" modes - ) - - # 2. Build Main Workflow Configuration - workflow_config = DocxWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Docx2HTMLExporterConfig(cdn=True) - ) - - # 3. Instantiate Workflow - workflow = DocxWorkflow(config=workflow_config) - - # 4. Read file and execute translation - workflow.read_path("path/to/your/notes.docx") - await workflow.translate_async() - # Or use synchronous method - # workflow.translate() - - # 5. Save results - workflow.save_as_docx(name="translated_notes.docx") - print("docx file saved.") - - # You can also export the translated docx bytes - text_bytes = workflow.export_to_docx() - - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### Example 5: Translate an Xlsx File (Using `XlsxWorkflow`) - -This example uses asynchronous execution. - -```python -import asyncio - -from docutranslate.exporter.xlsx.xlsx2html_exporter import Xlsx2HTMLExporterConfig -from docutranslate.translator.ai_translator.xlsx_translator import XlsxTranslatorConfig -from docutranslate.workflow.xlsx_workflow import XlsxWorkflowConfig, XlsxWorkflow - - -async def main(): - # 1. Build Translator Configuration - translator_config = XlsxTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="Chinese", - insert_mode="replace", # Options: "replace", "append", "prepend" - separator="\n", # Separator used for "append", "prepend" modes - ) - - # 2. Build Main Workflow Configuration - workflow_config = XlsxWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Xlsx2HTMLExporterConfig(cdn=True) - ) - - # 3. Instantiate Workflow - workflow = XlsxWorkflow(config=workflow_config) - - # 4. Read file and execute translation - workflow.read_path("path/to/your/notes.xlsx") - await workflow.translate_async() - # Or use synchronous method - # workflow.translate() - - # 5. Save results - workflow.save_as_xlsx(name="translated_notes.xlsx") - print("xlsx file saved.") - - # You can also export the translated xlsx bytes - text_bytes = workflow.export_to_xlsx() - - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### Example 6: Config Options for Other Workflows (Using `HtmlWorkflow`, `EpubWorkflow`) - -This example uses asynchronous execution. - -```python -# HtmlWorkflow -from docutranslate.translator.ai_translator.html_translator import HtmlTranslatorConfig -from docutranslate.workflow.html_workflow import HtmlWorkflowConfig, HtmlWorkflow - - -async def html(): - # 1. Build Translator Configuration - translator_config = HtmlTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="Chinese", - insert_mode="replace", # Options: "replace", "append", "prepend" - separator="\n", # Separator used for "append", "prepend" modes - ) - - # 2. Build Main Workflow Configuration - workflow_config = HtmlWorkflowConfig( - translator_config=translator_config, - ) - workflow_html = HtmlWorkflow(config=workflow_config) - - -# EpubWorkflow -from docutranslate.exporter.epub.epub2html_exporter import Epub2HTMLExporterConfig -from docutranslate.translator.ai_translator.epub_translator import EpubTranslatorConfig -from docutranslate.workflow.epub_workflow import EpubWorkflowConfig, EpubWorkflow - - -async def epub(): - # 1. Build Translator Configuration - translator_config = EpubTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="Chinese", - insert_mode="replace", # Options: "replace", "append", "prepend" - separator="\n", # Separator used for "append", "prepend" modes - ) - - # 2. Build Main Workflow Configuration - workflow_config = EpubWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Epub2HTMLExporterConfig(cdn=True), - ) - workflow_epub = EpubWorkflow(config=workflow_config) -``` +Key config options: +- **insert_mode**: `"replace"`, `"append"`, or `"prepend"` (for docx/xlsx/html/epub) +- **json_paths**: JSONPath expressions for JSON translation (e.g., `["$.*", "$.name"]`) +- **separator**: Text separator for `"append"` / `"prepend"` modes ## Prerequisites and Detailed Configuration @@ -562,31 +419,47 @@ converter_config = ConverterDoclingConfig( ) ``` +### 2.3. Locally Deployed MinerU Service + +For offline/intranet environments, deploy `minerU` locally with API enabled. Set `mineru_deploy_base_url` to your minerU API endpoint. + +**Client SDK:** +```python +from docutranslate.sdk import Client + +client = Client( + api_key="YOUR_LLM_API_KEY", + model_id="llama3", + to_lang="Chinese", + convert_engine="mineru_deploy", + mineru_deploy_base_url="http://127.0.0.1:8000", # Your minerU API address +) +result = client.translate("document.pdf") +result.save(fmt="markdown") +``` + ## FAQ -**Q: Why is the output still in the original language?** -A: Check the logs for errors. It is usually due to the AI platform running out of credits or network issues (check if system proxy needs to be enabled). +**Q: Output is in original language?** +A: Check logs for errors. Usually due to exhausted API credits or network issues. -**Q: Port 8010 is occupied, what should I do?** -A: Use the `-p` parameter to specify a new port, or set the `DOCUTRANSLATE_PORT` environment variable. +**Q: Port 8010 occupied?** +A: Use `docutranslate -i -p 8011` or set `DOCUTRANSLATE_PORT=8011`. -**Q: Are scanned PDFs supported?** -A: Yes. Please use the `mineru` parsing engine, which has powerful OCR capabilities. +**Q: Scanned PDFs supported?** +A: Yes, use `mineru` engine with OCR capabilities. -**Q: Why is the first PDF translation very slow?** -A: If you are using the `docling` engine, it needs to download models from Hugging Face on the first run. Please refer to the "Network Issues Solutions" section above to speed up this process. +**Q: First PDF translation slow?** +A: `docling` needs to download models on first run. Use Hugging Face mirror or pre-download artifact. -**Q: How can I use it in an Intranet (Offline) environment?** -A: Absolutely. You need to meet the following conditions: +**Q: Use in intranet/offline?** +A: Yes. Use local LLM (Ollama/LM Studio) and local minerU or docling. -1. **Local LLM**: Use tools like [Ollama](https://ollama.com/) or [LM Studio](https://lmstudio.ai/) to deploy the language model locally, and enter the local model's `base_url` in `TranslatorConfig`. -2. **Local PDF Parsing Engine** (Only needed for PDF parsing): Use the `docling` engine and follow the "Offline Use" instructions above to pre-download the model package. +**Q: PDF cache mechanism?** +A: `MarkdownBasedWorkflow` caches parsing results in memory (last 10 parses). Configure via `DOCUTRANSLATE_CACHE_NUM`. -**Q: How does the PDF parsing cache mechanism work?** -A: `MarkdownBasedWorkflow` automatically caches the results of document parsing (file-to-Markdown conversion) to avoid repeated parsing consuming time and resources. The cache is stored in memory by default and records the last 10 parses. You can modify the cache size via the `DOCUTRANSLATE_CACHE_NUM` environment variable. - -**Q: How to enable proxy support for the software?** -A: The software does not use the system proxy by default. You can enable it by setting `system_proxy_enable=True` in `TranslatorConfig`. +**Q: Enable proxy?** +A: Set `system_proxy_enable=True` in TranslatorConfig. ## Star History diff --git a/README_JP.md b/README_JP.md index 84f5d3f..a285913 100644 --- a/README_JP.md +++ b/README_JP.md @@ -48,9 +48,8 @@ すぐに使い始めたいユーザー向けに、[GitHub Releases](https://github.com/xunbu/docutranslate/releases) で統合パッケージを提供しています。ダウンロードして解凍し、AIプラットフォームのAPIキーを入力するだけで使用を開始できます。 -- **DocuTranslate**: 標準版。オンラインの `minerU` エンジンを使用してPDFドキュメントを解析します。ローカルでのPDF解析が不要な場合はこちらを選択してください(推奨)。 -- **DocuTranslate_full**: 完全版。`docling` ローカルPDF解析エンジンを内蔵しています。ローカルでPDFを解析する必要がある場合はこちらを選択してください。 -> バージョン1.5.1以降、ローカルにデプロイされたmineruサービスの呼び出しをサポートしています。 +- **DocuTranslate**: 標準版。`minerU`(オンラインまたはローカルデプロイ)を使用してPDFを解析します。ローカルの minerU API 呼び出しをサポートしています。(推奨) +- **DocuTranslate_full**: 完全版。`docling` ローカルPDF解析エンジンを内蔵しています。minerU なしでオフラインPDF解析が必要な場合はこちらを選択してください。 ## インストール @@ -99,33 +98,13 @@ docker run -d -p 8010:8010 xunbu/docutranslate:latest ## コアコンセプト:ワークフロー (Workflow) -新しい DocuTranslate の核となるのは **ワークフロー (Workflow)** です。各ワークフローは、特定の種類のファイル用に設計された、完全なエンドツーエンドの翻訳パイプラインです。巨大なクラスとやり取りするのではなく、ファイルの種類に基づいて適切なワークフローを選択し、設定します。 +DocuTranslate は **ワークフロー (Workflow)** システムを使用しています。各ワークフローは、特定のファイルタイプ向けの完全な翻訳パイプラインです。 -**基本的な使用手順は以下の通りです:** - -1. **ワークフローの選択**:入力ファイルの種類(例:PDF/Word または TXT)に基づいて、`MarkdownBasedWorkflow` や `TXTWorkflow` などのワークフローを選択します。 -2. **設定の構築**:選択したワークフローに対応する設定オブジェクト(例:`MarkdownBasedWorkflowConfig`)を作成します。この設定オブジェクトには、必要なすべてのサブ設定が含まれます: - * **コンバータ設定 (Converter Config)**: 元のファイル(例:PDF)をMarkdownに変換する方法を定義します。 - * **翻訳機設定 (Translator Config)**: 使用するLLM、APIキー、ターゲット言語などを定義します。 - * **エクスポータ設定 (Exporter Config)**: 出力形式(例:HTML)の特定のオプションを定義します。 -3. **ワークフローのインスタンス化**:設定オブジェクトを使用してワークフローのインスタンスを作成します。 -4. **翻訳の実行**:ワークフローの `.read_*()` および `.translate()` / `.translate_async()` メソッドを呼び出します。 -5. **結果のエクスポート/保存**:`.export_to_*()` または `.save_as_*()` メソッドを呼び出して翻訳結果を取得または保存します。 - -## 利用可能なワークフロー - -| ワークフロー | 適用シナリオ | 入力形式 | 出力形式 | コア設定クラス | -|:---|:---|:---|:---|:---| -| **`MarkdownBasedWorkflow`** | PDF、Word、画像などのリッチテキストドキュメントを処理。フロー:`ファイル -> Markdown -> 翻訳 -> エクスポート`。 | `.pdf`, `.docx`, `.md`, `.png`, `.jpg` 等 | `.md`, `.zip`, `.html` | `MarkdownBasedWorkflowConfig` | -| **`TXTWorkflow`** | プレーンテキストドキュメントを処理。フロー:`txt -> 翻訳 -> エクスポート`。 | `.txt` およびその他のテキスト形式 | `.txt`, `.html` | `TXTWorkflowConfig` | -| **`JsonWorkflow`** | JSONファイルを処理。フロー:`json -> 翻訳 -> エクスポート`。 | `.json` | `.json`, `.html` | `JsonWorkflowConfig` | -| **`DocxWorkflow`** | docxファイルを処理。フロー:`docx -> 翻訳 -> エクスポート`。 | `.docx` | `.docx`, `.html` | `docxWorkflowConfig` | -| **`XlsxWorkflow`** | xlsxファイルを処理。フロー:`xlsx -> 翻訳 -> エクスポート`。 | `.xlsx`, `.csv` | `.xlsx`, `.html` | `XlsxWorkflowConfig` | -| **`SrtWorkflow`** | srtファイルを処理。フロー:`srt -> 翻訳 -> エクスポート`。 | `.srt` | `.srt`, `.html` | `SrtWorkflowConfig` | -| **`EpubWorkflow`** | epubファイルを処理。フロー:`epub -> 翻訳 -> エクスポート`。 | `.epub` | `.epub`, `.html` | `EpubWorkflowConfig` | -| **`HtmlWorkflow`** | htmlファイルを処理。フロー:`html -> 翻訳 -> エクスポート`。 | `.html`, `.htm` | `.html` | `HtmlWorkflowConfig` | - -> インタラクティブ画面ではPDF形式でのエクスポートも可能です。 +**基本フロー:** +1. ファイルタイプに基づいてワークフローを選択 +2. ワークフローを設定(LLM、解析エンジン、出力形式) +3. 翻訳を実行 +4. 結果を保存 ## Web UI と API サービスの起動 @@ -154,6 +133,129 @@ docutranslate -i ## 使用方法 +### シンプルな Client SDK の使用 (推奨) + +翻訳を始める最も簡単な方法は `Client` クラスを使用することです。これはシンプルで直感的な API を提供します: + +```python +from docutranslate.sdk import Client + +# AI プラットフォームの設定でクライアントを初期化 +client = Client( + api_key="YOUR_OPENAI_API_KEY", # またはその他の AI プラットフォーム API キー + base_url="https://api.openai.com/v1/", + model_id="gpt-4o", + to_lang="中文", + concurrent=10, # 同時リクエスト数 +) + +# 単一ファイルを翻訳 (ファイル类型を自動検出) +result = client.translate("path/to/your/document.pdf") + +# デフォルトフォーマットで保存 (PDF -> markdown with embedded images) +print(f"翻訳完了!保存先: {result.save()}") + +# または出力フォーマットを明示的に指定 +# PDF/markdown_based は以下をサポート: +# - "markdown": Markdown フォーマット、base64 画像埋め込み (デフォルト) +# - "markdown_zip": Markdown フォーマット、画像分離保存 (ZIP アーカイブ) +# - "html": HTML フォーマット +# docx は "docx" をサポート +# xlsx は "xlsx" をサポート +result.save(fmt="html") # HTML として保存 +result.save(fmt="markdown") # Markdown として保存(画像埋め込み) +result.save(fmt="markdown_zip") # ZIP として保存(画像分離) + +# カスタム場所に保存 +result.save(output_dir="./my_translations", name="my_document.html") + +# または Base64 エンコード文字列としてエクスポート +base64_content = result.export(fmt="html") +print(f"エクスポートコンテンツ長さ: {len(base64_content)}") + +# 基盤のワークフローにアクセスして高度な操作を行うことも可能 +# workflow = result.workflow +``` + +**Client の機能:** +- **自動検出**: ファイル类型を自動検出し、適切なワークフローを選択 +- **柔軟な設定**: 翻訳呼び出しごとにデフォルト設定を上書き可能 +- **複数の出力オプション**: ディスクに保存または Base64 文字列としてエクスポート +- **非同期サポート**: 同時翻訳タスクには `translate_async()` を使用 + +#### Client SDK パラメータ一覧 + +| パラメータ | タイプ | デフォルト | 説明 | +|:---|:---|:---|:---| +| **api_key** | `str` | - | AI プラットフォーム API キー | +| **base_url** | `str` | - | AI プラットフォームベース URL(例: `https://api.openai.com/v1/`) | +| **model_id** | `str` | - | 翻訳に使用するモデル ID | +| **to_lang** | `str` | - | ターゲット言語(例: `"中文"`、`"English"`、`"日本語"`) | +| **concurrent** | `int` | 10 | 同時 LLM リクエスト数 | +| **convert_engine** | `str` | `"mineru"` | PDF 解析エンジン: `"mineru"`、`"docling"`、`"mineru_deploy"` | +| **mineru_deploy_base_url** | `str` | - | ローカル minerU API アドレス(`convert_engine="mineru_deploy"` の場合) | +| **mineru_token** | `str` | - | minerU API Token(オンライン minerU 使用時) | +| **skip_translate** | `bool` | `False` | 翻訳をスキップしてドキュメントのみを解析 | +| **output_dir** | `str` | `"./output"` | `save()` メソッドのデフォルト出力ディレクトリ | +| **chunk_size** | `int` | 3000 | LLM 処理のテキストチャンクサイズ | +| **temperature** | `float` | 0.3 | LLM 温度パラメータ | +| **timeout** | `int` | 60 | リクエストタイムアウト(秒) | +| **retry** | `int` | 3 | 失敗時の再試行回数 | +| **provider** | `str` | `"auto"` | AI プロバイダータイプ(auto、openai、azure など) | +| **force_json** | `bool` | `False` | 強制 JSON 出力モード | +| **rpm** | `int` | - | 1分あたりのリクエスト数制限 | +| **tpm** | `int` | - | 1分あたりのトークン数制限 | + +#### Result メソッド一覧 + +| メソッド | パラメータ | 説明 | +|:---|:---|:---| +| **save()** | `output_dir`, `name`, `fmt` | 翻訳結果をディスクに保存 | +| **export()** | `fmt` | Base64 エンコード文字列としてエクスポート | +| **supported_formats** | - | サポートされている出力フォーマット一覧を取得 | +| **workflow** | - | 基盤のワークフローオブジェクトにアクセス | + +```python +import asyncio +from docutranslate.sdk import Client + +async def translate_multiple(): + client = Client( + api_key="YOUR_API_KEY", + base_url="https://api.openai.com/v1/", + model_id="gpt-4o", + to_lang="中文", + ) + + # 複数のファイルを同時に翻訳 + files = ["doc1.pdf", "doc2.docx", "notes.txt"] + results = await asyncio.gather( + *[client.translate_async(f) for f in files] + ) + + for r in results: + print(f"保存先: {r.save()}") + +asyncio.run(translate_multiple()) +``` + +### 利用可能なワークフロー(Workflow API を使用) + +より精细な制御が必要な場合は、Workflow API を直接使用してください。以下は利用可能なワークフローです: + +| ワークフロー | 適用シナリオ | 入力形式 | 出力形式 | コア設定クラス | +|:---|:---|:---|:---|:---| +| **`MarkdownBasedWorkflow`** | PDF、Word、画像などのリッチテキストドキュメントを処理。フロー:`ファイル -> Markdown -> 翻訳 -> エクスポート`。 | `.pdf`, `.docx`, `.md`, `.png`, `.jpg` 等 | `.md`, `.zip`, `.html` | `MarkdownBasedWorkflowConfig` | +| **`TXTWorkflow`** | プレーンテキストドキュメントを処理。フロー:`txt -> 翻訳 -> エクスポート`。 | `.txt` およびその他のテキスト形式 | `.txt`, `.html` | `TXTWorkflowConfig` | +| **`JsonWorkflow`** | JSONファイルを処理。フロー:`json -> 翻訳 -> エクスポート`。 | `.json` | `.json`, `.html` | `JsonWorkflowConfig` | +| **`DocxWorkflow`** | docxファイルを処理。フロー:`docx -> 翻訳 -> エクスポート`。 | `.docx` | `.docx`, `.html` | `docxWorkflowConfig` | +| **`XlsxWorkflow`** | xlsxファイルを処理。フロー:`xlsx -> 翻訳 -> エクスポート`。 | `.xlsx`, `.csv` | `.xlsx`, `.html` | `XlsxWorkflowConfig` | +| **`SrtWorkflow`** | srtファイルを処理。フロー:`srt -> 翻訳 -> エクスポート`。 | `.srt` | `.srt`, `.html` | `SrtWorkflowConfig` | +| **`EpubWorkflow`** | epubファイルを処理。フロー:`epub -> 翻訳 -> エクスポート`。 | `.epub` | `.epub`, `.html` | `EpubWorkflowConfig` | +| **`HtmlWorkflow`** | htmlファイルを処理。フロー:`html -> 翻訳 -> エクスポート`。 | `.html`, `.htm` | `.html` | `HtmlWorkflowConfig` | + +> インタラクティブ画面ではPDF形式でのエクスポートも可能です。 + ### 例 1: PDFファイルの翻訳 (`MarkdownBasedWorkflow` を使用) これが最も一般的なユースケースです。`minerU` エンジンを使用して PDF を Markdown に変換し、その後 LLM を使用して翻訳します。ここでは非同期方式を例にします。 @@ -193,22 +295,6 @@ async def main(): translator_config=translator_config, # 翻訳機設定を渡す html_exporter_config=MD2HTMLExporterConfig(cdn=True) # HTMLエクスポート設定 ) - - # ローカルデプロイされたmineruサービスを使用する場合 - # from docutranslate.converter.x2md.converter_mineru_deploy import ConverterMineruDeployConfig - # converter_config = ConverterMineruDeployConfig( - # base_url = "http://127.0.0.1:8000", - # output_dir= "./output",# mineruの制限により、解析後のファイルはoutput_dir下に保存されるため、定期的なクリーニングが必要です - # backend= "pipeline", - # start_page_id = 0, - # end_page_id = 99999, - # ) - # workflow_config = MarkdownBasedWorkflowConfig( - # convert_engine="mineru_deploy", # 解析エンジンを指定 - # converter_config=converter_config, # コンバータ設定を渡す - # translator_config=translator_config, # 翻訳機設定を渡す - # html_exporter_config=MD2HTMLExporterConfig(cdn=True) # HTMLエクスポート設定 - # ) # 4. ワークフローのインスタンス化 workflow = MarkdownBasedWorkflow(config=workflow_config) @@ -237,254 +323,25 @@ if __name__ == "__main__": asyncio.run(main()) ``` -### 例 2: TXTファイルの翻訳 (`TXTWorkflow` を使用) +### その他のワークフロー -プレーンテキストファイルの場合、ドキュメント解析(変換)ステップが不要なため、プロセスはより簡単です。ここでは非同期方式を例にします。 +すべてのワークフローは同じパターンに従います。対応する設定とワークフローをインポートして設定します: ```python -import asyncio -from docutranslate.workflow.txt_workflow import TXTWorkflow, TXTWorkflowConfig -from docutranslate.translator.ai_translator.txt_translator import TXTTranslatorConfig -from docutranslate.exporter.txt.txt2html_exporter import TXT2HTMLExporterConfig - - -async def main(): - # 1. 翻訳機設定の構築 - translator_config = TXTTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - ) - - # 2. メインワークフロー設定の構築 - workflow_config = TXTWorkflowConfig( - translator_config=translator_config, - html_exporter_config=TXT2HTMLExporterConfig(cdn=True) - ) - - # 3. ワークフローのインスタンス化 - workflow = TXTWorkflow(config=workflow_config) - - # 4. ファイルの読み込みと翻訳実行 - workflow.read_path("path/to/your/notes.txt") - await workflow.translate_async() - # または同期メソッドを使用 - # workflow.translate() - - # 5. 結果の保存 - workflow.save_as_txt(name="translated_notes.txt") - print("TXTファイルが保存されました。") - - # 翻訳後のテキストをエクスポートすることも可能 - text = workflow.export_to_txt() - - -if __name__ == "__main__": - asyncio.run(main()) +# TXT: from docutranslate.workflow.txt_workflow import TXTWorkflow, TXTWorkflowConfig +# JSON: from docutranslate.workflow.json_workflow import JsonWorkflow, JsonWorkflowConfig +# DOCX: from docutranslate.workflow.docx_workflow import DocxWorkflow, DocxWorkflowConfig +# XLSX: from docutranslate.workflow.xlsx_workflow import XlsxWorkflow, XlsxWorkflowConfig +# EPUB: from docutranslate.workflow.epub_workflow import EpubWorkflow, EpubWorkflowConfig +# HTML: from docutranslate.workflow.html_workflow import HtmlWorkflow, HtmlWorkflowConfig +# SRT: from docutranslate.workflow.srt_workflow import SrtWorkflow, SrtWorkflowConfig +# ASS: from docutranslate.workflow.ass_workflow import AssWorkflow, AssWorkflowConfig ``` -### 例 3: JSONファイルの翻訳 (`JsonWorkflow` を使用) - -ここでは非同期方式を例にします。`JsonTranslatorConfig` の `json_paths` 項目で、翻訳対象のJSONパス(jsonpath-ng構文に準拠)を指定する必要があります。パスに一致する値のみが翻訳されます。 - -```python -import asyncio - -from docutranslate.exporter.js.json2html_exporter import Json2HTMLExporterConfig -from docutranslate.translator.ai_translator.json_translator import JsonTranslatorConfig -from docutranslate.workflow.json_workflow import JsonWorkflowConfig, JsonWorkflow - - -async def main(): - # 1. 翻訳機設定の構築 - translator_config = JsonTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - json_paths=["$.*", "$.name"] # jsonpath-ngパス構文に準拠、一致するパスの値が翻訳されます - ) - - # 2. メインワークフロー設定の構築 - workflow_config = JsonWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Json2HTMLExporterConfig(cdn=True) - ) - - # 3. ワークフローのインスタンス化 - workflow = JsonWorkflow(config=workflow_config) - - # 4. ファイルの読み込みと翻訳実行 - workflow.read_path("path/to/your/notes.json") - await workflow.translate_async() - # または同期メソッドを使用 - # workflow.translate() - - # 5. 結果の保存 - workflow.save_as_json(name="translated_notes.json") - print("jsonファイルが保存されました。") - - # 翻訳後のjsonテキストをエクスポートすることも可能 - text = workflow.export_to_json() - - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### 例 4: docxファイルの翻訳 (`DocxWorkflow` を使用) - -ここでは非同期方式を例にします。 - -```python -import asyncio - -from docutranslate.exporter.docx.docx2html_exporter import Docx2HTMLExporterConfig -from docutranslate.translator.ai_translator.docx_translator import DocxTranslatorConfig -from docutranslate.workflow.docx_workflow import DocxWorkflowConfig, DocxWorkflow - - -async def main(): - # 1. 翻訳機設定の構築 - translator_config = DocxTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - insert_mode="replace", # 選択肢 "replace" (置換), "append" (追記), "prepend" (前置) - separator="\n", # "append", "prepend" モード時の区切り文字 - ) - - # 2. メインワークフロー設定の構築 - workflow_config = DocxWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Docx2HTMLExporterConfig(cdn=True) - ) - - # 3. ワークフローのインスタンス化 - workflow = DocxWorkflow(config=workflow_config) - - # 4. ファイルの読み込みと翻訳実行 - workflow.read_path("path/to/your/notes.docx") - await workflow.translate_async() - # または同期メソッドを使用 - # workflow.translate() - - # 5. 結果の保存 - workflow.save_as_docx(name="translated_notes.docx") - print("docxファイルが保存されました。") - - # 翻訳後のdocxバイナリをエクスポートすることも可能 - text_bytes = workflow.export_to_docx() - - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### 例 5: xlsxファイルの翻訳 (`XlsxWorkflow` を使用) - -ここでは非同期方式を例にします。 - -```python -import asyncio - -from docutranslate.exporter.xlsx.xlsx2html_exporter import Xlsx2HTMLExporterConfig -from docutranslate.translator.ai_translator.xlsx_translator import XlsxTranslatorConfig -from docutranslate.workflow.xlsx_workflow import XlsxWorkflowConfig, XlsxWorkflow - - -async def main(): - # 1. 翻訳機設定の構築 - translator_config = XlsxTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - insert_mode="replace", # 選択肢 "replace", "append", "prepend" - separator="\n", # "append", "prepend" モード時の区切り文字 - ) - - # 2. メインワークフロー設定の構築 - workflow_config = XlsxWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Xlsx2HTMLExporterConfig(cdn=True) - ) - - # 3. ワークフローのインスタンス化 - workflow = XlsxWorkflow(config=workflow_config) - - # 4. ファイルの読み込みと翻訳実行 - workflow.read_path("path/to/your/notes.xlsx") - await workflow.translate_async() - # または同期メソッドを使用 - # workflow.translate() - - # 5. 結果の保存 - workflow.save_as_xlsx(name="translated_notes.xlsx") - print("xlsxファイルが保存されました。") - - # 翻訳後のxlsxバイナリをエクスポートすることも可能 - text_bytes = workflow.export_to_xlsx() - - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### 例 6: その他のワークフロー設定 (`HtmlWorkflow`、`EpubWorkflow` を使用) - -ここでは非同期方式を例にします。 - -```python -# HtmlWorkflow -from docutranslate.translator.ai_translator.html_translator import HtmlTranslatorConfig -from docutranslate.workflow.html_workflow import HtmlWorkflowConfig, HtmlWorkflow - - -async def html(): - # 1. 翻訳機設定の構築 - translator_config = HtmlTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - insert_mode="replace", # 選択肢 "replace", "append", "prepend" - separator="\n", # "append", "prepend" モード時の区切り文字 - ) - - # 2. メインワークフロー設定の構築 - workflow_config = HtmlWorkflowConfig( - translator_config=translator_config, - ) - workflow_html = HtmlWorkflow(config=workflow_config) - - -# EpubWorkflow -from docutranslate.exporter.epub.epub2html_exporter import Epub2HTMLExporterConfig -from docutranslate.translator.ai_translator.epub_translator import EpubTranslatorConfig -from docutranslate.workflow.epub_workflow import EpubWorkflowConfig, EpubWorkflow - - -async def epub(): - # 1. 翻訳機設定の構築 - translator_config = EpubTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - insert_mode="replace", # 選択肢 "replace", "append", "prepend" - separator="\n", # "append", "prepend" モード時の区切り文字 - ) - - # 2. メインワークフロー設定の構築 - workflow_config = EpubWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Epub2HTMLExporterConfig(cdn=True), - ) - workflow_epub = EpubWorkflow(config=workflow_config) -``` +主な設定オプション: +- **insert_mode**: `"replace"`, `"append"`, `"prepend"` (docx/xlsx/html/epub 用) +- **json_paths**: JSON 翻訳用の JSONPath 式 (例: `["$.*", "$.name"]`) +- **separator**: `"append"` / `"prepend"` モード用のテキスト区切り文字 ## 前提条件と設定詳細 @@ -562,31 +419,47 @@ converter_config = ConverterDoclingConfig( ) ``` +### 2.3. ローカルデプロイ MinerU サービス + +オフライン/イントラネット環境では、ローカルデプロイの `minerU` を推奨します。パフォーマンス向上、API制限なし。`mineru_deploy_base_url` に minerU API アドレスを設定してください。 + +**Client SDK:** +```python +from docutranslate.sdk import Client + +client = Client( + api_key="YOUR_LLM_API_KEY", + model_id="llama3", + to_lang="中文", + convert_engine="mineru_deploy", + mineru_deploy_base_url="http://127.0.0.1:8000", # minerU API アドレス +) +result = client.translate("document.pdf") +result.save(fmt="markdown") +``` + ## FAQ -**Q: なぜ翻訳結果が原文のままなのですか?** -A: ログを確認し、エラー内容をチェックしてください。通常、AIプラットフォームの残高不足か、ネットワークの問題(システムプロキシを有効にする必要があるか確認)です。 +**Q: 翻訳結果が原文のまま?** +A: ログを確認。通常、AIプラットフォーム残高不足またはネットワーク問題。 -**Q: 8010ポートが使用されていますが、どうすればいいですか?** -A: `-p` パラメータを使用して新しいポートを指定するか、`DOCUTRANSLATE_PORT` 環境変数を設定してください。 +**Q: 8010ポート使用中?** +A: `docutranslate -i -p 8011` または `DOCUTRANSLATE_PORT=8011`。 -**Q: スキャンされたPDFの翻訳はサポートされていますか?** -A: はい、サポートされています。強力なOCR機能を備えた `mineru` 解析エンジンを使用してください。 +**Q: スキャンPDF対応?** +A: はい。`mineru` エンジンのOCR機能を使用。 -**Q: 最初のPDF翻訳が非常に遅いのはなぜですか?** -A: `docling` エンジンを使用している場合、初回実行時に Hugging Face からモデルをダウンロードする必要があるためです。上記の「ネットワーク問題解決策」を参照して、このプロセスを高速化してください。 +**Q: 最初のPDF翻訳が遅い?** +A: `docling` は初回モデルダウンロードが必要。Hugging Face mirror または artifact 事前ダウンロードで解決。 -**Q: イントラネット(オフライン)環境で使用する方法は?** -A: 可能です。以下の条件を満たす必要があります: +**Q: イントラネット/オフライン使用?** +A: 可能。ローカルLLM(Ollama/LM Studio)とローカル minerU または docling を使用。 -1. **ローカルLLM**: [Ollama](https://ollama.com/) や [LM Studio](https://lmstudio.ai/) などのツールを使用してローカルに言語モデルをデプロイし、`TranslatorConfig` にローカルモデルの `base_url` を入力します。 -2. **ローカルPDF解析エンジン**(PDF解析が必要な場合のみ): `docling` エンジンを使用し、上記の「オフライン使用」の指示に従って事前にモデルパッケージをダウンロードしてください。 +**Q: PDFキャッシュ機構?** +A: `MarkdownBasedWorkflow` がメモリ内に解析結果をキャッシュ(最近10件)。`DOCUTRANSLATE_CACHE_NUM` で変更可。 -**Q: PDF解析のキャッシュメカニズムはどのように機能しますか?** -A: `MarkdownBasedWorkflow` は、ドキュメント解析(ファイルからMarkdownへの変換)の結果を自動的にキャッシュし、時間とリソースを消費する重複解析を回避します。キャッシュはデフォルトでメモリに保存され、最近の10件の解析を記録します。`DOCUTRANSLATE_CACHE_NUM` 環境変数でキャッシュ数を変更できます。 - -**Q: ソフトウェアでプロキシを使用するにはどうすればいいですか?** -A: ソフトウェアはデフォルトではシステムプロキシを使用しません。`TranslatorConfig` で `system_proxy_enable=True` を設定することで、システムプロキシを有効にできます。 +**Q: プロキシ有効化?** +A: TranslatorConfig で `system_proxy_enable=True` を設定。 ## Star History diff --git a/README_ZH.md b/README_ZH.md index 3a6dcdc..b7265b9 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -49,9 +49,8 @@ 对于希望快速上手的用户,我们在 [GitHub Releases](https://github.com/xunbu/docutranslate/releases) 上提供整合包。您只需下载、解压,并填入您的 AI 平台 API-Key 即可开始使用。 -- **DocuTranslate**: 标准版,使用在线的 `minerU` 引擎解析PDF文档,如果不需要本地解析pdf选这个版本(推荐)。 -- **DocuTranslate_full**: 完整版,内置 `docling` 本地PDF解析引擎,需要本地解析pdf选这个版本。 -> 1.5.1版本以后支持调用本地部署的mineru服务 +- **DocuTranslate**: 标准版,使用 `minerU`(在线或本地部署)解析PDF文档,支持调用本地部署的 minerU API。(推荐) +- **DocuTranslate_full**: 完整版,内置 `docling` 本地PDF解析引擎,无需 minerU 即可进行离线PDF解析时选择此版本。 ## 安装 @@ -100,33 +99,13 @@ docker run -d -p 8010:8010 xunbu/docutranslate:latest ## 核心概念:工作流 (Workflow) -新版 DocuTranslate 的核心是 **工作流 (Workflow)**。每个工作流都是一个专门为特定类型文件设计的、完整的端到端翻译管道。您不再与一个庞大的类交互,而是根据您的文件类型选择并配置一个合适的工作流。 +DocuTranslate 使用 **工作流 (Workflow)** 系统,每个工作流都是针对特定文件类型的完整翻译管道。 -**基本使用流程如下:** - -1. **选择工作流**:根据您的输入文件类型(例如,PDF/Word 或 TXT)选择一个工作流,如 `MarkdownBasedWorkflow` 或 `TXTWorkflow`。 -2. **构建配置**:为所选工作流创建相应的配置对象(如 `MarkdownBasedWorkflowConfig`)。此配置对象包含了所有需要的子配置,例如: - * **转换器配置 (Converter Config)**: 定义如何将原始文件(如PDF)转换为 Markdown。 - * **翻译器配置 (Translator Config)**: 定义使用哪个 LLM、API-Key、目标语言等。 - * **导出器配置 (Exporter Config)**: 定义输出格式(如HTML)的特定选项。 -3. **实例化工作流**:使用配置对象创建工作流实例。 -4. **执行翻译**:调用工作流的 `.read_*()` 和 `.translate()` / `.translate_async()` 方法。 -5. **导出/保存结果**:调用 `.export_to_*()` 或 `.save_as_*()` 方法获取或保存翻译结果。 - -## 可用工作流 - -| 工作流 | 适用场景 | 输入格式 | 输出格式 | 核心配置类 | -|:----------------------------|:--------------------------------------------------------|:-----------------------------------------|:-----------------------|:------------------------------| -| **`MarkdownBasedWorkflow`** | 处理富文本文档,如PDF、Word、图片等。流程为:`文件 -> Markdown -> 翻译 -> 导出`。 | `.pdf`, `.docx`, `.md`, `.png`, `.jpg` 等 | `.md`, `.zip`, `.html` | `MarkdownBasedWorkflowConfig` | -| **`TXTWorkflow`** | 处理纯文本文档。流程为:`txt -> 翻译 -> 导出`。 | `.txt` 及其他纯文本格式 | `.txt`, `.html` | `TXTWorkflowConfig` | -| **`JsonWorkflow`** | 处理json文件。流程为:`json -> 翻译 -> 导出`。 | `.json` | `.json`, `.html` | `JsonWorkflowConfig` | -| **`DocxWorkflow`** | 处理docx文件。流程为:`docx -> 翻译 -> 导出`。 | `.docx` | `.docx`, `.html` | `docxWorkflowConfig` | -| **`XlsxWorkflow`** | 处理xlsx文件。流程为:`xlsx -> 翻译 -> 导出`。 | `.xlsx`、`.csv` | `.xlsx`, `.html` | `XlsxWorkflowConfig` | -| **`SrtWorkflow`** | 处理srt文件。流程为:`srt -> 翻译 -> 导出`。 | `.srt` | `.srt`, `.html` | `SrtWorkflowConfig` | -| **`EpubWorkflow`** | 处理epub文件。流程为:`epub -> 翻译 -> 导出`。 | `.epub` | `.epub`, `.html` | `EpubWorkflowConfig` | -| **`HtmlWorkflow`** | 处理html文件。流程为:`html -> 翻译 -> 导出`。 | `.html`, `.htm` | `.html` | `HtmlWorkflowConfig` | - -> 在交互式界面中可以导出pdf格式 +**基本流程:** +1. 根据文件类型选择工作流 +2. 配置工作流(LLM、解析引擎、输出格式) +3. 执行翻译 +4. 保存结果 ## 启动 Web UI 和 API 服务 @@ -155,6 +134,129 @@ docutranslate -i ## 使用方式 +### 使用简单的 Client SDK (推荐) + +使用 `Client` 类是开始翻译最简单的方式,它提供了简洁直观的 API: + +```python +from docutranslate.sdk import Client + +# 使用您的 AI 平台设置初始化客户端 +client = Client( + api_key="YOUR_OPENAI_API_KEY", # 或其他 AI 平台 API key + base_url="https://api.openai.com/v1/", + model_id="gpt-4o", + to_lang="中文", + concurrent=10, # 并发请求数 +) + +# 翻译单个文件 (自动检测文件类型) +result = client.translate("path/to/your/document.pdf") + +# 使用默认格式保存 (PDF -> markdown with embedded images) +print(f"翻译完成!保存位置: {result.save()}") + +# 或显式指定输出格式 +# PDF/markdown_based 支持: +# - "markdown": Markdown 格式,内嵌 base64 图片 (默认) +# - "markdown_zip": Markdown 格式,图片分离存储 (ZIP 压缩包) +# - "html": HTML 格式 +# docx 支持: "docx" +# xlsx 支持: "xlsx" +result.save(fmt="html") # 保存为 HTML +result.save(fmt="markdown") # 保存为 Markdown(内嵌图片) +result.save(fmt="markdown_zip") # 保存为 ZIP(图片分离) + +# 保存到自定义位置 +result.save(output_dir="./my_translations", name="my_document.html") + +# 导出为 Base64 编码字符串 +base64_content = result.export(fmt="html") +print(f"导出内容长度: {len(base64_content)}") + +# 您还可以访问底层工作流以进行高级操作 +# workflow = result.workflow +``` + +**Client 功能特点:** +- **自动检测**: 自动检测文件类型并选择合适的工作流 +- **灵活配置**: 可在每次翻译调用时覆盖默认设置 +- **多种输出选项**: 保存到磁盘或导出为 Base64 字符串 +- **异步支持**: 使用 `translate_async()` 进行并发翻译任务 + +#### Client SDK 参数说明 + +| 参数 | 类型 | 默认值 | 说明 | +|:---|:---|:---|:---| +| **api_key** | `str` | - | AI 平台 API 密钥 | +| **base_url** | `str` | - | AI 平台基础 URL(如 `https://api.openai.com/v1/`) | +| **model_id** | `str` | - | 翻译使用的模型 ID | +| **to_lang** | `str` | - | 目标语言(如 `"中文"`、`"English"`、`"日本語"`) | +| **concurrent** | `int` | 10 | 并发 LLM 请求数 | +| **convert_engine** | `str` | `"mineru"` | PDF 解析引擎:`"mineru"`、`"docling"`、`"mineru_deploy"` | +| **mineru_deploy_base_url** | `str` | - | 本地 minerU API 地址(当 `convert_engine="mineru_deploy"` 时) | +| **mineru_token** | `str` | - | minerU API Token(使用在线 minerU 时) | +| **skip_translate** | `bool` | `False` | 跳过翻译,仅解析文档 | +| **output_dir** | `str` | `"./output"` | `save()` 方法的默认输出目录 | +| **chunk_size** | `int` | 3000 | LLM 处理的文本分块大小 | +| **temperature** | `float` | 0.3 | LLM 温度参数 | +| **timeout** | `int` | 60 | 请求超时时间(秒) | +| **retry** | `int` | 3 | 失败重试次数 | +| **provider** | `str` | `"auto"` | AI 提供商类型(auto、openai、azure 等) | +| **force_json** | `bool` | `False` | 强制 JSON 输出模式 | +| **rpm** | `int` | - | 每分钟请求数限制 | +| **tpm** | `int` | - | 每分钟 Token 数限制 | + +#### Result 方法说明 + +| 方法 | 参数 | 说明 | +|:---|:---|:---| +| **save()** | `output_dir`, `name`, `fmt` | 将翻译结果保存到磁盘 | +| **export()** | `fmt` | 导出为 Base64 编码的字符串 | +| **supported_formats** | - | 获取支持的输出格式列表 | +| **workflow** | - | 访问底层工作流对象 | + +```python +import asyncio +from docutranslate.sdk import Client + +async def translate_multiple(): + client = Client( + api_key="YOUR_API_KEY", + base_url="https://api.openai.com/v1/", + model_id="gpt-4o", + to_lang="中文", + ) + + # 并发翻译多个文件 + files = ["doc1.pdf", "doc2.docx", "notes.txt"] + results = await asyncio.gather( + *[client.translate_async(f) for f in files] + ) + + for r in results: + print(f"保存位置: {r.save()}") + +asyncio.run(translate_multiple()) +``` + +### 可用工作流(使用 Workflow API) + +如果您需要更精细的控制,可以直接使用 Workflow API。以下是可用的工作流: + +| 工作流 | 适用场景 | 输入格式 | 输出格式 | 核心配置类 | +|:----------------------------|:--------------------------------------------------------|:-----------------------------------------|:-----------------------|:------------------------------| +| **`MarkdownBasedWorkflow`** | 处理富文本文档,如PDF、Word、图片等。流程为:`文件 -> Markdown -> 翻译 -> 导出`。 | `.pdf`, `.docx`, `.md`, `.png`, `.jpg` 等 | `.md`, `.zip`, `.html` | `MarkdownBasedWorkflowConfig` | +| **`TXTWorkflow`** | 处理纯文本文档。流程为:`txt -> 翻译 -> 导出`。 | `.txt` 及其他纯文本格式 | `.txt`, `.html` | `TXTWorkflowConfig` | +| **`JsonWorkflow`** | 处理json文件。流程为:`json -> 翻译 -> 导出`。 | `.json` | `.json`, `.html` | `JsonWorkflowConfig` | +| **`DocxWorkflow`** | 处理docx文件。流程为:`docx -> 翻译 -> 导出`。 | `.docx` | `.docx`, `.html` | `docxWorkflowConfig` | +| **`XlsxWorkflow`** | 处理xlsx文件。流程为:`xlsx -> 翻译 -> 导出`。 | `.xlsx`、`.csv` | `.xlsx`, `.html` | `XlsxWorkflowConfig` | +| **`SrtWorkflow`** | 处理srt文件。流程为:`srt -> 翻译 -> 导出`。 | `.srt` | `.srt`, `.html` | `SrtWorkflowConfig` | +| **`EpubWorkflow`** | 处理epub文件。流程为:`epub -> 翻译 -> 导出`。 | `.epub` | `.epub`, `.html` | `EpubWorkflowConfig` | +| **`HtmlWorkflow`** | 处理html文件。流程为:`html -> 翻译 -> 导出`。 | `.html`, `.htm` | `.html` | `HtmlWorkflowConfig` | + +> 在交互式界面中可以导出pdf格式 + ### 示例 1: 翻译一个 PDF 文件 (使用 `MarkdownBasedWorkflow`) 这是最常见的用例。我们将使用 `minerU` 引擎将 PDF 转换为 Markdown,然后使用 LLM 进行翻译。这里以异步方式为例。 @@ -194,22 +296,6 @@ async def main(): translator_config=translator_config, # 传入翻译器配置 html_exporter_config=MD2HTMLExporterConfig(cdn=True) # HTML 导出配置 ) - - # 使用本地部署mineru服务 - # from docutranslate.converter.x2md.converter_mineru_deploy import ConverterMineruDeployConfig - # converter_config = ConverterMineruDeployConfig( - # base_url = "http://127.0.0.1:8000", - # output_dir= "./output",#受mineru限制,解析后的文件会保存到output_dir下,需要定期清理 - # backend= "pipeline", - # start_page_id = 0, - # end_page_id = 99999, - # ) - # workflow_config = MarkdownBasedWorkflowConfig( - # convert_engine="mineru_deploy", # 指定解析引擎 - # converter_config=converter_config, # 传入转换器配置 - # translator_config=translator_config, # 传入翻译器配置 - # html_exporter_config=MD2HTMLExporterConfig(cdn=True) # HTML 导出配置 - # ) # 4. 实例化工作流 workflow = MarkdownBasedWorkflow(config=workflow_config) @@ -238,255 +324,25 @@ if __name__ == "__main__": asyncio.run(main()) ``` -### 示例 2: 翻译一个 TXT 文件 (使用 `TXTWorkflow`) +### 其他工作流 -对于纯文本文件,流程更简单,因为它不需要文档解析(转换)步骤。这里以异步方式为例。 +所有工作流都遵循相同的模式。导入对应的配置和工作流,然后进行配置: ```python -import asyncio -from docutranslate.workflow.txt_workflow import TXTWorkflow, TXTWorkflowConfig -from docutranslate.translator.ai_translator.txt_translator import TXTTranslatorConfig -from docutranslate.exporter.txt.txt2html_exporter import TXT2HTMLExporterConfig - - -async def main(): - # 1. 构建翻译器配置 - translator_config = TXTTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - ) - - # 2. 构建主工作流配置 - workflow_config = TXTWorkflowConfig( - translator_config=translator_config, - html_exporter_config=TXT2HTMLExporterConfig(cdn=True) - ) - - # 3. 实例化工作流 - workflow = TXTWorkflow(config=workflow_config) - - # 4. 读取文件并执行翻译 - workflow.read_path("path/to/your/notes.txt") - await workflow.translate_async() - # 或者使用同步的方法 - # workflow.translate() - - # 5. 保存结果 - workflow.save_as_txt(name="translated_notes.txt") - print("TXT 文件已保存。") - - # 也可以导出翻译后的纯文本 - text = workflow.export_to_txt() - - -if __name__ == "__main__": - asyncio.run(main()) +# TXT: from docutranslate.workflow.txt_workflow import TXTWorkflow, TXTWorkflowConfig +# JSON: from docutranslate.workflow.json_workflow import JsonWorkflow, JsonWorkflowConfig +# DOCX: from docutranslate.workflow.docx_workflow import DocxWorkflow, DocxWorkflowConfig +# XLSX: from docutranslate.workflow.xlsx_workflow import XlsxWorkflow, XlsxWorkflowConfig +# EPUB: from docutranslate.workflow.epub_workflow import EpubWorkflow, EpubWorkflowConfig +# HTML: from docutranslate.workflow.html_workflow import HtmlWorkflow, HtmlWorkflowConfig +# SRT: from docutranslate.workflow.srt_workflow import SrtWorkflow, SrtWorkflowConfig +# ASS: from docutranslate.workflow.ass_workflow import AssWorkflow, AssWorkflowConfig ``` -### 示例 3: 翻译一个 json 文件 (使用 `JsonWorkflow`) - -这里以异步方式为例。其中JsonTranslatorConfig的json_paths项需要指明要翻译的json路径(满足jsonpath-ng语法规范) -,仅与json路径匹配的值会被翻译。 - -```python -import asyncio - -from docutranslate.exporter.js.json2html_exporter import Json2HTMLExporterConfig -from docutranslate.translator.ai_translator.json_translator import JsonTranslatorConfig -from docutranslate.workflow.json_workflow import JsonWorkflowConfig, JsonWorkflow - - -async def main(): - # 1. 构建翻译器配置 - translator_config = JsonTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - json_paths=["$.*", "$.name"] # 满足jsonpath-ng路径语法,匹配路径的值都会被翻译 - ) - - # 2. 构建主工作流配置 - workflow_config = JsonWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Json2HTMLExporterConfig(cdn=True) - ) - - # 3. 实例化工作流 - workflow = JsonWorkflow(config=workflow_config) - - # 4. 读取文件并执行翻译 - workflow.read_path("path/to/your/notes.json") - await workflow.translate_async() - # 或者使用同步的方法 - # workflow.translate() - - # 5. 保存结果 - workflow.save_as_json(name="translated_notes.json") - print("json文件已保存。") - - # 也可以导出翻译后的json文本 - text = workflow.export_to_json() - - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### 示例 4: 翻译一个 docx 文件 (使用 `DocxWorkflow`) - -这里以异步方式为例。 - -```python -import asyncio - -from docutranslate.exporter.docx.docx2html_exporter import Docx2HTMLExporterConfig -from docutranslate.translator.ai_translator.docx_translator import DocxTranslatorConfig -from docutranslate.workflow.docx_workflow import DocxWorkflowConfig, DocxWorkflow - - -async def main(): - # 1. 构建翻译器配置 - translator_config = DocxTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - insert_mode="replace", # 备选项 "replace", "append", "prepend" - separator="\n", # "append", "prepend"模式时使用的分隔符 - ) - - # 2. 构建主工作流配置 - workflow_config = DocxWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Docx2HTMLExporterConfig(cdn=True) - ) - - # 3. 实例化工作流 - workflow = DocxWorkflow(config=workflow_config) - - # 4. 读取文件并执行翻译 - workflow.read_path("path/to/your/notes.docx") - await workflow.translate_async() - # 或者使用同步的方法 - # workflow.translate() - - # 5. 保存结果 - workflow.save_as_docx(name="translated_notes.docx") - print("docx文件已保存。") - - # 也可以导出翻译后的docx的二进制 - text_bytes = workflow.export_to_docx() - - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### 示例 5: 翻译一个 xlsx 文件 (使用 `XlsxWorkflow`) - -这里以异步方式为例。 - -```python -import asyncio - -from docutranslate.exporter.xlsx.xlsx2html_exporter import Xlsx2HTMLExporterConfig -from docutranslate.translator.ai_translator.xlsx_translator import XlsxTranslatorConfig -from docutranslate.workflow.xlsx_workflow import XlsxWorkflowConfig, XlsxWorkflow - - -async def main(): - # 1. 构建翻译器配置 - translator_config = XlsxTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - insert_mode="replace", # 备选项 "replace", "append", "prepend" - separator="\n", # "append", "prepend"模式时使用的分隔符 - ) - - # 2. 构建主工作流配置 - workflow_config = XlsxWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Xlsx2HTMLExporterConfig(cdn=True) - ) - - # 3. 实例化工作流 - workflow = XlsxWorkflow(config=workflow_config) - - # 4. 读取文件并执行翻译 - workflow.read_path("path/to/your/notes.xlsx") - await workflow.translate_async() - # 或者使用同步的方法 - # workflow.translate() - - # 5. 保存结果 - workflow.save_as_xlsx(name="translated_notes.xlsx") - print("xlsx文件已保存。") - - # 也可以导出翻译后的xlsx的二进制 - text_bytes = workflow.export_to_xlsx() - - -if __name__ == "__main__": - asyncio.run(main()) -``` - -### 示例 5: 其它workflow的配置项(使用 `HtmlWorkflow`、`EpubWorkflow`) - -这里以异步方式为例。 - -```python -# HtmlWorkflow -from docutranslate.translator.ai_translator.html_translator import HtmlTranslatorConfig -from docutranslate.workflow.html_workflow import HtmlWorkflowConfig, HtmlWorkflow - - -async def html(): - # 1. 构建翻译器配置 - translator_config = HtmlTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - insert_mode="replace", # 备选项 "replace", "append", "prepend" - separator="\n", # "append", "prepend"模式时使用的分隔符 - ) - - # 2. 构建主工作流配置 - workflow_config = HtmlWorkflowConfig( - translator_config=translator_config, - ) - workflow_html = HtmlWorkflow(config=workflow_config) - - -# EpubWorkflow -from docutranslate.exporter.epub.epub2html_exporter import Epub2HTMLExporterConfig -from docutranslate.translator.ai_translator.epub_translator import EpubTranslatorConfig -from docutranslate.workflow.epub_workflow import EpubWorkflowConfig, EpubWorkflow - - -async def epub(): - # 1. 构建翻译器配置 - translator_config = EpubTranslatorConfig( - base_url="https://api.openai.com/v1/", - api_key="YOUR_OPENAI_API_KEY", - model_id="gpt-4o", - to_lang="中文", - insert_mode="replace", # 备选项 "replace", "append", "prepend" - separator="\n", # "append", "prepend"模式时使用的分隔符 - ) - - # 2. 构建主工作流配置 - workflow_config = EpubWorkflowConfig( - translator_config=translator_config, - html_exporter_config=Epub2HTMLExporterConfig(cdn=True), - ) - workflow_epub = EpubWorkflow(config=workflow_config) -``` +主要配置选项: +- **insert_mode**: `"replace"`, `"append"`, `"prepend"` (用于 docx/xlsx/html/epub) +- **json_paths**: JSONPath 表达式用于 JSON 翻译 (例如 `["$.*", "$.name"]`) +- **separator**: 用于 `"append"` / `"prepend"` 模式的文本分隔符 ## 前置条件与配置详解 @@ -565,33 +421,47 @@ converter_config = ConverterDoclingConfig( ) ``` +### 2.3. 本地部署 MinerU 服务 + +在离线或内网环境中,推荐使用本地部署的 `minerU`,性能更好且无 API 限制。设置 `mineru_deploy_base_url` 为您的 minerU API 地址。 + +**Client SDK:** +```python +from docutranslate.sdk import Client + +client = Client( + api_key="YOUR_LLM_API_KEY", + model_id="llama3", + to_lang="中文", + convert_engine="mineru_deploy", + mineru_deploy_base_url="http://127.0.0.1:8000", # 您的 minerU API 地址 +) +result = client.translate("document.pdf") +result.save(fmt="markdown") +``` + ## FAQ -**Q: 为什么翻译出来的还是原文** -A: 查看一下日志报了什么错,一般是AI平台欠费或网络有问题(查看是否需要开启系统代理)。 +**Q: 翻译出来的还是原文?** +A: 查看日志报错,通常是 AI 平台欠费或网络问题。 -**Q: 8010 端口被占用了怎么办?** -A: 使用 `-p` 参数指定一个新端口,或设置 `DOCUTRANSLATE_PORT` 环境变量。 +**Q: 8010 端口被占用?** +A: 使用 `docutranslate -i -p 8011` 或设置 `DOCUTRANSLATE_PORT=8011`。 -**Q: 支持PDF扫描件的翻译吗?** -A: 支持。请使用 `mineru` 解析引擎,它具备强大的 OCR 能力。 +**Q: 支持 PDF 扫描件?** +A: 支持,使用 `mineru` 引擎具备 OCR 能力。 -**Q: 第一次翻译PDF为什么很慢?** -A: 如果您使用 `docling` 引擎,它首次运行时需要从 Hugging Face 下载模型。请参考上文的“网络问题解决方案”来加速此过程。 +**Q: 第一次翻译 PDF 很慢?** +A: `docling` 首次需要下载模型。使用 Hugging Face 镜像或预下载 artifact。 -**Q: 如何在内网(离线)环境使用?** -A: 完全可以。您需要满足以下条件: +**Q: 内网/离线环境使用?** +A: 可以。使用本地 LLM(Ollama/LM Studio)和本地 minerU 或 docling。 -1. **本地 LLM**: 使用 [Ollama](https://ollama.com/) 或 [LM Studio](https://lmstudio.ai/) 等工具在本地部署语言模型,并在 - `TranslatorConfig` 中填入本地模型的 `base_url`。 -2. **本地PDF解析引擎**(仅解析pdf需要): 使用 `docling` 引擎,并按照上文“离线使用”的指引提前下载模型包。 +**Q: PDF 缓存机制?** +A: `MarkdownBasedWorkflow` 在内存中缓存解析结果(最近 10 次)。可通过 `DOCUTRANSLATE_CACHE_NUM` 配置。 -**Q: PDF解析缓存机制是如何工作的?** -A: `MarkdownBasedWorkflow` 会自动缓存文档解析(文件到Markdown的转换)的结果,以避免重复解析消耗时间和资源。缓存默认保存在内存中,并会记录最近的10次解析。您可以通过 -`DOCUTRANSLATE_CACHE_NUM` 环境变量来修改缓存数量。 - -**Q: 如何让软件可以经过代理** -A: 软件默认不使用系统代理,可以在`TranslatorConfig中令system_proxy_enable=True` 启用系统代理 +**Q: 启用代理?** +A: 在 TranslatorConfig 中设置 `system_proxy_enable=True`。 ## Star History diff --git a/docutranslate/sdk.py b/docutranslate/sdk.py index a376ecd..e47f3c2 100644 --- a/docutranslate/sdk.py +++ b/docutranslate/sdk.py @@ -19,17 +19,28 @@ from docutranslate.translator import default_params from docutranslate.global_values.conditional_import import DOCLING_EXIST # --- 映射配置 --- +# 格式说明: {workflow_type: {save_type: (method_name, default_suffix)}} +# 注意: 第一个格式为默认格式 _WORKFLOW_MAPPINGS = { - "markdown_based": {"save": "save_as_markdown_zip", "export": "export_to_markdown_zip"}, - "docx": {"save": "save_as_docx", "export": "export_to_docx"}, - "xlsx": {"save": "save_as_xlsx", "export": "export_to_xlsx"}, - "pptx": {"save": "save_as_pptx", "export": "export_to_pptx"}, - "epub": {"save": "save_as_epub", "export": "export_to_epub"}, - "txt": {"save": "save_as_txt", "export": "export_to_txt"}, - "json": {"save": "save_as_json", "export": "export_to_json"}, - "srt": {"save": "save_as_srt", "export": "export_to_srt"}, - "ass": {"save": "save_as_ass", "export": "export_to_ass"}, - "html": {"save": "save_as_html", "export": "export_to_html"}, + "markdown_based": { + "markdown": ("save_as_markdown", "md"), # 默认格式: 内嵌 base64 图片 + "markdown_zip": ("save_as_markdown_zip", "zip"), # 非内嵌图片,分离存储 + "html": ("save_as_html", "html"), + }, + "docx": {"docx": ("save_as_docx", "docx")}, + "xlsx": {"xlsx": ("save_as_xlsx", "xlsx")}, + "pptx": {"pptx": ("save_as_pptx", "pptx")}, + "epub": {"epub": ("save_as_epub", "epub")}, + "txt": {"txt": ("save_as_txt", "txt")}, + "json": {"json": ("save_as_json", "json")}, + "srt": {"srt": ("save_as_srt", "srt")}, + "ass": {"ass": ("save_as_ass", "ass")}, + "html": {"html": ("save_as_html", "html")}, +} + +# 每种工作流支持的输出格式列表 +_WORKFLOW_SUPPORTED_FORMATS = { + wf: list(formats.keys()) for wf, formats in _WORKFLOW_MAPPINGS.items() } @@ -41,40 +52,94 @@ class TranslationResult: def __init__(self, workflow: Any, workflow_type: str, original_filename: str): self._workflow = workflow self._workflow_type = workflow_type + self._original_filename = original_filename self._mapping = _WORKFLOW_MAPPINGS.get(workflow_type) + self._supported_formats = _WORKFLOW_SUPPORTED_FORMATS.get(workflow_type, []) - def save(self, output_dir: str = "./output", name: Optional[str] = None) -> str: + @property + def supported_formats(self) -> List[str]: + """获取当前工作流支持的输出格式""" + return self._supported_formats + + def save( + self, + output_dir: str = "./output", + name: Optional[str] = None, + fmt: Optional[str] = None + ) -> str: """ 保存结果到文件系统。 + :param output_dir: 输出目录。 - :param name: 文件名 (如 'result.docx')。若为 None,使用默认后缀命名。 + :param name: 文件名 (如 'result.html')。若为 None,使用原文件名 + 对应后缀。 + :param fmt: 输出格式 (如 'html', 'markdown', 'markdown_zip')。 + 若为 None,使用工作流默认格式。 :return: 保存文件的完整路径 (仅供参考)。 """ if not self._mapping: raise ValueError(f"工作流 {self._workflow_type} 不支持自动保存") + # 确定使用的格式 + if fmt: + if fmt not in self._mapping: + raise ValueError( + f"格式 '{fmt}' 不支持。可用格式: {self._supported_formats}" + ) + method_name, default_suffix = self._mapping[fmt] + else: + # 使用默认第一个格式 + fmt = self._supported_formats[0] + method_name, default_suffix = self._mapping[fmt] + + # 生成文件名 + if not name: + base_name = os.path.splitext(self._original_filename)[0] + name = f"{base_name}.{default_suffix}" + Path(output_dir).mkdir(parents=True, exist_ok=True) - method = self._mapping["save"] - if hasattr(self._workflow, method): - getattr(self._workflow, method)(name=name, output_dir=output_dir) - return os.path.join(output_dir, name) if name else f"{output_dir} (Auto named)" - raise AttributeError(f"Workflow 缺少方法 {method}") + method = getattr(self._workflow, method_name, None) + if method: + method(name=name, output_dir=output_dir) + return os.path.join(output_dir, name) + raise AttributeError(f"Workflow 缺少方法 {method_name}") - def export(self) -> str: + def export(self, fmt: Optional[str] = None) -> str: """ 导出为 Base64 编码的字符串 (用于 API 传输或无需落盘的场景)。 + + :param fmt: 输出格式。若为 None,使用工作流默认格式。 + :return: Base64 编码的结果。 """ if not self._mapping: raise ValueError(f"工作流 {self._workflow_type} 不支持导出") - method = self._mapping["export"] - if hasattr(self._workflow, method): - content = getattr(self._workflow, method)() + # 确定使用的格式 + if fmt: + if fmt not in self._mapping: + raise ValueError( + f"格式 '{fmt}' 不支持。可用格式: {self._supported_formats}" + ) + export_key = fmt + else: + # 使用默认第一个格式 + fmt = self._supported_formats[0] + export_key = fmt + + method_name = f"export_to_{export_key.replace('markdown_zip', 'markdown_zip')}" + # 特殊处理 markdown_zip -> export_to_markdown_zip + if export_key == "markdown_zip": + method_name = "export_to_markdown_zip" + elif export_key in ["html", "markdown"]: + method_name = f"export_to_{export_key}" + + method = getattr(self._workflow, method_name, None) + if method: + content = method() if isinstance(content, str): content = content.encode('utf-8') return base64.b64encode(content).decode('utf-8') - raise AttributeError(f"Workflow 缺少方法 {method}") + raise AttributeError(f"Workflow 缺少方法 {method_name}") @property def workflow(self): @@ -283,7 +348,10 @@ class Client: # 8. 执行逻辑 workflow.read_path(str(path_obj)) - await workflow.translate_async() + + # 仅当 skip_translate 为 False 时才执行翻译 + if not payload.skip_translate: + await workflow.translate_async() return TranslationResult(workflow, final_params["workflow_type"], path_obj.name)