大模型翻译能力评测

1. 背景介绍

随着自然语言处理技术的飞速发展,机器翻译已经成为一个重要的研究领域。近年来,基于大模型的语言模型在机器翻译任务上取得了显著的进展。这些大模型通常具有数亿甚至数千亿的参数,能够更好地理解和生成自然语言。

但是,现在市面上可用的大模型成百上千,每个模型又都有各自的功能特性和适用场景,我们应该如何评估不同模型的翻译效果呢?解决方案可能多种多样,本文尝试采用 WMT 数据集 + BLEU 评分的机制,来相对完善地评估几个大模型的翻译能力。

首先,简单补充一些基础知识:

WMT 数据集

WMT(Workshop on Machine Translation)数据集是一系列用于机器翻译的基准数据集,它由每年举办的WMT会议提供。WMT会议是机器翻译领域的重要国际会议,自2006年起每年举行,旨在推动机器翻译技术的发展。

WMT 数据集包含了多种语言对的翻译数据,这些数据通常来自于新闻文章、议会记录、书籍以及其他公开可用的文本资源。这些数据集被广泛用于训练、评估和比较不同的机器翻译系统。其中一些知名的语言对包括英语-法语、英语-德语、英语-西班牙语等。WMT 提供了比较权威的基准数据,可供我们来评估不同模型的翻译准确率。

BLEU 评分

BLEU(Bilingual Evaluation Understudy)评分是一种用于评估机器翻译输出质量的自动评价指标。 BLEU由IBM在2002年提出,目的是为了提供一个快速、客观且成本较低的方法来评估翻译系统的性能。BLEU评分已经成为机器翻译领域最广泛使用的评价标准之一。

BLEU 通过计算匹配度(Precision)、修饰(Modified)、几何平均、最终评分等流程,最终生成一个 [0,1] 范围内的 score,其中1表示完美的匹配,即机器翻译的输出与参考翻译完全一致。我们通过不同大模型之间评分的相对值,就可以评估出翻译能力的差异。

有了这些基础知识,我们就可以来实现具体的评测程序了。
下面的程序采用 LangChain 框架,以英译中场景为例,介绍翻译评测的具体实现流程。

2. 实现流程

加载语料数据集

首先安装 datasets 库:

bash 复制代码
pip install datasets

然后我们实现一个 DataSetLoader ,用于加载 WMT 的语料数据集。wmt19 这个仓库下就包含了英汉互译的数据集。 我们假定英文为原始语言,中文为目标翻译语言。

python 复制代码
from datasets import load_dataset


class DataSetLoader:
    """数据集加载器"""

    def __init__(self):
        """初始化方法"""

        # 加载英译汉数据集
        self.ds = load_dataset('wmt19', 'zh-en')
        print("加载[en-zh]数据集完成")

    def get_origin_content(self, idx: int) -> str:
        """获取原始内容"""
        return self.ds['train'][idx]['translation']['en']

    def get_ref_trans(self, idx: int) -> str:
        """获取参考翻译"""
        return self.ds['train'][idx]['translation']['zh']

BLEU 评分计算

接下来,我们定义一个 BleuScoreCaculator 组件,用于计算 BLEU 分数。这里直接使用 nltk.translate 包即可(需要安装):

python 复制代码
from nltk.translate.bleu_score import sentence_bleu


class BleuScoreCaculator:
    """BLEU分数计算器"""

    @staticmethod
    def calc_score(references, hypothesis) -> float:
        """计算BLEU分数"""
        return sentence_bleu(references, hypothesis, weights=(1,))

分词处理

除此之外,为了避免不同分词规则所造成的影响,我们再开发一个分词组件,按照统一的规则,对文本进行分词。分词库采用应用广泛的 jieba 即可:

python 复制代码
from typing import List

import jieba


class Tokenizer:
    """分词器"""

    @staticmethod
    def clean_and_tokenize(text: str) -> List[str]:
        """
        清理文本并分词
        :param text: 原始文本
        :return: 分词列表
        """

        # 去除多余空格和标点符号
        trimmed = text.replace('\n', ' ').replace('  ', ' ').strip()

        # 使用 jieba 进行分词
        return list(jieba.cut(trimmed))

翻译评测

所有的基础组件已经准备就绪了,下面就可以开始完成核心的翻译评测功能。

