基于Gradio的AI应用搭建实践课④:前后端联调及应用发布:打通前后端的任督二脉,就是完整的AI应用!

文摘   2025-01-20 17:53   浙江  

在上一节课我们学习了 AI模型的选择与部署

基于Gradio的AI应用搭建实践课③:AI模型部署与推理:应用功能可无限拓展


核心内容包括:


  1. 在魔搭上搜索模型

  2. 使用Notebook环境运行模型

  3. 使用 SwingDeploy部署模型API

通过这些学习,我们能够更加系统化和高效地选择合适的 AI模型,并顺利完成从模型选择到部署再到推理的整个流程,为实现应用功能的无限拓展提供了坚实的技术支撑。


接下来,我们将打通前后端的任督二脉,完成前后端联调及应用发布。


建议学习步骤


Step1: 先看一遍视频教程,对本节课程内容有一个整体的了解 



Step2: 然后根据下方图文版教程和demo示例动手实践,学以致用 



一、背景

在【Gradio组件学习:应用UI界面可无限DIY】课程中,我们学习了如何使用Gradio方便地搭建一些前端页面,实现包括文本、图像、音视频等各种类型的输入和输出的界面搭建。在【AI模型部署与推理:应用功能可无限拓展】课程中,我们学习了在魔搭平台搜索合适的模型,并通过多种方式验证模型的效果,包括在Notebook中运行模型、使用SwingDeploy部署模型API等。


本次课程,我们将结合前两个课程的内容,综合使用Gradio和模型推理,将AI模型实际搭建成为一个可以使用的AI应用,并发布为可用的创空间。


二、课程目标

在本节课中,你将学习:


1、基于Gradio和大语言模型搭建「聊天机器人」(文本输入,聊天框文本输出)

2、基于Gradio、大语言模型、文本转语音模型搭建「带有语音回复的聊天机器人」(文本输入,聊天框文本+音频输出),并将此应用发布到创空间(使用魔搭的免费CPU资源)。

3、基于Gradio、文生图模型,搭建「文生图」应用(文本输入,图片输出),并将此应用发布到创空间(使用魔搭的免费xGPU资源)

三、课程内容

Notebook可以在这个链接中直接运行:

https://modelscope.cn/notebook/share/ipynb/292eea82/studio_example.ipynb


1、前置操作

Notebook是ModelScope提供的免费计算资源,可以通过登录并编码的方式进行模型的体验。


可以通过如下的方式进行体验:

1. 首先需要将您的modelscope账号绑定阿里云账号,详细文档参考:https://www.modelscope.cn/docs/notebooks/free-trial


2. 进入首页->我的Notebook,可以根据模型的大小选择GPU或CPU实例,点击启动Notebook


预装如下依赖

!pip install gradio==5.4.0 openai modelscope_studio


2、聊天机器人

下面我们展示使用大语言模型,构建一个聊天机器人。我们使用Modelscope平台提供的模型推理API,快速上手功能验证。https://modelscope.cn/docs/model-service/API-Inference/intro

Modelscope平台提供的模型推理API兼容OpenAI协议,可以在Python中使用OpenAI的client调用。

