【Qwen-Audio部署实战】Qwen-Audio-Chat模型之对话机器人部署测试
系列篇章💥
No. | 文章 |
---|---|
1 | 【Qwen部署实战】探索Qwen-7B-Chat:阿里云大型语言模型的对话实践 |
2 | 【Qwen2部署实战】Qwen2初体验:用Transformers打造智能聊天机器人 |
3 | 【Qwen2部署实战】探索Qwen2-7B:通过FastApi框架实现API的部署与调用 |
4 | 【Qwen2部署实战】Ollama上的Qwen2-7B:一键部署大型语言模型指南 |
5 | 【Qwen2部署实战】llama.cpp:一键部署高效运行Qwen2-7B模型 |
6 | 【Qwen2部署实战】部署高效AI模型:使用vLLM进行Qwen2-7B模型推理 |
7 | 【AI大模型Agent探索】Qwen-Agent:基于Qwen的LLM应用开发框架 |
8 | 【AI大模型Agent探索】深入探索实践 Qwen-Agent 的 Function Calling |
9 | 【AI大模型Agent探索】Qwen-Agent之RAG智能助手实践 |
10 | 【RAG检索增强生成】LlamaIndex与Qwen2的高效检索增强生成实践 |
11 | 【Qwen2微调实战】Lora微调Qwen2-7B-Instruct实践指南 |
12 | 【Qwen2微调实战】LLaMA-Factory框架对Qwen2-7B模型的微调实践 |
13 | 【Qwen-Audio部署实战】Qwen-Audio-Chat模型之FastApi部署实战 |
14 | 【Qwen-Audio部署实战】Qwen-Audio-Chat模型之对话机器人部署测试 |
目录
- 系列篇章💥
- 引言
- 一、环境准备
- 二、安装依赖
- 1、升级pip并更换源
- 2、安装基础依赖包
- 3、安装特定工具包及版本
- 4、安装ffmpeg
- 三、模型下载
- 1、模型下载准备
- 2、模型下载执行
- 四、对话聊天机器人代码准备
- 五、对话聊天机器人运行实践
- 1、修改默认端口
- 2、启动运行web chat机器人
- 3、端口代理映射
- 4、访问web聊天对话界面
- 5、普通对话聊天
- 6、音频文件识别
- 结语
引言
在自然语言处理的浩瀚星海中,Qwen-Audio-Chat 模型以其卓越的性能和创新性,犹如一颗冉冉升起的新星,照亮了智能对话技术的前行之路。它不仅代表着对话系统的前沿发展,更是为实现自然、流畅且富有洞察力的交流体验提供了坚实的技术基础。本文将带领读者深入探讨 Qwen-Audio-Chat 模型的部署与测试流程,揭示其背后的技术奥秘,共同踏上这段充满挑战与创新的技术探索之旅。我们将重点介绍如何在 web 端构建并测试一个基于 Qwen-Audio-Chat 模型的对话机器人。
一、环境准备
在开始我们的技术之旅之前,确保拥有一个稳定而强大的运行环境是至关重要的。为此,可以在 autodl 平台上租赁一台性能卓越的服务器,该服务器应配备至少 24GB 的显存,例如 NVIDIA 的 RTX 3090 显卡,以满足模型训练和推理过程中对计算资源的高需求。
在镜像的选择上,我们建议采用 PyTorch-2.0.0 作为基础框架,并搭配 Python 3.8 环境(基于 Ubuntu 20.04 系统),同时推荐使用 CUDA 11.8 版本(至少 11.3 版本)以确保与 PyTorch 的兼容性和性能优化。完成服务器的租赁后,您可以通过 JupyterLab 图形界面快速访问服务器,并在其终端中进行环境配置、模型下载以及运行演示等关键步骤。
二、安装依赖
在终端中,我们需要执行一系列命令来完成 pip 换源以及相关依赖包的安装。为了确保顺利完成这些步骤,请按照以下指令操作。
1、升级pip并更换源
# 升级pip
python -m pip install --upgrade pip
# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
2、安装基础依赖包
# 安装常用的科学计算和机器学习库
pip install scipy torchvision pillow tensorboard matplotlib
3、安装特定工具包及版本
# 安装模型管理和优化相关的包
pip install modelscope==1.9.5 accelerate tiktoken einops transformers_stream_generator==0.0.4
# 安装较新版本的Transformers 和 gradio 库以支持AI大模型的部署
pip install transformers==4.32.0 gradio==3.39.0 nest_asyncio
4、安装ffmpeg
打开终端,输入以下命令安装ffmpeg:
sudo apt update
sudo apt install ffmpeg
通过以上步骤,您可以顺利更新pip、更换为更快的软件源,并安装所需的Python包和库,为您的Python开发环境做好准备。
三、模型下载
1、模型下载准备
使用 modelscope 中的snapshot_download函数下载模型,第一个参数为模型名称,参数cache_dir为模型的下载路径。
在 /root/autodl-tmp 路径下新建 d.py 文件并在其中输入以下内容
import torchfrom modelscope import snapshot_download, AutoModel, AutoTokenizerfrom modelscope import GenerationConfigmodel_dir = snapshot_download('qwen/Qwen-Audio-Chat', cache_dir='/root/autodl-tmp', revision='master')
2、模型下载执行
运行 python /root/autodl-tmp/d.py
执行下载,模型大小为 20 GB,下载模型大概需要10~20分钟
四、对话聊天机器人代码准备
在/root/autodl-tmp路径下新建web_demo_audio.py 文件并在其中输入以下内容:
# 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=6006,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("<", "<")line = line.replace(">", ">")line = line.replace(" ", " ")line = line.replace("*", "*")line = line.replace("_", "_")line = line.replace("-", "-")line = line.replace(".", ".")line = line.replace("!", "!")line = line.replace("(", "(")line = line.replace(")", ")")line = line.replace("$", "$")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>  |
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>  |
 <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()
