[大模型]基于 ChatGLM3 和 LangChain 搭建知识库助手

基于 ChatGLM3 和 LangChain 搭建知识库助手

环境配置

在已完成 ChatGLM3 的部署基础上,还需要安装以下依赖包:

pip install langchain==0.0.292
pip install gradio==4.4.0
pip install chromadb==0.4.15
pip install sentence-transformers==2.2.2
pip install unstructured==0.10.30
pip install markdown==3.3.7

同时,我们需要使用到开源词向量模型 Sentence Transformer(HuggingFace 链接名为:sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2),可以将其模型参数以类似于下载 ChatGLM3 模型参数的方式下载到本地 /root/autodl-tmp/sentence-transformer。同时,在本节中,ChatGLM3-6B 的模型参数文件存储在本地 autodl-tmp/ZhipuAI/chatglm3-6b。

知识库搭建

我们选择 Datawhale 的一系列 LLM 开源教程作为语料库来源,包括:

  • Self LLM:一个围绕开源大模型、针对国内初学者、基于 AutoDL 平台的中国宝宝专属大模型教程。
  • LLM Universe:一个面向小白开发者的大模型应用开发教程,旨在结合个人知识库助手项目,通过一个课程完成大模型开发的重点入门。
  • LLM tutorial for Developers:一个面向开发者的 LLM 入门教程,基于吴恩达老师大模型系列课程内容实现。
  • So Large LLM:一个大规模预训练语言模型的教程,从数据准备、模型构建、训练策略到模型评估与改进,以及模型在安全、隐私、环境和法律道德方面的方面来提供开源知识。
  • Hugging LLM:介绍 ChatGPT 原理、使用和应用,降低使用门槛,让更多感兴趣的非NLP或算法专业人士能够无障碍使用LLM创造价值。

首先我们需要将上述远程开源仓库 Clone 到本地,可以使用以下命令:

# 进入到数据库盘
cd /root/autodl-tmp
# 打开学术资源加速
source /etc/network_turbo
# clone 上述开源仓库
git clone https://github.com/datawhalechina/self-llm.git
git clone https://github.com/datawhalechina/llm-universe.git
git clone https://github.com/datawhalechina/prompt-engineering-for-developers.git
git clone https://github.com/datawhalechina/so-large-lm.git
git clone https://github.com/datawhalechina/hugging-llm.git
# 关闭学术资源加速
unset http_proxy && unset https_proxy

接着,为语料处理方便,我们将选用上述仓库中所有的 markdown、txt 文件作为示例语料库。注意,也可以选用其中的代码文件加入到知识库中,但需要针对代码文件格式进行额外处理。

我们首先将上述仓库中所有满足条件的文件路径找出来,我们定义一个函数,该函数将递归指定文件夹路径,返回其中所有满足条件(即后缀名为 .md 或者 .txt 的文件)的文件路径:

import os 
def get_files(dir_path):# args:dir_path,目标文件夹路径file_list = []for filepath, dirnames, filenames in os.walk(dir_path):# os.walk 函数将递归遍历指定文件夹for filename in filenames:# 通过后缀名判断文件类型是否满足要求if filename.endswith(".md"):# 如果满足要求,将其绝对路径加入到结果列表file_list.append(os.path.join(filepath, filename))elif filename.endswith(".txt"):file_list.append(os.path.join(filepath, filename))return file_list

得到所有目标文件路径之后,我们可以使用 LangChain 提供的 FileLoader 对象来加载目标文件,得到由目标文件解析出的纯文本内容。由于不同类型的文件需要对应不同的 FileLoader,我们判断目标文件类型,并针对性调用对应类型的 FileLoader,同时,调用 FileLoader 对象的 load 方法来得到加载之后的纯文本对象:

from tqdm import tqdm
from langchain.document_loaders import UnstructuredFileLoader
from langchain.document_loaders import UnstructuredMarkdownLoaderdef get_text(dir_path):# args:dir_path,目标文件夹路径# 首先调用上文定义的函数得到目标文件路径列表file_lst = get_files(dir_path)# docs 存放加载之后的纯文本对象docs = []# 遍历所有目标文件for one_file in tqdm(file_lst):file_type = one_file.split('.')[-1]if file_type == 'md':loader = UnstructuredMarkdownLoader(one_file)elif file_type == 'txt':loader = UnstructuredFileLoader(one_file)else:# 如果是不符合条件的文件,直接跳过continuedocs.extend(loader.load())return docs