# 仅在 Notebook 中运行时需要,本地运行无需该部分import osos.environ['GRADIO_ROOT_PATH'] = f"/{os.environ['JUPYTER_NAME']}/proxy/7860"print(os.environ['GRADIO_ROOT_PATH'])
import gradio as gr  # 导入 Gradio 库,用于构建和部署 Web 应用程序from openai import OpenAI  # 导入 OpenAI 库,用于访问 Modelscope 的 APIimport os  # 导入 os 库,用于访问环境变量
# 初始化 OpenAI 客户端client = OpenAI( api_key=os.getenv("MODELSCOPE_ACCESS_TOKEN"), # 从环境变量中获取 Modelscope API 密钥,即个人SDK token base_url="https://api-inference.modelscope.cn/v1" # 设置基础 URL为 Modelscope API地址)
# 仅在 Notebook 中运行时需要,本地运行无需该部分:检查是否已存在名为 `app` 的 Gradio 应用try: app.close() # 如果 `app` 存在,则关闭它except NameError: # 如果 `app` 不存在,捕获 NameError 异常,并忽略该异常 pass
# 创建 Gradio 应用程序with gr.Blocks() as app: # 使用 Gradio 的 Blocks 创建新的应用 gr.Markdown("# Chat with history") # 使用 Markdown 添加标题 chatbot = gr.Chatbot(type="messages") # 创建一个聊天机器人组件,用于显示消息历史 input = gr.Textbox(show_label=False) # 创建一个文本框组件,用于输入用户信息
# 定义聊天函数,支持历史消息处理和流式输出 def chat(prompt, messages): # 打印当前的聊天记录 print(messages)
# 将用户的输入添加到消息记录中 messages.append({'role': 'user', 'content': prompt}) # 使用 yield 返回初始状态以开始流式响应 yield '', messages
try: # 调用 OpenAI 的聊天接口,启动流模式获取响应 response = client.chat.completions.create( model="Qwen/Qwen2.5-7B-Instruct", # 指定使用的 OpenAI 模型 messages=messages, # 传入当前的消息记录 stream=True # 开启流式响应 )
# 逐步处理来自流响应的数据 full_response = "" # 初始化完整响应 messages.append({'role': 'assistant', 'content': full_response}) # 为助手的响应添加占位 for chunk in response: # 迭代响应流的每个块 content = chunk.choices[0].delta.content # 获取当前数据块的内容 full_response += content # 将新的内容追加到完整响应 messages[-1]['content'] = full_response # 更新历史记录中的助手内容 # 使用 yield 实时更新使用界面的显示 yield '', messages
except Exception as e: # 如果请求失败,捕获异常并返回错误信息 yield str(e)
# 当用户提交输入时,调用 `chat` 函数,并实时更新聊天记录 input.submit(fn=chat, inputs=[input, chatbot], outputs=[input, chatbot])
# 启动 Gradio 应用程序,设置服务器端口为 7860app.launch(server_port=7860)

3、带有语音回复的聊天机器人

我们可以将大模型与TTS(文本转语音)技术结合,就可以让大模型输出文本后,用语音给我们播报。


首先我们验证单独的语音合成功能,使用魔搭社区的语音合成模型:https://modelscope.cn/models/iic/speech_sambert-hifigan_tts_zh-cn_16k

from modelscope.outputs import OutputKeys  # 导入 OutputKeys,用于访问输出结构中的特定组件from modelscope.pipelines import pipeline  # 导入 pipeline,用于创建处理任务的管道from modelscope.utils.constant import Tasks  # 导入 Tasks,包含任务类型的常量定义
# 指定要使用的模型 ID,这里是一个中文语音合成模型model_id = 'iic/speech_sambert-hifigan_tts_zh-cn_16k'
# 创建一个文本到语音的处理管道,指定任务类型为文本到语音,并使用指定的模型sambert_hifigan_tts = pipeline(task=Tasks.text_to_speech, model=model_id)
# 要合成的文本text = '今天天气很晴朗'
# 使用管道处理输入文本,指定使用的语音风格为 'zhitian_emo'output = sambert_hifigan_tts(input=text, voice='zhitian_emo')
# 从输出中提取生成的 WAV 音频数据wav = output[OutputKeys.OUTPUT_WAV]
# 将生成的音频数据写入一个 WAV 文件with open('output.wav', 'wb') as f: f.write(wav) # 以二进制形式写入音频文件
# 使用这段代码在notebook中播放保存的音频文件
from IPython.display import Audio, display
audio = Audio(filename='output.wav')display(audio)

以下代码将对话和转音频相结合,构建了一个gradio应用。