五、对话聊天机器人运行实践
1、修改默认端口
注意下面代码中默认端口的设置,修改为6006
2、启动运行web chat机器人
执行以下命令启动对话聊天机器人
python /root/autodl-tmp/web_demo_audio.py
启动成功如下:
3、端口代理映射
使用autoDL SSH隧道工具代理端口
4、访问web聊天对话界面
在浏览器中打开链接 http://localhost:6006/ ,即可看到聊天界面。
5、普通对话聊天
6、音频文件识别
1)通过“上传文件”按钮,上传前面准备的音频文件
https://github.com/QwenLM/Qwen-Audio/raw/main/assets/audio/1272-128104-0000.flac
2)基于音频文件进行对话聊天
基于音频文件,测试模型对音频文件内容的识别是否准确
结语
本文的探索之旅即将结束,但我们对 Qwen-Audio-Chat 模型的深入理解和应用实践才刚刚开始。通过本文的指导,我们不仅成功部署了基于此模型的对话机器人,更对智能对话系统的构建有了更深刻的认识。
随着技术的不断演进,我们期待对话机器人在更多场景下展现出其独特的价值,为人类社会带来便利和创新。同时,我们也鼓励读者继续探索和实践,以推动智能对话技术的发展,实现更自然、更智能的交互体验。
🎯🔖更多专栏系列文章:AI大模型提示工程完全指南、AI大模型探索之路(零基础入门)、AI大模型预训练微调进阶、AI大模型开源精选实践、AI大模型RAG应用探索实践🔥🔥🔥 其他专栏可以查看博客主页📑
😎 作者介绍:我是寻道AI小兵,资深程序老猿,从业10年+、互联网系统架构师,目前专注于AIGC的探索。
📖 技术交流:欢迎关注【小兵的AI视界】公众号或扫描下方👇二维码,加入技术交流群,开启编程探索之旅。
💘精心准备📚500本编程经典书籍、💎AI专业教程,以及高效AI工具。等你加入,与我们一同成长,共铸辉煌未来。
如果文章内容对您有所触动,别忘了点赞、⭐关注,收藏!加入我,让我们携手同行AI的探索之旅,一起开启智能时代的大门!
相关文章:

【Qwen-Audio部署实战】Qwen-Audio-Chat模型之对话机器人部署测试
系列篇章💥 No.文章1【Qwen部署实战】探索Qwen-7B-Chat:阿里云大型语言模型的对话实践2【Qwen2部署实战】Qwen2初体验:用Transformers打造智能聊天机器人3【Qwen2部署实战】探索Qwen2-7B:通过FastApi框架实现API的部署与调用4【Q…...

第一百八十五节 Java XML教程 - Java DOM简介
Java XML教程 - Java DOM简介 DOM是标准的树结构,其中每个节点包含来自XML结构的一个组件。 XML文档中两种最常见的节点类型是元素节点和文本节点。 使用Java DOM API,我们可以创建节点,删除节点,更改其内容,并遍历节…...

一款功能强大且免费的图片查看和管理工具
XnView MP是一款功能强大且免费的图片查看和管理工具,支持多种平台(Windows、Mac和Linux),并基于相同的源代码实现统一的用户界面和体验。它不仅能够查看各种图片格式,还提供了丰富的编辑和管理功能。 图片查看与浏览…...
动手学强化学习 第 11 章 TRPO 算法(TRPOContinuous) 训练代码
基于 Hands-on-RL/第11章-TRPO算法.ipynb at main boyu-ai/Hands-on-RL GitHub 理论 TRPO 算法 修改了警告和报错 运行环境 Debian GNU/Linux 12 Python 3.9.19 torch 2.0.1 gym 0.26.2 运行代码 TRPOContinuous.py #!/usr/bin/env pythonimport torch import numpy a…...

数量关系模块
三年后指的不是现在 选A注意单位 注意单位换算 A 正方形减去扇形 256-X5y 那么小李拿的一定是末尾是1或者是6,所以小李拿的是26,那么y46,那么小王或者小周拿的是92,所以选择三个数之和等于92的,所以选择D 分数 百分数 …...
滑模面、趋近律设计过程详解(滑模控制)
目录 1. 确定系统的状态变量和目标2. 定义滑模面3. 选择滑模面的参数4. 设计控制律5. 验证滑模面设计6. 总结 设计滑模面(Sliding Surface)是滑模控制(Sliding Mode Control,SMC)中的关键步骤。滑模控制是一种鲁棒控制…...

