☰
大模型翻译智能体实战:从API接入到提示词与函数调用
2026/10/21 4:18:37 网站建设 项目流程

最近我把翻译工具这个老需求重新做了一遍,基于 SiliconCloud 的 API 搭建了一个叫 Para 的翻译智能体。最开始只是一个随手测试的小脚本,后来发现这类项目的工程细节比想象中多很多,踩了一些坑之后,决定把整个开发过程整理成一篇实操记录,希望对正在选型大模型 API、或者准备做类似 AI 翻译工具的朋友有帮助。

Para 这个名字取自 Parallel 的缩写,想表达的是“打破语言之间的平行线”这层意思。这个项目解决的核心问题,就是把大模型从“能翻译”升级成“稳定地翻译”:输入一篇技术文档或者一段口语对话,输出时保持术语一致、风格统一,还能按照指定格式呈现。它适合三类人参考:想入门大模型应用开发的技术人员、需要私有化翻译方案的内容团队,以及在纠结 Prompt 和工具调用怎么配合的初学者。

1. 项目背景与功能定位

1.1 为什么还要自己造一个翻译工具

现在市面上的翻译工具非常多,网页翻译、桌面端词典、浏览器插件都做得挺成熟,普通用户直接拿来用就够了。但如果把“翻译”拆开看,会发现通用工具始终绕不开三个老问题:术语不统一、上下文信息丢失、输出格式不可控。

举个很常见的例子:你给一个翻译工具发一整段医疗文献,里面某个专业名词第一次被翻成“心肌梗死”,第二次却变成了“心脏病发作”,如果人工校对不够仔细,这种前后不一致很容易漏过去。通用翻译引擎通常没有术语记忆能力,它只看局部句子,不会回头检查自己刚才用了哪个词。Para 在架构设计上针对这个问题做了专门处理:通过提示词约束和术语表工具,把术语管理的能力外置,让模型在翻译前先查询术语库,再动笔。

另外一个痛点是上下文。翻译不是查字典,尤其是在处理长文档、多轮对话或者前后文强相关的内容时,如果模型只看当前这一句,很容易闹出指代不明、语序混乱这类毛病。Para 的思路是不做一次性的“句子翻译”,而是模拟一个真实的翻译工作流:先理解整体语境,再分块处理,最后统一术语和风格。

至于输出格式,做文档翻译的人肯定有体会——要求“保持原文 Markdown 格式”“代码块不要翻译”“危险词汇不要直译”等等。这些需求在通用工具里很难配置,而智能体的优势就在这里,它允许你把规则写进系统提示词里,让模型按照约定去执行。Para 把这三个问题的解决方案揉进了同一个项目里,这也是我把它定位成“智能体”而不是“翻译脚本”的根本原因。

1.2 Para 的总体架构与设计原则

Para 的整体架构并不复杂,但也绝不是简单的“API 封装”。从结构上可以拆成三块:交互层、智能体核心层、工具层。

交互层负责接收用户输入,可以是命令行,也可以是后续扩展的 Web 页面或者聊天机器人接口。智能体核心层是真正的大脑,里面包含系统提示词、对话管理逻辑和工具调度逻辑。工具层则是一组可以被模型调用的外部函数,比如术语表查询、双语对照格式化等。

这里有一点值得展开说。很多人会把“调一次模型 API”理解成“做了一个智能体”,这是认知上的误区。真正的智能体应该具备一种能力:根据用户意图自主决定要不要调用工具、调用哪个工具。Para 利用函数调用(Function Calling)机制,模型在翻译前可以主动请求查询术语表。这个决策过程不是写死在代码里的,而是模型根据用户输入的上下文自己判断的。

设计原则方面,我给自己定了三条:优先保证输出质量、尽量少的依赖、保留足够的可扩展性。优先保证输出质量意味着模型选型、提示词调优的时间占比会非常大,我自己估算项目里大约六成精力花在了这上面。少的依赖原则很好理解,Para 最初只用了 OpenAI SDK 这一层依赖,没有引入重型的 Agent 框架,因为简单才能看清每一步发生了什么。可扩展性则是说术语表查询、内容格式化这类功能尽量做成独立模块,后面接了新数据源也不会破坏主流程。

