吴恩达的TranslationAgent学习(一)

618 阅读7分钟

TranslationAgent构成

整个TranslationAgent (github.com)在流程上分为短文本的一次性翻译和长文本的分chunk翻译(按照Token进行划分)。 但是不论长文本翻译还是短文本翻译,总体流程遵循执行、纠正再执行的逻辑循环实现。 这种按照自省思路来使用大模型的逻辑在近阶段的一些大模型应用论文和项目中经常出现,比如DoubleCheck的Prompt、(CRAG(Corrective Retrieval Augmented Generation))的论文或者LangChain使用的ReAct。 这种自省的逻辑其实都体现了一个核心思路,别让大模型一次做太复杂的事。感觉大模型在推理解决问题方面的方案在逐渐统一:

  1. 大模型逐步规划
  2. 执行计划
  3. 结合结果重新规划
  4. 再执行
  5. ...

回归正题,我们先看看短文章翻译。翻译分为三个阶段

  1. chunk_initial_translation:单次翻译,得到结果。
  2. chunk_reflect_on_translation:审视检查翻译结果,决定如何改进
  3. chunk_improve_translation:根据改进点重新翻译得到结果

所以思路看起来很清晰,熟悉LangChain、LlamaIndex等项目这个思路会感觉很熟悉。我觉得代码并不重要,一个是思路,另一个是Prompt的写法。 本次先重点看一下Prompt的写法,吸取一下经验。

一、首轮翻译-one_chunk_initial_translation

System

f"You are an expert linguist, specializing in translation from {source_lang} to {target_lang}".

你是一个语言专家,擅长把信息从{source_lang}翻译成{target_lang}

Message

f"""This is an {source_lang} to {target_lang} translation, please provide the {target_lang} translation for this text. Do not provide any explanations or text apart from the translation.  
{source_lang}: {source_text}  
  
{target_lang}:"""

这是一个从{source_lang}{target_lang}的翻译,请为这段文本提供{target_lang}的译文。除了译文,不要提供任何解释或其他文字。
{source_lang}:{source_text}

{target_lang}:

这段Prompt是最简单的一段,定义了角色、提出了要求、限制。在Message中增加了固定格式的用户输入的嵌入{source_lang}: {source_text}。 另外这里能常看到一种引导大模型回复的方式{target_lang}:。 LLM是一个语言概率的推测模型,给出适当的开头引导是一个常用的手段。

二、自省翻译结果-one_chunk_reflect_on_translation

System

f"You are an expert linguist specializing in translation from {source_lang} to {target_lang}. \
You will be provided with a source text and its translation and your goal is to improve the translation."

你是一个语言专家,擅长把信息从{source_lang}翻译成{target_lang}。 你会得到一段源语言的文本和一段译文,你的目标是改进这段译文。

Message

f"""Your task is to carefully read a source text and a translation from {source_lang} to {target_lang}, and then give constructive criticism and helpful suggestions to improve the translation. \  
The final style and tone of the translation should match the style of {target_lang} colloquially spoken in {country}.  
  
The source text and initial translation, delimited by XML tags <SOURCE_TEXT></SOURCE_TEXT> and <TRANSLATION></TRANSLATION>, are as follows:  
  
<SOURCE_TEXT>  
{source_text}  
</SOURCE_TEXT>  
  
<TRANSLATION>  
{translation_1}  
</TRANSLATION>  
  
When writing suggestions, pay attention to whether there are ways to improve the translation's \n\  
(i) accuracy (by correcting errors of addition, mistranslation, omission, or untranslated text),\n\  
(ii) fluency (by applying {target_lang} grammar, spelling and punctuation rules, and ensuring there are no unnecessary repetitions),\n\  
(iii) style (by ensuring the translations reflect the style of the source text and takes into account any cultural context),\n\  
(iv) terminology (by ensuring terminology use is consistent and reflects the source text domain; and by only ensuring you use equivalent idioms {target_lang}).\n\  
  
Write a list of specific, helpful and constructive suggestions for improving the translation.  
Each suggestion should address one specific part of the translation.  
Output only the suggestions and nothing else."""