使用上文函数,我们得到的 docs 为一个纯文本对象对应的列表。得到该列表之后,我们就可以将它引入到 LangChain 框架中构建向量数据库。由纯文本对象构建向量数据库,我们需要先对文本进行分块,接着对文本块进行向量化。

LangChain 提供了多种文本分块工具,此处我们使用字符串递归分割器,并选择分块大小为 500,块重叠长度为 150:

from langchain.text_splitter import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=150)
split_docs = text_splitter.split_documents(docs)

接着我们选用开源词向量模型 Sentence Transformer来进行文本向量化。LangChain 提供了直接引入 HuggingFace 开源社区中的模型进行向量化的接口:

from langchain.embeddings.huggingface import HuggingFaceEmbeddingsembeddings = HuggingFaceEmbeddings(model_name="autodl-tmp/sentence-transformer")

同时,我们选择 Chroma 作为向量数据库,基于上文分块后的文档以及加载的开源向量化模型,将语料加载到指定路径下的向量数据库:

from langchain.vectorstores import Chroma# 定义持久化路径
persist_directory = 'data_base/vector_db/chroma'
# 加载数据库
vectordb = Chroma.from_documents(documents=split_docs,embedding=embeddings,persist_directory=persist_directory  # 允许我们将persist_directory目录保存到磁盘上
)
# 将加载的向量数据库持久化到磁盘上
vectordb.persist()

将上述代码整合在一起为知识库搭建的脚本:

# 首先导入所需第三方库
from langchain.document_loaders import UnstructuredFileLoader
from langchain.document_loaders import UnstructuredMarkdownLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
from tqdm import tqdm
import os# 获取文件路径函数
def get_files(dir_path):# args:dir_path,目标文件夹路径file_list = []for filepath, dirnames, filenames in os.walk(dir_path):# os.walk 函数将递归遍历指定文件夹for filename in filenames:# 通过后缀名判断文件类型是否满足要求if filename.endswith(".md"):# 如果满足要求,将其绝对路径加入到结果列表file_list.append(os.path.join(filepath, filename))elif filename.endswith(".txt"):file_list.append(os.path.join(filepath, filename))return file_list# 加载文件函数
def get_text(dir_path):# args:dir_path,目标文件夹路径# 首先调用上文定义的函数得到目标文件路径列表file_lst = get_files(dir_path)# docs 存放加载之后的纯文本对象docs = []# 遍历所有目标文件for one_file in tqdm(file_lst):file_type = one_file.split('.')[-1]if file_type == 'md':loader = UnstructuredMarkdownLoader(one_file)elif file_type == 'txt':loader = UnstructuredFileLoader(one_file)else:# 如果是不符合条件的文件,直接跳过continuedocs.extend(loader.load())return docs# 目标文件夹
tar_dir = ["/root/autodl-tmp/self-llm","/root/autodl-tmp/llm-universe","/root/autodl-tmp/prompt-engineering-for-developers","/root/autodl-tmp/so-large-lm","/root/autodl-tmp/hugging-llm",
]# 加载目标文件
docs = []
for dir_path in tar_dir:docs.extend(get_text(dir_path))# 对文本进行分块
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=150)
split_docs = text_splitter.split_documents(docs)# 加载开源词向量模型
embeddings = HuggingFaceEmbeddings(model_name="autodl-tmp/sentence-transformer")# 构建向量数据库
# 定义持久化路径
persist_directory = 'data_base/vector_db/chroma'
# 加载数据库
vectordb = Chroma.from_documents(documents=split_docs,embedding=embeddings,persist_directory=persist_directory  # 允许我们将persist_directory目录保存到磁盘上
)
# 将加载的向量数据库持久化到磁盘上
vectordb.persist()

运行上述脚本,即可在本地构建已持久化的向量数据库,后续直接导入该数据库即可,无需重复构建。

InternLM 接入 LangChain

为便捷构建 LLM 应用,我们需要基于本地部署的 ChatGLM3-6B,自定义一个 LLM 类,将 ChatGLM 接入到 LangChain 框架中。完成自定义 LLM 类之后,可以以完全一致的方式调用 LangChain 的接口,而无需考虑底层模型调用的不一致。

基于本地部署的 ChatGLM3-6B 自定义 LLM 类并不复杂,我们只需从 LangChain.llms.base.LLM 类继承一个子类,并重写构造函数与 _call 函数即可:

from langchain.llms.base import LLM
from typing import Any, List, Optional
from langchain.callbacks.manager import CallbackManagerForLLMRun
from transformers import AutoTokenizer, AutoModelForCausalLMclass ChatGLM_LLM(LLM):# 基于本地 InternLM 自定义 LLM 类tokenizer : AutoTokenizer = Nonemodel: AutoModelForCausalLM = Nonedef __init__(self, model_path :str):# model_path: InternLM 模型路径# 从本地初始化模型super().__init__()print("正在从本地加载模型...")self.tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)self.model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True).to(torch.bfloat16).cuda()self.model = self.model.eval()print("完成本地模型的加载")def _call(self, prompt : str, stop: Optional[List[str]] = None,run_manager: Optional[CallbackManagerForLLMRun] = None,**kwargs: Any):# 重写调用函数response, history = self.model.chat(self.tokenizer, prompt , history=[])return response@propertydef _llm_type(self) -> str:return "ChatGLM3-6B"

在上述类定义中,我们分别重写了构造函数和 _call 函数:对于构造函数,我们在对象实例化的一开始加载本地部署的 ChatGLM3-6B 模型,从而避免每一次调用都需要重新加载模型带来的时间过长;_call 函数是 LLM 类的核心函数,LangChain 会调用该函数来调用 LLM,在该函数中,我们调用已实例化模型的 chat 方法,从而实现对模型的调用并返回调用结果。

在整体项目中,我们将上述代码封装为 llm.py,后续将直接从该文件中引入自定义的 LLM 类。

构建检索问答链

LangChain 通过提供检索问答链对象来实现对于 RAG 全流程的封装。即我们可以调用一个 LangChain 提供的 RetrievalQA 对象,通过初始化时填入已构建的数据库和自定义 LLM 作为参数,来简便地完成检索增强问答的全流程,LangChain 会自动完成基于用户提问进行检索、获取相关文档、拼接为合适的 Prompt 并交给 LLM 问答的全部流程。

首先我们需要将上文构建的向量数据库导入进来,我们可以直接通过 Chroma 以及上文定义的词向量模型来加载已构建的数据库:

from langchain.vectorstores import Chroma
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
import os# 定义 Embeddings
embeddings = HuggingFaceEmbeddings(model_name="autodl-tmp/sentence-transformer")# 向量数据库持久化路径
persist_directory = 'data_base/vector_db/chroma'# 加载数据库
vectordb = Chroma(persist_directory=persist_directory, embedding_function=embeddings
)

上述代码得到的 vectordb 对象即为我们已构建的向量数据库对象,该对象可以针对用户的 query 进行语义向量检索,得到与用户提问相关的知识片段。

接着,我们实例化一个基于 ChatGLM3-6B 自定义的 LLM 对象:

from LLM import ChatGLM_LLM
llm = ChatGLM_LLM(model_path = "autodl-tmp/ZhipuAI/chatglm3-6b")
llm.predict("你是谁")

构建检索问答链,还需要构建一个 Prompt Template,该 Template 其实基于一个带变量的字符串,在检索之后,LangChain 会将检索到的相关文档片段填入到 Template 的变量中,从而实现带知识的 Prompt 构建。我们可以基于 LangChain 的 Template 基类来实例化这样一个 Template 对象:

from langchain.prompts import PromptTemplate# 我们所构造的 Prompt 模板
template = """使用以下上下文来回答最后的问题。如果你不知道答案,就说你不知道,不要试图编造答案。尽量使答案简明扼要。总是在回答的最后说“谢谢你的提问!”。
{context}
问题: {question}
有用的回答:"""# 调用 LangChain 的方法来实例化一个 Template 对象,该对象包含了 context 和 question 两个变量,在实际调用时,这两个变量会被检索到的文档片段和用户提问填充
QA_CHAIN_PROMPT = PromptTemplate(input_variables=["context","question"],template=template)

最后,可以调用 LangChain 提供的检索问答链构造函数,基于我们的自定义 LLM、Prompt Template 和向量知识库来构建一个基于 InternLM 的检索问答链:

from langchain.chains import RetrievalQAqa_chain = RetrievalQA.from_chain_type(llm,retriever=vectordb.as_retriever(),return_source_documents=True,chain_type_kwargs={"prompt":QA_CHAIN_PROMPT})

得到的 qa_chain 对象即可以实现我们的核心功能,即基于 InternLM 模型的专业知识库助手。我们可以对比该检索问答链和纯 LLM 的问答效果:

# 检索问答链回答效果
question = "什么是 Self LLM"
result = qa_chain({"query": question})
print("检索问答链回答 question 的结果:")
print(result["result"])# 仅 LLM 回答效果
result_2 = llm(question)
print("大模型回答 question 的结果:")
print(result_2)

部署 Web Demo

在完成上述核心功能后,我们可以基于 Gradio 框架将其部署到 Web 网页,从而搭建一个小型 Demo,便于测试与使用。

我们首先将上文的代码内容封装为一个返回构建的检索问答链对象的函数,并在启动 Gradio 的第一时间调用该函数得到检索问答链对象,后续直接使用该对象进行问答对话,从而避免重复加载模型:


from langchain.vectorstores import Chroma
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
import os
from LLM import ChatGLM_LLM
from langchain.prompts import PromptTemplate
from langchain.chains import RetrievalQAdef load_chain():# 加载问答链# 定义 Embeddingsembeddings = HuggingFaceEmbeddings(model_name="autodl-tmp/sentence-transformer")# 向量数据库持久化路径persist_directory = 'data_base/vector_db/chroma'# 加载数据库vectordb = Chroma(persist_directory=persist_directory,  # 允许我们将persist_directory目录保存到磁盘上embedding_function=embeddings)# 加载自定义 LLMllm = ChatGLM_LLM(model_path = "autodl-tmp/ZhipuAI/chatglm3-6b")# 定义一个 Prompt Templatetemplate = """使用以下上下文来回答最后的问题。如果你不知道答案,就说你不知道,不要试图编造答案。尽量使答案简明扼要。总是在回答的最后说“谢谢你的提问!”。{context}问题: {question}有用的回答:"""QA_CHAIN_PROMPT = PromptTemplate(input_variables=["context","question"],template=template)# 运行 chainqa_chain = RetrievalQA.from_chain_type(llm,retriever=vectordb.as_retriever(),return_source_documents=True,chain_type_kwargs={"prompt":QA_CHAIN_PROMPT})return qa_chain

接着我们定义一个类,该类负责加载并存储检索问答链,并响应 Web 界面里调用检索问答链进行回答的动作:

class Model_center():"""存储检索问答链的对象 """def __init__(self):# 构造函数,加载检索问答链self.chain = load_chain()def qa_chain_self_answer(self, question: str, chat_history: list = []):"""调用问答链进行回答"""if question == None or len(question) < 1:return "", chat_historytry:chat_history.append((question, self.chain({"query": question})["result"]))# 将问答结果直接附加到问答历史中,Gradio 会将其展示出来return "", chat_historyexcept Exception as e:return e, chat_history

然后我们只需按照 Gradio 的框架使用方法,实例化一个 Web 界面并将点击动作绑定到上述类的回答方法即可:

import gradio as gr# 实例化核心功能对象
model_center = Model_center()
# 创建一个 Web 界面
block = gr.Blocks()
with block as demo:with gr.Row(equal_height=True):   with gr.Column(scale=15):# 展示的页面标题gr.Markdown("""<h1><center>Self LLM</center></h1><center>Self LLM</center>""")with gr.Row():with gr.Column(scale=4):# 创建一个聊天机器人对象chatbot = gr.Chatbot(height=450, show_copy_button=True)# 创建一个文本框组件,用于输入 prompt。msg = gr.Textbox(label="Prompt/问题")with gr.Row():# 创建提交按钮。db_wo_his_btn = gr.Button("Chat")with gr.Row():# 创建一个清除按钮,用于清除聊天机器人组件的内容。clear = gr.ClearButton(components=[chatbot], value="Clear console")# 设置按钮的点击事件。当点击时,调用上面定义的 qa_chain_self_answer 函数,并传入用户的消息和聊天历史记录,然后更新文本框和聊天机器人组件。db_wo_his_btn.click(model_center.qa_chain_self_answer, inputs=[msg, chatbot], outputs=[msg, chatbot])gr.Markdown("""提醒:<br>1. 初始化数据库时间可能较长,请耐心等待。2. 使用中如果出现异常,将会在文本输入框进行展示,请不要惊慌。 <br>""")
gr.close_all()
# 直接启动
demo.launch()