这样的架构下来,Para 的本质就是一个有工具调用能力的对话应用,它可以跑在命令行、跑在服务端,也能挂载到飞书或企业微信这类平台上。诚然,这类项目发展到后期会越来越像 Agent,但你不需要从第一天就引入跨领域概念,先跑通主链路更重要。

2. 开发环境准备与 API 接入

2.1 SiliconCloud 账号与 API Key 配置

开始写代码之前,先把环境准备好。SiliconCloud 是一个提供大模型 API 的服务平台,注册流程和常见的云服务差不多:打开官网、手机号注册、进入控制台,然后在“API 密钥”页面创建一个新的 Key。这里有两个经验可以分享。

第一,创建 Key 之后要立刻复制保存好,因为很多平台只在创建时显示一次完整密钥。建议本地用一个.env文件来存,不要硬编码在代码里。Para 的配置方式是这样的:

# .env SILICONCLOUD_API_KEY=sk-xxxxxxxxxxxxxxxx SILICONFLOW_BASE_URL=https://api.siliconflow.cn/v1

第二,国内网络环境下访问 SiliconCloud 的 API 基本是顺畅的,不需要额外的网络调整。官方提供了https://api.siliconflow.cn/v1这个地址,和 OpenAI 的请求格式保持一致,这意味着你只需要改 base_url 和 api_key 就能用同一套 SDK 发起请求。

2.2 快速连通性验证

环境变量配好之后,先不要直接跑到完整功能,写一个最简短的连通性脚本。这一步能帮你快速排查 Key、网络、模型 ID 三个常见问题。

from openai import OpenAI client = OpenAI( api_key=os.getenv("SILICONCLOUD_API_KEY"), base_url=os.getenv("SILICONFLOW_BASE_URL") ) response = client.chat.completions.create( model="Qwen/Qwen2.5-7B-Instruct", messages=[{"role": "user", "content": "请翻译这句话:Hello, world!"}] ) print(response.choices[0].message.content)

跑通之后,你会得到一个简单的翻译输出,这时候最基础的链路就通了。如果这个脚本报错,问题基本集中在三个地方:API Key 是否有效、模型 ID 是否填写正确、请求格式是否和 OpenAI SDK 版本匹配。我自己排查过的一次情况是把模型 ID 写成了平台控制台里的显示名而不是调用 ID,导致 404,这个坑相当容易踩。

2.3 模型选型考量

SiliconCloud 上提供的模型非常多,从轻量推理模型到指令微调模型都有。Para 的翻译场景推荐从这三个维度做选型:语言能力、指令遵循能力、价格。

指令遵循能力在翻译场景中特别重要。翻译这件事不只是“知道意思”,还得“按照你的格式输出”。有些小参数模型在理解复杂规则时会偷懒,比如让它输出双语对照,它只给中文,或者擅自添加额外解释。Para 默认使用了“Qwen/Qwen2.5-7B-Instruct”作为主力模型,实测下来它在中文理解、英文生成和对多轮指令的遵循上都表现稳定,而且价格很低,适合开发和批量翻译场景。如果预算充裕,也可以切换到参数量更大的模型,翻译质量会有一定提升,但响应速度和成本也需要相应考虑。

做选择时我倾向于先用轻量模型把逻辑跑通,再考虑是否升级。因为智能体的逻辑问题(比如函数调用没被触发、格式解析失败)和模型能力是两回事,你用再强的模型,代码逻辑不对也一样出错。先用便宜模型把架构调稳,再拿大的模型去压哨提升质量,这个顺序最划算。

3. 翻译系统提示词的设计

3.1 提示词决定翻译质量

如果说 API 接入是骨架,那系统提示词就是 Para 翻译质量的灵魂。同一个模型,给它的提示词不同,输出结果可以天差地别。最开始我写了一个非常宽松的提示词,内容只有“你是一个翻译助手,请将用户输入翻译成英文”,结果输出非常不稳定:有时直译、有时过度意译、有时还带着解释性的括号。后来我花了大块时间打磨提示词结构,才算把质量拉到了一个稳定水准。

好的翻译提示词,我认为至少要覆盖四件事:角色定位、翻译策略、格式要求、约束条件。