SQL Server 端口配置
目录 默认端口 更改端口 示例:更改 TCP 端口 示例:验证端口设置 远程连接测试 示例:使用 telnet 测试连接 配置防火墙 示例:Windows 防火墙设置 远程连接测试 示例:使用 telnet 测试连接 默认端口 TCP/IP: …...

同一窗口还是新窗口打开链接更利于SEO优化
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storm…...
kafka 安装
docker安装kafka(KRaft 模式) KRaft模式不再对Zookeeper依赖。 docker run -d --name kafka-kraft \-p 9092:9092 -p 9093:9093 \-e KAFKA_PROCESS_ROLESbroker,controller \-e KAFKA_NODE_ID1 \-e KAFKA_CONTROLLER_QUORUM_VOTERS1127.0.0.1:9093 \-e KAFKA_LISTENERSPLAINTEX…...
消息队列中间件 - Kafka:高效数据流处理的引擎
作者:逍遥Sean 简介:一个主修Java的Web网站\游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有疑问和建议,请私信或评论留言! 前言 在现代大数据和…...
el-table表格动态合并相同数据单元格(可指定列+自定义合并)
el-table表格动态合并相同数据单元格(可指定列自定义合并)_el-table 合并单元格动态-CSDN博客 vue2elementUI表格实现实现多列动态合并_element table动态合并列-CSDN博客...

复习Nginx
1.关于Nginx Nginx的关键特性 1.支持高并发 2.内存资源消耗低 3.高扩展性(模块化设计) 4.高可用性(master-worker) Nginx运行架构 注意 默认情况下,Nginx会创建和服务器cpu核心数量相等的worker进程 worker进程之间…...
nvm:Node.js 版本管理工具
nvm(Node Version Manager)是一个用于管理多个 Node.js 版本的工具,它允许你在同一个系统上安装和使用不同版本的 Node.js。这对于开发者来说非常有用,特别是当不同的项目需要不同版本的 Node.js 时。 以下是 nvm 的一些主要特性…...

springboot校园商店配送系统-计算机毕业设计源码68448
摘要 本文详细阐述了基于Spring Boot框架的校园商店配送系统的设计与实现过程。该系统针对校园内的用户需求,整合了用户注册与登录、商品浏览与购买、订单管理、配送追踪、用户反馈收集以及后台管理等功能,为校园内的普通用户、商家、配送员和管理员提供…...

【Redis 初阶】客户端(C++ 使用样例列表)
一、编写 helloworld 需要先使用 redis-plus-plus 连接一下 Redis 服务器,再使用 ping 命令检测连通性。 1、Makefile Redis 库最多可以支持到 C17 版本。(如果是用 Centos,需要注意 gcc/g 的版本,看是否支持 C17。不支持的话&a…...

【STM32】STM32单片机入门
个人主页~ 这是一个新的系列,stm32单片机系列,资料都是从网上找的,主要参考江协科技还有正点原子以及csdn博客等资料,以一个一点没有接触过单片机但有一点编程基础的小白视角开始stm32单片机的学习,希望能对也没有学过…...

学生信息管理系统(Python+PySimpleGUI+MySQL)
吐槽一下 经过一段时间学习pymysql的经历,我深刻的体会到了pymysql的不靠谱之处; 就是在使用int型传参,我写的sql语句中格式化%d了之后,我在要传入的数据传递的每一步的去强制转换了,但是他还是会报错,说我…...

Java8.0标准之重要特性及用法实例(十九)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列…...
Linux系统中,`buffer`和`cache` 区别
在Linux系统中,buffer和cache都是操作系统用来提高磁盘I/O性能的机制,它们通过将数据暂存于内存中来减少对磁盘的直接访问。尽管它们的目的相似,但它们在实现和用途上有所不同。 Buffer 定义:buffer主要用于存储即将被写入磁盘的…...
python创建进度条的两个手搓方法
# 使用\b 回删进行手搓 import sys,time for i in range(1, 101):# 这里的10代表你的进度: 一个汉字2字节print(你的进度:,str(i)\b*(i10),flushTrue,end)time.sleep(0.5) # 利用\r手搓 import sys,time for i in range(1, 101):# \r光标回到开头print("\r", end&qu…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...

RabbitMQ 各类交换机
为什么要用交换机? 交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机 交换机类型 1,fanout:广播 特点 广播所有消息:将消息…...
第22节 Node.js JXcore 打包
Node.js是一个开放源代码、跨平台的、用于服务器端和网络应用的运行环境。 JXcore是一个支持多线程的 Node.js 发行版本,基本不需要对你现有的代码做任何改动就可以直接线程安全地以多线程运行。 本文主要介绍JXcore的打包功能。 JXcore 安装 下载JXcore安装包&a…...