多轮对话推理示例函数,这里我们采用assistant生成的text作为下一轮的输入 Args: model_path: 模型路径 audio_paths: 输入音频路径列表
(model_path, audio_paths)
| 90 | print(f"Audio saved to: {output_path}") |
| 91 | |
| 92 | def infer_multiturn_example(model_path, audio_paths): |
| 93 | """ |
| 94 | 多轮对话推理示例函数,这里我们采用assistant生成的text作为下一轮的输入 |
| 95 | |
| 96 | Args: |
| 97 | model_path: 模型路径 |
| 98 | audio_paths: 输入音频路径列表 |
| 99 | """ |
| 100 | # 加载模型和处理器 |
| 101 | config = AutoConfig.from_pretrained(model_path) |
| 102 | processor = AutoProcessor.from_pretrained(model_path) |
| 103 | model = AutoModelForSeq2SeqLM.from_pretrained(model_path, config=config, torch_dtype=torch.bfloat16, device_map=device) |
| 104 | |
| 105 | # 加载CosyVoice detokenizer用于将token转换为wav |
| 106 | print("Loading CosyVoice detokenizer...") |
| 107 | cosyvoice_model = get_audio_detokenizer() |
| 108 | |
| 109 | # 生成参数 |
| 110 | sp_gen_kwargs = DEFAULT_SP_GEN_KWARGS.copy() |
| 111 | sp_gen_kwargs['text_greedy'] = True |
| 112 | gen_kwargs = DEFAULT_S2M_GEN_KWARGS.copy() |
| 113 | gen_kwargs['max_new_tokens'] = 2048 |
| 114 | model.sp_gen_kwargs.update(sp_gen_kwargs) |
| 115 | |
| 116 | conversation = [ |
| 117 | {"role": "system", "content": SPOKEN_S2M_PROMPT}, |
| 118 | ] |
| 119 | audio = [] |
| 120 | for index, audio_path in enumerate(audio_paths): |
| 121 | # ignore assistant ground truth audio |
| 122 | if index % 2 == 1: |
| 123 | continue |
| 124 | |
| 125 | audio.append(librosa.load(audio_path, sr=16000)[0]) |
| 126 | conversation.append({"role": "user", "content": AUDIO_TEMPLATE}) |
| 127 | |
| 128 | text = processor.apply_chat_template(conversation, add_generation_prompt=True, tokenize=False) |
| 129 | inputs = processor(text=text, audio=audio, return_tensors="pt", return_token_type_ids=False).to(model.device) |
| 130 | generate_ids, audio_ids = model.generate(**inputs, **gen_kwargs) |
| 131 | generate_ids = generate_ids[:, inputs.input_ids.size(1):] |
| 132 | generate_text = processor.decode(generate_ids[0], skip_special_tokens=True) |
| 133 | generate_audio = processor.speech_tokenizer.decode(audio_ids[0]) |
| 134 | |
| 135 | print("generate_text: ", generate_text) |
| 136 | print("generate_audio_token: ", generate_audio) |
| 137 | |
| 138 | token_for_cosyvoice = list(filter(lambda x: 0 <= x < 6561, audio_ids[0].tolist())) |
| 139 | |
| 140 | # 使用默认的中文女声,你可以根据需要修改 |
| 141 | print("Converting audio tokens to wav...") |
| 142 | speech = token2wav(cosyvoice_model, token_for_cosyvoice, embedding=None, token_hop_len=25 * 30, pre_lookahead_len=3) |
| 143 | |
| 144 | # 保存wav文件 |
| 145 | output_uuid = str(uuid.uuid4()) |
| 146 | os.makedirs('saves', exist_ok=True) |
| 147 | output_path = f'saves/output_audio_{output_uuid}.wav' |
| 148 | torchaudio.save(output_path, speech.cpu(), cosyvoice_model.sample_rate) |
| 149 | print(f"Audio saved to: {output_path}") |
nothing calls this directly
no test coverage detected