import gradio as gr  # 导入 Gradio 库,用于创建 Web 应用from openai import OpenAI  # 导入 OpenAI 库,用于使用 Modelscope 的 APIimport os  # 导入 os 模块,用于处理文件系统路径和环境变量import datetime  # 导入 datetime 模块,用于处理日期和时间import modelscope_studio.components.base as msimport modelscope_studio.components.legacy as legacyfrom modelscope.outputs import OutputKeys  # 导入 OutputKeys,用于处理输出的关键字from modelscope.pipelines import pipeline  # 导入 pipeline 用于创建 AI 管道from modelscope.utils.constant import Tasks  # 导入 Tasks,包含常见任务类型的常量定义
# 初始化 OpenAI 客户端client = OpenAI( api_key=os.getenv("MODELSCOPE_ACCESS_TOKEN"), # 从环境变量中获取 Modelscope API 密钥,即个人Modelscope SDK token base_url="https://api-inference.modelscope.cn/v1" # 设置基础 URL为 Modelscope)
# 定义文本到语音合成的模型 ID,并创建相应的处理管道model_id = 'iic/speech_sambert-hifigan_tts_zh-cn_16k'sambert_hifigan_tts = pipeline(task=Tasks.text_to_speech, model=model_id)
# 创建用于保存音频文件的目录directory_path = "output_wavs"if not os.path.exists(directory_path): os.makedirs(directory_path) # 如果目录不存在,则创建该目录
# 定义函数,用于解析资源路径,将相对路径转换为绝对路径def resolve_assets(relative_path): return os.path.join(os.getcwd(), "./output_wavs", relative_path)
# 将消息转换为可在 Chatbot 组件中显示的格式def messages_to_chatbot(messages, disable_flush=False): history = [] # 迭代处理成对的消息,交替处理用户和助手的消息 for q, r in zip(messages[0::2], messages[1::2]): # 创建一个包含用户和助手消息的列表,并根据需求决定是否禁用刷新 history.append([{'text': q['content']}, {'text': r['content'], 'flushing': not disable_flush}]) return history
# 仅在 Notebook 中使用需要以下代码,如果之前已经定义过 `app`,关闭它try: app.close()except NameError: # 如果 `app` 不存在,忽略这个异常 pass
# 创建 Gradio 应用with gr.Blocks() as app: # 使用 Gradio 的 Blocks 创建新的应用 with ms.Application(): gr.Markdown("# Chat And TTS") # 使用 Markdown 添加应用标题 chatbot = legacy.Chatbot(value=[], height=300) # 创建聊天机器人组件,设置初始为空,指定高度 input = gr.Textbox(show_label=False) # 创建一个输入框用于文本输入 history = gr.State([]) # 创建一个状态用于存储聊天历史
# 定义聊天函数,支持历史消息处理和流式输出 def chat(prompt, history): # 将用户输入添加到历史中,并生成初始输出 history.append({'role': 'user', 'content': prompt}) yield '', history, messages_to_chatbot(history)
try: # 调用 OpenAI API 进行聊天,启用流式响应 response = client.chat.completions.create( model="Qwen/Qwen2.5-7B-Instruct", # 使用指定的 OpenAI 模型 messages=history, # 传入当前的消息历史 stream=True # 启用流式输出 )
# 处理流式响应并逐步更新聊天记录 full_response = "" # 初始化完整的响应 history.append({'role': 'assistant', 'content': full_response}) # 在历史中添加助手响应占位 for chunk in response: # 迭代收到的流块 content = chunk.choices[0].delta.content # 获取当前块的文本内容 full_response += content # 将内容追加到完整响应中 if chunk.choices[0].finish_reason == 'stop': # 检查响应结束原因 # 生成语音合成的音频 output = sambert_hifigan_tts(input=full_response, voice='zhitian_emo') wav = output[OutputKeys.OUTPUT_WAV] # 使用当前时间戳生成唯一的文件名 timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"{timestamp}.wav" file_path = os.path.join(directory_path, filename) # 将音频保存到文件 with open(file_path, 'wb') as f: f.write(wav) # 生成嵌入网页的音频播放元素 audio_content = f"\n<audio src=\"{resolve_assets(filename)}\"></audio>" # 更新历史记录中的助手响应包含音频 history[-1]['content'] = full_response + audio_content yield '', history, messages_to_chatbot(history, True) else: # 实时更新助手的响应内容 history[-1]['content'] = full_response yield '', history, messages_to_chatbot(history)
except Exception as e: print(e) # 打印异常信息以进行调试
# 配置当用户提交输入时,调用 `chat` 函数,更新历史和聊天界面 input.submit(fn=chat, inputs=[input, history], outputs=[input, history, chatbot])
# 启动 Gradio 应用,设置服务器端口为 7860app.launch(server_port=7860)

将编写的Gradio应用发布到创空间

在魔搭网站上点击创建创空间:


填写好名称和描述,使用gradio SDK类型创建创空间:

关联云资源:创空间内可以直接选择免费CPU资源。同时,Modelscope平台也提供了免费GPU资源供申请,若您的代码需要GPU运行环境,可以参考文档《xGPU创空间介绍》https://modelscope.cn/docs/studios/xGPU申请GPU资源。


创建完成后,在git仓库中创建新文件:


  • 创建app.py,内容与notebook中相同:


  • 创建requirements.txt,内容如下:

openaimodelscope_studio

填写环境变量,填入SDK token:


上线创空间,即可将应用分享给他人使用:

带有语音的聊天机器人


4、构建一个文生图Gradio应用

我们先验证一下文生图模型的效果。以下代码请用Notebook GPU实例运行,否则耗时较长。