通过将上述代码封装为 run_gradio.py 脚本,直接通过 python 命令运行,即可在本地启动知识库助手的 Web Demo,默认会在 7860 端口运行,使用类似于部署的方式将服务器端口映射到本地端口即可访问:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/811461.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务项目实战-黑马头条(一):环境搭建 + APP登录功能【前端静态资源+nginx反向代理+网关+过滤器】

文章目录 一、搭建nacos二、初始工程的搭建2.1 环境准备2.2主体结构 三、APP登录3.1 需求分析3.2 表结构分析3.3 接口定义3.4 功能实现 四、接口工具postman、swagger、knife4j4.1 postman4.2 swagger4.3 knife4j 五、网关5.1 网关搭建5.2 全局过滤器实现jwt校验 六、前端集成6…

目前电视盒子哪个最好?测评工作室盘点超强电视盒子推荐

每年我们会进行数十次电视盒子测评&#xff0c;对各个品牌的产品都有深入的了解&#xff0c;最近我们收到了很多私信不知道目前电视盒子哪个最好&#xff0c;这次我们结合配置总结了五款性能超强的电视盒子推荐给各位&#xff0c;预算足够想买高配电视盒子的朋友们可不要错过啦…

高级Java开发工程师手把手教你用AI人工智能帮你写JAVA代码实际案例二(生成自定义springboot定时器组件)全网唯一

高级Java开发工程师手把手教你用AI人工智能帮你写JAVA代码实际案例二全网唯一 一、需求背景案例说明 笔者有个实际的生产项目&#xff0c;想自己自定义定时器到数据库表里面&#xff0c;不想配置到配置文件里面&#xff0c;很麻烦&#xff01;这次想用AI帮我写代码&#xff0…

蓝桥杯算法题:栈(Stack)

这道题考的是递推动态规划&#xff0c;可能不是很难&#xff0c;不过这是自己第一次靠自己想出状态转移方程&#xff0c;所以纪念一下&#xff1a; 要做这些题目&#xff0c;首先要把题目中会出现什么状态给找出来&#xff0c;然后想想他们的状态可以通过什么操作转移&#xf…

学习数通HCIE选择誉天有什么优势?

誉天数通课程亮点 课程内容详实&#xff0c;千万级实训环境 涵盖数通技术全场景热门技术&#xff0c;涉及传统园区网&#xff0c;虚拟化园区网&#xff0c;广域互联技术&#xff0c;数据中心网络&#xff0c;网络自动化运维 专业机房环境&#xff0c;全真机教学演示&#xf…

模块化组合优势凸显钡铼IOy系列轻松应对大规模工业自动化工程

模块化组合是钡铼IOy系列独立式I/O模块的一大优势&#xff0c;它为大规模工业自动化工程提供了灵活性、可扩展性和定制性&#xff0c;从而轻松应对不同规模和复杂度的工厂应用。以下是关于模块化组合优势的详细解析&#xff1a; 1. 灵活性和定制性 模块化设计使得钡铼IOy系列…

小鸡宝宝考考你每匹斑马身上的条纹都不相同吗?蚂蚁庄园4.13答案

蚂蚁庄园是一款爱心公益游戏&#xff0c;用户可以通过喂养小鸡&#xff0c;产生鸡蛋&#xff0c;并通过捐赠鸡蛋参与公益项目。用户每日完成答题就可以领取鸡饲料&#xff0c;使用鸡饲料喂鸡之后&#xff0c;会可以获得鸡蛋&#xff0c;可以通过鸡蛋来进行爱心捐赠。其中&#…

【工具-工具指南】

项目-开发工具 ■ 编辑器■ Xmind ■ UI交互设计■ AxureRP9 ■ 项目管理■ boardmix■ excalidraw ■ Markdown■ MarkText■ Typora■ Ulysses■ Notable■ VNote■ Mou■ Bears■ Notion■ 有道云■ 印象笔记 ■ 硬件画图■ AD■ Allegro■ PADS■ Eagle■ Altium■ Fritzin…

大型网站系统架构演化

大型网站质量属性优先级&#xff1a;高性能 高可用 可维护 应变 安全 一、单体架构 应用程序&#xff0c;数据库&#xff0c;文件等所有资源都在一台服务器上。 二、垂直架构 应用和数据分离&#xff0c;使用三台服务器&#xff1a;应用服务器、文件服务器、数据服务器 应用服…

Mongo 报错 Can‘t canonicalize query: BadValue $in needs an array

