[大模型]Qwen-Audio-chat WebDemo 部署

news/2024/9/25 17:18:36/

Qwen-Audio-chat WebDemo 部署

Qwen-Audio 介绍

Qwen-Audio 是阿里云研发的大规模音频语言模型(Large Audio Language Model)。Qwen-Audio 可以以多种音频 (包括说话人语音、自然音、音乐、歌声)和文本作为输入,并以文本作为输出。

环境准备

在autodl平台中租一个3090等24G显存的显卡机器,如下图所示镜像选择PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8(11.3版本以上的都可以)
接下来打开刚刚租用服务器的JupyterLab图像, 并且打开其中的终端开始环境配置、模型下载和运行演示。
在这里插入图片描述

pip换源和安装依赖包

# 升级pip
python -m pip install --upgrade pip
# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simplepip install modelscope==1.9.5pip install accelerate
pip install tiktoken
pip install einops
pip install transformers_stream_generator==0.0.4
pip install scipy
pip install torchvision
pip install pillow
pip install tensorboard
pip install matplotlib
pip install transformers==4.32.0
pip install gradio==3.39.0
pip install nest_asyncio

模型下载

使用 modelscope 中的snapshot_download函数下载模型,第一个参数为模型名称,参数cache_dir为模型的下载路径。

在 /root/autodl-tmp 路径下新建 download.py 文件并在其中输入以下内容,粘贴代码后记得保存文件,如下图所示。并运行 python /root/autodl-tmp/download.py 执行下载,模型大小为 20 GB,下载模型大概需要10~20分钟

python">import torch
from modelscope import snapshot_download, AutoModel, AutoTokenizer
from modelscope import GenerationConfig
model_dir = snapshot_download('qwen/Qwen-Audio-Chat', cache_dir='/root/autodl-tmp', revision='master')

代码准备

/root/autodl-tmp路径下新建 chatBot.py 文件并在其中输入以下内容,粘贴代码后记得保存文件。下面的代码有很详细的注释,大家如有不理解的地方,欢迎提出issue。

