Chainlit集成Dashscope实现语音交互网页对话AI应用
前言
本篇文章讲解和实战,如何使用Chainlit
集成Dashscope
实现语音交互网页对话AI应用。实现方案是对接阿里云提供的语音识别SenseVoice
大模型接口和语音合成CosyVoice
大模型接口使用。针对SenseVoice
大模型和CosyVoice
大模型,阿里巴巴在github
提供的有开源代码,也可以自己本地部署SenseVoice
大模型和CosyVoice
大模型接口服务。特别提及一下,阿里云上还有另外一套,语音识别和语音合成的接口,Paraformer
语音识别和Sambert
语音合成,相比之下个人觉得不如SenseVoice
大模型和CosyVoice
大模型。中间踩了一个坑,浪费我好几天研究,就是阿里云平台上Paraformer
语音识别的接口,可以直接传文件路径或者文件流而SenseVoice
大模型的接口。所以我一直中意用Paraformer
语音识别的接口,但是识别的语音文件,老是识别不出来,一开始我觉得是哪些参数没传对,或者是我麦克风生成语音文件有问题,老是语音识别不出来,后来看了一些文档,支持的音频采样率,只有16khz
的,而我音频格式不是。所以就换成SenseVoice
大模型的接口,只接受文件的url
不支持本地文件直接上传,这个接口需要需要将音频文件先上传到oss
等生成一个可以访问文件的url
。一开始我觉得会很慢,但是实测起来,速度还行。
Dashscope
DashScope 是阿里云推出的一款模型服务产品,旨在简化人工智能(AI)模型的应用与部署过程。它针对主流的AI大模型进行了标准化封装,提供了API接口,使得开发者能够轻松调用这些模型,并进行推理、训练、微调等操作。DashScope 的主要特点包括:
- 丰富的模型选择:DashScope 提供了多种类型的模型,涵盖自然语言处理、计算机视觉等多个领域,满足不同场景下的需求。
- 简便的集成方式:通过Python/Java SDK或HTTP请求,开发者可以方便地将AI模型集成到自己的应用程序中。
- 开箱即用:无需深入了解模型内部机制,用户可以直接调用API完成复杂的AI任务。
- 高效的性能优化:在模型推理优化、高效微调训练等方面积累了大量的技术实力,提升了模型使用的效率和效果。
- 灵活的弹性底座:改善了模型推理、微调效率低及规模响应慢的问题,提供了更加灵活的服务支持。
- 成本经济:提供了合理的计费模式,包括免费试用额度,帮助开发者降低成本。
此外,DashScope 还支持特定领域的高级功能,如语音合成、图像识别等,适用于广泛的行业和应用场景。通过DashScope,开发者可以获得一个强大的工具集来加速AI项目的开发和部署。
语音识别SenseVoice大模型
阿里巴巴的语音识别大模型 SenseVoice 是其在语音技术领域的一项重要成果,主要特点和能力如下:
-
高精度多语言语音识别:SenseVoice 能够提供高精度的语音转文字服务,支持多种语言的识别,适用于跨国界、跨文化的交流场景。
-
情感辨识:除了传统的语音识别外,SenseVoice 还能够识别说话者的情感状态,如高兴、悲伤、愤怒等,这对于构建更加人性化的对话系统非常有用。
-
音频事件检测:SenseVoice 可以检测音频中的特定事件,例如掌声、笑声、咳嗽等,这种能力在媒体分析、智能监控等领域具有广泛应用前景。
-
快速适应不同场景:通过先进的模型训练技术和算法优化,SenseVoice 能够快速适应不同的环境和使用场景,即使是在嘈杂的环境中也能保持较高的识别精度。
-
支持语音克隆:SenseVoice 具备语音克隆的能力,可以通过少量样本学习特定人的声音特征,进而生成相似的声音输出,这项技术在个性化语音助手、虚拟主播等领域有着广阔的应用空间。
-
开源共享:作为阿里通义实验室的一部分,SenseVoice 已经被开源,这促进了学术界和工业界之间的技术交流和进步,也为更多开发者提供了研究和应用的机会。
-
强大的技术支持:依托阿里巴巴深厚的技术积累和丰富的应用场景,SenseVoice 在性能、稳定性等方面得到了充分保障。
综上所述,SenseVoice 是一款集成了多项先进功能和技术的语音识别大模型,旨在通过提供高质量的语音处理服务,推动人机交互体验的进一步提升。
语音合成CosyVoice大模型
CosyVoice 是阿里通义实验室开发的一款先进的多语言语音合成大模型,旨在通过融合大规模预训练语言模型和深度学习技术,提供高质量、自然流畅的语音合成服务。以下是 CosyVoice 的主要特点和优势:
-
多语言支持:CosyVoice 支持包括中文、英文、日文、粤语和韩语在内的多种语言的语音合成,满足全球用户的多样化需求。
-
自然逼真的语音质量:通过超过15万小时的多语言语音数据训练,CosyVoice 能够生成几乎与真人无异的语音,无论是发音清晰度还是情感表达都达到了很高的水平。
-
快速音色克隆:CosyVoice 可以在短短几秒钟内从提供的音频样本中学习并复制特定的音色特性,使用户能够轻松创建个性化的语音内容。
-
情感和韵律控制:CosyVoice 允许对合成语音的情感色彩和节奏进行细致调整,从而更好地适应不同的应用场景和内容需求。
-
开源开放:CosyVoice 已经对外开源,不仅为开发者提供了使用这一先进技术的机会,同时也促进了学术界和工业界之间的技术交流和发展。
-
灵活的部署选项:CosyVoice 提供了从云端服务到本地部署的多种解决方案,用户可以根据自身需求选择最适合的部署方式。
-
全面的技术文档和支持:为了帮助用户更好地理解和使用 CosyVoice,官方提供了详细的使用教程和技术文档,以及持续的技术支持。
总之,CosyVoice 是一个功能强大、使用灵活的语音合成工具,它不仅能够为个人用户提供高质量的语音内容创作能力,同时也为企业和开发者提供了实现语音相关应用和服务的重要手段。
快速上手
创建一个文件,例如“chainlit_chat”
mkdir chainlit_chat
进入 chainlit_chat
文件夹下,执行命令创建python 虚拟环境空间(需要提前安装好python sdk
。 Chainlit
需要python>=3.8
。,具体操作,由于文章长度问题就不在叙述,自行百度),命令如下:
python -m venv .venv
- 这一步是避免python第三方库冲突,省事版可以跳过
.venv
是创建的虚拟空间文件夹可以自定义
接下来激活你创建虚拟空间,命令如下:
#linux or mac
source .venv/bin/activate
#windows
.venv\Scripts\activate
在项目根目录下创建requirements.txt
,内容如下:
chainlit
dashscope
执行以下命令安装依赖:
pip install -r .\requirements.txt
- 安装后,项目根目录下会多出
.chainlit
和.files
文件夹和chainlit.md
文件
代码创建
只使用通义千问的DashScope
模型服务灵积的接口
在项目根目录下创建.env
环境变量,配置如下:
DASHSCOPE_API_KEY="sk-api_key"
DASHSCOPE_API_KEY
是阿里dashscope的服务的APIkey,代码中使用DashScope的sdk实现,所以不需要配置base_url。默认就是阿里的base_url。- 阿里模型接口地址 https://dashscope.console.aliyun.com/model
- DashScope模型服务灵积文档地址 https://help.aliyun.com/zh/dashscope/
在项目根目录下创建app.py文件,代码如下:
import re
import tempfile
import time
from http import HTTPStatus
from io import BytesIOimport chainlit as cl
import dashscope.file
import requests
from chainlit.element import ElementBased
from dashscope.audio.tts_v2 import SpeechSynthesizer
from dashscope.common.constants import FilePurposeasync def text_to_speech(text: str):synthesizer = SpeechSynthesizer(model='cosyvoice-v1', voice='longxiaochun')audio = synthesizer.call(text)return "", audioasync def speech_to_text(audio_file):result = dashscope.Files.upload(file_path=audio_file,purpose=FilePurpose.assistants)file_id = result.output['uploaded_files'][0]['file_id']file_res = dashscope.Files.get(file_id)task_response = dashscope.audio.asr.Transcription.async_call(model='sensevoice-v1',file_urls=[file_res.output['url']],language_hints=['zh', 'en'],)transcribe_response = dashscope.audio.asr.Transcription.wait(task=task_response.output.task_id)if transcribe_response.status_code == HTTPStatus.OK:transcription_url = transcribe_response.output["results"][0]["transcription_url"]# 发送GET请求response = requests.get(transcription_url)# 检查请求是否成功if response.status_code == 200:# 使用内置的json()方法将响应体解析为字典data = response.json()print(data)print(data['transcripts'][0]['text'])text = data['transcripts'][0]['text']# 使用正则表达式提取标签之间的文本pattern = r'<\|Speech\|>(.*?)<\|/Speech\|>'match = re.search(pattern, text, re.DOTALL)if match:text = match.group(1).strip()else:text = ''return textelse:print(f"Failed to retrieve data: {response.status_code}")return "fail"@cl.step(type="tool", name="AI问答")
async def generate_text_answer(message: cl.Message):start_time = time.time()msg = cl.Message(content="")await msg.send()messages = [{'role': 'system', 'content': 'You are a helpful assistant.'},{'role': 'user', 'content': message.content}]print('content', message.content)stream = dashscope.Generation.call(model="qwen-plus",messages=messages,result_format='message',stream=True,incremental_output=True)print(f"代码执行时间: {time.time() - start_time} 秒")for part in stream:if token := part.output.choices[0].message.content or "":await msg.stream_token(token)return msg@cl.on_message
async def on_message(message: cl.Message):msg = await generate_text_answer(message)await msg.update()@cl.on_audio_chunk
async def on_audio_chunk(chunk: cl.AudioChunk):if chunk.isStart:buffer = BytesIO()buffer.name = f"input_audio.{chunk.mimeType.split('/')[1]}"# Initialize the session for a new audio streamcl.user_session.set("audio_buffer", buffer)cl.user_session.set("audio_mime_type", chunk.mimeType)# For now, write the chunks to a buffer and transcribe the whole audio at the endcl.user_session.get("audio_buffer").write(chunk.data)@cl.on_audio_end
async def on_audio_end(elements: list[ElementBased]):# Get the audio buffer from the sessionaudio_buffer: BytesIO = cl.user_session.get("audio_buffer")audio_mime_type: str = cl.user_session.get("audio_mime_type")audio_buffer.seek(0) # 将文件指针移到开头# 使用pydub处理音频try:with tempfile.NamedTemporaryFile(delete=False, suffix=".webm") as tmpFile:tmpFile.write(audio_buffer.read())tmpFile_path = tmpFile.nameexcept Exception as e:print(f"Error processing audio: {e}")print('tmpFile_path', tmpFile_path)transcription = await speech_to_text(tmpFile_path)input_audio_el = cl.Audio(mime=audio_mime_type, path=tmpFile_path, name="",)message = await cl.Message(author="You",type="user_message",content=transcription,elements=[input_audio_el, *elements]).send()print('transcription', transcription)msg = await generate_text_answer(message)output_name, output_audio = await text_to_speech(msg.content)output_audio_el = cl.Audio(name=output_name, auto_play=True, mime='audio/wav', content=output_audio)msg.elements = [output_audio_el]await msg.update()
- 这里我使用的国内阿里云的
DashScope sdk
服务。 - 如果要保存用户聊天记录,这里生成语音文件,如果要保存起来,本地或者oss等。
- 代码实现的是,语音问答的时候会回复文字和语音,语音设置的默认播放,文字问答的时候,只回复文字。
- 代码还有一些不完善的地方,比如异常的处理还不完善,部署生产的时候记得完善
代码解读
这段代码是一个基于 chainlit
框架的聊天机器人应用,它结合了阿里云的多个服务,包括语音合成(TTS)、语音识别(ASR)和文本生成(Text Generation),实现了从语音输入到文本处理再到语音输出的完整流程。下面是各个部分的功能解读:
1. 引入必要的模块
import re
import tempfile
import time
from http import HTTPStatus
from io import BytesIOimport chainlit as cl
import dashscope.file
import requests
from chainlit.element import ElementBased
from dashscope.audio.tts_v2 import SpeechSynthesizer
from dashscope.common.constants import FilePurpose
- 导入了用于处理字符串、文件操作、时间测量、HTTP状态码、字节流处理、网络请求、链式元素以及阿里云 DashScope 相关模块。
2. 定义 text_to_speech
函数
async def text_to_speech(text: str):synthesizer = SpeechSynthesizer(model='cosyvoice-v1', voice='longxiaochun')audio = synthesizer.call(text)return "", audio
- 使用
SpeechSynthesizer
对象调用语音合成功能,将文本转换为语音。这里使用的是 CosyVoice 模型和特定的声音(longxiaochun
)。
3. 定义 speech_to_text
函数
async def speech_to_text(audio_file):# 上传音频文件至阿里云result = dashscope.Files.upload(file_path=audio_file, purpose=FilePurpose.assistants)file_id = result.output['uploaded_files'][0]['file_id']file_res = dashscope.Files.get(file_id)# 调用语音转文字服务task_response = dashscope.audio.asr.Transcription.async_call(model='sensevoice-v1',file_urls=[file_res.output['url']],language_hints=['zh', 'en'],)transcribe_response = dashscope.audio.asr.Transcription.wait(task=task_response.output.task_id)if transcribe_response.status_code == HTTPStatus.OK:transcription_url = transcribe_response.output["results"][0]["transcription_url"]response = requests.get(transcription_url)if response.status_code == 200:data = response.json()text = data['transcripts'][0]['text']# 使用正则表达式提取标签之间的文本pattern = r'<\|Speech\|>(.*?)<\|/Speech\|>'match = re.search(pattern, text, re.DOTALL)if match:text = match.group(1).strip()else:text = ''return textelse:print(f"Failed to retrieve data: {response.status_code}")return "fail"
- 此函数负责将音频文件上传到阿里云,并调用语音识别服务将音频转换为文本。如果识别成功,则返回识别后的文本;否则返回
"fail"
。
4. 定义 generate_text_answer
函数
@cl.step(type="tool", name="AI问答")
async def generate_text_answer(message: cl.Message):start_time = time.time()msg = cl.Message(content="")await msg.send()messages = [{'role': 'system', 'content': 'You are a helpful assistant.'},{'role': 'user', 'content': message.content}]stream = dashscope.Generation.call(model="qwen-plus",messages=messages,result_format='message',stream=True,incremental_output=True)for part in stream:if token := part.output.choices[0].message.content or "":await msg.stream_token(token)return msg
- 使用阿里云的文本生成模型
qwen-plus
根据用户的输入生成回复。此函数会将生成的每个片段逐步发送给用户,以实现流式响应。
5. 定义消息处理函数
@cl.on_message
async def on_message(message: cl.Message):msg = await generate_text_answer(message)await msg.update()
- 当接收到用户的消息时,调用
generate_text_answer
函数生成回复,并更新消息对象。
6. 处理音频数据
@cl.on_audio_chunk
async def on_audio_chunk(chunk: cl.AudioChunk):if chunk.isStart:buffer = BytesIO()buffer.name = f"input_audio.{chunk.mimeType.split('/')[1]}"cl.user_session.set("audio_buffer", buffer)cl.user_session.set("audio_mime_type", chunk.mimeType)cl.user_session.get("audio_buffer").write(chunk.data)
- 当接收到音频数据块时,将其写入内存中的缓冲区。如果是音频流的开始,则初始化缓冲区。
7. 结束音频处理
@cl.on_audio_end
async def on_audio_end(elements: list[ElementBased]):audio_buffer: BytesIO = cl.user_session.get("audio_buffer")audio_mime_type: str = cl.user_session.get("audio_mime_type")audio_buffer.seek(0)with tempfile.NamedTemporaryFile(delete=False, suffix=".webm") as tmpFile:tmpFile.write(audio_buffer.read())tmpFile_path = tmpFile.nametranscription = await speech_to_text(tmpFile_path)input_audio_el = cl.Audio(mime=audio_mime_type, path=tmpFile_path, name="")message = await cl.Message(author="You",type="user_message",content=transcription,elements=[input_audio_el, *elements]).send()msg = await generate_text_answer(message)output_name, output_audio = await text_to_speech(msg.content)output_audio_el = cl.Audio(name=output_name, auto_play=True, mime='audio/wav', content=output_audio)msg.elements = [output_audio_el]await msg.update()
- 当音频流结束时,将所有收集到的音频数据保存到临时文件中,并调用
speech_to_text
函数进行语音识别。然后根据识别结果生成回复,并将回复转换为语音发送给用户。
总结
这个应用实现了从接收用户语音输入,到自动转录为文本,再到根据文本生成回复,最后将回复转换为语音输出的全过程。通过阿里云的多个服务,它能够提供流畅的交互体验。
运行应用程序
要启动 Chainlit
应用程序,请打开终端并导航到包含的目录app.py。然后运行以下命令:
chainlit run app.py -w
- 该
-w
标志告知Chainlit
启用自动重新加载,因此您无需在每次更改应用程序时重新启动服务器。您的聊天机器人 UI 现在应该可以通过http://localhost:8000访问。 - 自定义端口可以追加
--port 80
启动后界面如下:
相关文章推荐
《Chainlit快速实现AI对话应用的界面定制化教程》
《Chainlit接入FastGpt接口快速实现自定义用户聊天界面》
《使用 Xinference 部署本地模型》
《Fastgpt接入Whisper本地模型实现语音输入》
《Fastgpt部署和接入使用重排模型bge-reranker》
《Fastgpt部署接入 M3E和chatglm2-m3e文本向量模型》
《Fastgpt 无法启动或启动后无法正常使用的讨论(启动失败、用户未注册等问题这里)》
《vllm推理服务兼容openai服务API》
《vLLM模型推理引擎参数大全》
《解决vllm推理框架内在开启多显卡时报错问题》
《Ollama 在本地快速部署大型语言模型,可进行定制并创建属于您自己的模型》
相关文章:

