把飞书、QQ 变成翻译助手,这活儿我最近用 n8n + LangBot + GPT-6 真跑通了。先别急着划走,这听起来像折腾玩具,实际上解决的是群里刚需:老外消息进来,你希望能翻译,但又不希望人名被翻错、时间格式乱掉、链接被截断。我把它拆成了三层:n8n 负责工作流编排,LangBot 负责打通飞书和 QQ 的消息通路,GPT-6 负责真正干翻译的活。这套组合的好处是,以后不只是翻译,你想加情感分析、摘要、关键词提取,都只在 n8n 里拖节点就行,不用重写一套机器人逻辑。
先说几个关键词:n8n 是一个开源自动化工具,拖着节点就能搭流程,支持 Webhook、HTTP、数据库、消息等几百个节点;LangBot 是一个连接大模型和聊天平台的网关,能把飞书、QQ 这类 IM 接入到大模型后面;GPT-6 是我们这次用的模型接口,我这边跑的是它当前可用的 API 版本,如果你用的是别的兼容接口,也能照着同样的套路改过来。整个过程做完,群里发一段英文消息,机器人自动回中文;发一段中文,它自动回英文。人名保持原样,时间能看懂,链接点得动。
这套东西适合谁?如果你在运营跨境社群、做海外客户支持、或者只是经常和外语群友聊天,又不想把聊天记录粘来粘去地找翻译软件,那这篇文章就是给你写的。下面我按自己实操的顺序,从需求拆解、环境部署、工作流设计、完整实现到问题排查,一条条讲清楚。
1. 先拆需求:为什么翻译助手必须“保留人名、时间和链接”
1.1 翻译不是“换个语言”这么简单
我做第一版的时候,直接写了个最简单的 prompt:“把输入翻译成中文”。结果跑起来发现,群里一个叫 Michael 的人说话,翻译完变成了“迈克尔”;明明是“3pm Friday”,被翻成“周五下午3点”也就算了,最离谱的是消息里贴的文档链接,被模型“好心”地读成了文字,或者被空格和标点切碎了。
这个问题的本质是:大模型翻译时,会自己对文本做“理解性重写”。它觉得“Michael”就是一个普通英文名,翻译成“迈克尔”才符合中文习惯;它觉得网址太长,直接省略掉后面的路径。但在真实的协作场景里,人名是身份标识,时间是排期依据,链接是资源入口。翻错任何一个,机器人不是在帮忙,而是在帮倒忙。
所以“保留人名、时间和链接”不是一个可选的加分项,而是决定这个翻译助手能不能实际用的底线。我的目标不是“翻得信达雅”,而是“翻得准、翻得稳、关键信息零损失”。
1.2 飞书和 QQ 的接入差异
飞书这边最常见的做法是自建机器人,通过事件订阅接受消息,然后往你的回调服务推 JSON。QQ 那边情况稍复杂,官方机器人接口和社区适配器都有,但消息格式和鉴权方式各不相同。如果我为每个平台单独写一套对接逻辑,后面维护就是个灾难。
LangBot 的价值就是把这一层统一掉。它本身已经实现了飞书、QQ 等多个 IM 的适配,你只需在 LangBot 里配置好平台凭据,它收到消息后统一转成内部事件,再通过脚本或插件转发给你指定的地址。我直接把 LangBot 的消息转发到 n8n 的 Webhook,后面全部逻辑都在 n8n 里做,代码几乎不用碰。
1.3 为什么是 n8n + LangBot + GPT-6 这个组合
先说 GPT-6。翻译质量直接取决于模型的指令遵循能力。GPT-6 在理解“哪些内容必须原样保留”这类约束上做得比早期模型好很多,温度调低之后输出也比较稳定。如果你暂时用不上 GPT-6,换一个支持相同 API 格式的模型也行,但注意它的少样本遵循能力不能太差,否则后面那些规则很难稳住。
再说 n8n。它把翻译流程变得可视化、可维护。以前我们写脚本,改一个逻辑要重新部署;现在直接在可视化画布里加节点、连线条、改字段,立刻生效。n8n 的 Webhook 节点能接收 LangBot 转来的消息,HTTP Request 节点能调模型接口,IF 节点能判断成功失败,Respond to Webhook 能把结果返回给 LangBot。这一串下来,几乎全是配置,不写一行业务代码。
最后说 LangBot。它解决了“谁去接消息、谁把结果发回去”的问题。没有 LangBot,我得自己处理飞书和 QQ 的鉴权、回调、重连、消息序列化;有了它,我只用关心业务逻辑。很多做自动化的人容易忽略“消息入口”这一层,结果花了大半时间在排平台接口的坑,不值。
这个组合不是唯一解,但如果你要同时覆盖飞书和 QQ,还要保证后续可扩展,它是当前最省心的一条路。接下来进入实操,先看环境怎么搭。
2. 环境准备:把地基打稳
2.1 用 Docker Compose 部署 n8n
n8n 的官方推荐是 Docker 部署,尤其适合要长期跑工作流的场景。我直接用 Docker Compose 起了一个实例,持久化数据放在宿主机目录,避免容器删了数据全丢。
# docker-compose.yml services: n8n: image: docker.n8n.io/n8nio/n8n container_name: n8n restart: unless-stopped ports: - "5678:5678" environment: - TZ=Asia/Shanghai - N8N_HOST=your-domain.example.com - N8N_PROTOCOL=https - WEBHOOK_URL=https://your-domain.example.com/ - GENERIC_TIMEZONE=Asia/Shanghai volumes: - ./n8n_data:/home/node/.n8n注意几个关键点:N8N_HOST要填实际对外访问的域名,如果你的 n8n 只在内网测试,可以先用本机 IP;WEBHOOK_URL影响生成的 Webhook 回调地址,LangBot 转发消息时要用它;TZ和GENERIC_TIMEZONE统一时区,不然日志时间和翻译时可能出现 8 小时偏差。
如果你只是想快速体验,不搞域名和反代,也可以一条命令跑起来:
docker run -it --rm -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n不过这种模式不持久化配置到文件,重启会有风险,我不建议在正式场景里这么用。还有一种 Node.js 安装方式,直接npm install n8n -g,然后n8n start。适合本地开发速测,但生产环境还是容器更干净、更便于回滚。
2.2 部署 LangBot 并连接飞书和 QQ
LangBot 的部署方式有两种,一种是 Docker,一种是基于 Python 的安装包。我这次图省事,直接用了它的 Docker 镜像。先拉镜像,配置好langbot的数据目录,然后按官方文档填入平台证书。
飞书这边你需要先创建一个飞书应用,在“机器人”能力里开启机器人,拿到 App ID、App Secret。然后在事件订阅里配置请求地址。这里有个容易搞混的点:飞书要求回调地址必须是公网可访问的 HTTPS 地址。你得确保你的 LangBot 服务能被外网访问到,并且在飞书后台把“Encrypt Key”“Verification Token”填到 LangBot 配置里。请求方式最好直接选“长连接”,少一个公网回调的麻烦。
QQ 那边比较复杂。如果你用的是官方机器人接口,流程跟飞书类似,创建机器人、绑定应用、设置回调。如果你用的是社区适配器,LangBot 一般都内置了对应的连接模块,按照配置模板填好 token 和 API 地址就行。我的经验是:不要纠结于协议细节,LangBot 的文档写得比早期版本清楚很多,照着配一次就能通。
配完后,在 LangBot 管理面板里测试一下,用对应平台账号给机器人发条消息,看后台能不能打印出事件日志。能收到日志,说明 LangBot 已经打通了平台;收不到,优先检查机器人是否启用、token 是否填错、回调地址是否真实可达。
2.3 接入 GPT-6 兼容接口并配置 n8n Credentials
有了 n8n 和 LangBot,还差模型接口。GPT-6 我这边用的是兼容 OpenAI 格式的接口,所以 n8n 里有两种接法:一是直接用内置的 OpenAI 节点,把 Base URL 改成你的接口地址;二是更通用的 HTTP Request 节点,手写请求体。我倾向于用后者,因为不依赖 n8n 的节点更新速度,换模型时只要改 URL 和模型名。
但有一个原则必须守住:API Key 不能明文散落在每个节点里。n8n 有 Credentials 功能,专门用来存这类敏感信息。我创建一个 HTTP Request 类型的 Credential:
- 类型选 “Header Auth”
- Name 填
Authorization - Value 填
Bearer sk-xxxxxxxx - 在节点里选择这个 Credential,n8n 会自动带上请求头。
这个操作为什么重要?因为 n8n 的流程是可视化存储的,如果直接把密钥填在节点参数里,导出流程分享给别人时密钥也跟着泄露。用 Credential 统一管理,导出时只会看到“使用凭据 ID”,别人拿不到真实 Key。我见过太多人图省事把密钥写死在 URL 里,最后被扫描到盗刷的,千万别学。
如果你用的是 OpenAI 节点而不是 HTTP Request,同样在 Credentials 里新增 OpenAI 账号,填 API Key,如果有自定义 Base URL,在连接选项中设置。n8n 的 OpenAI 节点封装了 chat completion 接口,响应解析也帮你做了,适合不想碰 JSON 的朋友。但因为它封装得比较厚,有些特殊参数(比如某些模型的reasoning_effort字段)不一定暴露出来,所以我个人还是习惯 HTTP 节点,后面调试直观。
2.4 n8n 忘记密码怎么办
这个坑我踩过,而且频率不低。自己搭的 n8n 跑了一段时间,密码忘了,登录不上,又不想删库重来。n8n 自带命令行工具可以重置密码。
容器部署时,先确认容器的执行方式:
docker compose exec n8n n8n user:reset-password --email=admin@example.com --password=newpassword执行成功后会提示密码已更新。注意,如果 n8n 还在运行,部分老版本需要先停掉再执行,否则会有权限冲突。如果你是用 Node.js 直接起的进程,就把docker compose exec换成n8n user:reset-password --email=... --password=...。
还有一个更底层的方案:如果用户表损坏,或你实在找不到管理员账号,直接清空掉settings表里的用户数据也是办法,但这样会丢失所有用户配置,我只有在万不得已时才用。
从这里开始,你的 n8n 和 LangBot 应该都已经跑起来了。接下来就是最核心的部分:怎么设计一条工作流,让消息进来后自动走完“接收→翻译→回复”的全过程。
3. 工作流设计:消息进来之后发生了什么
3.1 从 LangBot 到 n8n 的 Webhook 链路
整个消息链路可以用一句话概括:用户在飞书/QQ 发消息 → 平台推给 LangBot → LangBot 处理并转发给 n8n 的 Webhook → n8n 执行翻译流程 → 返回结果给 LangBot → LangBot 把回复发回原会话。
这里有一个动手前必须想清楚的设计点:LangBot 该以什么格式把消息传给 n8n?我建议统一成一个 JSON 结构,至少包含这些字段:
{ "rawText": "好,这条消息要不要翻译?", "platform": "feishu", "userId": "ou_xxx", "conversationId": "oc_xxx", "messageId": "msg_xxx" }为什么要把platform和conversationId传过来?因为 n8n 回复时,需要知道回给谁。LangBot 内部能拿到这些信息,但如果 n8n 只管“翻译”不知道“回哪儿”,那工作流就没法闭环。所以从 LangBot 写转发脚本的第一刻起,就把这些字段带全。
我在 LangBot 这边用了一个很简单的自定义事件脚本,核心逻辑就是收到消息时判断文本类型,构造上面的 JSON,然后requests.post到 n8n 的 Webhook URL。这里要注意 n8n 的 Webhook 可以开启“响应后返回”,所以 LangBot 会同步收到 n8n 的返回值,再把它作为回复内容发出去。如果你的场景需要排队,也可以让 n8n 异步处理完再主动调 LangBot 的接口发消息,但我建议第一版用同步响应,简单可靠。
3.2 翻译提示词:如何保住人名、时间和链接
提示词是整个助手的大脑。我在这个项目里迭代过至少四个版本,最终用了一套“规则 + 示例 + 输出约束”的结构。先放出来给你看:
你是一个跨语言翻译助手。请将用户输入的内容翻译成目标语言。 必须遵守的硬性规则: 1. 人名一律保留原文,不要翻译、不要音译、不要加括号注释。 2. 时间信息按目标语言习惯表达,但必须保留原始时区标注;如果原文使用 12 小时制,目标语言习惯 24 小时制时可转换,但要确保等价。 3. URL、链接、邮箱、文件名、版本号、代码片段、HTML 标签、页面路径等一律原样输出,不得删除、截断或改写。 4. 保持消息原有的换行和分段结构。 5. 只输出翻译结果,不输出任何附加说明、修饰语或问候语。 示例: 输入:Hey Michael, could you share the link by 3pm ET? https://example.com/doc?id=123 输出:Michael,你可以在美国东部时间下午3点前分享链接吗?https://example.com/doc?id=123 现在开始翻译: 输入:{rawText}注意几个细节:
第一,不要只写“不要翻译人名”,要写清楚“人名保留原文”。模型在理解否定指令时容易矫枉过正,你写“不要音译”,它可能保留,但如果你不告诉他“人名的处理方式是保留原文”,它还是会试图本地化。直接给正面处理方案,效果明显更稳。
第二,必须给示例。少样本学习在约束类任务里几乎是必杀技。GTP-6 对复杂指令的理解很强,但给它一个“标准答案”看看,它就知道你要求的具体表现是什么。实践证明,同样的规则,给一个示例命中率从 70% 提到 95% 以上。
第三,输出约束要放在最后,并且用“只输出翻译结果”收尾。这一步是为了防止模型自己加一句“好的,我是您的翻译助手”之类的废话。聊天模型有迎合用户的本能,不给强约束,它就会把回复当成对话而不是翻译任务。
3.3 调用 GPT-6 的 HTTP 节点与关键参数
编写 n8n 流程时,我把调用模型的部分做成了一个 HTTP Request 节点,因为这样最直接。配置如下:
- 节点类型:HTTP Request
- 方法:POST
- URL:
https://api-model.example.com/v1/chat/completions - 认证:选择第 2.3 节创建好的 Credential
- 请求体格式:JSON
- 请求体内容:
{ "model": "gpt-6", "messages": [ { "role": "system", "content": "{{ $('Set 消息文本').item.json.prompt }}" } ], "temperature": 0.2, "max_tokens": 1024, "top_p": 0.9 }这里有个关键点:不要在 HTTP 节点里拼长文本。我会在它前面放一个 Set(Edit Fields)节点,把第 3.2 节的提示词模板和rawText用表达式拼接好,存成一个字段叫prompt。然后在 HTTP 节点的 messages 里只引用prompt。这样流程清爽,以后调 prompt 不用挖到 HTTP 节点的深层配置里。
温度调到 0.2,是这个场景比较稳的参数。翻译任务偏向“确定性输出”,温度过高会带来随机性,可能出现同一条消息每次翻译结果不一样;温度太低又可能让模型过度机械。0.2 是我试过的一个平衡点。max_tokens给 1024,对绝大多数群聊消息足够;如果你经常要翻译长文,可以调到 2048,但要注意成本和响应时间。
3.4 结果解析与回传
调用模型后,n8n 会拿到类似这样的响应:
{ "choices": [ { "message": { "role": "assistant", "content": "翻译结果是..." } } ] }我需要把这个content取出来,再回传给 LangBot。在 n8n 里最直接的方式是使用 Code 节点,或者直接用一个 HTTP Response 返回。我的流程是:HTTP Request 节点之后接一个 Set 节点,把$json['choices'][0]['message']['content']存成translatedText;然后接一个 Respond to Webhook 节点,返回一个 JSON:
{ "replyText": "{{ $json.translatedText }}" }LangBot 收到这个响应后,读取replyText字段,作为机器人回复发回原会话。注意:如果 LangBot 转发脚本写的是res.json()['replyText'],那字段名必须完全一致。我前面为了字段名问题排查过好一阵子,一会儿是reply,一会儿是text,最后统一成replyText,世界安静了。
4. 实操全流程:从零搭建一个可用的翻译机器人
4.1 在 LangBot 里加一个消息路由
LangBot 的插件机制允许你监听消息事件。我用的是一个 Python 插件,代码如下(关键逻辑,可运行到 LangBot 的插件目录):
import requests import json N8N_WEBHOOK_URL = "https://your-n8n.example.com/webhook/translate" def on_message(message, **kwargs): raw = message.get("raw_text", "") platform = message.get("platform", "") conversation_id = message.get("conversation_id", "") user_id = message.get("user_id", "") # 这里你可以加一个开关:只在指定群里翻译 # if conversation_id not in ["oc_allowlist_group"]: # return None payload = { "rawText": raw, "platform": platform, "userId": user_id, "conversationId": conversation_id, "messageId": message.get("message_id", "") } try: resp = requests.post( N8N_WEBHOOK_URL, json=payload, timeout=120 ) data = resp.json() reply = data.get("replyText", "") if reply: # 返回字符串给 LangBot 作为自动回复 return reply except Exception as e: return f"翻译服务暂不可用:{e}" return None这个脚本做的事很朴素:组装好消息数据,POST 给 n8n,拿到replyText就返回。注意timeout=120要够大,因为大模型接口响应经常要十几秒,默认的几秒超时根本不够。我把超时设置在 120 秒,并且因为 n8n 那边也是同步等待模型,整体链路最长可能接近两分钟。
如果你不想写插件,LangBot 也可以配置内置的“HTTP 转发”选项,把收到的消息直接转发到指定 URL。但那种方式需要你自己在 n8n 端适配 LangBot 的默认字段,不如自定义脚本可控。我是直接写脚本的,省去字段映射的麻烦。
4.2 在 n8n 里搭核心流程
打开 n8n,新建工作流,从左侧节点列表里拖出这几个节点,按顺序连接:
Webhook:作为流程起点。Method 选 POST,Path 填
translate。这样完整的 Webhook URL 就是https://your-n8n.example.com/webhook/translate。生成后,复制这个 URL 填到 LangBot 脚本的N8N_WEBHOOK_URL里。Set(消息预处理):把 LangBot 传来的 JSON 里的
rawText提取出来,顺便拼接翻译提示词。这里用 n8n 的表达式,{{ $json.rawText }}取到消息原文,然后和固定模板拼成一个字段prompt。HTTP Request(调用模型):配置已经在第 3.3 节写清楚。直接选择创建好的 Credential,填入模型接口地址和请求体。
Set(提取回复):从模型响应里取出
choices[0].message.content,存成translatedText。Respond to Webhook:返回
replyText给 LangBot。
整个流程只有五个节点,但已经能完成一次完整翻译。做完了先不要直接挂到正式环境,先在 n8n 里点击“Execute workflow”手动测试。你会发现 n8n 可以单独运行一个节点,也可以运行整条链,每条执行记录都有输入输出 JSON,排查问题非常方便。
4.3 用工作流变量保存会话语言偏好
多一步思考:如果群里一半人要求中译英,一半人要求英译中,机器人怎么知道谁想要什么?最简单的方案是在 LangBot 脚本里加一个“指令前缀”,比如消息以/en开头就翻译成英文,以/zh开头就翻译成中文,否则自动检测原语言并翻译成另一种。
在 n8n 里,你可以在 Set 节点中判断rawText是否以/en开头,然后用 IF 节点分两条线路,分别走“中译英提示词”和“英译中提示词”。这个其实不难,但我建议第一版只做“翻译成中文”和“翻译成英文”两种模式,并且不自动检测语言,因为自动检测很容易翻反:一段夹杂大量英文术语的中文,模型可能把它当成英文,输出还是中文,用户会一脸懵。
我的默认逻辑是:检测原文里中文字符的比例,如果超过 10%,就当它是中文,翻译成英文;否则翻译成中文。这个阈值可以写在一个 Code 节点里,十几行代码。但如果你懂得“杨辉三角”式的判断,也可以直接在 n8n 的表达式里用正则,不过可读性很差,我建议用 Code 节点。
4.4 测试和联调
联调是个耐心活。我先用 curl 模拟 LangBot 的转发,验证整个 n8n 流程能通:
curl -X POST https://your-n8n.example.com/webhook/translate \ -H "Content-Type: application/json" \ -d '{ "rawText": "Hi Sarah, please review the file by 2025-06-01. https://example.com/report", "platform": "feishu", "userId": "test", "conversationId": "test", "messageId": "test1" }'如果返回:
{"replyText": "Sarah,请在2025-06-01前审阅这个文件。https://example.com/report"}就说明 n8n 这边已经通了。接下来再到 LangBot 后台设置测试平台,发一条真实消息,看整条链路。这里最容易出问题的点反而是 LangBot 的“响应超时”设置。因为模型生成可能有 10-30 秒延迟,有些 IM 平台对回调响应有硬性超时限制,比如飞书要求 3 秒内响应。所以同步等待模型结果在某些平台上是行不通的。
怎么解决?我给出三种路径,按复杂程度递增:
- 路径一:在 LangBot 里把“会话回复”模式设置为“被动回复”,让 LangBot 先立即响应“翻译中,请稍候…”,同时把 n8n 的流程改成异步,翻译完成后调用平台的主动消息接口。这个需要额外配一个回调节点。
- 路径二:降低模型延迟,选一个更快的模型版本,或者把
max_tokens降小,200 以下的效果会更敏捷。实测很多群聊短消息不需要 1024 tokens。 - 路径三:接受 30 秒内等待,只在企业微信群或个人 QQ 上使用(这些场景对响应时间容忍度高)。我第一版就是这么干的,能用,但体验一般。
如果你要拿它当正式群助手,我强烈建议做异步改造:n8n 的 Webhook 先立即返回 200,然后继续执行模型调用,最后通过 HTTP Request 调用 LangBot 提供的“主动发送消息”接口,把翻译结果发回原会话。整个过程依然是 n8n 一条流程,只是中间多了两个节点,后半段不再走“Respond to Webhook”,而是改成普通 HTTP 调用。
5. 常见问题与排查技巧实录
5.1 收到消息但不触发工作流
先别怀疑模型,先查 n8n 的 Webhook。打开 n8n 的 exec 日志,看有没有webhook事件被触发。如果完全没有触发,大概率是 LangBot 转发时请求没到 n8n。用curl手动打一下 Webhook,能通就说明 n8n 没问题,问题在 LangBot 的 URL 或网络连通性。如果手动打通,就看 LangBot 那边是否发生了异常,常见原因是 requests 库没安装、插件没启用、回调地址被拦截。f词:先在 n8n 日志确认,再逐层排查,别一上来就改 prompt。
5.2 翻译结果中的人名还是被翻译了
这个问题,我把 prompt 里的“人名保留原文”改成“对所有表示人名的词,无论目标语言是否存在对应翻译,都保持其原始字符”,同时加了一个 few-shot 示例。如果你还是被翻译,试试“不翻译”的替代方案:在后处理里做一次“双语校验”,把原文中所有看起来像人名的专有名词摘出来,翻译后再用正则检查是否还存在。但这不是长久之计,最靠谱的还是换一个对指令遵循更强的模型版本。我实测下来,GPT-6 在指令遵循上比前代强不少,但前提是 prompt 里规则要写成一二三四,不要用一段话混在一起。
5.3 链接被截断或乱码
链接出问题有三个常见原因:
- n8n 在请求体序列化时把 URL 里的字符做了转义,导致 LangBot 收到的内容里
&变成了&。这个通常发生在 HTML 实体转义,第一次用飞书消息尤其常见。解决方法是设置消息类型为纯文本,不启用 Markdown/富文本。 - 模型自己截断了链接。有些模型在生成回复时,如果觉得链接太长,会加省略号。我们 prompt 里明确写了“禁止截断”,一般能解决。如果还没解决,就把温度调低到 0。
- LangBot 在发送回复时按文本长度截断。很多 IM 平台对单条消息有长度限制,超长链接可能会被平台侧截断。你需要在 LangBot 里把消息拆分成多条发送,或者压缩链接格式。
5.4 模型接口超时
这种事在高峰期很常见。我建议在 n8n 的 HTTP Request 节点里把 Timeout 从默认的 10 秒调到 120 秒。但 LangBot 那边同步等待不一定能撑到 120 秒,所以最终还是回到异步方案。另外,可以在 n8n 流程里加一个“重试”逻辑:HTTP 节点失败时,用 n8n 的“Error Trigger”或直接在节点设置里配置重试次数(我一般设 2 次,间隔 3 秒)。但注意,重试模型接口会导致重复计费,只在明确看到超时错误时才开。
5.5 n8n 企业级部署的小心得
如果你准备把这条流程放到团队里长期用,有几个点特别值得提前做好:
第一,持久化目录一定要挂出来。n8n 默认的数据存储是 SQLite,存在容器里。如果容器被重建,流程全部丢失。我在docker-compose.yml里挂载了n8n_data目录,并且每天自动备份一次这个目录。
第二,用环境变量管理敏感配置。n8n 连接外部 API 时,虽然可以存到 Credentials,但WEBHOOK_URL、数据库连接串这类基础设施配置最好放在.env里,不要提交到代码仓库。一旦泄露,别人可以拿到你的 Webhook 地址去刷调用。
第三,n8n 连接 RAGFlow 做术语库,是我最近尝试的方向。现在翻译要求“人名保留”,但机票、产品名、团队代号这些专有名词也有自己的固定译法。我准备在 n8n 里加一个 RAGFlow 检索节点,把企业内部的术语表喂给 RAGFlow,翻译前先查术语,替换成标准说法,再丢给模型翻译。这样既保留了约束,又保证了术语统一。如果你也有这个需求,可以在 n8n 里直接用 HTTP 请求调用 RAGFlow 的 API,提前建好知识库,然后在 Set 节点里把检索结果拼到 prompt 里。
第四,访问控制别裸奔。n8n 默认单用户模式,如果你要多人协同,建议启用外部用户认证或反向代理加 Basic Auth。我在 Nginx 层加了访问限制,只允许内网 IP 访问管理界面,Webhook 路径单独放开,这样兼顾安全和可用性。
6. 一些踩坑后的真心话
这套系统从有想法到稳定跑通,我前前后后用了三个晚上。最大的坑不是技术,而是“你以为模型懂你的意思”。第一次写好 prompt,我觉得已经说得很明白了,结果人名还是翻。后来加了示例,情况立刻好转。这件事给我留下的习惯是:凡是涉及大模型输出约束的场景,必须给 few-shot,而不是只写规则。
如果你也想搭,我的建议是先不要搞异步、多语言、术语库这些高级功能。把最简的链路——飞书或 QQ 里选一个平台,LangBot 转发消息,n8n 调用模型,回复翻译结果——跑通,你就已经拿到 80% 的收益。剩下的再一点点加。
另外一个小技巧:n8n 的 Webhook 节点测试时,可以在 LangBot 脚本里加一个调试字段debug: true,然后在 n8n 流程里用一个 IF 节点判断,如果是调试消息,就直接返回JSON.stringify($json)出来,省得每次都去看日志。
翻译助手做到这里,已经不只是“翻译”了。你可以把这段基础流程里的模型调用节点替换成“总结”“提取待办”“情感分析”,就能得到不同的助手。n8n 和 LangBot 搭配的底层能力,其实是让每个 IM 用户都能用自己的数据、自己的模型,快速定制一个自己的自动化服务。模型会越来越聪明,但“把关键信息保护好”这个需求永远都在,这一步做好了,后面的一切才有根。