python"># Copyright (c) Alibaba Cloud.
#
# This source code is licensed under the license found in the
# LICENSE file in the root directory of this source tree."""A simple web interactive chat demo based on gradio."""from argparse import ArgumentParser
from pathlib import Pathimport copy
import gradio as gr
import os
import re
import secrets
import tempfile
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.generation import GenerationConfig
from pydub import AudioSegment# DEFAULT_CKPT_PATH = 'Qwen/Qwen-Audio-Chat'
DEFAULT_CKPT_PATH = "/root/autodl-tmp/qwen/Qwen-Audio-Chat"def _get_args():parser = ArgumentParser()parser.add_argument("-c", "--checkpoint-path", type=str, default=DEFAULT_CKPT_PATH,help="Checkpoint name or path, default to %(default)r")parser.add_argument("--cpu-only", action="store_true", help="Run demo with CPU only")parser.add_argument("--share", action="store_true", default=False,help="Create a publicly shareable link for the interface.")parser.add_argument("--inbrowser", action="store_true", default=False,help="Automatically launch the interface in a new tab on the default browser.")parser.add_argument("--server-port", type=int, default=8000,help="Demo server port.")parser.add_argument("--server-name", type=str, default="127.0.0.1",help="Demo server name.")args = parser.parse_args()return argsdef _load_model_tokenizer(args):tokenizer = AutoTokenizer.from_pretrained(args.checkpoint_path, trust_remote_code=True, resume_download=True,)if args.cpu_only:device_map = "cpu"else:device_map = "cuda"model = AutoModelForCausalLM.from_pretrained(args.checkpoint_path,device_map=device_map,trust_remote_code=True,resume_download=True,).eval()model.generation_config = GenerationConfig.from_pretrained(args.checkpoint_path, trust_remote_code=True, resume_download=True,)return model, tokenizerdef _parse_text(text):lines = text.split("\n")lines = [line for line in lines if line != ""]count = 0for i, line in enumerate(lines):if "```" in line:count += 1items = line.split("`")if count % 2 == 1:lines[i] = f'<pre><code class="language-{items[-1]}">'else:lines[i] = f"<br></code></pre>"else:if i > 0:if count % 2 == 1:line = line.replace("`", r"\`")line = line.replace("<", "&lt;")line = line.replace(">", "&gt;")line = line.replace(" ", "&nbsp;")line = line.replace("*", "&ast;")line = line.replace("_", "&lowbar;")line = line.replace("-", "&#45;")line = line.replace(".", "&#46;")line = line.replace("!", "&#33;")line = line.replace("(", "&#40;")line = line.replace(")", "&#41;")line = line.replace("$", "&#36;")lines[i] = "<br>" + linetext = "".join(lines)return textdef _launch_demo(args, model, tokenizer):uploaded_file_dir = os.environ.get("GRADIO_TEMP_DIR") or str(Path(tempfile.gettempdir()) / "gradio")def predict(_chatbot, task_history):query = task_history[-1][0]print("User: " + _parse_text(query))history_cp = copy.deepcopy(task_history)full_response = ""history_filter = []audio_idx = 1pre = ""global last_audiofor i, (q, a) in enumerate(history_cp):if isinstance(q, (tuple, list)):last_audio = q[0]q = f'Audio {audio_idx}: <audio>{q[0]}</audio>'pre += q + '\n'audio_idx += 1else:pre += qhistory_filter.append((pre, a))pre = ""history, message = history_filter[:-1], history_filter[-1][0]response, history = model.chat(tokenizer, message, history=history)ts_pattern = r"<\|\d{1,2}\.\d+\|>"all_time_stamps = re.findall(ts_pattern, response)print(response)if (len(all_time_stamps) > 0) and (len(all_time_stamps) % 2 ==0) and last_audio:ts_float = [ float(t.replace("<|","").replace("|>","")) for t in all_time_stamps]ts_float_pair = [ts_float[i:i + 2] for i in range(0,len(all_time_stamps),2)]# 读取音频文件format = os.path.splitext(last_audio)[-1].replace(".","")audio_file = AudioSegment.from_file(last_audio, format=format)chat_response_t = response.replace("<|", "").replace("|>", "")chat_response = chat_response_ttemp_dir = secrets.token_hex(20)temp_dir = Path(uploaded_file_dir) / temp_dirtemp_dir.mkdir(exist_ok=True, parents=True)# 截取音频文件for pair in ts_float_pair:audio_clip = audio_file[pair[0] * 1000: pair[1] * 1000]# 保存音频文件name = f"tmp{secrets.token_hex(5)}.{format}"filename = temp_dir / nameaudio_clip.export(filename, format=format)_chatbot[-1] = (_parse_text(query), chat_response)_chatbot.append((None, (str(filename),)))else:_chatbot[-1] = (_parse_text(query), response)full_response = _parse_text(response)task_history[-1] = (query, full_response)print("Qwen-Audio-Chat: " + _parse_text(full_response))return _chatbotdef regenerate(_chatbot, task_history):if not task_history:return _chatbotitem = task_history[-1]if item[1] is None:return _chatbottask_history[-1] = (item[0], None)chatbot_item = _chatbot.pop(-1)if chatbot_item[0] is None:_chatbot[-1] = (_chatbot[-1][0], None)else:_chatbot.append((chatbot_item[0], None))return predict(_chatbot, task_history)def add_text(history, task_history, text):history = history + [(_parse_text(text), None)]task_history = task_history + [(text, None)]return history, task_history, ""def add_file(history, task_history, file):history = history + [((file.name,), None)]task_history = task_history + [((file.name,), None)]return history, task_historydef add_mic(history, task_history, file):if file is None:return history, task_historyos.rename(file, file + '.wav')print("add_mic file:", file)print("add_mic history:", history)print("add_mic task_history:", task_history)# history = history + [((file.name,), None)]# task_history = task_history + [((file.name,), None)]task_history = task_history + [((file + '.wav',), None)]history = history + [((file + '.wav',), None)]print("task_history", task_history)return history, task_historydef reset_user_input():return gr.update(value="")def reset_state(task_history):task_history.clear()return []with gr.Blocks() as demo:gr.Markdown("""\
<p align="center"><img src="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Audio/logo.jpg" style="height: 80px"/><p>""")  ## todogr.Markdown("""<center><font size=8>Qwen-Audio-Chat Bot</center>""")gr.Markdown("""\
<center><font size=3>This WebUI is based on Qwen-Audio-Chat, developed by Alibaba Cloud. \
(本WebUI基于Qwen-Audio-Chat打造,实现聊天机器人功能。)</center>""")gr.Markdown("""\
<center><font size=4>Qwen-Audio <a href="https://modelscope.cn/models/qwen/Qwen-Audio/summary">🤖 </a> 
| <a href="https://huggingface.co/Qwen/Qwen-Audio">🤗</a>&nbsp | 
Qwen-Audio-Chat <a href="https://modelscope.cn/models/qwen/Qwen-Audio-Chat/summary">🤖 </a> | 
<a href="https://huggingface.co/Qwen/Qwen-Audio-Chat">🤗</a>&nbsp | 
&nbsp<a href="https://github.com/QwenLM/Qwen-Audio">Github</a></center>""")chatbot = gr.Chatbot(label='Qwen-Audio-Chat', elem_classes="control-height", height=750)query = gr.Textbox(lines=2, label='Input')task_history = gr.State([])mic = gr.Audio(source="microphone", type="filepath")with gr.Row():empty_bin = gr.Button("🧹 Clear History (清除历史)")submit_btn = gr.Button("🚀 Submit (发送)")regen_btn = gr.Button("🤔️ Regenerate (重试)")addfile_btn = gr.UploadButton("📁 Upload (上传文件)", file_types=["audio"])mic.change(add_mic, [chatbot, task_history, mic], [chatbot, task_history])submit_btn.click(add_text, [chatbot, task_history, query], [chatbot, task_history]).then(predict, [chatbot, task_history], [chatbot], show_progress=True)submit_btn.click(reset_user_input, [], [query])empty_bin.click(reset_state, [task_history], [chatbot], show_progress=True)regen_btn.click(regenerate, [chatbot, task_history], [chatbot], show_progress=True)addfile_btn.upload(add_file, [chatbot, task_history, addfile_btn], [chatbot, task_history], show_progress=True)gr.Markdown("""\
<font size=2>Note: This demo is governed by the original license of Qwen-Audio. \
We strongly advise users not to knowingly generate or allow others to knowingly generate harmful content, \
including hate speech, violence, pornography, deception, etc. \
(注:本演示受Qwen-Audio的许可协议限制。我们强烈建议,用户不应传播及不应允许他人传播以下内容,\
包括但不限于仇恨言论、暴力、色情、欺诈相关的有害信息。)""")demo.queue().launch(share=args.share,inbrowser=args.inbrowser,server_port=args.server_port,server_name=args.server_name,file_directories=["/tmp/"])def main():args = _get_args()model, tokenizer = _load_model_tokenizer(args)_launch_demo(args, model, tokenizer)if __name__ == '__main__':main()

运行 demo

在终端中运行以下命令,启动streamlit服务,并按照 autodl 的指示将端口映射到本地,然后在浏览器中打开链接 http://localhost:6006/ ,即可看到聊天界面。

streamlit run /root/autodl-tmp/chatBot.py --server.address 127.0.0.1 --server.port 6006

如下所示:

在这里插入图片描述


http://www.ppmy.cn/news/1426672.html

相关文章

avail 批量查询空投余额脚本

查询以太坊账户是否有空投的脚本。 首先,定义了一个空的`private_key_lst`列表,用于存储你的私钥。 然后,通过循环遍历`private_key_lst`中的每个私钥,在每次迭代中执行以下操作: 1. 使用私钥生成以太坊账户的地址 `from_address = Account.from_key(private_key).addr…

k8s 架构

1、概述 想要学习k8s的使用还是有必要学习一下k8s的架构。文章这个图是官网上k8s的架构图&#xff0c;这个架构展示了所有k8s的组件。Kubernetes架构可以分为两个主要部分&#xff1a;控制平面&#xff08;Control Plane&#xff09;和数据平面&#xff08;Data Plane&#xf…

【Spring高级】Springboot自动配置类原理

目录 如何引入第三方库第三方库与当前项目Bean重复自定义自动配置类 自动配置类通常位于Spring Boot的自动配置模块中&#xff0c;并且被标记为 Configuration类。这些类使用 Conditional注解来检查某些条件是否满足&#xff0c;如果满足&#xff0c;则创建和配置相关的bean。…

HttpServletRequest/Response

HttpServletRequest 一些常用类的用法 package Demo;import javax.jws.WebService; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import ja…

python中isinstance()作用

Python 中的 isinstance() 函数具有以下作用 &#xff08;类似Java 中的 instanceof &#xff09; 类型检查&#xff1a; isinstance() 用于判断一个对象是否属于特定的类型&#xff08;或类型集合&#xff09;。它接受两个参数&#xff1a;一个是待检测的对象&#xff0c;另一…

web、android和ios共同能够实现滑动及同步测试(实测)

web、android和ios共同能够实现滑动及同步测试&#xff08;实测&#xff09; 1、三者滑动效果 描述&#xff1a;在web页面拼好了之后&#xff0c;使用android和ios进行测试的时候&#xff0c;android轮播图能够实现触摸滑动&#xff0c;但是ios不可以&#xff0c;于是添加一下…

提升性能:QML Canvas 绘图优化技巧

减少绘制操作&#xff1a; 当我们有一个动态更新的图形&#xff0c;例如实时更新的数据可视化图表&#xff0c;可以通过设置一个定时器来控制更新频率&#xff0c;而不是每次数据更新都重新绘制整个图形。 使用硬件加速&#xff1a; 通过将Canvas的renderTarget属性设置为Canv…

springboot 启动非web应用

问题描述 非web应用&#xff0c;启动完成自动退出 问题原因 因为任务完成了&#xff0c;所以系统退出了。需要给spring一个任务&#xff0c;而且这个任务无法解决 包括&#xff1a; web定时任务一个无法完成的任务 解决方案 其中一个是&#xff1a; 非web不自动退出 注意…