Chainlit集成Dashscope实现语音交互网页对话AI应用
前言 本篇文章讲解和实战,如何使用Chainlit集成Dashscope实现语音交互网页对话AI应用。实现方案是对接阿里云提供的语音识别SenseVoice大模型接口和语音合成CosyVoice大模型接口使用。针对SenseVoice大模型和CosyVoice大模型,阿里巴巴在github提供的有开…...

Canal 扩展篇(阿里开源用于数据同步备份,监控表和表字段(日志))
1.Canal介绍 Canal把自己伪装成从数据库,获取mysql主数据库的日志(binlog)信息,所以要想使用canal就得先开启数据库日志 https://github.com/alibaba/canal Canal 主要用途是基于 MySQL 数据库增量日志解析,提供增量…...

顺序表的定义
一.顺序表的定义 顺序表--用顺序存储的方式实现线性表 顺序存储。把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关 系由存储单元的邻接关系来体现。 二.顺序表的实现--静态分配 #include<stdio.h> #define MaxSize 10 //定义最大长度 …...

青少年编程能力等级测评CPA C++一级试卷(1)
青少年编程能力等级测评CPA C一级试卷(1) 一、单项选择题(共20题,每题3.5分,共70分) CP1_1_1.在C中,下列变量名正确的是( )。 A.$123 B&#…...