我们采用 LangChain 框架,构造标准化的处理流程 Chain。采用一下三个候选模型:

  • glm-4-plus
  • gpt-4o
  • qwen-32b

这三个都是当前业界功能非常强大的模型,那么他们的翻译能力到底孰优孰劣呢?我们写代码看一下:

python 复制代码
import json
from typing import List, Dict, Any

import dotenv
from langchain_community.chat_models import ChatZhipuAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

from bleu import BleuScoreCaculator
from loader import DataSetLoader
from tokenizer import Tokenizer

if __name__ == '__main__':
    # 加载环境变量
    dotenv.load_dotenv()

    # 对比3个LLM: glm-4-plus、gpt-4o和qwen-32b
    chat_glm_4_plus = ChatZhipuAI(model="glm-4-plus", temperature=0.1)

    chat_gpt_4o = ChatOpenAI(model="gpt-4o", temperature=0.1)

    chat_qwen_32b = ChatOpenAI(model="qwen-32b", temperature=0.1)

    # 构造prompt
    query = """
    待翻译内容:
    {content}
    
    原始语言:
    {origin_lang}
    
    翻译成的目标语言:
    {target_lang}
    
    特别注意:直接生成翻译好的文本即可,无需任何额外信息!
    """
    prompt = ChatPromptTemplate.from_messages([
        ("system", "你是一个翻译专家,请根据用户需要翻译文本"),
        ("human", query)
    ])

    prompt = prompt.partial(origin_lang="英语", target_lang="汉语")

    # 构造Chain
    glm_4_plus_chain = prompt | chat_glm_4_plus | StrOutputParser()
    gpt_4o_chain = prompt | chat_gpt_4o | StrOutputParser()
    qwen_32b_chain = prompt | chat_qwen_32b | StrOutputParser()

    print("翻译评测开始\n\n")

    # 创建数据集加载器
    loader = DataSetLoader()

    # 创建分词器
    tokenizer = Tokenizer()

    # 创建BLEU分数计算器
    calculator = BleuScoreCaculator()

    count = 20  # 评测20条数据,可以视具体情况调整

    glm_4_plus_total_score: float = 0
    gpt_4o_total_score: float = 0
    qwen_32b_total_score: float = 0

    result: List[Dict[str, Any]] = []

    for i in range(count):
        # 执行翻译
        print(f"\n==========第{i + 1}组==========\n")
        origin = loader.get_origin_content(i)
        print(f"[原始内容]: {origin}\n")
        ref_trans = loader.get_ref_trans(i)
        print(f"[参考翻译]: {ref_trans}\n")

        glm_4_plus_trans = glm_4_plus_chain.invoke({"content": origin})
        print(f"[glm-4-plus 翻译结果]: {glm_4_plus_trans}\n")

        gpt_4o_trans = gpt_4o_chain.invoke({"content": origin})
        print(f"[gpt_4o 翻译结果]: {gpt_4o_trans}\n")

        qwen_32b_trans = qwen_32b_chain.invoke({"content": origin})
        print(f"[qwen-32b 翻译结果]: {qwen_32b_trans}\n")

        # 分词处理
        ref_tokens = tokenizer.clean_and_tokenize(ref_trans)
        glm_4_plus_trans_tokens = tokenizer.clean_and_tokenize(glm_4_plus_trans)
        gpt_4o_trans_tokens = tokenizer.clean_and_tokenize(gpt_4o_trans)
        qwen_32b_trans_tokens = tokenizer.clean_and_tokenize(qwen_32b_trans)

        # 计算BLEU分数
        glm_4_plus_trans_score = calculator.calc_score([ref_tokens], glm_4_plus_trans_tokens)
        print(f"[glm-4-plus BLEU分数]: {glm_4_plus_trans_score}\n")
        gpt_4o_trans_score = calculator.calc_score([ref_tokens], gpt_4o_trans_tokens)
        print(f"[gpt_4o BLEU分数]: {gpt_4o_trans_score}\n")
        qwen_32b_trans_score = calculator.calc_score([ref_tokens], qwen_32b_trans_tokens)
        print(f"[qwen-32b BLEU分数]: {qwen_32b_trans_score}\n")

        glm_4_plus_total_score += glm_4_plus_trans_score
        gpt_4o_total_score += gpt_4o_trans_score
        qwen_32b_total_score += qwen_32b_trans_score

        # 保存结果
        single_result = {
            "origin": origin,
            "ref_trans": ref_trans,
            "glm_4_plus_trans": glm_4_plus_trans,
            "gpt_4o_trans": gpt_4o_trans,
            "qwen_32b_trans": qwen_32b_trans,
            "glm_4_plus_trans_score": glm_4_plus_trans_score,
            "gpt_4o_trans_score": gpt_4o_trans_score,
            "qwen_32b_trans_score": qwen_32b_trans_score,
        }
        result.append(single_result)
        print(f"\n{json.dumps(result)}\n")

    print("翻译评测完成\n\n")

    # 保存结果
    with open("./trans_result.json", "w") as f:
        json.dump(result, f, ensure_ascii=False, indent=4)

    print("[glm-4-plus BLEU平均分]: ", glm_4_plus_total_score / count)
    print("[gpt-4o BLEU平均分]: ", gpt_4o_total_score / count)
    print("[qwen-32b BLEU平均分]: ", qwen_32b_total_score / count)

