SeamlessM4T v2を試す on Databricks

# 導入

Meta社からSeamlessM4Tのv2が出ました。

https://ai.meta.com/blog/seamless-communication/

GIGAZINEさんでも取り上げられています。

https://gigazine.net/news/20231201-meta-seamlessm4t-v2/

以下の記事でv1を試してみており、非常におもしろかったので今回もDatabricks上で試してみます。

https://qiita.com/isanakamishiro2/items/2dc119432632d06e917d

# Seamless M4T v2とは

テキストと音声を同時に取り扱うマルチモーダルモデルです。
指定した文章を違う言語で文章に翻訳したり(T2T)、音声出力したり(T2S)、その逆(S2T)をしたりなどできます。
研究用途を想定しており、商用不可のライセンス体系で公開されています。

v2ではv1よりもレイテンシの短縮や品質向上が図られているようです。

また、音声の感情を維持したまま別の言語に翻訳した音声を出力するSeamlessExpressiveや、ストリームでの音声を翻訳出力するSeamlessStreamingが公開されています。

# 試す

では、試してみましょう。以下の内容をベースに動かします。

https://huggingface.co/facebook/seamless-m4t-v2-large

## 準備

まずはモデルをダウンロード。容量はかなり大きめ。

```python
def download_model(model_id:str):
    import os
    from huggingface_hub import snapshot_download

    UC_VOLUME = "/Volumes/training/llm/model_snapshots"

    local_dir = f"/tmp/{model_id}"
    uc_dir = f"/models--{model_id.replace('/', '--')}"

    snapshot_location = snapshot_download(
        repo_id=model_id,
        local_dir=local_dir,
        local_dir_use_symlinks=False,
    )

    dbutils.fs.cp(f"file:{local_dir}", f"{UC_VOLUME}{uc_dir}", recurse=True)

model_id = "facebook/seamless-m4t-v2-large"
download_model(model_id)
```

必要なパッケージをインストール。

```python
%pip install -U git+https://github.com/huggingface/transformers.git sentencepiece torchaudio scipy
dbutils.library.restartPython()
```

ダウンロードしたモデルのパスを指定してモデルをロード。

```python
from transformers import AutoProcessor, SeamlessM4Tv2Model
import torchaudio

model_path = "/Volumes/training/llm/model_snapshots/models--facebook--seamless-m4t-v2-large"

processor = AutoProcessor.from_pretrained(model_path)
model = SeamlessM4Tv2Model.from_pretrained(model_path)
```

これで準備が整いましたので、いろいろ試してみます。

## Text 2 Speech

英語テキストから日本語の音声を生成してみます。

```python
text_inputs = processor(text = "Hello, my dog is cute", src_lang="eng", return_tensors="pt")
audio_array_from_text = model.generate(**text_inputs, tgt_lang="jpn")[0].cpu().numpy().squeeze()
```

再生は以下を実行することで出来ます。

```python
from IPython.display import Audio

Audio(audio_array_from_text, rate=16_000)
```

音声をアップできないのですが、ちゃんと日本語に翻訳して再生されました。
ただ、少し違和感がある感じで、日本語はまだ改善の余地がありそうです。

## Text 2 Speech

英語テキストから日本語の音声を生成してみます。

```python
text_inputs = processor(text = "Hello, my dog is cute", src_lang="eng", return_tensors="pt")
audio_array_from_text = model.generate(**text_inputs, tgt_lang="jpn")[0].cpu().numpy().squeeze()
```

再生は以下を実行することで出来ます。

```python
from IPython.display import Audio

Audio(audio_array_from_text, rate=16_000)
```

音声をアップできないのですが、ちゃんと日本語に翻訳して再生されました。
ただ、少し違和感がある感じで、日本語はまだ改善の余地がありそうです。

## Speech 2 Speech

音声データから、翻訳された音声を生成してみます。
変換先言語を変更している以外は、サンプルコードと同様です。

```python
# from audio
audio, orig_freq =  torchaudio.load("https://www2.cs.uic.edu/~i101/SoundFiles/preamble10.wav")
audio =  torchaudio.functional.resample(audio, orig_freq=orig_freq, new_freq=16_000) # must be a 16 kHz waveform array
audio_inputs = processor(audios=audio, return_tensors="pt")
audio_array_from_audio = model.generate(**audio_inputs, tgt_lang="jpn")[0].cpu().numpy().squeeze()

```

```python
Audio(audio_array_from_audio, rate=16_000)
```

実は元ファイルの音声を聞いていないのですが、意味の分かる日本語で音声が生成されました。
ただ、上と同様、イントネーションや発話内容など少し違和感はあります。

ちなみに、変換した音声のファイル保管は以下のようなコードで実行できます。

```python
import scipy

scipy.io.wavfile.write("out_from_text.wav", rate=16_000, data=audio_array_from_audio)
```


## Text 2 Text

テキストから別言語のテキストを生成します。
テキスト出力の場合は```generate```メソッドのパラメータ```generate_speech```をFalse指定するようです。

```python
# from text
text_inputs = processor(text = "Hello, my dog is cute", src_lang="eng", return_tensors="pt")
output_tokens = model.generate(**text_inputs, tgt_lang="jpn", generate_speech=False)
translated_text_from_text = processor.decode(output_tokens[0].tolist()[0], skip_special_tokens=True)
```

```python
print(translated_text_from_text)
```

```:出力
こんにちは私の犬は可愛いです
```

## Speech 2 Text

音声データからのテキスト生成。
audio_inputsはSpeech 2 Speechのときに読んだデータを流用しました。

```python
# from audio
output_tokens = model.generate(**audio_inputs, tgt_lang="jpn", generate_speech=False)
translated_text_from_audio = processor.decode(output_tokens[0].tolist()[0], skip_special_tokens=True)
```

```python
print(translated_text_from_audio)
```

```:出力
我々は米国の国民より完璧な連合を形成するために正義を確立し国内の安らぎを確保し共通の防衛を確保する
```

## おまけ

音声生成の際に、speaker_idを指定すると、声質が変わるようでした。
例えば、speaker_id=2を指定すると男性の声で生成されます。（デフォルトだと女性の声でした）

```python
# from text
text_inputs = processor(text = "生きているということは誰かに知ってもらって覚えていてもらうことだ。", src_lang="jpn", return_tensors="pt")
audio_array_from_text = model.generate(**text_inputs, tgt_lang="jpn", speaker_id=2)[0].cpu().numpy().squeeze()

Audio(audio_array_from_text, rate=16_000)
```

# まとめ

SeamlessM4T v2を試してみました。
TransformersでSeamlessM4Tがサポートされたので、簡単に試せるようになったのがいいですね。

マルチモーダルモデルは画像＋テキストが多く出ていますが、ビジネス用途を考えると音声＋テキストのモデルも選択肢として上がると思っています。
この領域でも商用利用可能なモデルが出てくることを願っています。