你的任务是仔细查看源文本和对应的{source_lang}{target_lang}的译文,然后给出有建设性的批评和有用的建议来改进译文。 译文的最终风格和语气应与在{country}口语中使用的{target_lang}的风格相匹配。 The source text and initial translation, delimited by XML tags <SOURCE_TEXT></SOURCE_TEXT> and <TRANSLATION></TRANSLATION>, are as follows:
.... 在撰写建议时,请注意是否有方法可以改进翻译的 (i) 准确性(通过纠正添加、误译、遗漏或未翻译文本的错误), (ii) 流畅性(通过应用{target_lang} 语法、拼写和标点规则,并确保没有不必要的重复), (iii) 风格(通过确保翻译反映源文本的风格并考虑任何文化背景), (iv) 术语(通过确保术语使用一致并反映源文本领域;并且仅确保您使用等效术语)习语 {target_lang})。 列出具体、有用且有建设性的建议,以改进翻译。 每条建议应针对翻译的一个特定部分。 仅输出建议,不输出其他内容。

这里我省略了一些翻译内容。重点注意Prompt中的这两点:

1. 如何挂入我要给大模型的信息?

从初始翻译和这个自省的Prompt能看到两种常见的方式

  1. Q:A\n Q:A:这种用引号和换行的形式来做分割,这种方式简单易懂,Prompt模板很容易书写。但是缺点显而易见,太容易被外挂的内容搅乱。虽然能力强的LLM可能也能够识别到,但是这个很难能做到稳定,效果也很难评估
  2. <Q><\Q><A><\A>:用XML标签来携带数据,比较推荐这种形式。这种形式也是RAG场景中携带知识库内容最常见的形式。这里我个人之所以推荐这种形式是因为这种形式跟Transformer的decoder机制有些形似,Transformer在开始生成的时候会输入一个特殊的Token,当到达[STOP]的时候就停止预测生成,用XML标签对也是类似的结构,而且Embedding之后,位置信息被捕获对大模型应该有促进理解的作用(没论文支撑,存粹从Transformer原理的角度理解)。

2. 结构化的Prompt。

整个Prompt其实可以划分为三部分,也是结构化编写Prompt的常规方式。

  1. 角色:定义出你需要让大模型扮演什么角色,比如这里的语言专家。角色部分的要求不会经常变化,也不会需要大量的变量。一般写在System Prompt。
  2. 能力和任务:能力用来告诉大模型怎么做、任务用来告诉大模型要做什么。这一部分可以结合出很多种实现方式,比如COT、TOT、PS等Prompt思路都可以放在这里实现。
  3. 要求和限制:这部分常用来要求LLM按照我们的要求生成、输出内容。比如这里的准确、流畅、风格、术语等。

另外这里有个小细节country是个可选参数,当没传的时候对方言的要求就不再写入Prompt中了。这不仅要求Prompt要结构化的组织,对于上下文的行文也要能灵活组合。

三、改进翻译结果-one_chunk_improve_translation

System

f"You are an expert linguist, specializing in translation editing from {source_lang} to {target_lang}."

Message

f"""Your task is to carefully read, then edit, a translation from {source_lang} to {target_lang}, taking into  
account a list of expert suggestions and constructive criticisms.  
  
The source text, the initial translation, and the expert linguist suggestions are delimited by XML tags <SOURCE_TEXT></SOURCE_TEXT>, <TRANSLATION></TRANSLATION> and <EXPERT_SUGGESTIONS></EXPERT_SUGGESTIONS> \  
as follows:  
  
<SOURCE_TEXT>  
{source_text}  
</SOURCE_TEXT>  
  
<TRANSLATION>  
{translation_1}  
</TRANSLATION>  
  
<EXPERT_SUGGESTIONS>  
{reflection}  
</EXPERT_SUGGESTIONS>  
  
Please take into account the expert suggestions when editing the translation. Edit the translation by ensuring:  
  
(i) accuracy (by correcting errors of addition, mistranslation, omission, or untranslated text),  
(ii) fluency (by applying {target_lang} grammar, spelling and punctuation rules and ensuring there are no unnecessary repetitions), \  
(iii) style (by ensuring the translations reflect the style of the source text)  
(iv) terminology (inappropriate for context, inconsistent use), or  
(v) other errors.  
  
Output only the new translation and nothing else."""

最后这部分就不做翻译了,结合前面的内容大家都看得懂。 改进翻译其实就很好理解了,用第二步生成的reflection让大模型再次改写。

四、总结

吴恩达老师的这个项目在我们实际测试下来效果确实很好,一方面得益于自省式的实现思路;另一方面Prompt的使用确实也很到位。 当然项目也有缺陷,就像是Git上的Readme所说的。后面我也会再分析下长文本是如何实现自省和翻译的。

之后会整理更多学习、工作中遇到的问题和思考,欢迎大家关注Global AI Pro