角色定位规定了模型用谁的视角来处理任务。Para 的系统提示词里明确写了一句“你是一名拥有二十年经验的资深专业译员”,这听起来有点虚,但它确实能引导模型进入翻译状态而不是闲聊状态。翻译策略则规定了直译和意译的边界。我不喜欢一刀切地规定“必须直译”或“必须意译”,因为不同文体对这两种策略的要求完全不一样。Para 的提示词里写的是“在保持语义准确的前提下,优先采用符合目标语言表达习惯的方式”,这句话给模型留下了判断空间。

格式要求和约束条件放在一起也是重点。比如 Para 会明确告诉模型:不要添加原文本没有的内容,不要解释你在翻译,不要输出翻译备注,只输出翻译结果。这些约束最大的作用就是消灭大模型的“自作多情”——很多人用翻译工具都遇到过,明明只让它翻译,它却在输出结尾加上一段“需要注意的是,这句话中的某某词在中文中有多种含义”,非常烦人。

3.2 翻译规则与格式约束的细化

系统提示词可以先写一份模板,然后针对不同的使用场景做参数化。Para 把提示词拆成了固定部分和可变部分,固定部分包含角色和通用策略,可变部分在每次请求时由代码拼接进去,比如目标语言、术语表内容、格式要求。

下面是一个简化过的 Para 系统提示词结构,给大家做个参考:

def build_translation_prompt(target_lang="English", glossary=None, doc_type="general"): system_prompt = f""" 你是一名拥有二十年经验的资深专业译员。你的任务是将用户提供的内容翻译为{target_lang}。 翻译策略: 1. 保持语义准确,优先采用符合目标语言表达习惯的表达方式。 2. 对于技术术语,必须严格遵循术语表;未在术语表中出现的专有名词,保留原文或采用业界通用译法。 3. 不允许添加原文没有的解释、注释或补充说明。 4. 保持原有的段落结构和标记格式,不要自作主张调整排版。 输出格式: 只输出翻译结果,不要输出任何额外说明。 当前文档类型:{doc_type} """ if glossary: glossary_text = "\n".join(f"{en} => {zh}" for en, zh in glossary.items()) system_prompt += f"\n术语表:\n{glossary_text}\n如果原文中出现上述英文术语,请严格按术语表中的中文翻译输出;如果翻译到英文,也请使用表中的英文原词。" return system_prompt

之所以把术语表放到系统提示词末尾,而不是让模型从零记忆,是因为越靠近任务末尾的指令,模型越容易遵循。这是一个基于实际使用体验得出的经验。

另外还有一个容易被忽略的点:目标语言的表达应该写“English”而不是“英文”或“英语”,模型对这类描述更敏感。如果你需要英译中,可以把target_lang改为“简体中文”,同时把 A 语言策略部分做对应调整。

3.3 提示词调优前后的效果对比

做提示词调优的时候,建议先准备一组固定测试集,每次修改提示词之后用同样的输入做对比。我用的是一个包含三句话的技术说明片段:

原文:“The API endpoint returns a JSON object containing user metadata. This includes timestamps and role flags. Please note that the rate limit window is 60 seconds.”

在宽松提示词下,模型输出的译文是“API端点返回一个包含用户元数据的JSON对象,这包括时间戳和角色标志。请注意速率限制窗口是60秒。”整体没有大错,但“这包括”这个表达明显欧化,读起来不自然。

在详细提示词下,模型输出的译文是“API 接口会返回包含用户元数据的 JSON 对象,其中包含时间戳和角色标志。需要留意的是,速率限制的时间窗口为 60 秒。”可以看到,同一个模型在加了约束之后,措辞会从“翻译腔”往“本地化”靠拢,这就是提示词发挥的作用。

这类测试不用做得太复杂,收集十条不同风格的短句就够了,关键是每次修改之后批量跑一遍,用对比结果倒推提示词的哪个部分有效。

4. 函数调用:让翻译智能体真正“智能”

4.1 术语表工具的设计

纯粹的提示词拼字符串有一个明显局限:术语表如果很长,全部塞进提示词会占用大量上下文窗口,而且模型不一定能记住所有条目。Para 的处理方式是改成“按需查询”:把术语表封装成一个函数,让模型在翻译过程中决定是否需要查询某个术语的译法。