3. 总结

我们测试了20条数据集,最终结果如下:

powershell 复制代码
[glm-4-plus BLEU平均分]:  0.6133968696381211
[gpt-4o BLEU平均分]:  0.5818961018843368
[qwen-32b BLEU平均分]:  0.580947364126585

生成的结果 json 文件格式如下:

json 复制代码
[{
	"origin": "For geo-strategists, however, the year that naturally comes to mind, in both politics and economics, is 1989.",
	"ref_trans": "然而,作为地域战略学家,无论是从政治意义还是从经济意义上,让我自然想到的年份是1989年。",
	"glm_4_plus_trans": "对于地缘战略家来说,无论是在政治还是经济上,自然而然会想到的年份是1989年。",
	"gpt_4o_trans": "对于地缘战略家来说,无论在政治还是经济方面,自然而然想到的年份是1989年。",
	"qwen_32b_trans": "然而,对于地缘战略家来说,无论是政治还是经济,自然想到的一年是1989年。",
	"glm_4_plus_trans_score": 0.5009848620501905,
	"gpt_4o_trans_score": 0.42281285383122796,
	"qwen_32b_trans_score": 0.528516067289035
}]

可以看出,针对中文翻译,这3个大模型的 BLEU 相差不大,而且都超过了 0.5,基本可以认为翻译质量较好,能够传达原文的基本意思,错误较少,流畅性较好。其中分数最高的是 glm-4-plus,大概率是因为智谱 AI 针对中文语料做了很多 fine-tuning 和优化的工作,因为在机器翻译领域,数据是非常重要的关键因素。

本文仅采用了20条数据进行评测,结果可能存在一些偏差,而且不同的测试数据也会对结果产生影响,可以结合特定业务场景调整参数。重要的是,这里提供了一种相对客观的评估方式,可以直观地评测不同大模型的翻译效果,可以作为业务应用和技术选型的有力依据。

相关推荐
山川而川-R25 分钟前
yolov8的深度学习环境安装(cuda12.4、ubuntu22.04)
人工智能·深度学习·yolov8
whaosoft-14341 分钟前
51c自动驾驶~合集38
人工智能
Joker23731 小时前
【目标跟踪】AntiUAV410数据集详细介绍
人工智能·计算机视觉·目标跟踪
白书宇1 小时前
23.100ASK_T113-PRO 移植opencv
人工智能·嵌入式硬件·opencv·物联网·计算机视觉·硬件工程
奔波儿灞爱霸波尔奔1 小时前
浅谈人工智能之基于容器云进行图生视频大模型搭建
人工智能·音视频
程序猿000001号1 小时前
DETR:一种新颖的端到端目标检测与分割框架
人工智能·目标检测·计算机视觉
知恩呐1111 小时前
GAN是一种自监督模型那在判别器中,同时输入生成器生成的SR与真实值HR作比较的话,不就是将HR作为SR的标签吗,如何体现自监督学习呢
人工智能·python·机器学习
知新_ROL1 小时前
LLM*:路径规划的大型语言模型增强增量启发式搜索
人工智能·语言模型·自然语言处理
神经美学_茂森1 小时前
【通俗理解】步长和学习率在神经网络中是一回事吗?
人工智能·神经网络·学习
新加坡内哥谈技术1 小时前
全新AI模型家族登场:完全可复现的开源语言模型OLMo 2
人工智能