diff --git a/README-CN.md b/README-CN.md index 1686c22..599bdf9 100644 --- a/README-CN.md +++ b/README-CN.md @@ -16,7 +16,7 @@ bilingual_book_maker 是一个 AI 翻译工具,使用 ChatGPT 帮助用户制 ## 使用 - `pip install -r requirements.txt` 或 `pip install -U bbook_maker` -- 使用 `--openai_key` 指定 OpenAI API key,如果有多个可以用英文逗号分隔(xxx,xxx,xxx),可以减少接口调用次数限制带来的错误。 +- 使用 `--openai_key` 指定 OpenAI API key,如果有多个可以用英文逗号分隔(xxx,xxx,xxx),可以减少接口调用次数限制带来的错误。 或者,指定环境变量 `BBM_OPENAI_API_KEY` 来略过这个选项。 - 本地放了一个 `test_books/animal_farm.epub` 给大家测试 - 默认用了 [GPT-3.5-turbo](https://openai.com/blog/introducing-chatgpt-and-whisper-apis) 模型,也就是 ChatGPT 正在使用的模型。 @@ -24,10 +24,11 @@ bilingual_book_maker 是一个 AI 翻译工具,使用 ChatGPT 帮助用户制 - 可以使用 DeepL free `--model deeplfree` - 可以使用 [Claude](https://console.anthropic.com/docs) 模型进行翻译 `--model claude --claude_key ${claude_key}` - 可以使用 google 来翻译 `--model google` -- 可用使用彩云进行翻译 `--model caiyun --caiyun_key ${caiyun_key}` -- 可用使用 Gemini 进行翻译 `--model gemini --gemini_key ${gemini_key}` +- 可以使用彩云进行翻译 `--model caiyun --caiyun_key ${caiyun_key}` +- 可以使用 Gemini 进行翻译 `--model gemini --gemini_key ${gemini_key}` +- 可以使用腾讯交互翻译(免费)进行翻译`--model tencentransmart` - 使用 `--test` 命令如果大家没付费可以加上这个先看看效果(有 limit 稍微有些慢) -- 使用 `--language` 指定目标语言,例如: `--language "Simplified Chinese"`,预设值为 `"Simplified Chinese"`. +- 使用 `--language` 指定目标语言,例如: `--language "Simplified Chinese"`,预设值为 `"Simplified Chinese"`. 请阅读 helper message 来查找可用的目标语言: `python make_book.py --help` - 使用 `--proxy` 参数,方便中国大陆的用户在本地测试时使用代理,传入类似 `http://127.0.0.1:7890` 的字符串 - 使用 `--resume` 命令,可以手动中断后,加入命令继续执行。 @@ -35,7 +36,7 @@ bilingual_book_maker 是一个 AI 翻译工具,使用 ChatGPT 帮助用户制 使用 `--translate-tags` 指定需要翻译的标签。使用逗号分隔多个标签。例如: `--translate-tags h1,h2,h3,p,div` - 请使用 --book_from 选项指定电子阅读器类型(现在只有 kobo 可用),并使用 --device_path 指定挂载点。 -- 如果你遇到了墙需要用 Cloudflare Workers 替换 api_base 请使用 `--api_base ${url}` 来替换。 +- 如果你遇到了墙需要用 Cloudflare Workers 替换 api_base 请使用 `--api_base ${url}` 来替换。 **请注意,此处你输入的api应该是'`https://xxxx/v1`'的字样,域名需要用引号包裹** - 翻译完会生成一本 ${book_name}_bilingual.epub 的双语书 - 如果出现了错误或使用 `CTRL+C` 中断命令,不想接下来继续翻译了,会生成一本 ${book_name}_bilingual_temp.epub 的书,直接改成你想要的名字就可以了 @@ -84,8 +85,8 @@ python3 make_book.py --book_name test_books/animal_farm.epub --prompt "Please tr python3 make_book.py --book_from kobo --device_path /tmp/kobo # 翻译 txt 文件 -python3 make_book.py --book_name test_books/the_little_prince.txt --test -# 聚合多行翻译 txt 文件 +python3 make_book.py --book_name test_books/the_little_prince.txt --test +# 聚合多行翻译 txt 文件 python3 make_book.py --book_name test_books/the_little_prince.txt --test --batch_size 20 diff --git a/README.md b/README.md index 72b457b..4e809fb 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Find more info here for using liteLLM: https://github.com/BerriAI/litellm/blob/m - support DeepL free model `--model deeplfree` - support Google [Gemini](https://makersuite.google.com/app/apikey) model `--model gemini --gemini_key ${gemini_key}` - Support [Claude](https://console.anthropic.com/docs) model, use `--model claude --claude_key ${claude_key}` +- Support [Tencent TranSmart](https://transmart.qq.com) model (Free), use `--model tencentransmart` - Use `--test` option to preview the result if you haven't paid for the service. Note that there is a limit and it may take some time. - Set the target language like `--language "Simplified Chinese"`. Default target language is `"Simplified Chinese"`. Read available languages by helper message: `python make_book.py --help` diff --git a/book_maker/translator/__init__.py b/book_maker/translator/__init__.py index c0f265a..27872ea 100644 --- a/book_maker/translator/__init__.py +++ b/book_maker/translator/__init__.py @@ -5,6 +5,7 @@ from book_maker.translator.deepl_free_translator import DeepLFree from book_maker.translator.google_translator import Google from book_maker.translator.claude_translator import Claude from book_maker.translator.gemini_translator import Gemini +from book_maker.translator.tencent_transmart_translator import TencentTranSmart from book_maker.translator.custom_api_translator import CustomAPI MODEL_DICT = { @@ -16,6 +17,7 @@ MODEL_DICT = { "gpt4": ChatGPTAPI, "claude": Claude, "gemini": Gemini, + "tencentransmart": TencentTranSmart, "customapi": CustomAPI, # add more here } diff --git a/book_maker/translator/tencent_transmart_translator.py b/book_maker/translator/tencent_transmart_translator.py new file mode 100644 index 0000000..3561a5e --- /dev/null +++ b/book_maker/translator/tencent_transmart_translator.py @@ -0,0 +1,86 @@ +import re +import time +import uuid +import requests + +from rich import print +from .base_translator import Base + + +class TencentTranSmart(Base): + """ + Tencent TranSmart translator + """ + + def __init__(self, key, language, **kwargs) -> None: + super().__init__(key, language) + self.api_url = "https://transmart.qq.com/api/imt" + self.header = { + "authority": "transmart.qq.com", + "content-type": "application/json", + "origin": "https://transmart.qq.com", + "referer": "https://transmart.qq.com/zh-CN/index", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36", + } + self.uuid = str(uuid.uuid4()) + self.session = requests.Session() + self.translate_type = "zh" + if self.language == "english": + self.translate_type = "en" + + def rotate_key(self): + pass + + def translate(self, text): + print(text) + source_language, text_list = self.text_analysis(text) + client_key = self.get_client_key() + api_form_data = { + "header": { + "fn": "auto_translation", + "client_key": client_key, + }, + "type": "plain", + "model_category": "normal", + "source": { + "lang": source_language, + "text_list": [""] + text_list + [""], + }, + "target": {"lang": self.translate_type}, + } + + response = self.session.post( + self.api_url, json=api_form_data, headers=self.header, timeout=3 + ) + t_text = "".join(response.json()["auto_translation"]) + print("[bold green]" + re.sub("\n{3,}", "\n\n", t_text) + "[/bold green]") + return t_text + + def text_analysis(self, text): + client_key = self.get_client_key() + self.header.update({"Cookie": "TSMT_CLIENT_KEY={}".format(client_key)}) + analysis_request_data = { + "header": { + "fn": "text_analysis", + "session": "", + "client_key": client_key, + "user": "", + }, + "text": text, + "type": "plain", + "normalize": {"merge_broken_line": "false"}, + } + r = self.session.post( + self.api_url, json=analysis_request_data, headers=self.header + ) + if not r.ok: + return text + response_json_data = r.json() + text_list = [item["tgt_str"] for item in response_json_data["sentence_list"]] + language = response_json_data["language"] + return language, text_list + + def get_client_key(self): + return "browser-chrome-121.0.0-Windows_10-{}-{}".format( + self.uuid, int(time.time() * 1e3) + )