这个思路的价值在于模拟真实翻译行为。专业译员拿到一份技术文档,遇到不确定的术语时,不是靠猜,而是去查术语库。模型也是一样,虽然它本身已经知道很多英文词汇的中文译法,但在特定行业、特定公司内部,往往有一套自己的术语约定,这时候外部知识库比模型内部的参数记忆更可靠。

Para 的术语表工具结构非常简单,就是一个查询接口,输入英文术语,返回对应的行业译法。为了让模型正确使用,工具的描述信息必须写得很清楚,因为模型是通过描述来决定何时调用工具的。

tools = [ { "type": "function", "function": { "name": "query_glossary", "description": "查询指定英文术语在项目术语表中的标准中文译法。只有在原文包含对翻译结果有重要影响的专业术语时,才调用该工具。", "parameters": { "type": "object", "properties": { "term": { "type": "string", "description": "需要查询的英文术语" } }, "required": ["term"] } } } ]

注意这里的描述不能写得太宽泛,比如“查询术语”,模型可能拿不准什么时候该用。明确写出“只有专业术语影响翻译时才调用”反而能减少无效的调用次数。

4.2 函数调用的完整接入流程

函数调用的完整流程分四步:声明工具、发起请求、处理函数调用结果、把结果回传给模型。下面这张流程图描述了 Para 的完整规划路径,它体现了模型在遇到专业术语时主动触发工具的行为逻辑。

第一步,请求阶段。把用户消息和工具列表一起发给模型:

response = client.chat.completions.create( model="Qwen/Qwen2.5-7B-Instruct", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_content} ], tools=tools, tool_choice="auto" )

第二步,判断返回值。如果模型认为需要查询术语,返回的finish_reason会是tool_calls,同时message.tool_calls里包含函数名和参数。如果模型觉得不需要调用工具,直接返回翻译结果。

第三步,执行本地函数。从tool_calls中解析出参数,调用本地的query_glossary,得到一个查询结果。

第四步,把工具结果拼接回对话并再次请求。

messages.append({ "role": "assistant", "content": None, "tool_calls": tool_calls }) for call in tool_calls: messages.append({ "role": "tool", "tool_call_id": call.id, "content": json.dumps({"translation": matched_term}), }) response = client.chat.completions.create( model="Qwen/Qwen2.5-7B-Instruct", messages=messages, tools=tools, tool_choice="auto" )

第二次请求时,模型已经知道了术语查询结果,接着产出最终翻译。这一步是智能体和普通 API 调用的分水岭——模型拥有了“查资料”的能力,输出自然会更可信。

4.3 让模型学会“先查后译”

“先查后译听上去是一个简单的行为规则,但实际调试中花了我不少时间。核心难点在于模型并不天然知道什么时候该查、什么时候不该查。我在调试过程中总结出三条有效经验。

第一个经验是术语表工具的 description 里要给出触发条件的反面例子。直接写“不要查询日常通用词汇”比只写“请查询专业术语”更有效。比如不加入反面约束时,模型有时候会把process这个词也拿去翻术语表,白白增加一次工具调用。

第二个经验是在系统提示词里加入一道流程引导,比如“如果原文包含你的专业术语表范围内的词汇,请先查询术语表,再进行翻译”。模型在看到明确流程之后,tool_calls 的触发准确率会明显提高。

第三个经验是工具返回内容要尽量精简。最开始我把术语表的匹配度、来源信息全部返回给模型,结果模型有时会把额外信息也当成翻译内容的一部分输出。后来改成只返回“标准译法”四个字,问题立刻消失了。工具返回给模型的不管什么结构都会成为模型预测依据,所以越干净越好。

5. 实测调优与常见问题排查

5.1 实测场景:中英双语技术文档翻译

Para 完整接好之后,我选了一份真实场景的测试文档做二次调优。这是一份系统部署文档,里面包含命令行指令、配置文件段落和网络协议相关描述。这种文档的翻译难点集中在三处:Markdown 格式需要保留、代码块不能翻译、部分自造词汇需要参照术语表。