一、遇到的问题 Mongo in查询 [ UserId > array($in>$userIds)] $userIds数组不是连续索引&#xff0c;报错Cant canonicalize query: BadValue $in needs an array 二、解决 array_values($userIds) 重新索引一下变成连续索引即可。 Mongo in查询的数组要是连续索…

凡尔码搭建物流消防安全巡查系统

物流行业在现代经济中扮演着重要角色&#xff0c;由于物流过程涉及到大量的货物运输和存储&#xff0c;伴随着存在安全隐患、消防安全、设备设施安全等问题&#xff1b;安全问题也为物流企业管理者们需要高度关注的重要问题之一&#xff1b;近年来&#xff0c;随着消防安全管理…

华为校园公开课走入上海交大,鸿蒙成为专业核心课程

4月12日&#xff0c;华为校园公开课在中国上海交通大学成功举办&#xff0c;吸引了来自计算机等相关专业的150余名学生参加。据了解&#xff0c;由吴帆、陈贵海、过敏意、吴晨涛、刘生钟等教授在中国上海交通大学面向计算机系本科生开设的《操作系统》课程&#xff0c;是该系学…

揭秘大前端开发方向的新机遇!

众所周知&#xff0c;华为开发者大会2023&#xff0c;宣布不再兼容安卓&#xff0c;同时宣布了“鸿飞计划”&#xff0c;欲与iOS、安卓在市场三分天下&#xff0c;这对中国国产操作系统而言&#xff0c;具有划时代的意义。 鸿蒙应用开发的兴起&发展 鸿蒙操作系统是华为自…

如何androd动态注册编写计算器

源地址&#xff1a;https://www.ctvol.com/asreverse/41030.html 如何androd动态注册编写计算器 直接开上es开鲁&#xff0c;配置我们就不用多说了。 创建layout&#xff1b;在之后写debug时候回出现乱掉的情况&#xff0c;可以直接慢慢调试 在红圈中是layout基本设置&#…

细胞世界:1.内膜系统(物流网络)与跨膜运输(交通方式)

内膜系统就像一个高度组织化、效率卓越的现代化物流网络&#xff0c;各组成部分协同工作&#xff0c;确保细胞内外的物质转运和处理高效、准确进行。每个部分都承担着不同但相互关联的角色&#xff0c;通过这样的内部物流系统&#xff0c;细胞能够维持其生命活动&#xff0c;响…

网络广播系统是什么?网络广播的作用及应用

网络广播系统是什么?网络广播的作用及应用 商场广播的目的&#xff1a;提醒人员有序、监控配合点对点呼叫、物品遗失广播、背景音乐防噪、紧急情况呼叫等等&#xff0c;各个场景有各个场景的需求模式&#xff0c;广播系统的建设重点在于突发情况的应对&#xff0c;国家已经把广…

清明美食制作|“心灵护航,增能培力”残疾人职业能力提升培养

为提高残疾人的动手能力&#xff0c;提升个人的自身素质和自主就业创业能力&#xff0c;弘扬中华民族传统文化&#xff0c;临近清明之际&#xff0c;淳安县从益舍社会工作服务中心于浪川乡展开了以“品尝春天味道 制作清明粿 清明美食制作”为主题的清明节活动。 【清明粿制作】…

0点起C语言

用sizeof()来查看在你的平台上到底占用多少你多少字节的内存。 Int x sizeof(int); Int xsizeof(shrt int); Int xsizeof(long); Int xsizeof(long double); 等等。 http://www.enet.com.cn/article/2012/0822/A20120822153730_2.shtml #—是个预处理的标志&#xff0c;表示对文…

PCIe总线-存储器域和PCIe总线域访问流程(二)

1.概述 PCIe总线的最大特点是像CPU访问DDR一样&#xff0c;可以直接使用地址访问PCIe设备&#xff08;桥&#xff09;&#xff0c;但不同的是DDR和CPU同属于存储器域&#xff0c;而CPU和PCIe设备属于两个不同的域&#xff0c;PCIe设备&#xff08;桥&#xff09;的地址空间属于…

【MATLAB第104期】基于MATLAB的xgboost的敏感性分析/特征值排序计算(针对多输入单输出回归预测模型)

【MATLAB第104期】基于MATLAB的xgboost的敏感性分析/特征值排序计算&#xff08;针对多输入单输出回归预测模型&#xff09; 因matlab的xgboost训练模型不含敏感性分析算法&#xff0c;本文通过使用single算法&#xff0c;即单特征因素对输出影响进行分析&#xff0c;得出不同…