AI 工具

DeepL Write correct 与 rephrase 模式的选择

只要纠错、尽量保留作者原话时,应走 /v2/write/correct;需要语气/文体时才用 rephrase。这篇用 writemodes.py 在本地强制互斥规则,并对比两种模式输出。

BINBHO · 图文教程

只要纠错、尽量保留作者原话时,应走 /v2/write/correct;需要语气/文体时才用 rephrase。这篇用 write_modes.py 在本地强制互斥规则,并对比两种模式输出。

先看清成品

  • dry-run 能打出正确 path/payload。
  • mock 上 correct 与 business rephrase 结果不同。
  • 3 项 pytest 通过。

合规提醒:DeepL Write API 目前需要 API Pro(以官方说明为准),Free 计划可能不可用。密钥用 Authorization: DeepL-Auth-Key ...,勿提交到公开仓库。Write 是同语种润色,不是翻译;不要用它处理你无权处理的保密文本(注意 Pro 数据保护条款)。

运行说明:无 DeepL Pro 密钥。A/B/C 均用本地 mock 验证;对 api-free 用无效密钥实测 Write 返回 HTTP 403 鉴权失败。2026-10-23(Asia/Shanghai)pytest 通过。正式调用基址一般为 https://api.deepl.com 。

做完之后你会得到什么?

成果 说明
write_modes.py 模式选择器
mock_deepl_write.py 假服务
test_98b.py 3 项测试

需要准备哪些环境?

项目 说明
Python 3.10+

关键事实

事实 来源
correct 不接受 writing_style/tone 官方 Correct text
rephrase 上 style 与 tone 不能同时出现;可用 prefer_ 回退 官方 Style and tone
请求体总大小限制约 10 KiB 官方 Write Quickstart

文件结构

98-deepl-write-B-src/
├── write_modes.py
├── mock_deepl_write.py
└── test_98b.py

第 1 步:模式脚本

#!/usr/bin/env python3
"""Choose DeepL Write endpoint and validate style/tone exclusivity."""
from __future__ import annotations

import argparse
import json
import os
import sys
import urllib.error
import urllib.request


def build_payload(texts, target_lang, mode, style, tone):
    if mode not in {"rephrase", "correct"}:
        raise ValueError("mode must be rephrase or correct")
    if style and tone:
        raise ValueError("writing_style and tone are mutually exclusive")
    if mode == "correct" and (style or tone):
        raise ValueError("correct endpoint rejects writing_style/tone")
    payload = {"text": texts, "target_lang": target_lang}
    if mode == "rephrase":
        if style:
            payload["writing_style"] = style
        if tone:
            payload["tone"] = tone
    return payload


def call(base, key, mode, payload):
    path = f"/v2/write/{mode}"
    req = urllib.request.Request(
        f"{base.rstrip('/')}{path}",
        data=json.dumps(payload).encode(),
        headers={"Authorization": f"DeepL-Auth-Key {key}", "Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        raise SystemExit(f"HTTP {e.code}: {e.read().decode(errors='replace')}") from e


def main(argv=None) -> int:
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument("text")
    ap.add_argument("--mode", choices=["rephrase", "correct"], default="correct")
    ap.add_argument("--style", default=None)
    ap.add_argument("--tone", default=None)
    ap.add_argument("--lang", default="en-US")
    ap.add_argument("--base", default=os.environ.get("DEEPL_BASE_URL", "https://api.deepl.com"))
    ap.add_argument("--key", default=os.environ.get("DEEPL_API_KEY", ""))
    ap.add_argument("--dry-run", action="store_true")
    args = ap.parse_args(argv)
    try:
        payload = build_payload([args.text], args.lang, args.mode, args.style, args.tone)
    except ValueError as e:
        print(f"INVALID: {e}", file=sys.stderr)
        return 2
    if args.dry_run:
        print(json.dumps({"path": f"/v2/write/{args.mode}", "payload": payload}, ensure_ascii=False, indent=2))
        return 0
    if not args.key:
        print("设置 DEEPL_API_KEY", file=sys.stderr)
        return 2
    r = call(args.base, args.key, args.mode, payload)
    print((r.get("improvements") or [{}])[0].get("text"))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

第 2 步:测试

import subprocess
import sys
import time
from pathlib import Path
from write_modes import build_payload

HERE = Path(__file__).resolve().parent


def test_mutex():
    try:
        build_payload(["hi"], "en-US", "rephrase", "business", "friendly")
        assert False
    except ValueError:
        pass


def test_correct_rejects_style():
    try:
        build_payload(["hi"], "en-US", "correct", "business", None)
        assert False
    except ValueError:
        pass


def test_correct_vs_rephrase():
    port = 18981
    proc = subprocess.Popen(
        [sys.executable, str(HERE / "mock_deepl_write.py"), "--port", str(port)],
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
    )
    try:
        time.sleep(0.3)
        env_base = f"http://127.0.0.1:{port}"
        c = subprocess.run(
            [
                sys.executable,
                str(HERE / "write_modes.py"),
                "I could relly use sum help with edits on thiss text !",
                "--mode",
                "correct",
                "--base",
                env_base,
                "--key",
                "deepl-test-key",
            ],
            capture_output=True,
            text=True,
            check=True,
        )
        r = subprocess.run(
            [
                sys.executable,
                str(HERE / "write_modes.py"),
                "I could relly use sum help with edits on thiss text !",
                "--mode",
                "rephrase",
                "--style",
                "business",
                "--base",
                env_base,
                "--key",
                "deepl-test-key",
            ],
            capture_output=True,
            text=True,
            check=True,
        )
        assert "really" in c.stdout.lower()
        assert c.stdout.strip() != r.stdout.strip()
    finally:
        proc.terminate()
        proc.wait(timeout=5)

第 3 步:运行

INVALID: writing_style and tone are mutually exclusive
{
  "path": "/v2/write/correct",
  "payload": {
    "text": [
      "hello"
    ],
    "target_lang": "en-US"
  }
}
...                                                                      [100%]
3 passed in 0.42s

怎么检查结果?

  • --dry-run 时不联网。
  • correct 模式加 --style 应被本地拒绝。

调试示例

UI「Corrections Only」对应 correct 端点。 若你在网页端选了只纠错,API 集成却调用 rephrase,作者会抱怨「被改腔调」。先在客户端层把模式选死。

常见问题

现象 原因 处理
想要礼貌语气 用 rephrase + tone 不要塞进 correct
检测到英式/美式 target_lang en-GB / en-US
400 非法枚举 对照官方 enum

模板规则

  • 模式与产品语义一致。
  • 互斥参数本地先挡。
  • 对比样例留档。

项目资源

用途 地址
Correct text(官方) https://developers.deepl.com/api-reference/improve-text/correct-text
Style and tone(官方) https://developers.deepl.com/docs/translate/controlling-writing-style-and-tone
Improve text(官方) https://developers.deepl.com/api-reference/improve-text/request-text-improvement

选对端点,比调温度更重要。