基于 HTTP 协议 开发 Telegram 翻译机器人
本文档旨在指导开发者使用 HTTP 协议开发 Telegram 机器人。通过配置 Webhook 地址,并结合提供的 Java 代码示例,您可以实现一个具备翻译功能的 Telegram 机器人。
目录
简介
Telegram 机器人是基于 Telegram 平台的自动化程序,可以与用户进行互动,实现各种功能。本文将介绍如何使用 HTTP 协议开发一个支持翻译功能的 Telegram 机器人。通过配置 Webhook 地址,机器人能够接收并处理来自用户的消息,并返回翻译结果。
协议支持
Telegram 机器人开发支持两种协议:
- HTTP 协议:通过 Webhook 接收和发送消息,适用于大多数应用场景。
- MTProto 协议:Telegram 自有的协议,适用于需要更高性能和安全性的场景。
本文将重点介绍如何使用 HTTP 协议 进行开发。
配置 Telegram 机器人
在开发 Telegram 机器人之前,需要完成以下配置步骤:
1. 创建 Telegram 机器人
通过 Telegram 的 BotFather 创建一个新的机器人,并获取机器人的 API Token。
2. 设置 Webhook 地址
配置机器人的 Webhook 地址,使 Telegram 能够将用户消息推送到您的服务器。参考以下文档进行配置:
确保您的服务器能够通过 HTTPS 访问,并且 Webhook 地址是可用的。
提示词配置
为了实现翻译功能,需要配置一个提示词文件 translator_prompt.txt
,用于指导翻译模型的行为。以下是提示词的内容:
You are a helpful translator.
- Please translate the following #(src_lang) into #(dst_lang).
- Preserve the format of the source content during translation.
- Do not provide any explanations or text apart from the translation.
<data>
#(source_text)
</data>
提示词说明
- src_lang:源语言,例如 "Chinese"。
- dst_lang:目标语言,例如 "English"。
- source_text:需要翻译的文本内容。
此提示词指示翻译模型仅返回翻译结果,不添加额外的解释或文本。
开发实现
本文档提供了两个关键的 Java 类,用于实现 Telegram 机器人的 Webhook 控制器和翻译服务。
TelegramWebhookController
TelegramWebhookController
负责接收来自 Telegram 的 Webhook 请求,解析消息内容,并调用翻译服务进行处理。
package com.litongjava.gpt.translator.controller;
import com.alibaba.fastjson2.JSONObject;
import com.litongjava.annotation.RequestPath;
import com.litongjava.gpt.translator.services.TranslatorService;
import com.litongjava.gpt.translator.vo.TranslatorTextVo;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.tio.boot.http.TioRequestContext;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.utils.json.FastJson2Utils;
import com.litongjava.tio.utils.telegram.Telegram;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequestPath("/telegram")
public class TelegramWebhookController {
@RequestPath("/webhook")
public HttpResponse handleTelegramWebhook(HttpRequest request) {
String bodyString = request.getBodyString();
JSONObject jsonObject = FastJson2Utils.parseObject(bodyString);
JSONObject message = jsonObject.getJSONObject("message");
JSONObject chat = message.getJSONObject("chat");
String chatId = chat.getString("id");
String text = message.getString("text");
log.info("Received text: {}", text);
// 根据文本内容设置源语言和目标语言
String srcLang;
String destLang;
if (containsChinese(text)) {
srcLang = "Chinese";
destLang = "English";
} else {
srcLang = "English";
destLang = "Chinese";
}
// 创建翻译请求对象
TranslatorTextVo translatorTextVo = new TranslatorTextVo();
translatorTextVo.setSrcText(text);
translatorTextVo.setSrcLang(srcLang);
translatorTextVo.setDestLang(destLang);
String responseText;
try {
// 调用翻译服务
responseText = Aop.get(TranslatorService.class).translate(chatId, translatorTextVo);
} catch (Exception e) {
log.error("Exception", e);
responseText = "Exception: " + e.getMessage();
}
// 发送翻译结果回 Telegram
Telegram.use().sendMessage(chatId.toString(), responseText);
return TioRequestContext.getResponse();
}
/**
* 判断文本中是否包含中文字符
*
* @param text 输入的文本
* @return 如果包含中文字符则返回 true,否则返回 false
*/
private boolean containsChinese(String text) {
if (text == null || text.isEmpty()) {
return false;
}
// 使用正则表达式检查是否包含中文字符
return text.matches(".*[\\u4e00-\\u9fa5]+.*");
}
}
代码解析
- 接收请求:通过
/telegram/webhook
路径接收来自 Telegram 的 Webhook 请求。 - 解析消息:使用
FastJson2Utils
解析请求体中的 JSON 数据,提取消息内容和聊天 ID。 - 语言检测:通过
containsChinese
方法判断消息文本是否包含中文字符,从而确定源语言和目标语言。 - 调用翻译服务:创建
TranslatorTextVo
对象,设置源文本及其语言信息,调用TranslatorService
进行翻译。 - 发送翻译结果:将翻译后的文本通过 Telegram 发送回用户。
TranslatorService
TranslatorService
负责与翻译模型进行交互,并处理翻译请求的缓存和记录。
package com.litongjava.gpt.translator.services;
import java.util.HashMap;
import java.util.Map;
import com.jfinal.template.Engine;
import com.jfinal.template.Template;
import com.litongjava.db.activerecord.Db;
import com.litongjava.db.activerecord.Row;
import com.litongjava.gpt.translator.constant.TableNames;
import com.litongjava.gpt.translator.vo.TranslatorTextVo;
import com.litongjava.openai.chat.ChatResponseUsage;
import com.litongjava.openai.chat.ChatResponseVo;
import com.litongjava.openai.client.OpenAiClient;
import com.litongjava.openai.constants.OpenAiModels;
import com.litongjava.tio.utils.crypto.Md5Utils;
import com.litongjava.tio.utils.snowflake.SnowflakeIdUtils;
public class TranslatorService {
public ChatResponseVo translate(TranslatorTextVo translatorTextVo) {
String srcLang = translatorTextVo.getSrcLang();
String destLang = translatorTextVo.getDestLang();
String srcText = translatorTextVo.getSrcText();
Engine engine = Engine.use();
Template template = engine.getTemplate("translator_prompt.txt");
Map<String, String> values = new HashMap<>();
values.put("src_lang", srcLang);
values.put("dst_lang", destLang);
values.put("source_text", srcText);
String renderToString = template.renderToString(values);
ChatResponseVo respnseVo = null;
try {
respnseVo = OpenAiClient.chatCompletionsByModel(OpenAiModels.gpt_4o, "system", renderToString);
} catch (Exception e) {
try {
respnseVo = OpenAiClient.chatCompletionsByModel(OpenAiModels.gpt_4o, "system", renderToString);
} catch (Exception e2) {
respnseVo = OpenAiClient.chatCompletionsByModel(OpenAiModels.gpt_4o, "system", renderToString);
}
}
return respnseVo;
}
public String translate(String chatId, TranslatorTextVo translatorTextVo) {
String srcText = translatorTextVo.getSrcText();
String md5 = Md5Utils.getMD5(srcText);
Row record = Db.findColumnsById(TableNames.max_kb_sentence_tanslate_cache, "dst_text", "md5", md5);
String dstText = null;
if (record != null) {
dstText = record.getStr("dst_text");
if (dstText != null) {
return dstText;
}
}
long start = System.currentTimeMillis();
ChatResponseVo chatRespnseVo = this.translate(translatorTextVo);
long end = System.currentTimeMillis();
dstText = chatRespnseVo.getChoices().get(0).getMessage().getContent();
long id = SnowflakeIdUtils.id();
ChatResponseUsage usage = chatRespnseVo.getUsage();
Row saveRecord = Row.by("id", id)
.set("md5", md5)
.set("from", "telegram")
.set("user_id", chatId)
.set("src_lang", translatorTextVo.getSrcLang())
.set("src_text", translatorTextVo.getSrcText())
.set("dst_lang", translatorTextVo.getDestLang())
.set("dst_text", dstText)
.set("model", chatRespnseVo.getModel())
.set("system_fingerprint", chatRespnseVo.getSystem_fingerprint())
.set("completion_tokens", usage.getCompletion_tokens())
.set("prompt_tokens", usage.getPrompt_tokens())
.set("total_tokens", usage.getTotal_tokens())
.set("elapsed", (end - start));
Db.save(TableNames.max_kb_sentence_tanslate_cache, saveRecord);
return dstText;
}
}
代码解析
翻译请求构建:
- 使用 JFinal 模板引擎加载
translator_prompt.txt
文件,并填充源语言、目标语言及源文本。 - 生成完整的提示词字符串,用于发送给 OpenAI 的翻译模型。
- 使用 JFinal 模板引擎加载
调用 OpenAI 翻译模型:
- 使用
OpenAiClient
调用 GPT-4 模型进行翻译。 - 实现重试机制,确保请求的可靠性。
- 使用
缓存机制:
- 通过 MD5 哈希值检查是否存在翻译缓存,避免重复翻译相同文本,提高效率。
- 若缓存中存在翻译结果,直接返回缓存内容;否则,进行翻译并将结果保存到数据库中。
记录翻译使用情况:
- 保存翻译请求和响应的详细信息,包括使用的模型、令牌数量等,便于后续分析和优化。
测试翻译功能
完成上述配置和开发后,即可通过 Telegram 与机器人进行对话,测试翻译功能。以下是测试步骤:
- 启动服务器:确保您的服务器正在运行,并且 Webhook 地址已正确配置。
- 与机器人对话:在 Telegram 中找到您的机器人,发送需要翻译的文本。
- 查看翻译结果:机器人将根据文本内容自动检测源语言,并返回翻译后的文本。
示例
用户发送:
你好,世界!
机器人回复:
Hello, World!
用户发送:
Good morning!
机器人回复:
早上好!
总结
本文档详细介绍了如何使用 HTTP 协议开发一个具备翻译功能的 Telegram 机器人。通过配置 Webhook 地址、设置翻译提示词,并结合提供的 Java 代码示例,您可以快速搭建并测试自己的翻译机器人。该机器人具备自动语言检测、翻译缓存和使用记录等功能,确保高效和可靠的用户体验。
如在开发过程中遇到任何问题,请参考相关文档或寻求社区支持。