Revayat Novel — 英語 → ペルシア語 書籍翻訳
以下の9ステップを順番に実行してください。各ステップはコマンドとその出力の処理ルールで構成されています。異なる順序で実行したり、前のステップが問題なく見えたからといってスキップしたりしないでください。
4つの変数を一度設定し、その後はすべての場所でそれらを使用します。
SKILL_DIR— このファイルが置かれているフォルダ。Claude Codeプラグインの場合は${CLAUDE_PLUGIN_ROOT}/skills/revayat-novelです。WORK— この書籍用のワーキングフォルダ。例:work/。PY— Pythonインタープリタ。一度解決してください。python3はほとんどのWindowsインストールでは存在しないため、これをハードコードしたコマンドラインは3つのプラットフォームのうち2つでしか動作しません。- macOS / Linux:
PY=python3 - Windows:
PY=python— またはPY="py -3"(ランチャーがインストールされている場合) - どちらも動作しない場合、ステップ1の
doctorは開始されず、それがシグナルとなります。
- macOS / Linux:
OCR_LANG— 翻訳している書籍に印刷されている言語のTesseractコード。翻訳先の言語ではありません。通常の英語→ペルシア語のジョブではengです。ペルシア語のソースはfas、ドイツ語はdeu、フランス語はfra、アラビア語はaraです。すべてのOCRステップで同じ値を使用する必要があります。 ペルシア語モデルで英語ページを認識すると、自信に満ちた見た目のナンセンスが返されます。これは低いスコアよりも悪質です。なぜなら、下流のどこでもそれを検出できないからです。
すべてのコマンドは $PY $SKILL_DIR/scripts/revayat-novel.py <stage> ... です。
決して破ってはならない5つのルール
- ペルシア語のテキストを逆転させて右から左に読ませないでください。 方向はビルダーが設定します。逆転させると、1つのビューアを除いてどこでも壊れるファイルが生成されます。
@@ idヘッダーを発明、削除、マージ、分割、または並べ替えないでください。 与えられたものをそのまま返してください。[[fn:…]]、**bold**、*italic*、`verbatim`マーカーを決して削除しないでください。 これらはカウントされており、不一致はQAに失敗します。- 翻訳を修正するために
book.jsonを手動で編集しないでください。 ワークシートを修正し、マージを再実行してください。 - 書籍を短縮しないでください。 要約したり、難しい文をスキップしたり、言い回しを和らげたりしないでください。ステップがコンテンツの欠落を報告した場合は、そのチャンクを再実行してください。
ステップ1 — ツールの確認
$PY $SKILL_DIR/scripts/revayat-novel.py doctor
"ready": true→ 続行。"ready": false→pip install -r $SKILL_DIR/requirements.txtを実行し、再度doctorを実行。optional_toolsがnot foundと表示しても、今は問題ありません。ステップ2で実際にOCRが必要かどうかがわかります。
ステップ2 — 抽出
$PY $SKILL_DIR/scripts/revayat-novel.py extract "<入力ファイル>" --out $WORK --ocr-lang $OCR_LANG
$OCR_LANG は書籍に印刷されている言語であり、上記で一度設定します。ここで間違えても目に見える失敗にはなりません。OCRはそれでもテキストを返しますが、単に間違ったテキストです。
出力されるJSONを読み、以下の表に従ってください。
| 表示される内容 | 実行すること |
|---|---|
"kind": "digital" | 何もしない。OCRは不要でした。 |
"kind": "scanned" または "mixed" | OCRが自動的に実行されました。ocr.probe_after.text_share が 0.7 を超えていることを確認してください。 |
| OCRmyPDFを指定するエラー | メッセージの指示に従ってインストールし、このステップを再実行してください。 |
clean_scan.cleaned が0以上 | その数のページからカラーウォーターマークが除去されました。 |
ocr.warning がnullではない | 内容を読んでください。ファイルはまだ使用可能なので、続行してください。 |
page_scans_dropped が0以上 | その数のページ全体のラスターが、画像としてではなくスキャン自体として認識されました。 |
クリーナーはあなたのファイルを編集しません。元のファイルはそのまま残り、クリーンされたコピーは $WORK/cleaned.pdf に書き込まれ、clean_scan にはページごとに何が除去され、何がそのまま残されたかの記録が残ります。完全にスキップするには --clean-scan off を、スタンプが残っている場合は --clean-scan force を渡してください。
書籍がスキャンされた場合、以下の2つの追加パスを今すぐ実行してください。
認識信頼度 — これがないと、誤読された単語を正しい単語と区別できません。なぜなら、どちらもソース言語の普通の単語であり、文法的な文の中にあるからです。パイプラインの後のステージではそれらを区別できず、翻訳者は間違った単語を忠実にレンダリングします。
$PY $SKILL_DIR/scripts/revayat-novel.py ocr-sidecar \
--pdf $WORK/ocr.pdf --out $WORK --lang $OCR_LANG --book $WORK/book.json
ここでの --lang は、extract に指定したのと同じ $OCR_LANG です。そうでなければなりません。このパスは同じページを再認識してエンジンの確信度を調べるため、異なるモデルは異なる単語を読み取り、書籍に書かれていないものをスコアリングします。
これにより、単語ごとのボックス、信頼度、読み順を行、ブロック、ページに集約し、実行された前処理も含めた source.ocr.json と source.ocr.txt が書き込まれ、book.json の各ブロックにその領域の信頼度がスタンプされます。low と評価されたブロックは qa check によって ocr-low-confidence として報告され、それを受け入れることはページ画像を確認することを意味します。しきい値のデフォルトは85と60で、--high / --low で変更できます。
スキャン内のイラスト — スキャンされたページは1つのフラットな画像なので、その中の写真は何かが見つけるまで別の画像ではありません。
mineru -p $WORK/cleaned.pdf -o $WORK/mineru -b pipeline -l en
$PY $SKILL_DIR/scripts/revayat-novel.py extract "<入力ファイル>" --out $WORK \
--figures-from-mineru $WORK/mineru
MinerUの -l はTesseractとは異なる独自のコードを使用します。英語ソースの場合は en、ペルシア語またはアラビア文字の場合は arabic です。$OCR_LANG と同じように、書籍に合わせて設定してください。レイアウト検出ではスクリプトを使用してページをセグメント化します。
MinerUは元のファイルではなく cleaned.pdf で実行してください。そうしないと、ウォーターマークを図のように切り取ってしまいます。MinerUからは画像のみを取得してください。 実際のペルシア語スキャンで測定したところ、MinerU自身の認識テキストは単語とその中の文字が反転して返ってきたのに対し、Tesseractは同じページを正しく読み取りました。したがって、テキストは上記のOCRパスから引き続き取得し、MinerUはOCRではできない、フラットなラスター内で画像がどこにあるかを見つけるという唯一の目的にのみ使用します。MinerUがページ範囲で実行された場合は、--figures-page-offset N を使用してください。
その後、先に進む前に結果を確認してください。
$PY $SKILL_DIR/scripts/revayat-novel.py qa check --book $WORK/book.json --allow-incomplete
ここでは untranslated-block は無視してください。まだ何も翻訳されていません。探しているのは asset-missing です。実際の書籍で stats.text_blocks が20未満の場合、抽出に失敗しています。references/extraction.md を参照してください。
ステップ3 — 用語集
$PY $SKILL_DIR/scripts/revayat-novel.py glossary scan \
--book $WORK/book.json --out $WORK/glossary.json
レポートは needs_persian を、頻度の高い順にリストします。$WORK/glossary.json を開き、最初の20エントリのそれぞれに4つのフィールドを入力します。
"target": "الیزابت بنت",
"later_form": "الیزابت بنت",
"first_form": "الیزابت بنت (Elizabeth Bennet)",
"locked": true
エントリに aliases(書籍が単独で使用する姓や名)がある場合は、そのペルシア語を alias_targets に入力します。
"aliases": ["Ashcroft", "Margaret"],
"alias_targets": ["اشکرافت", "مارگارت"]
ソースが単に「Ashcroft」とだけ述べている場合、ペルシア語も単に「اشکرافت」とだけ述べるべきです。これを空のままにすると、ドリフトチェックが毎回フルネームを要求するようになり、ペルシア語としても悪く、誤報でもあります。
first_block_id はそのままにして、パイプラインが名前を導入する単一のチャンクを決定するために使用します。編集したり、最初の言及を自分で決定したりしないでください。
実際の名前ではないエントリは削除してください。その後、続行します。
ステップ4 — ワークシートへの分割
小説全体を1つのモデルコンテキストに入れてはいけないため、最初に分割されます。分割方法は2つあり、ソースがどちらかを決定します — これは好みではありません。
| ソース | ルート |
|---|---|
| PDF(デジタル原稿またはスキャン) | ページごと — 以下 |
| EPUB、DOCX、プレーンテキスト | 文字数予算による — ステップ4b |
PDFをページごとに分割します。 ページは書籍がすでに持っている境界であり、実行間で安定しており、レビューアが見る単位であり、レンダリングされたページを比較できる唯一の単位です。文字数予算で分割されたワークシートは、予算が尽きたところで区切られますが、それは特にどこでもなく、ソースに存在しないページはソースと照合できません。以下の形式には独自のページがないため、予算ルートを採用し、そのチェックを放棄します。
$PY $SKILL_DIR/scripts/revayat-novel.py pages build \
--book $WORK/book.json --out $WORK/pages --glossary $WORK/glossary.json
これにより、ソースページごとに1つのワークシートが書き込まれます。page0001.md とその翻訳は、その横に out_page0001.md として配置されます。ステップ5の chunkNNNN.md ではなく、これらの名前を使用してください。 形式は同じで、ファイル名だけが異なり、pages next は開くべきファイルを正確に指示するため、推測する必要はありません。
また、$WORK/pages/source/page-0001.pdf も書き込まれます。各ソースページが個別のPDFとして、再レンダリングではなくコピーされるため、ボックス、回転、画質は書籍独自のものになります。マニフェストはそれぞれをSHA-256で記録し、reference_pdf には全体の実行が読み取られた元のファイルを記録します。マニフェストからソースPDFを読み取ってください。 デジタル原稿の書籍の場合はオリジナル、スキャンの場合はOCRコピーであり、どちらかをハードコードすることは他方にとって間違いです。
各ページジョブは、必要なものだけを保持します。そのページに適用される用語集の行、そこで話されている声、OCRが確信を持てなかった単語、および隣接ページの範囲指定されたスライス(翻訳しないとマークされています)。自身のテキストが予算を超えるページは、切り捨てられるのではなく、番号付きのパートに分割され(マニフェストの part と parts で示されます)、パートはページが評価される前に再結合されます。
ページ区切りで半分に切られた段落は、それが始まったページに属し、正確に1回翻訳されます。続くページではコンテキストとしてのみ表示されます。隣接コンテキストの見出しの下に表示されるブロックを決して翻訳しないでください。それはすでに別のページのワークシートに属しています。
$PY $SKILL_DIR/scripts/revayat-novel.py pages status --pages $WORK/pages
$PY $SKILL_DIR/scripts/revayat-novel.py pages next --pages $WORK/pages
status はすべてのページの状態を報告します。next は次に実行すべき最初のページを指定するため、中断された実行は最初からではなく停止した場所から再開されます。
ページループ
ソースPDFは、この実行が読み取られたもの、つまりデジタル原稿PDFの場合は書籍自身のもの、スキャンの場合はOCRコピーです。マニフェストがそれを記録しているので、存在しない可能性のあるファイルを指定するのではなく、そこから取得してください。
SOURCE_PDF=$($PY -c "import json,sys;print(json.load(open(sys.argv[1]))['reference_pdf'])" $WORK/pages/manifest.json)
一度に1ページずつ、この順序で実行します。各コマンドは前のコマンドが生成したものを必要とするため、早すぎるステップは単に拒否されます。
P=12 # `pages next` が指定したもの
# 3. 翻訳を書籍にマージ
$PY $SKILL_DIR/scripts/revayat-novel.py pages merge \
--book $WORK/book.json --pages $WORK/pages --page $P --glossary $WORK/glossary.json
# 4. その1ページを単独でレイアウト
$PY $SKILL_DIR/scripts/revayat-novel.py pages preview \
--book $WORK/book.json --pages $WORK/pages --page $P
# 5. ソースページと比較
$PY $SKILL_DIR/scripts/revayat-novel.py render-qa \
--book $WORK/book.json --work $WORK --page $P \
--docx $WORK/previews/page-0012.docx --source-pdf $SOURCE_PDF
# 6. 2つの画像を確認(ステップ8で何を確認するかを説明)
$PY $SKILL_DIR/scripts/revayat-novel.py pages review \
--pages $WORK/pages --page $P \
--answer figure-placement=yes --answer script-integrity=yes \
--answer no-source-language=yes --answer hierarchy=yes \
--answer reads-as-a-book=yes --note "見たもの"
# 7. ここでのみ
$PY $SKILL_DIR/scripts/revayat-novel.py pages accept \
--book $WORK/book.json --pages $WORK/pages --page $P
その後、pages next を再度実行し、何も残っていないと表示されるまで繰り返します。
ステップ4は必須ではなく、スキップするとステップ5が代わりに実行します。 --docx を省略すると、render-qa が自力でプレビューを構築します。明示的なコマンドは、Wordでページを開いて自分で確認したい場合に使用します。
プレビューは1つのソースページが単独でレイアウトされたものです。 これは強調しておきますが、書籍全体ではありません。ペルシア語はリフローされるため、ソースの12ページが書籍の12ページになるとは限らず、小説の中盤では数ページのずれが生じます。書籍の12枚目のシートを12ページの期待値と照合すると、正しいページがテキストすべてを欠き、隣のページのテキストを運んでいるとして報告されます。プレビューはプロダクションビルダー(同じスタイル、フォント、RTL、画像サイズ設定、見出しロジック)で設定されているため、見ているものは実際のコンテンツの実際のタイプセットです。
ペルシア語が英語より長いページは2枚のシートになります。これは普通のことで、両方とも renders/target/page-0012.png と page-0012-2.png として保存され、QAはそれらすべてを読み取ります。
accept はすべてのゲートが実際に通過しない限り拒否します。あなたの言葉を信じるのではなく証拠を読み取るため、そうだと主張するだけではページを完了とマークできません。必要なものは4つです。ページが送信したすべてのユニットに対する書籍内のペルシア語、実行記録のレンダリングQA合格、それをまだ示しているレポート、そして最新のビジュアルレビューです。
再構築は安全であり、翻訳を破棄することはありません。最後にカットされてからソーステキストが変更されたページは invalidated の下にリストされます。これらのページだけが再翻訳を必要とします。異なる予算での再構築から残されたワークシートは orphaned の下にリストされます。ディスク上にはまだ存在しますが、もう誰も読み取らないため、その翻訳は書籍に到達しません。
ステップ4b — ソースにページがない場合
EPUB、DOCX、プレーンテキストのみ。PDFの場合はステップ4を使用してください。
$PY $SKILL_DIR/scripts/revayat-novel.py chunk build \
--book $WORK/book.json --out $WORK/chunks --glossary $WORK/glossary.json
チャンクの数をメモしてください。それぞれが1つの翻訳タスクになります。
すでにいくつかのワークシートを翻訳していて、その後に入力が変更された場合、これは静かに、ブックと一致しなくなったワークシートを渡すのではなく、"refused": "stale-worksheets" で拒否します。
[翻訳のため省略]