使用 🤗 Transformers 微调 SpeechT5:从 VoxPopuli 荷兰语数据到自定义 TTS 语音合成
文本转语音(Text-to-Speech,TTS)是让机器把文字变成自然语音的核心任务,支持多语言、多说话人生成。本文以 🤗 Transformers 官方任务指南 docs/source/en/tasks/text-to-speech.md(及对应日文版 docs/source/ja/tasks/text-to-speech.md)为骨架,完整讲解两条主线:一是通过 text-to-speech 流水线开箱即用地合成语音;二是以 SpeechT5 为代表,从数据集加载、文本与音频预处理、说话人嵌入到训练与推理,端到端微调一个多说话人 TTS 模型。读完本文,你将掌握在 Transformers 中落地自定义 TTS 模型的完整实战方案。
TTS 任务与 🤗 Transformers 中的可用模型
TTS 的输入是文本,输出是可以直接播放的语音波形,且同一模型往往能生成多语言、多说话人的语音。在 🤗 Transformers 当前仓库中,可直接使用的 TTS 模型包括 Bark、MMS、VITS、SpeechT5,以及较新加入的 Dia、CSM、FastSpeech2Conformer 等。其中部分模型还支持超出纯文本的生成能力,例如 Bark 可通过文本标记生成笑声、叹息、哭泣等非语言交流,甚至附带音乐;Dia 则支持 [S1]、[S2] 这类说话人标签来生成多人对话。
从微调角度看,目前仓库内可微调的 TTS 模型主要是 SpeechT5(以及 Dia、CSM、FastSpeech2Conformer 等)。SpeechT5 的特别之处在于它同时使用语音转文本(speech-to-text)与文本转语音(text-to-speech)两类数据进行预训练,从而学到文本与语音共享的统一隐表示空间——这意味着同一个预训练模型可以针对不同任务进行微调。此外,SpeechT5 通过 x-vector 说话人嵌入(speaker embeddings)支持多说话人生成,这也是本文微调流程的核心输入之一。
快速上手:text-to-speech 流水线
最简单的语音合成方式是利用 "text-to-audio" 流水线(其别名是 "text-to-speech")。流水线的实现位于 src/transformers/pipelines/text_to_audio.py 中的 TextToAudioPipeline,它支持任意 AutoModelForTextToWaveform 或 AutoModelForTextToSpectrogram 模型。以 Bark 为例:
>>> from transformers import pipeline
>>> pipe = pipeline("text-to-speech", model="suno/bark-small")
>>> text = "[clears throat] This is a test ... and I just took a long pause."
>>> output = pipe(text)
在 Notebook 中可以用下面的代码直接收听结果:
>>> from IPython.display import Audio
>>> Audio(output["audio"], rate=output["sampling_rate"])
output 是一个包含 audio(波形数组)与 sampling_rate(采样率)字段的字典。从源码可见,TextToAudioPipeline 对 model_type == "speecht5" 的模型会自动加载默认的 HiFi-GAN 声码器(SpeechT5HifiGan)并将采样率设为声码器的采样率(16 kHz);对 Bark 这类需要语义长度的模型,则会在预处理阶段使用 generation_config 中的 max_input_semantic_length(默认 256)来约束输入。
微调 SpeechT5:环境准备与数据加载
本文的微调目标是:把原本在英语语音上训练的 SpeechT5 检查点 microsoft/speecht5_tts,在 VoxPopuli 数据集的荷兰语(nl)子集上微调,得到能说荷兰语的多说话人 TTS 模型。
安装依赖与检查 GPU
首先确保以下库已安装:
pip install datasets soundfile speechbrain accelerate
注意:英文版指南还推荐安装
librosa、torchcodec等音频加载库,可根据实际环境按需补充。
由于 SpeechT5 的部分 TTS 特性尚未全部合并进正式发布版,指南建议从源码安装 Transformers:
pip install git+https://github.com/huggingface/transformers.git
微调需要 GPU。在 Notebook 中可通过以下命令确认 GPU 可用(AMD GPU 则用 !rocm-smi):
!nvidia-smi
建议先登录 Hugging Face 账号,便于训练后把模型上传分享:
>>> from huggingface_hub import notebook_login
>>> notebook_login()
加载 VoxPopuli 数据集
VoxPopuli 是一个大规模多语言语音语料库,数据源自 2009–2020 年欧洲议会的会议录音,包含 15 种欧洲语言的带标注语音-转写数据。本指南使用荷兰语子集,你也可以自由换成其他子集:
>>> from datasets import load_dataset, Audio
>>> dataset = load_dataset("facebook/voxpopuli", "nl", split="train")
>>> len(dataset)
20968
20968 条样本对微调已经足够。需要说明的是,VoxPopuli 这类自动语音识别(ASR)数据集并非 TTS 训练的理想选择——对 ASR 有利的特性(如过多背景噪声)通常对 TTS 反而有害;但高质量、多语言、多说话人的 TTS 数据集往往很难获得,因此这里用它做演示。
SpeechT5 期望音频采样率为 16 kHz,因此需要把数据集中的音频列强制转换为该采样率:
dataset = dataset.cast_column("audio", Audio(sampling_rate=16000))
从源码看,SpeechT5 的 feature_extraction_speecht5.py 中默认 sampling_rate=16000、num_mel_bins=80,模型配置 configuration_speecht5.py 同样以 80 个 mel bin、16 kHz 为默认前提,二者必须保持一致。
数据预处理
预处理阶段的核心任务是把原始文本与音频整理成模型能消费的 input_ids、labels(log-mel 频谱)、stop_labels 与 speaker_embeddings。
先定义检查点并加载对应的处理器(Processor 由分词器 + 特征提取器组合而成):
>>> from transformers import SpeechT5Processor
>>> checkpoint = "microsoft/speecht5_tts"
>>> processor = SpeechT5Processor.from_pretrained(checkpoint)
文本清理:字符级词汇检查与替换
处理文本需要用到处理器的分词器部分:
>>> tokenizer = processor.tokenizer
数字规范化:注意 SpeechT5 分词器没有数字 token,文本中的数字会被转成 <unk>。因此如果数据集含数字,应先将数字规范化为书写形式。仓库中 tokenization_speecht5.py 内置了 normalizer 属性,且附带 number_normalizer.py 实现了数字拼写转换(spell_number / convert),可在分词时启用 normalize=True 来自动处理。
特殊字符:SpeechT5 在英语上训练,可能不认识荷兰语中的某些字符(如 à 这类用于音节重读的字符),若不做处理会被转成 <unk>。为了保留文本语义,可以把它们替换为对应的普通字母。
先用 SpeechT5Tokenizer(以字符为 token)提取数据集中所有唯一字符。写一个 extract_all_chars 映射函数,把所有转写拼接成一个字符串并转为字符集合;注意 dataset.map() 中必须设置 batched=True 且 batch_size=-1,才能让映射函数一次性看到全部转写:
>>> def extract_all_chars(batch):
... all_text = " ".join(batch["normalized_text"])
... vocab = list(set(all_text))
... return {"vocab": [vocab], "all_text": [all_text]}
>>> vocabs = dataset.map(
... extract_all_chars,
... batched=True,
... batch_size=-1,
... keep_in_memory=True,
... remove_columns=dataset.column_names,
... )
>>> dataset_vocab = set(vocabs["vocab"][0])
>>> tokenizer_vocab = {k for k, _ in tokenizer.get_vocab().items()}
现在有了两个字符集合:数据集词汇与分词器词汇。两者做差集即可找出数据集中存在但分词器不支持的字符:
>>> dataset_vocab - tokenizer_vocab
{' ', 'à', 'ç', 'è', 'ë', 'í', 'ï', 'ö', 'ü'}
对识别出的不支持字符,定义一个替换映射到有效 token。注意空格在分词器中已被替换为 ▁,无需单独处理:
>>> replacements = [
... ("à", "a"),
... ("ç", "c"),
... ("è", "e"),
... ("ë", "e"),
... ("í", "i"),
... ("ï", "i"),
... ("ö", "o"),
... ("ü", "u"),
... ]
>>> def cleanup_text(inputs):
... for src, dst in replacements:
... inputs["normalized_text"] = inputs["normalized_text"].replace(src, dst)
... return inputs
>>> dataset = dataset.map(cleanup_text)
说话人分析:统计分布与过滤
VoxPopuli 包含多位说话人。为了解数据分布,先统计每个说话人贡献的样本数:
>>> from collections import defaultdict
>>> speaker_counts = defaultdict(int)
>>> for speaker_id in dataset["speaker_id"]:
... speaker_counts[speaker_id] += 1
绘制直方图可直观看出各说话人的数据量:
>>> import matplotlib.pyplot as plt
>>> plt.figure()
>>> plt.hist(speaker_counts.values(), bins=20)
>>> plt.ylabel("Speakers")
>>> plt.xlabel("Examples")
>>> plt.show()
从直方图可以看出:约三分之一的说话人样本不足 100 条,而约 10 位说话人拥有超过 500 条样本。为提高训练效率并平衡数据集,把数据限制在每位说话人 100~400 条样本:
>>> def select_speaker(speaker_id):
... return 100 <= speaker_counts[speaker_id] <= 400
>>> dataset = dataset.filter(select_speaker, input_columns=["speaker_id"])
过滤后剩余说话人数量与样本数:
>>> len(set(dataset["speaker_id"]))
42
>>> len(dataset)
9973
约 40 位独特说话人、近一万条样本,对微调而言已经足够。需要说明的是,样本少但单条长的说话人实际可用的音频总量可能更多,但统计这一信息需要扫描并解码整个数据集,耗时较长,本指南选择跳过。
说话人嵌入:用 SpeechBrain 提取 x-vector
要让 TTS 模型区分不同说话人,需要为每条样本生成一个说话人嵌入——它是模型的一个额外输入,用于捕捉特定说话人的音色特征。这里使用 SpeechBrain 预训练的 spkrec-xvect-voxceleb 模型。
写一个 create_speaker_embedding() 函数:输入音频波形,输出 512 维向量:
>>> import os
>>> import torch
>>> from speechbrain.pretrained import EncoderClassifier
>>> spk_model_name = "speechbrain/spkrec-xvect-voxceleb"
>>> device = "cuda" if torch.cuda.is_available() else "cpu"
>>> speaker_model = EncoderClassifier.from_hparams(
... source=spk_model_name,
... run_opts={"device": device},
... savedir=os.path.join("/tmp", spk_model_name),
... )
>>> def create_speaker_embedding(waveform):
... with torch.no_grad():
... speaker_embeddings = speaker_model.encode_batch(torch.tensor(waveform))
... speaker_embeddings = torch.nn.functional.normalize(speaker_embeddings, dim=2)
... speaker_embeddings = speaker_embeddings.squeeze().cpu().numpy()
... return speaker_embeddings
需要注意:spkrec-xvect-voxceleb 是在 VoxCeleb 英语语音上训练的,而本指南的训练数据是荷兰语。通常它仍能为荷兰语数据生成合理的说话人嵌入,但这个假设并非在所有情况下都成立。为获得最佳效果,建议先在目标语音上训练一个 x-vector 模型,使其更好地捕捉荷兰语中独特的语音特征。
从模型侧印证:SpeechT5Config 的 speaker_embedding_dim 默认值为 512(见 configuration_speecht5.py),与 x-vector 输出维度一致;模型 forward 接收的 speaker_embeddings 形状即为 (batch_size, config.speaker_embedding_dim)。
处理数据集:生成标签与嵌入
最后把数据整理成模型期望的格式。prepare_dataset 函数处理单条样本:用 SpeechT5Processor 对输入文本做 tokenize,并把目标音频加载成 log-mel 频谱;同时额外加入说话人嵌入:
>>> def prepare_dataset(example):
... audio = example["audio"]
... example = processor(
... text=example["normalized_text"],
... audio_target=audio["array"],
... sampling_rate=audio["sampling_rate"],
... return_attention_mask=False,
... )
... # strip off the batch dimension
... example["labels"] = example["labels"][0]
... # use SpeechBrain to obtain x-vector
... example["speaker_embeddings"] = create_speaker_embedding(audio["array"])
... return example
用单条样本验证处理结果:
>>> processed_example = prepare_dataset(dataset[0])
>>> list(processed_example.keys())
['input_ids', 'labels', 'stop_labels', 'speaker_embeddings']
说话人嵌入应是 512 维向量:
>>> processed_example["speaker_embeddings"].shape
(512,)
labels 则是包含 80 个 mel bin 的 log-mel 频谱,可可视化确认:
>>> import matplotlib.pyplot as plt
>>> plt.figure()
>>> plt.imshow(processed_example["labels"].T)
>>> plt.show()
小提示:如果你觉得这张频谱图"上下颠倒",是因为 matplotlib 把 y 轴翻转了(图像坐标系中 y 轴向下增长),并非数据出错。这与习惯上"低频在下、高频在上"的绘图约定相反。
把处理函数应用到整个数据集(约需 5~10 分钟):
>>> dataset = dataset.map(prepare_dataset, remove_columns=dataset.column_names)
过程中会出现警告:部分样本超过模型能处理的最大输入长度(600 token)。将这些样本删除;这里更进一步,为了允许更大的 batch size,把超过 200 token 的样本也一并删除:
>>> def is_not_too_long(input_ids):
... input_length = len(input_ids)
... return input_length < 200
>>> dataset = dataset.filter(is_not_too_long, input_columns=["input_ids"])
>>> len(dataset)
8259
最后做基本的训练/测试划分:
>>> dataset = dataset.train_test_split(test_size=0.1)
自定义数据整理器:TTSDataCollatorWithPadding
要把多条样本合成一个 batch,需要自定义数据整理器。它将较短的序列用 padding token 补齐到相同长度;对于频谱标签,padding 部分替换为特殊值 -100,该值会在计算频谱损失时告诉模型忽略对应区域(这一点与模型 forward 中"labels 中被设为 -100.0 的时间步在损失计算时被忽略"的约定完全一致):
>>> from dataclasses import dataclass
>>> from typing import Any, Dict, List, Union
>>> @dataclass
... class TTSDataCollatorWithPadding:
... processor: Any
... def __call__(self, features: list[dict[str, Union[list[int], torch.Tensor]]]) -> dict[str, torch.Tensor]:
... input_ids = [{"input_ids": feature["input_ids"]} for feature in features]
... label_features = [{"input_values": feature["labels"]} for feature in features]
... speaker_features = [feature["speaker_embeddings"] for feature in features]
... # collate the inputs and targets into a batch
... batch = processor.pad(input_ids=input_ids, labels=label_features, return_tensors="pt")
... # replace padding with -100 to ignore loss correctly
... batch["labels"] = batch["labels"].masked_fill(batch.decoder_attention_mask.unsqueeze(-1).ne(1), -100)
... # not used during fine-tuning
... del batch["decoder_attention_mask"]
... # round down target lengths to multiple of reduction factor
... if model.config.reduction_factor > 1:
... target_lengths = torch.tensor([len(feature["input_values"]) for feature in label_features])
... target_lengths = target_lengths.new(
... [length - length % model.config.reduction_factor for length in target_lengths]
... )
... max_length = max(target_lengths)
... batch["labels"] = batch["labels"][:, :max_length]
... # also add in the speaker embeddings
... batch["speaker_embeddings"] = torch.tensor(speaker_features)
... return batch
关于 reduction_factor:SpeechT5 的 decoder 输入会被缩减 2 倍,即丢弃目标序列中每隔一个的时间步,decoder 随后预测长度两倍的序列。由于原始目标序列长度可能为奇数,数据整理器需要把 batch 的最大长度向下取整为 2 的倍数。该缩减因子对应 configuration_speecht5.py 中的 reduction_factor(默认 2),在推理调优时也可以把它改成 1 来观察效果。
实例化数据整理器:
>>> data_collator = TTSDataCollatorWithPadding(processor=processor)
训练模型
从与加载处理器相同的检查点加载预训练模型:
>>> from transformers import SpeechT5ForTextToSpeech
>>> model = SpeechT5ForTextToSpeech.from_pretrained(checkpoint)
use_cache=True 与梯度检查点不兼容,训练前需关闭:
>>> model.config.use_cache = False
从 modeling_speecht5.py 的源码可见,SpeechT5ForTextToSpeech 由文本预网编码器(SpeechT5EncoderWithTextPrenet)、语音预网解码器(SpeechT5DecoderWithSpeechPrenet)和语音解码器 postnet(SpeechT5SpeechDecoderPostnet)构成;训练时若提供 labels,会通过 shift_spectrograms_right 对频谱右移,并由 SpeechT5SpectrogramLoss 计算损失(包括 use_guided_attention_loss 引导注意力损失,默认开启)。
训练参数详解
定义训练参数。这里在训练过程中不计算评估指标,只观察 loss:
>>> from transformers import Seq2SeqTrainingArguments
>>> training_args = Seq2SeqTrainingArguments(
... output_dir="speecht5_finetuned_voxpopuli_nl", # change to a repo name of your choice
... per_device_train_batch_size=4,
... gradient_accumulation_steps=8,
... learning_rate=1e-5,
... warmup_steps=500,
... max_steps=4000,
... gradient_checkpointing=True,
... fp16=True,
... eval_strategy="steps",
... per_device_eval_batch_size=2,
... save_steps=1000,
... eval_steps=1000,
... logging_steps=25,
... report_to=["tensorboard"],
... load_best_model_at_end=True,
... greater_is_better=False,
... label_names=["labels"],
... push_to_hub=True,
... )
各关键参数的作用:
output_dir:checkpoint 输出目录,建议改为自己命名的仓库名;per_device_train_batch_size=4、gradient_accumulation_steps=8:等效 batch size 为 4×8=32,两者可按显存情况联动调整;learning_rate=1e-5:微调建议用较小学习率;max_steps=4000:以步数而非 epoch 控制训练总量;gradient_checkpointing=True:以计算换显存,是 SpeechT5 这类 seq2seq 模型可训练的关键(也因此必须关闭use_cache);fp16=True:混合精度训练,进一步节省显存;eval_strategy="steps"与eval_steps=1000:每隔 1000 步评估一次;load_best_model_at_end=True配合greater_is_better=False:按最小 loss 挑选最佳 checkpoint;label_names=["labels"]:告诉 Trainer 频谱标签字段名,避免与Seq2SeqLM的默认labels语义混淆;push_to_hub=True:训练结束后把模型推送到 Hub。
实例化 Seq2SeqTrainer,传入模型、数据集与数据整理器:
>>> from transformers import Seq2SeqTrainer
>>> trainer = Seq2SeqTrainer(
... args=training_args,
... model=model,
... train_dataset=dataset["train"],
... eval_dataset=dataset["test"],
... data_collator=data_collator,
... processing_class=processor,
... )
启动训练与显存调优
>>> trainer.train()
训练耗时数小时。若在启动时遇到 CUDA "out of memory" 错误,可将 per_device_train_batch_size 按 2 的倍数逐步减小,同时把 gradient_accumulation_steps 翻倍来补偿等效 batch size。
要让 checkpoint 能被流水线使用,务必把 processor 与 checkpoint 一起保存:
>>> processor.save_pretrained("YOUR_ACCOUNT_NAME/speecht5_finetuned_voxpopuli_nl")
最后把最终模型推送到 Hub:
>>> trainer.push_to_hub()
推理
方式一:使用 pipeline
微调完成后即可用于推理。先用 "text-to-speech" 流水线加载自己的 checkpoint:
>>> from transformers import pipeline
>>> pipe = pipeline("text-to-speech", model="YOUR_ACCOUNT_NAME/speecht5_finetuned_voxpopuli_nl")
选择一段希望朗读的荷兰语文本,例如:
>>> text = "hallo allemaal, ik praat nederlands. groetjes aan iedereen!"
通过流水线使用 SpeechT5 需要说话人嵌入,可从测试集某条样本取得:
>>> example = dataset["test"][304]
>>> speaker_embeddings = torch.tensor(example["speaker_embeddings"]).unsqueeze(0)
把文本与说话人嵌入一起传给流水线,其余交给它处理:
>>> forward_params = {"speaker_embeddings": speaker_embeddings}
>>> output = pipe(text, forward_params=forward_params)
>>> output
{'audio': array([-6.82714235e-05, -4.26525949e-04, 1.06134125e-04, ...,
-1.22392643e-03, -7.76011671e-04, 3.29112721e-04], dtype=float32),
'sampling_rate': 16000}
收听结果:
>>> from IPython.display import Audio
>>> Audio(output['audio'], rate=output['sampling_rate'])
这里 forward_params 会被透传给模型 forward/generate,对应 text_to_audio.py 中 _forward 对额外张量参数的设备对齐处理;对于 SpeechT5 这类频谱模型,流水线还会自动加载 HiFi-GAN 声码器把频谱转成波形,并保证 sampling_rate 与声码器一致(16 kHz)。
方式二:手动推理
不经过流水线也能得到相同结果,只是步骤更多。从 Hub 加载模型:
>>> model = SpeechT5ForTextToSpeech.from_pretrained("YOUR_ACCOUNT/speecht5_finetuned_voxpopuli_nl")
从测试集取一条样本获得说话人嵌入:
>>> example = dataset["test"][304]
>>> speaker_embeddings = torch.tensor(example["speaker_embeddings"]).unsqueeze(0)
定义输入文本并分词:
>>> text = "hallo allemaal, ik praat nederlands. groetjes aan iedereen!"
>>> inputs = processor(text=text, return_tensors="pt")
用模型生成频谱:
>>> spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings)
如需可视化频谱:
>>> plt.figure()
>>> plt.imshow(spectrogram.T)
>>> plt.show()
最后用声码器把频谱转成声音:
>>> with torch.no_grad():
... speech = vocoder(spectrogram)
>>> from IPython.display import Audio
>>> Audio(speech.numpy(), rate=16000)
其中 generate_speech 是 SpeechT5ForTextToSpeech 的核心推理接口(见 modeling_speecht5.py),底层调用 _generate_speech。其关键参数包括:
threshold=0.5:当预测的停止 token 概率超过该值时结束生成;minlenratio=0.0/maxlenratio=20.0:用于计算输出序列的最小/最大允许长度;vocoder=None:若提供声码器则直接输出波形,否则输出 log-mel 频谱;output_cross_attentions、return_output_lengths:分别控制是否返回解码器交叉注意力与具体长度。
结果调优与注意事项
根据官方指南的实践经验,从该模型获得满意结果可能有一定挑战:
- 说话人嵌入质量是关键因素:SpeechT5 使用英语 x-vector 预训练,因此在英语说话人嵌入上表现最佳。若合成语音质量差,可尝试换用不同的说话人嵌入。
- 延长训练时长:通常能进一步提升音质。即便使用较短训练,荷兰语口音仍清晰可辨,并能捕捉示例中原说话人的音色特征。
- 调整模型配置:例如尝试
config.reduction_factor = 1,观察是否改善结果。
伦理考虑
最后必须强调伦理问题。TTS 技术有大量正当用途,但也可能被用于恶意目的,例如在他人不知情或未同意的情况下伪造其声音。请审慎且负责任地使用 TTS。
延伸阅读
- SpeechT5 模型文档:模型架构、配置项与完整 API 说明
- Bark 模型文档、VITS 模型文档、MMS 模型文档:其他可直接使用的 TTS 模型
- SpeechT5 核心实现:
SpeechT5ForTextToSpeech、generate_speech与 HiFi-GAN 声码器 - SpeechT5 配置:
num_mel_bins=80、speaker_embedding_dim=512、reduction_factor=2等默认值 - SpeechT5 特征提取器 与 分词器:16 kHz / 80 mel bin 的频谱提取与字符级分词、数字规范化
- text-to-audio 流水线实现:
TextToAudioPipeline的预处理、生成参数透传与声码器自动加载 - 对应测试用例可参考 tests/models/speecht5 目录,了解模型行为与边界条件
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00