# 导入必要的库from modelscope.utils.constant import Tasksfrom modelscope.pipelines import pipelineimport cv2from matplotlib import pyplot as plt
# 创建一个文本到图像合成的管道pipe = pipeline( task=Tasks.text_to_image_synthesis, # 指定任务类型 model='AI-ModelScope/stable-diffusion-v1-5', # 指定使用的模型 model_revision='v1.0.0' # 指定模型版本)
# 定义用于图像生成的文本提示prompt = '飞流直下三千尺,油画'
# 使用给定的提示通过管道生成输出output = pipe({'text': prompt})
# 将生成的图像保存到文件cv2.imwrite('result.png', output['output_imgs'][0])
# 使用matplotlib显示生成的图像img = cv2.cvtColor(output['output_imgs'][0], cv2.COLOR_BGR2RGB) # 将BGR格式转换为RGB格式plt.imshow(img) # 显示图片plt.axis('off') # 关闭坐标轴标签plt.title('生成的图像') # 设置图片的标题plt.show() # 展示图片


我们可以将其增加Gradio的页面,开发为一个应用。

若要将此应用部署到Modelscope创空间内,您可以查阅文档( https://www.modelscope.cn/brand/view/xGPU )获取免费的GPU资源。

# 导入必要的库import gradio as grimport cv2from modelscope.utils.constant import Tasksfrom modelscope.pipelines import pipelineimport numpy as npimport randomimport torch
# 仅在 Notebook 中使用需要以下代码,如果之前已经定义过 `app`,关闭它try: app.close()except NameError: # 如果 `app` 不存在,忽略这个异常 pass

# 设备检查device = "cuda" if torch.cuda.is_available() else "cpu"
# 创建一个文本到图像合成的管道pipe = pipeline( task=Tasks.text_to_image_synthesis, model='AI-ModelScope/stable-diffusion-v1-5', model_revision='v1.0.0')
# 设置随机种子上限MAX_SEED = np.iinfo(np.int32).max
# 定义图像生成的函数def infer(prompt, seed=42, randomize_seed=False): if randomize_seed: seed = random.randint(0, MAX_SEED)
generator = torch.Generator(device).manual_seed(seed)
# 通过管道生成图像 output = pipe({'text': prompt, 'generator': generator}) img = output['output_imgs'][0]
return img, seed
# 示例中的提示examples = [ "飞流直下三千尺,油画",]
# 构建Gradio应用接口with gr.Blocks() as demo: gr.Markdown("### 文生图生成应用")
# 输入文本提示 prompt = gr.Textbox( label="提示词", placeholder="输入你的提示词", )
# 创建运行按钮 run_button = gr.Button("生成图像")
# 输出生成的图像 result = gr.Image(label="生成的图像")
# 可选设置:随机种子 randomize_seed = gr.Checkbox(label="使用随机种子", value=False)
# 设定的seeds seed = gr.Number(label="种子", value=42)
# 添加示例 gr.Examples(examples=examples, inputs=[prompt], outputs=[result, seed], fn=infer)
# 设置按钮动作 run_button.click( infer, inputs=[prompt, seed, randomize_seed], outputs=[result, seed], )
# 启动应用if __name__ == "__main__": demo.launch()

发布为xGPU创空间

关联云资源:创空间内可以直接选择免费CPU资源。同时,Modelscope平台也提供了免费GPU资源供申请,若您的代码需要GPU运行环境,可以参考文档《xGPU创空间介绍》https://modelscope.cn/docs/studios/xGPU申请GPU资源。

与前文部署方式相似,在申请完成免费GPU资源后,即可选择xGPU部署创空间。


Step3: 反馈学习需求 



预设课程大纲如下


✔️课程一:全栈产品经理启发课:AI加持后,从想法到落地,就是这么简单!

✔️课程二:Gradio组件学习:应用UI界面可无限DIY

✔️课程三:AI模型部署与推理:应用功能可无限拓展

✔️课程四:前后端联调及应用发布:打通前后端的任督二脉,就是完整的AI应用!(本次内容

✔️课程五:案例学习:通过AI应用案例来实践,用微调的思路先做出你自己的第一个AI应用!

无论是对课程内容的疑问、对教学方式的建议,还是对未来课程主题的期待,都请不吝赐教。你可以通过公众号留言或是直接加入我们学习群的方式,分享你的想法。

课程学习群:


我们会从公众号留言中选取有用的建议来赠送魔搭周边小礼品哦!




👇点击关注ModelScope公众号获取
更多技术信息~



魔搭ModelScope社区
模型开源社区魔搭社区ModelScope官方账号
 最新文章