我把测试输出和人工标准翻译做了对比,整体准确率在线,大部分问题集中在术语表覆盖不全导致的个别专有名词不统一。改进方案是在术语表里补齐缺省条目,同时检查系统提示词里对代码块的处理描述是否足够明确。加入“代码块、命令行、文件路径不翻译”之后,这个方向的错误基本消失了。

输入输出长度比较长时,上下文管理也是值得注意的问题。如果用户一次传入超过模型上下文长度的文本,可以在代码里增加分块逻辑,按段落数量切分后分批翻译,再拼接输出。Para 目前使用的是按空行切分的方式,简单稳定,没有引入分词依赖。

5.2 常见问题速查

把开发过程中遇到的典型问题整理成一张速查表,方便读者对照排查。

现象可能原因解决方案
调用 API 返回 401API Key 错误或失效检查.env中的 Key,重新创建验证
返回 404 模型不存在模型 ID 拼写错误从平台控制台复制标准模型 ID,不要手打
返回超时或限流并发过高或模型响应过慢降低并发,增加重试机制
模型的翻译结果带解释提示词缺少约束条件在系统提示词中明确“只输出翻译结果”
工具函数没有被调用工具描述太模糊在描述中加入触发条件与反例
工具被不必要地调用反面约束不足增加“不适用于常见词汇”的说明
长文本丢失上下文超过模型上下文窗口代码中按段落分块,分批翻译

这个地方我想多说一句。很多人在开发大模型应用时,遇到模型行为不符合预期,第一反应是换更大的模型,而不是检查提示词和工具设计。但实际经验里,大部分问题都出在逻辑设计层面,换模型只是在掩盖问题。调试顺序很重要:先看提示词合理性,再看工具设计,最后再考虑模型参数量。

5.3 后续扩展方向

Para 做到目前这个状态,已经能承担日常翻译任务,但距离“完整产品”还有一段路。接下来值得探索的方向有三个。

第一个方向是增加双语对照输出。在翻译结果旁边保留原文,逐句对齐。这个功能已经在规划中,主要实现方式是让模型按“文本块 ID + 译文”的格式返回 JSON 结构,再由展示层渲染成对照表格。

第二个方向是接入自定义术语库的自动更新。现在的术语表是静态文件,后续可以考虑让用户通过聊天直接添加新术语,比如用户说“以后 Server 统一翻译成服务器”,智能体自动更新术语表。这需要引入一个写入函数,技术难度不大,但需要对权限和校验流程做一些设计。

第三个方向是结合知识库和 RAG 做更深度的领域翻译。比如在法律或医学这类对术语准确性要求极高的行业,把行业标准文档或法规条文作为知识库底座,让模型在翻译时不仅能查术语,还能查相关条文的固定翻译口径,进一步提升高风险场景下的可靠性。

关于最后这个方向要提前打个预防针:RAG 不是银弹。如果翻译文本本身没有涉及复杂的背景知识,加检索反而会拖慢响应速度、引入噪声。II 在设计时务必先明确场景痛点要具体到“哪些知识缺失导致现有翻译不够好”,再决定要不要上 RAG。

落笔后的几点体会

回到标题本身,Para 这个项目的意义不在于“做了个翻译工具”,而在于把一条完整的智能体开发路径走通了:从选型 API、写提示词、设计工具调用,到处理真实场景里的各种边界情况,每一个环节都有实实在在的取舍。

我个人在折腾完这个项目之后,最大的体会有三条。第一条,工具调用的产品逻辑比模型参数重要得多,先把“让模型学会用工具”这件事做扎实,再考虑换更大的模型;第二条,提示词调试要有测试集思维,不要靠感觉,尽量固定输入、观察输出、对比变化;第三条,做应用层开发时,API 平台的稳定性、兼容性远比参数大小更能决定开发体验。

最后再分享一个小技巧:如果你打算做类似项目,建议第一版千万不要直接引入 Agent 框架,用 OpenAI SDK 原生函数调用手写一遍全过程。这个过程会让你对每一步请求、每一次 tool_calls 都了如指掌,后面再迁移到框架时,遇到问题也更容易定位。Para 目前还在继续迭代,计划加入更丰富的格式控制能力和术语库的自动更新机制,如果你也在做同类的智能体项目,欢迎一起交流踩坑心得。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询