# 📊 MultiMetric-Eval

**全能型评测工具箱**：一套工具，同时满足 **机器翻译 (MT)**、**语音识别 (ASR)**、**语音合成 (TTS)**、**同声传译 (SimulST)** 与 **变声 (VC)** 的评测需求。

[![PyPI version](https://badge.fury.io/py/multimetriceval.svg)](https://pypi.org/project/multimetriceval/0.4.4/)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## 🌟 核心功能

本工具包含三个独立的评测模块，按需导入：

1.  **`TranslationEvaluator` (翻译与语义评测)**
    *   **场景**: 机器翻译、语音翻译 (ST)、ASR。
    *   **指标**: BLEU, chrF++, COMET, BLEURT。
    *   **特点**: 关注语义一致性，支持文本和语音输入。

2.  **`SpeechEvaluator` (语音质量评测)**
    *   **场景**: 语音合成 (TTS)、变声 (Voice Conversion)。
    *   **指标**: UTMOS (自然度), WER/CER (识别准确率)。
    *   **特点**: 关注声音听感自然度和发音准确性。

3.  **`LatencyEvaluator` (同传延迟评测)**
    *   **场景**: 同声传译 (S2T / S2S)。
    *   **指标**: StartOffset, ATD (Average Token Delay)。
    *   **特点**:
        *   支持 **计算感知 (Computation Aware)** 延迟。
        *   支持 **MFA 强制对齐**，实现精确的 S2S 延迟测量。
        *   **一键集成质量评测** (自动调用 TranslationEvaluator/SpeechEvaluator)。

---

## 🚀 安装

### 1. 基础安装

```bash
# 基础版 (仅支持文本指标 + UTMOS)
pip install multimetriceval
```

### 2. 按需安装依赖

根据你需要使用的功能安装额外的库：

```bash
# [模块一] 启用 COMET (翻译评测)
pip install "multimetriceval[comet]"

# [模块二] 启用 Whisper (语音评测 WER / ASR功能)
# *注意: 需要系统已安装 ffmpeg
pip install "multimetriceval[whisper]"

# [模块三] 启用同传可视化 (Matplotlib)
pip install "multimetriceval[viz]"

# 安装所有功能 (推荐)
pip install "multimetriceval[all]"
```

### 3. 安装 BLEURT (可选)

如果你需要使用 BLEURT 指标（PyTorch版），需手动安装：
```bash
pip install git+https://github.com/lucadiliello/bleurt-pytorch.git
```

---


## 📖 模块一：翻译评测 (`TranslationEvaluator`)
用于多维度评估机器翻译质量或语音翻译的语义准确性（支持 BLEU, chrF++, COMET, BLEURT 等指标）。

### ⚡ 快速开始

```python
from multimetriceval import TranslationEvaluator

# 初始化 (首次运行会自动下载模型权重)
evaluator = TranslationEvaluator(use_comet=True)

# 基础评测 (直接传入文本列表)
results = evaluator.evaluate(
    target_text=["The cat sits on the mat."],  # 你的翻译结果
    reference=["The cat is sitting on the mat."], # 参考译文
    source=["猫坐在垫子上。"]  # 源文本 (COMET 指标需要)
)

print(results)
# Output: {'sacreBLEU': 45.2, 'chrF++': 62.1, 'COMET': 0.85}
```

### 🛠️ 三种输入模式 (统一使用 `evaluate` 接口)

现在的 `evaluate` 方法非常智能，支持混合输入不同类型的数据。

#### 1. 纯文本评测 (列表或文件)
你可以直接传入字符串列表，**或者直接传入文件路径**（支持 `.txt` 或 `.json`）。

```python
# 方式 A: 传入文件路径 (推荐)
results = evaluator.evaluate(
    target_text="./outputs/model_prediction.txt",  # 自动读取文件
    reference=["Reference translation 1", ...],
    source=["源文本 1", ...]
)

# 方式 B: 传入内存中的列表
results = evaluator.evaluate(
    target_text=["My translation."],
    reference=["Reference translation."],
    source=["源文本。"]
)
```

#### 2. 纯语音评测 (ASR 模式)
评估语音翻译模型（Speech-to-Text）的语义准确性。工具会自动调用 Whisper 将语音转录为文本，然后与参考译文计算 BLEU/COMET。

```python
# 初始化时需启用 Whisper
evaluator = TranslationEvaluator(use_comet=True, use_whisper=True)

results = evaluator.evaluate(
    target_speech="./my_audio_folder/",  # 传入音频文件夹路径
    reference=["Reference translation."],
    source=["源文本。"]
)
# 返回结果包含: sacreBLEU_ASR, COMET_ASR 等后缀指标
```

#### 3. 双模式评测 (文本 + 语音)
同时评估“文本翻译”和“语音翻译”的质量，常用于端到端语音翻译系统（Speech-to-Speech Translation）。

```python
results = evaluator.evaluate(
    reference=["Ref"], 
    source=["Src"],
    target_text="./outputs/text_predictions.txt", # 文本结果文件
    target_speech="./outputs/audio_predictions/"  # 语音结果文件夹
)
# 返回结果将同时包含文本指标 (无后缀) 和语音指标 (_ASR 后缀)
```

---

## 🎧 模块二：语音质量评测 (`SpeechEvaluator`)
专为 **TTS (语音合成)** 和 **VC (变声)** 设计。

### ⚡️ 核心特性：WER/CER 智能适配
本工具内置了智能分词逻辑：
*   **英文/印欧语系**：保持空格分词，计算 **WER (Word Error Rate)**。
*   **中文/日文**：自动在字符间插入空格，计算 **CER (Character Error Rate)**。
*   **混合文本**：混合处理。
> 无需用户手动分词，直接传入原始文本即可。

### 快速开始

```python
from multimetriceval import SpeechEvaluator

# 初始化 (自动加载 UTMOS 和 Whisper)
evaluator = SpeechEvaluator(device="cuda")

# 评测列表数据
audio_paths = ["/data/gen_en.wav", "/data/gen_zh.wav"]
ref_texts = ["Hello world", "你好世界"]

results = evaluator.evaluate(audio_paths, ref_texts)
print(results)
# Output: 
# {
#   'UTMOS': 4.15,  # 自然度 (1-5分)
#   'WER': 0.05     # 这里不仅包含英文WER，也包含中文CER
# }
```

### 数据输入方式

#### 方式 A: CSV 文件 (推荐)
最适合批量评测，避免文件乱序问题。

```csv
wav_path,text
/exp/tts/001.wav,Hello world
/exp/tts/002.wav,你好世界
```

```python
results = evaluator.evaluate_from_csv("data.csv", wav_col="wav_path", text_col="text")
```

#### 方式 B: 文件夹 + 文本文件
适用于生成了一堆 wav 文件，且有一个对应的 txt 文件。
*注意：音频文件将按文件名排序后与文本行对应。*

```python
results = evaluator.evaluate_from_folder(
    audio_folder="./outputs", 
    text_file="./scripts.txt"
)
```
---

## ⏱️ 模块三：同传延迟评测 (`LatencyEvaluator`)

专为 **Simultaneous Translation (同声传译)** 任务设计，支持 S2T (Speech-to-Text) 和 S2S (Speech-to-Speech)。

> **核心理念**：用户只需定义 Agent（读/写策略），本工具负责模拟流式环境、计算延迟并自动调用质量评测。

### 1. 编写你的 Agent

你需要创建一个 Python 文件（例如 `my_agent.py`），继承 `GenericAgent` 并实现 `policy` 方法。

```python
# my_agent.py
from multimetriceval.latency import GenericAgent, ReadAction, WriteAction

class MyAgent(GenericAgent):
    def policy(self, states=None):
        # 策略示例：如果源端没读完，就请求更多音频 (Read)
        if not self.states.source_finished:
            return ReadAction()
        
        # 如果源端读完了，但还没输出，就输出翻译 (Write)
        if not self.states.target_finished:
            return WriteAction("Hello World", finished=True)
            
        return ReadAction()
```

### 2. 命令行一键评测

使用内置的 CLI 工具运行评测。支持同时计算 **延迟指标** 和 **质量指标**。

```bash
python -m multimetriceval.latency.cli \
    --source data/audio_list.txt \
    --target data/ref.txt \
    --agent-script my_agent.py \
    --agent-class MyAgent \
    --task s2t \
    --computation-aware \
    --quality
```

#### 参数详解:
*   `--source`: 音频文件路径列表。
*   `--target`: 参考文本路径列表。
*   `--agent-script`: 包含 Agent 类的 Python 文件路径。
*   `--agent-class`: Agent 类名。
*   `--task`: `s2t` 或 `s2s`。
*   `--computation-aware`: 开启计算感知延迟（统计模型推理耗时）。
*   `--quality`: **(推荐)** 跑完延迟后，自动调用 `TranslationEvaluator` (S2T) 或 `SpeechEvaluator` (S2S) 计算 BLEU/WER/UTMOS。
*   `--visualize`: 生成延迟阶梯图 (需安装 `[viz]`)。

### 3. S2S 进阶：MFA 强制对齐

对于 **Speech-to-Speech** 任务，为了精确计算延迟（基于生成的音频内容而非切片），本工具支持调用 **Montreal Forced Aligner (MFA)**。

**前置要求**:
1.  安装 MFA: `conda install -c conda-forge montreal-forced-aligner`
2.  下载模型: `mfa model download dictionary english_mfa` & `mfa model download acoustic english_mfa`

**使用方法**:
只需在运行 S2S 任务时，脚本会自动检测 MFA 环境。如果环境就绪，会自动计算额外的对齐指标：
*   `StartOffset_SpeechAlign`
*   `ATD_SpeechAlign`

---

## 🛡️ 离线 / 内网环境使用指南 (SpeechEvaluator)

如果在无法连接 GitHub 或 HuggingFace 的服务器（如校园网 HPC）上使用，请按以下步骤操作。

### 1. 准备 UTMOS 模型
UTMOS 依赖 GitHub 源码加载。
1.  **源码**: 下载并解压 [SpeechMOS 源码](https://github.com/tarepan/SpeechMOS/archive/refs/heads/main.zip) 到本地（例如 `/path/to/SpeechMOS-main`）。
2.  **权重**: 下载 [utmos22_strong.pth](https://github.com/tarepan/SpeechMOS/releases/download/v1.0.0/utmos22_strong.pth) 到本地任意位置（例如 `/path/to/utmos22_strong.pth`）。

### 2. 准备 Whisper 模型
1.  下载权重文件（如 [medium.pt](https://openaipublic.azureedge.net/main/whisper/models/345ae4da62f9b3d59415adc6017195dc-medium.pt)）。
2.  放入文件夹（例如 `/path/to/whisper_weights/`）。


### 3. 准备 MFA (针对同传评测)
`LatencyEvaluator` 的 S2S 任务需要 MFA 进行强制对齐。由于 MFA 依赖较多，离线安装推荐使用 **Conda Pack** 方法。

**步骤 A: 在联网机器上打包环境**
```bash
# 1. 创建并激活新环境
conda create -n mfa_env python=3.9
conda activate mfa_env

# 2. 安装 MFA
conda install -c conda-forge montreal-forced-aligner
pip install conda-pack

# 3. 下载必要模型 (重要: 必须在联网时下载，否则离线无法使用)
mfa model download dictionary english_mfa
mfa model download acoustic english_mfa

# 4. 打包环境
conda pack -n mfa_env -o mfa_env_packed.tar.gz
```

**步骤 B: 在离线机器上解压使用**
```bash
# 1. 传输并解压
mkdir -p mfa_env
tar -xzf mfa_env_packed.tar.gz -C mfa_env

# 2. 激活环境
source mfa_env/bin/activate

# 3. 运行评测
python -m multimetriceval.latency.cli ...
```


### 4. 代码调用

通过参数显式指定路径，**无需**将文件放入系统缓存目录。

```python
evaluator = SpeechEvaluator(
    device="cuda",
    # [新增] 指定本地源码路径
    utmos_model_path="/path/to/SpeechMOS-main",
    # [新增] 指定本地权重路径 (.pth)
    utmos_ckpt_path="/path/to/utmos22_strong.pth", 
    # 指定 Whisper 权重目录
    whisper_root="/path/to/whisper_weights/"
)
```

### 5. 命令行调用 (CLI)

```bash
python -m multimetriceval.speech_evaluator \
    --csv data.csv \
    --utmos_path /path/to/SpeechMOS-main \
    --utmos_ckpt /path/to/utmos22_strong.pth \
    --whisper_root /path/to/whisper_weights
```

---

## ⚙️ 全局配置

### GPU 设置
所有模块均支持自动检测 GPU。手动指定方式如下：

```python
# 指定第 0 号 GPU
evaluator = SpeechEvaluator(device="cuda:0")

# 强制使用 CPU
evaluator = SpeechEvaluator(device="cpu")
```

或者使用环境变量：
```bash
CUDA_VISIBLE_DEVICES=1 python my_script.py
```

### 国内网络镜像
如果下载模型超时，请在代码开头设置 HF 镜像：
```python
import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
```
---

## 📊 指标速查表

| 模块 | 指标 | 全称 | 用途 | 备注 |
| :--- | :--- | :--- | :--- | :--- |
| **TranslationEvaluator** | **BLEU** | Bilingual Evaluation Understudy | 翻译 n-gram 匹配度 | 传统指标 |
| | **chrF++** | Character n-gram F-score | 字符级匹配度 | 适合形态丰富的语言 |
| | **COMET** | Crosslingual Optimized Metric | 基于神经网络的语义相似度 | **推荐** |
| | **BLEURT** | Bilingual Evaluation Understudy with Representations | 基于 BERT 的语义评分 | Google 出品 |
| **SpeechEvaluator**| **UTMOS** | UTMOS22 Strong | 语音自然度/MOS 预测 | 无需参考音频 |
| | **WER/CER** | Word/Character Error Rate | 识别准确率 | **自动适配中英文** |
| **LatencyEvaluator**| **StartOffset** | Start Offset | 首字/首音延迟 | 反应速度 |
| | **ATD** | Average Token Delay | 平均 Token 延迟 | 综合延迟指标 |
| | **(Custom)** | Custom ATD | 在ATD基础上除去音频播放时长 | 支持扩展 |

---

## ❓ 常见问题 (FAQ)

**Q: 为什么中文计算出的 WER 是 1.0 (100%)？**
A: 这是因为传统 WER 算法以空格分词，中文没有空格会被当成一个词，错一个字就算全错。**本工具已修复此问题**，会自动给中文字符间插入空格，计算 CER，请放心使用。

**Q: UTMOS 加载报错 `HTTP 404` 或 `Connection Refused`？**
A: 这是因为服务器无法连接 GitHub 下载源码。请参考上文 **“离线 / 内网环境使用指南”**，手动下载 `SpeechMOS` 源码包并指定 `utmos_model_path`。

**Q: 安装时提示 `ffmpeg` not found?**
A: Whisper 依赖系统级的 ffmpeg。请安装它：
*   Ubuntu: `sudo apt install ffmpeg`
*   Windows: 下载 ffmpeg.exe 并添加到环境变量 PATH 中。

**Q: `SpeechEvaluator` 报错缺少 Whisper?**
A: 请运行 `pip install "multimetriceval[whisper]"`。如果不想用 WER 指标，可以忽略该错误，UTMOS 依然可用。

**Q: `LatencyEvaluator` 报错 `matplotlib` not found?**
A: 请运行 `pip install "multimetriceval[viz]"` 安装可视化依赖。

**Q: S2S 任务中 `ATD_SpeechAlign` 没有结果？**
A: 这通常是因为未安装 MFA 或未下载 MFA 模型。请参考模块三文档安装 `montreal-forced-aligner`。如果未安装，工具会自动跳过对齐指标，仅计算基础切片延迟。

**Q: 如何在 Python 代码中手动调用同传评测？**
```python
from multimetriceval.latency import GenericAgent, LatencyEvaluator

# 定义 Agent
class MyAgent(GenericAgent): ...

# 运行评测
agent = MyAgent()
evaluator = LatencyEvaluator(agent)
instances = evaluator.run(src_files, ref_files, task="s2t")

# 计算分数
scores = evaluator.compute_latency(computation_aware=True)
print(scores)
```

---

## 📜 License

MIT License

## 🤝 Contributing

欢迎提交 Issue 和 Pull Request！
GitHub: [https://github.com/sjtuayj/MultiMetric-Eval](https://github.com/sjtuayj/MultiMetric-Eval)