R语言中的plumber介绍
R语言中的plumber介绍 基本用法常用 API 方法1. GET 方法2. POST 方法3. 带路径参数的 GET 方法 使用 R 对数据进行操作处理 JSON 输入和输出运行 API 的其他选项其他功能 plumber 是个强大的 R 包,用于将 R 代码转换为 Web API,通过使用 plumber&#x…...

uniapp 设置 tabbar 的 midButton 按钮
效果展示: 中间的国际化没生效(忽略就行) 示例代码: 然后在 App.vue 中进行监听: <script>export default {onLaunch(e) {// #ifdef APPuni.onTabBarMidButtonTap(()>{console.log("中间按钮点击回调…...

php 生成随机数
记录:随机数抽奖 要求:每次生成3个 1 - 10 之间可重复(或不可重复)的随机数,10次为一轮,每轮要求数字5出现6次、数字4出现3次、…。 提炼需求: 1,可设置最小数、最大数、每次抽奖生成随机数的个数、是否允许重复 2,可设置每轮指定数字的出现次数 3,可设置每轮的抽奖…...
MySQL 8.4修改初始化后的默认密码
MySQL 8.4修改初始化后的默认密码 (1)初始化mysql: mysqld --initialize --console (2)之后,mysql会生成一个默认复杂的密码,如果打算修改这个密码,可以先用旧密码登录: mysql -u…...

前端开发笔记--css 黑马程序员1
文章目录 1. css 语法规范2.css的书写风格3.基础选择器选择器的分类标签选择器类选择器类选择器的特殊使用--多类名 id 选择器 字体属性常见字体字体大小字体粗细字体倾斜字体的复合简写字体属性总结 文本属性文本颜色文本对齐装饰文本文本缩进文本间距文本属性总结 css的引入方…...
ORACLE 19C创建多个不同字符集PDB
现在需要在一个测试环境创建1个为AL32UTF8的PDB,2个ZHS16GBK的PDB 这种情况下,必须先创建的CDB为AL32UTF8,下面是具体步骤: 1.AL32UTF8的pdb在建实例的时候一起创建完成 2.创建第一个ZHS16GBK的PDB cdr,通过pdbseed来克隆: SQL> create pluggable database cdr admin us…...

基于协同过滤的景区旅游可视化与景区推荐系统(自动爬虫,地点可换)
文章目录 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主项目介绍过程展示项目移植每文一语 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主 项目介绍 本项目是一个综合性的旅游景区数据管理与分析推荐系统,集成了用…...

ElasticSearch搜索引擎
npm run start ELK: ESLogstashKibana Kibana:端口号5601 elasticSearch是面向文档 Kibana可以将ElasticSearch的数据通过友好的页面展示出来。 Es与Kibana的版本一致 es查询的效率很高,处理大数据 ES和solr的区别: 当单纯的对已有…...
leetcode哈希表(二)-两个数组的交集
题目 . - 力扣(LeetCode) 给定两个数组 nums1 和 nums2 ,返回 它们的交集。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序 。 示例 1: 输入:nums1 [1,2,2,1], nums2 [2,2] 输出:[…...

嵌入式硬件设计中EDA布局与布线实现
大家好,今天主要给大家分享一下,如何使用立创EDA进行布局和布线,具体实现过程如下: 第一:PCB概念介绍 在介绍PCB的时候,先来说明一下,电子管的发明史。 贝尔在1876年发明了电话,爱迪生1879年发明了白炽灯、特斯拉于1888年发明了电动机,所有这些,都为电子学的诞生准…...

entity,pojo,vo,dto 详解
在Java项目中,包名通常用于组织代码,使其更加清晰和易于维护。entity、pojo、vo和dto是常见的包名,它们各自有不同的含义和用途。下面将详细解释这些包名的含义,并提供一个示例,帮助你更好地理解它们在项目中的应用。 …...
C语言常见知识点
目录 一、单位 二、变量 三、常量 四、转义字符 五、操作符 六、指针 七、数组 一、单位 在刚接触编程时,肯定会了解到计算机的存储单位,它们由小到大分别为bit(位)、Byte(字节)、KB(千字…...

产品设计——应用架构
我的理解应用架构是业务架构的落地,微服务架构下平台的应用架构设计,实质是根据业务来明确应用微服务的边界。因此业务不同,应用架构图也不同。但是基本框架应该相差不大。 其划分原则莫过于高内聚、低耦合。这个跟接口设计是一致的。我们总是…...
Linux初阶——动静态库
一、静态库(格式:libxxx.a) 1. 原理 在运行之前就已经把函数的实现代码拷进 main.c 文件里了,因此静态库的权限是没有可执行权限的,因为根本不会执行到静态库里的内容。静态库的创建原理本质上就是把所有的函数源文件…...

创建一个c#程序,实现字符串类型转整数类型
首先,创建一个c#程序 在代码编辑器中编写代码,点击Run按钮或者按下F5键来运行程序。 下面,编写将字符串类型转换为整数类型的代码。 sing System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Task…...

Spring Boot知识管理系统:敏捷开发实践
3系统分析 3.1可行性分析 通过对本知识管理系统实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本知识管理系统采用JAVA作为开发语言,Spring Boot框…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...

【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

C++实现分布式网络通信框架RPC(2)——rpc发布端
有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...