当前位置: 首页 > news >正文

5 分钟内搭建一个免费问答机器人:Milvus + LangChain

搭建一个好用、便宜又准确的问答机器人需要多长时间?

答案是 5 分钟。只需借助开源的 RAG 技术栈、LangChain 以及好用的向量数据库 Milvus。必须要强调的是,该问答机器人的成本很低,因为我们在召回、评估和开发迭代的过程中不需要调用大语言模型 API。只有在最后一步——生成最终问答结果的时候会调用到 1 次 API。

如有兴趣深入了解问答机器人背后的技术,可以查看 GitHub 上的源代码(https://github.com/zilliztech/akcio)。本文完整代码可通过 Bootcamp (https://github.com/milvus-io/bootcamp/blob/master/bootcamp/RAG/readthedocs_zilliz_langchain.ipynb)获取。

在正式开始前,我们先复习一下 RAG。RAG 的主要用途是为了给生成式 AI 输出的文本提供支撑。换言之,RAG 就是通过事实、自定义数据以减少 LLM 幻觉。具体而言,在 RAG 中,我们可以使用可靠可信的自定义数据文本,如产品文档,随后从向量数据库中检索相似结果。然后,将准确的文本答案作为“上下文”和“问题”一起插入到“Prompt”中,并将其输入到诸如 OpenAI 的 ChatGPT 之类的 LLM 中。最终,LLM 生成一个基于事实的聊天答案。

alt

RAG 的具体流程:

  1. 准备可信的自定义数据和一个 Embeding 模型。

  2. 用 Encoder 对数据进行分块并生成 Embedding 向量,将数据和元数据保存在向量数据库中。

  3. 用户提出一个问题。使用第 1 步中相同的 Encoder 将问题转化为 Embedding 向量。

  4. 用向量数据库进行语义搜索来检索问题的答案。

  5. 将搜索答案文本块作为“上下文”和用户问题结果,形成 Prompt。将 Prompt 发送给 LLM。

  6. LLM 生成答案。

01.获取数据

首先介绍一下本次搭建过程中会用到的工具:

Milvus 是一款开源高性能向量数据库,可简化非结构化数据搜索流程。Milvus 可存储、索引、搜索海量 Embedding 向量数据。

OpenAI 主要开发 AI 模型和工具,其最出名的产品为 GPT。

LangChain 工具和 wrapper 库能够帮助开发人员在传统软件和 LLM 中构建一座桥梁。

我们将用到产品文档页面,ReadTheDocs 是一款开源的免费文档软件,通过 Sphinx 生成文档。

Download readthedocs pages locally.DOCS_PAGE="https://pymilvus.readthedocs.io/en/latest/"wget -r -A.html -P rtdocs --header="Accept-Charset: UTF-8" $DOCS_PAGE

上述代码将文档页面下载到本地路径rtdocs中。接着,在 LangChain 中读取这些文档:

#!pip install langchain
from langchain.document_loaders import ReadTheDocsLoader
loader = ReadTheDocsLoader("rtdocs/pymilvus.readthedocs.io/en/latest/",features="html.parser")
docs = loader.load()

02.使用 HTML 结构切分数据

需要确定分块策略、分块大小、分块重叠(chunk overlap)。本教程中,我们的配置如下所示:

  • 分块策略 = 根据 Markdown 标题结构切分。

  • 分块大小 = 使用 Embedding 模型参数 MAX_SEQ_LENGTH

  • Overlap = 10-15%

  • 函数 =

    Langchain HTMLHeaderTextSplitter 切分markdown 文件标题。

    Langchain RecursiveCharacterTextSplitter 将长文切分。

from langchain.text_splitter import HTMLHeaderTextSplitter, RecursiveCharacterTextSplitter
Define the headers to split on for the HTMLHeaderTextSplitter
headers_to_split_on = [("h1", "Header 1"),("h2", "Header 2"),]
Create an instance of the HTMLHeaderTextSplitter
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
Use the embedding model parameters.
chunk_size = MAX_SEQ_LENGTH - HF_EOS_TOKEN_LENGTH
chunk_overlap = np.round(chunk_size * 0.10, 0)
Create an instance of the RecursiveCharacterTextSplitter
child_splitter = RecursiveCharacterTextSplitter(chunk_size = chunk_size,chunk_overlap = chunk_overlap,length_function = len,)
Split the HTML text using the HTMLHeaderTextSplitter.
html_header_splits = []
for doc in docs:splits = html_splitter.split_text(doc.page_content)for split in splits:# Add the source URL and header values to the metadatametadata = {}new_text = split.page_contentfor header_name, metadata_header_name in headers_to_split_on:header_value = new_text.split("¶ ")[0].strip()metadata[header_name] = header_valuetry:new_text = new_text.split("¶ ")[1].strip()except:breaksplit.metadata = {**metadata,"source": doc.metadata["source"]}# Add the header to the textsplit.page_content = split.page_contenthtml_header_splits.extend(splits)
Split the documents further into smaller, recursive chunks.
chunks = child_splitter.split_documents(html_header_splits)
end_time = time.time()
print(f"chunking time: {end_time - start_time}")
print(f"docs: {len(docs)}, split into: {len(html_header_splits)}")
print(f"split into chunks: {len(chunks)}, type: list of {type(chunks[0])}") 
Inspect a chunk.
print()
print("Looking at a sample chunk...")
print(chunks[1].page_content[:100])
print(chunks[1].metadata)
alt

本段文本块都有文档作为支撑。此外,标题和文本块也保存在一起,标题可以后续使用。

03.生成 Embedding 向量

最新的 MTEB 性能测试结果显示,开源 Embedding/召回模型和 OpenAI Embeddings (ada-002)效果相似。下图中分数最高的小模型是bge-large-en-v1.5,本文将选择这个模型。

alt

上图为 Embedding 模型排名表,排名最高的是voyage-lite-01-instruct(size 4.2 GB, and third rankbge-base-en-v1.5(size 1.5 GB)OpenAIEmbeddingtext-embeddings-ada-002 排名第 22。

现在,我们来初始化模型;

#pip install torch, sentence-transformers
import torch
from sentence_transformers import SentenceTransformer
Initialize torch settings
DEVICE = torch.device('cuda:3' if torch.cuda.is_available() else 'cpu')
Load the encoder model from huggingface model hub.
model_name = "BAAI/bge-base-en-v1.5"
encoder = SentenceTransformer(model_name, device=DEVICE)
Get the model parameters and save for later.
MAX_SEQ_LENGTH = encoder.get_max_seq_length() 
EMBEDDING_LENGTH = encoder.get_sentence_embedding_dimension()

接着,使用模型生成 Embedding 向量,将所有数据整合成 dictionary。

chunk_list = []
for chunk in chunks:# Generate embeddings using encoder from HuggingFace.embeddings = torch.tensor(encoder.encode([chunk.page_content]))embeddings = F.normalize(embeddings, p=2, dim=1)converted_values = list(map(np.float32, embeddings))[0]# Assemble embedding vector, original text chunk, metadata.chunk_dict = {'vector': converted_values,'text': chunk.page_content,'source': chunk.metadata['source'],'h1': chunk.metadata['h1'][:50],'h2': chunk.metadata['h1'][:50],}chunk_list.append(chunk_dict)

04.在 Milvus 中创建索引并插入数据

我们将原始文本块以 vectortextsourceh1h2的形式存储在向量数据库中。

alt

启动并连接 Milvus 服务器。如需使用 serverless 集群,你需要在连接时提供ZILLIZ_API_KEY

#pip install pymilvus
from pymilvus import connections
ENDPOINT=”https://xxxx.api.region.zillizcloud.com:443”
connections.connect(uri=ENDPOINT,token=TOKEN)

创建 Milvus Collection 并命名为 MilvusDocs。Collection 类似于传统数据库中的表,其具备 Schema,定义字段和数据类型。Schema 中的向量维度应该与 Embedding 模型生成向量的维度保持一致。与此同时,创建索引:

from pymilvus import (FieldSchema, DataType, CollectionSchema, Collection)
1. Define a minimum expandable schema.
fields = [FieldSchema(“pk”, DataType.INT64, is_primary=True, auto_id=True),FieldSchema(“vector”, DataType.FLOAT_VECTOR, dim=768),]
schema = CollectionSchema(fields,enable_dynamic_field=True,)
2. Create the collection.
mc = Collection(“MilvusDocs”, schema)
3. Index the collection.
mc.create_index(field_name=”vector”,index_params={“index_type”: “AUTOINDEX”,“metric_type”: “COSINE”,}

在 Milvus/Zilliz 中插入数据的速度比 Pinecone快!

Insert data into the Milvus collection.
insert_result = mc.insert(chunk_list)
After final entity is inserted, call flush
to stop growing segments left in memory.
mc.flush() 
print(mc.partitions)
alt

05.提出问题

接下来,我们就可以用语义搜索的力量来回答有关文档的问题。语义搜索在向量空间中使用最近邻技术来找到最匹配的文档,以回答用户的问题。语义搜索的目标是理解问题和文档背后的含义,而不仅仅是匹配关键词。在检索过程中,Milvus 还可以利用元数据来增强搜索体验(在 Milvus API 选项expr=中使用布尔表达式)。

Define a sample question about your data.
QUESTION = "what is the default distance metric used in AUTOINDEX?"
QUERY = [question]
Before conducting a search, load the data into memory.
mc.load()
Embed the question using the same encoder.
embedded_question = torch.tensor(encoder.encode([QUESTION]))
Normalize embeddings to unit length.
embedded_question = F.normalize(embedded_question, p=2, dim=1)
Convert the embeddings to list of list of np.float32.
embedded_question = list(map(np.float32, embedded_question))
Return top k results with AUTOINDEX.
TOP_K = 5
Run semantic vector search using your query and the vector database.
start_time = time.time()
results = mc.search(data=embedded_question, anns_field="vector", # No params for AUTOINDEXparam={},# Boolean expression if anyexpr="",output_fields=["h1", "h2", "text", "source"], limit=TOP_K,consistency_level="Eventually")
elapsed_time = time.time() - start_time
print(f"Milvus search time: {elapsed_time} sec")
alt

下面是检索结果,我们把这些文本放入 context 字段中:

for n, hits in enumerate(results):print(f"{n}th query result")for hit in hits:print(hit)
Assemble the context as a stuffed string.
context = ""
for r in results[0]:text = r.entity.textcontext += f"{text} "
Also save the context metadata to retrieve along with the answer.
context_metadata = {"h1": results[0][0].entity.h1,"h2": results[0][0].entity.h2,"source": results[0][0].entity.source,}
alt

上图显示,检索出了 5 个文本块。其中第一个文本块中包含了问题的答案。因为我们在检索时使用了output_fields=,所以检索返回的输出字段会带上引用和元数据。

id: 445766022949255988, distance: 0.708217978477478, entity: {'chunk': "...# Optional, default MetricType.L2 } timeout (float) –An optional duration of time in seconds to allow for theRPC. …",'source': 'https://pymilvus.readthedocs.io/en/latest/api.html','h1': 'API reference','h2': 'Client'}

06.使用 LLM 根据上下文生成用户问题的回答

这一步中,我们将使用一个小型生成式 AI 模型(LLM),该模型可通过 HuggingFace 获取。

#pip install transformers
from transformers import AutoTokenizer, pipeline
tiny_llm = "deepset/tinyroberta-squad2"
tokenizer = AutoTokenizer.from_pretrained(tiny_llm)
context cannot be empty so just put random text in it.
QA_input = {'question': question,'context': 'The quick brown fox jumped over the lazy dog'}
nlp = pipeline('question-answering', model=tiny_llm, tokenizer=tokenizer)
result = nlp(QA_input)
print(f"Question: {question}")
print(f"Answer: {result['answer']}")
alt

答案不是很准确,我们用召回的文本提出同样的问题试试看:

QA_input = {'question': question,'context': context,}
nlp = pipeline('question-answering', model=tiny_llm, tokenizer=tokenizer)
result = nlp(QA_input)
Print the question, answer, grounding sources and citations.
Answer = assemble_grounding_sources(result[‘answer’], context_metadata)
print(f"Question: {question}")
print(answer)
alt

答案准确多了!

接下来,我们用 OpenAI 的 GPT 试试,发现回答结果和我们自己搭建的开源机器人相同。

def prepare_response(response):return response["choices"][-1]["message"]["content"]
def generate_response(llm, temperature=0.0, #0 for reproducible experimentsgrounding_sources=None,system_content="", assistant_content="", user_content=""):response = openai.ChatCompletion.create(model=llm,temperature=temperature,api_key=openai.api_key,messages=[{"role": "system", "content": system_content},{"role": "assistant", "content": assistant_content},{"role": "user", "content": user_content}, ])answer = prepare_response(response=response)# Add the grounding sources and citations.answer = assemble_grounding_sources(answer, grounding_sources)return answer
Generate response
response = generate_response(llm="gpt-3.5-turbo-1106",temperature=0.0,grounding_sources=context_metadata,system_content="Answer the question using the context provided. Be succinct.",user_content=f"question: {QUESTION}, context: {context}")
Print the question, answer, grounding sources and citations.
print(f"Question: {QUESTION}")
print(response)
alt

07.总结

本文完整展示了如何针对自定义文档搭建一个 RAG 聊天机器人。得益于 LangChain、Milvus 和开源的 LLM,我们轻而易举实现了对制定数据进行免费问答。在检索过程中,Milvus 提供了数据来源。我们搭建的聊天机器人是个低成本的问答机器人,因为在召回、评估和开发迭代的过程中不需要调用大语言模型 API。只有在最后一步——生成最终问答结果的时候会调用到 1 次 API。

本文由 mdnice 多平台发布

相关文章:

5 分钟内搭建一个免费问答机器人:Milvus + LangChain

搭建一个好用、便宜又准确的问答机器人需要多长时间? 答案是 5 分钟。只需借助开源的 RAG 技术栈、LangChain 以及好用的向量数据库 Milvus。必须要强调的是,该问答机器人的成本很低,因为我们在召回、评估和开发迭代的过程中不需要调用大语言…...

WPF Border

在 WPF 中&#xff0c;Border 是一种常用的控件&#xff0c;用于给其他控件提供边框和背景效果。 要使用 Border 控件&#xff0c;您可以在 XAML 代码中添加以下代码&#xff1a; <Border BorderBrush"Black" BorderThickness"2" Background"Lig…...

基于博弈树的开源五子棋AI教程[4 静态棋盘评估]

引子 静态棋盘的评估是棋力的一个很重要的体现&#xff0c;一个优秀的基于博弈树搜索的AI往往有上千行工作量&#xff0c;本文没有做深入讨论&#xff0c;仅仅写了个引子用来抛砖引玉。 评估一般从两个角度入手&#xff0c;一个是子力&#xff0c;另一个是局势。 1 评估维度 …...

STL--排序与检索

题目 现有N个大理石&#xff0c;每个大理石上写了一个非负整数。首先把各数从小到大排序&#xff0c;然后回答Q个问题。每个问题是否有一个大理石写着某个整数x,如果是&#xff0c;还要回答哪个大理石写着x。排序后的大理石从左到右编写为1-N。&#xff08;样例中&#xff0c;…...

大数据处理与分析-Spark

导论 (基于Hadoop的MapReduce的优缺点&#xff09; MapReduce是一个分布式运算程序的编程框架&#xff0c;是用户开发“基于Hadoop的数据分析应用”的核心框架 MapReduce是一种用于处理大规模数据集的编程模型和计算框架。它将数据处理过程分为两个主要阶段&#xff1a;Map阶…...

虚拟机的下载、安装(模拟出服务器)

下载 vmware workstation&#xff08;收费的虚拟机&#xff09; 下载vbox 网址&#xff1a;Oracle VM VirtualBox&#xff08;免费的虚拟机&#xff09; 以下选择一个下载即可&#xff0c;建议下载vbox&#xff0c;因为是免费的。安装的时候默认下一步即可&#xff08;路径最好…...

K8S Pod Terminating/Unknown故障排查

一、pod异常出现现象 优雅终止周期(Graceful termination period): 当pod被删除时&#xff0c;会进入"Terminating"状态&#xff0c;等待容器优雅关闭。如果容器关闭所需时间超过默认期限(默认30秒)&#xff0c;则pod将保持在"Terminating"状态。 Finalize…...

labelme标注的json文件数据转成coco数据集格式(可处理目标框和实例分割)

这里主要是搬运一下能找到的 labelme标注的json文件数据转成coco数据集格式&#xff08;可处理目标框和实例分割&#xff09;的代码&#xff0c;以供需要时参考和提供相关帮助。 1、官方labelme实现 如下是labelme官方网址&#xff0c;提供了源代码&#xff0c;以及相关使用方…...

MySQL报错:1366 - Incorrect integer value: ‘xx‘ for column ‘xx‘ at row 1的解决方法

我在插入表数据时遇到了1366报错&#xff0c;报错内容&#xff1a;1366 - Incorrect integer value: Cindy for column name at row 1&#xff0c;下面我演示解决方法。 根据上图&#xff0c;原因是Cindy’对应的name字段数据类型不正确。我们在左侧找到该字段所在的grade_6表&…...

MySQL中MVCC的流程

参考文章一 参考文章二 当谈到数据库的并发控制时&#xff0c;多版本并发控制&#xff08;MVCC&#xff09;是一个重要的概念。MVCC 是一种用于实现数据库事务隔离性的技术&#xff0c;常见于像 PostgreSQL 和 Oracle 这样的数据库系统中。 MVCC 的核心思想是为每个数据行维护…...

朴素贝叶斯法_naive_Bayes

朴素贝叶斯法&#xff08;naive Bayes&#xff09;是基于贝叶斯定理与特征条件独立假设的分类方法。对于给定的训练数据集&#xff0c;首先基于特征条件独立假设学习输入输出的联合概率分布&#xff1b;然后基于此模型&#xff0c;对给定的输入 x x x&#xff0c;利用贝叶斯定理…...

Windows下安装MongoDB实践总结

本文记录Windows环境下的MongoDB安装与使用总结。 【1】官网下载 官网下载地址&#xff1a;Download MongoDB Community Server | MongoDB 这里可以选择下载zip或者msi&#xff0c;zip是解压后自己配置&#xff0c;msi是傻瓜式一键安装。这里我们分别对比进行实践。 【2】ZI…...

华为云Stack 8.X 流量模型分析(二)

二、流量模型分析相关知识 1.vNIC ​ 虚拟网络接口卡(vNIC)是基于主机物理 NIC 的虚拟网络接口。每个主机可以有多个 NIC&#xff0c;每个 NIC 可以是多个 vNIC 的基础。 ​ 将 vNIC 附加到虚拟机时&#xff0c;Red Hat Virtualization Manager 会在虚拟机之间创建多个关联的…...

rk3588 之启动

目录 uboot版本配置修改编译 linux版本配置修改编译 启动sd卡启动制作spi 烧录 参考 uboot 版本 v2024.01-rc2 https://github.com/u-boot/u-boot https://github.com/rockchip-linux/rkbin 配置修改 使用这两个配置即可&#xff1a; orangepi-5-plus-rk3588_defconfig r…...

ARM GIC (五)gicv3架构-LPI

在gicv3中,引入了一种新的中断类型。message based interrupts,消息中断。 一、消息中断 外设,不在通过专用中断线,向gic发送中断,而是写gic的寄存器,来发送中断。 这样的一个好处是,可以减少中断线的个数。 为了支持消息中断,gicv3,增加了LPI,来支持消息中断。并且…...

sql-labs服务器结构

双层服务器结构 一个是tomcat的jsp服务器&#xff0c;一个是apache的php服务器&#xff0c;提供服务的是php服务器&#xff0c;只是tomcat向php服务器请求数据&#xff0c;php服务器返回数据给tomcat。 此处的29-32关都是这个结构&#xff0c;不是用docker拉取的镜像要搭建一下…...

【小沐学写作】Docsify制作在线电子书、技术文档(Docsify + Markdown + node)

文章目录 1、简介2、安装2.1 node2.2 docsify-cli 3、配置3.1 初始化3.2 预览效果3.3 加载对话框3.4 更多页面3.5 侧 栏3.6 自定义导航栏 结语 1、简介 https://docsify.js.org/#/?iddocsify 一个神奇的文档网站生成器。 简单轻巧没有静态构建的 html 文件多个主题 Docsify…...

电脑完全重装教程——原版系统镜像安装

注意事项 本教程会清除所有个人文件 请谨慎操作 请谨慎操作 请谨慎操作 前言 本教程是以系统安装U盘为介质进行系统重装操作&#xff0c;照着流程操作会清除整个硬盘里的文件&#xff0c;请考虑清楚哦&#xff5e; 有些小伙伴可能随便在百度上找个WinPE作为启动盘就直接…...

【智慧办公】如何让智能会议室的电子标签实现远程、批量更新信息?东胜物联网硬件网关让解决方案更具竞争力

近年来&#xff0c;为了减少办公耗能、节能环保、降本增效&#xff0c;越来越多的企业开始从传统的办公模式转向智慧办公。 以智能会议室为例&#xff0c;会议是企业业务中不可或缺的一部分&#xff0c;但在传统办公模式下&#xff0c;一来会议前行政人员需要提前准备会议材料…...

面向对象设计与分析40讲(16)静态工厂方法模式

前面我们介绍了简单工厂模式&#xff0c;在创建对象前&#xff0c;我们需要先创建工厂&#xff0c;然后再通过工厂去创建产品。 如果将工厂的创建方法static化&#xff0c;那么无需创建工厂即可通过静态方法直接调用的方式创建产品&#xff1a; // 工厂类&#xff0c;定义了静…...

【贪心】买卖股票的最佳时机含手续费

/** 贪心&#xff1a;每次选取更低的价格买入&#xff0c;遇到高于买入的价格就出售(此时不一定是最大收益)。* 使用buy表示买入股票的价格和手续费的和。遍历数组&#xff0c;如果后面的股票价格加上手续费* 小于buy&#xff0c;说明有更低的买入价格更新buy。如…...

Altium Designer入门到就业【目录】

&#x1f3e1;《AD目录》 欢迎大家来到《Altium Designer入门到就业》该专栏包括【电路设计篇】【PCB设计篇】【电路仿真篇】【PCB仿真篇】四个部分&#xff0c;以供大家参考。大家直接点击大纲中蓝色标题即可轻松传送。 【电路设计篇】 Altium Designer&#xff08;AD24&#…...

cmake 查看编译命令,以及在vscode中如何使用cmke

通过设置如下配置选项&#xff0c;可以生成compile_commands.json 文件&#xff0c;记录使用的编译命令 set(CMAKE_EXPORT_COMPILE_COMMANDS ON)获得现有模块列表 cmake --help-module-list查看命令文档 cmake --help-command find_file查看模块的详细信息 cmake --help-mo…...

玩转 Scrapy 框架 (一):Scrapy 框架介绍及使用入门

目录 一、Scrapy 框架介绍二、Scrapy 入门 一、Scrapy 框架介绍 简介&#xff1a; Scrapy 是一个基于 Python 开发的爬虫框架&#xff0c;可以说它是当前 Python 爬虫生态中最流行的爬虫框架&#xff0c;该框架提供了非常多爬虫的相关组件&#xff0c;架构清晰&#xff0c;可扩…...

node.js mongoose index(索引)

目录 简介 索引类型 单索引 复合索引 文本索引 简介 在 Mongoose 中&#xff0c;索引&#xff08;Index&#xff09;是一种用于提高查询性能的数据结构&#xff0c;它可以加速对数据库中文档的检索操作 索引类型 单索引、复合索引、文本索引、多键索引、哈希索引、地理…...

谷歌推大语言模型VideoPoet:文本图片皆可生成视频和音频

Google Research最近发布了一款名为VideoPoet的大型语言模型&#xff08;LLM&#xff09;&#xff0c;旨在解决当前视频生成领域的挑战。该领域近年来涌现出许多视频生成模型&#xff0c;但在生成连贯的大运动时仍存在瓶颈。现有领先模型要么生成较小的运动&#xff0c;要么在生…...

ES-mapping

类似数据库中的表结构定义&#xff0c;主要作用如下 定义Index下的字段名( Field Name) 定义字段的类型&#xff0c;比如数值型、字符串型、布尔型等定义倒排索引相关的配置&#xff0c;比如是否索引、记录 position 等 index_options 用于控制倒排索记录的内容&#xff0c;有如…...

Centos 7.9安装Oracle19c步骤亲测可用有视频

视频介绍了在虚拟机安装centos 7.9并安装数据库软件的全过程 视频链接&#xff1a;https://www.zhihu.com/zvideo/1721267375351996416 下面的文字描述是安装数据库的部分介绍 一.安装环境准备 链接&#xff1a;https://pan.baidu.com/s/1Ogn47UZQ2w7iiHAiVdWDSQ 提取码&am…...

.NET中的Swagger使用

目录 前言 一、Swagger是什么&#xff1f; 二、如何Swagger文档说明的信息 1.在AddSwaggerGen方法中写入文档信息 2.运行效果 二、文档UI界面标题、路由设置 1.在中间件UseSwaggerUI方法中配置 三、文档UI界面添加接口注释 1.在 .csproj中配置 2.在AddSwaggerGen方法中配置Incl…...

结构屈曲分析

结构屈曲分析主要用于判定结构受载后是否有失稳风险&#xff0c;作为工程应用&#xff0c;一般分为线性屈曲分析和非线性屈曲分析。 线性屈曲分析需要具备较多的前提条件&#xff0c;如载荷无偏心、材料无缺陷等&#xff0c;在实际工程应用中结构制作过程和加载方式很难达到线性…...

Flink 客户端操作命令及可视化工具

Flink提供了丰富的客户端操作来提交任务和与任务进行交互。下面主要从Flink命令行、Scala Shell、SQL Client、Restful API和 Web五个方面进行整理。 在Flink安装目录的bin目录下可以看到flink&#xff0c;start-scala-shell.sh和sql-client.sh等文件&#xff0c;这些都是客户…...

csrf自动化检测调研

https://github.com/pillarjs/understanding-csrf/blob/master/README_zh.md CSRF 攻击者在钓鱼站点&#xff0c;可以通过创建一个AJAX按钮或者表单来针对你的网站创建一个请求&#xff1a; <form action"https://my.site.com/me/something-destructive" metho…...

记录一个Python鼠标自动模块用法和selenium加载网页插件的设置

写爬虫&#xff0c;或者网页自动化&#xff0c;让程序自动完成一些重复性的枯燥的网页操作&#xff0c;是最常见的需求。能够解放双手&#xff0c;空出时间看看手机&#xff0c;或者学习别的东西&#xff0c;甚至还能帮朋友亲戚减轻工作量。 然而&#xff0c;网页自动化代码编写…...

【数据库系统概论】第3章-关系数据库标准语言SQL(1)

文章目录 3.1 SQL概述3.2 学生-课程数据库3.3 数据定义3.3.1 数据库定义3.3.2 模式的定义3.3.3 基本表的定义3.3.4 索引的建立与删除3.3.5 数据字典 3.1 SQL概述 动词 分类 三级模式 3.2 学生-课程数据库 3.3 数据定义 3.3.1 数据库定义 创建数据库 tips&#xff1a;[ ]表…...

【Python】基于flaskMVT架构与session实现博客前台登录登出功能

目录 一、MVT说明 1.Model层 2.View层 3.Template层 二、功能说明 三、代码框架展示 四、具体代码实现 models.py 登录界面前端代码 博客界面前端代码&#xff08;profile.html&#xff09; main.py 一、MVT说明 MVT架构是Model-View-Template的缩写&#xff0c;是…...

为什么有的开关电源需要加自举电容?

一、什么是自举电路&#xff1f; 1.1 自举的概念 首先&#xff0c;自举电路也叫升压电路&#xff0c;是利用自举升压二极管&#xff0c;自举升压电容等电子元件&#xff0c;使电容放电电压和电源电压叠加&#xff0c;从而使电压升高。有的电路升高的电压能达到数倍电源电压。…...

【MCAL】TC397+EB-treso之MCU配置实战 - 芯片时钟

本篇文章介绍了在TC397平台使用EB-treso对MCU驱动模块进行配置的实战过程&#xff0c;主要介绍了后续基本每个外设模块都要涉及的芯片时钟部分&#xff0c;帮助读者了解TC397芯片的时钟树结构&#xff0c;在后续计算配置不同外设模块诸如通信速率&#xff0c;定时器周期等&…...

高级人工智能之群体智能:蚁群算法

群体智能 鸟群&#xff1a; 鱼群&#xff1a; 1.基本介绍 蚁群算法&#xff08;Ant Colony Optimization, ACO&#xff09;是一种模拟自然界蚂蚁觅食行为的优化算法。它通常用于解决路径优化问题&#xff0c;如旅行商问题&#xff08;TSP&#xff09;。 蚁群算法的基本步骤…...

【SpringBoot应用篇】【AOP+注解】SpringBoot+SpEL表达式基于注解实现权限控制

【SpringBoot应用篇】【AOP注解】SpringBootSpEL表达式基于注解实现权限控制 Spring SpEL基本表达式类相关表达式表达式模板 SpEL表达式实现权限控制PreAuthAuthFunPreAuthAspectUserControllerSpelParserUtils Spring SpEL Spring 表达式语言 SpEL 是一种非常强大的表达式语言…...

Java研学-HTTP 协议

一 概述 1 概念和作用 概念&#xff1a;HTTP 是 HyperText Transfer Protocol (超文本传输协议)的简写&#xff0c;它是 TCP/IP 协议之上的一个应用层协议。简单理解就是 HTTP 协议底层是对 TCP/IP 协议的封装。   作用&#xff1a;用于规定浏览器和服务器之间数据传输的格式…...

差生文具多之(二): perf

栈回溯和符号解析是使用 perf 的两大阻力&#xff0c;本文以应用程序 fio 的观测为例子&#xff0c;提供一些处理它们的经验法则&#xff0c;希望帮助大家无痛使用 perf。 前言 系统级性能优化通常包括两个阶段&#xff1a;性能剖析和代码优化&#xff1a; 性能剖析的目标是寻…...

【SPI和API有什么区别】

✅什么是SPI&#xff0c;和API有什么区别 ✅典型解析&#x1f7e2;拓展知识仓&#x1f7e2;如何定义一个SPI&#x1f7e2;SPI的实现原理 ✅SPI的应用场景SpringDubbo ✅典型解析 Java 中区分 API和 SPI&#xff0c;通俗的进: API和 SPI 都是相对的概念&#xff0c;他们的差别只…...

Day67力扣打卡

打卡记录 美丽塔 II&#xff08;前缀和 单调栈&#xff09; 链接 class Solution:def maximumSumOfHeights(self, maxHeights: List[int]) -> int:n len(maxHeights)stack collections.deque()pre, suf [0] * n, [0] * nfor i in range(n):while stack and maxHeights…...

什么是网站监控?

网站监控是跟踪网站的可用性和性能&#xff0c;以最小化宕机时间&#xff0c;优化性能并确保顺畅的用户体验。维护网站正常运行对于任何企业来说都是至关重要的&#xff0c;因而对大多数业务来说&#xff0c;网站应用监控都是一个严峻的挑战。Applications Manager网站应用监控…...

游戏软件提示d3dcompiler_43.dll的五个解决方法,亲测靠谱

在使用电脑进行工作&#xff0c;玩游戏的时候&#xff0c;我们常常会遇到一些错误提示&#xff0c;其中之一就是“D3DCompiler_43.dll丢失”的提示。D3DCompiler_43.dll是一个非常重要的动态链接库文件。它是由DirectX SDK提供的&#xff0c;用于编译和优化DirectX着色器代码的…...

python使用opencv提取视频中的每一帧、最后一帧,并存储成图片

提取视频每一帧存储图片 最近在搞视频检测问题&#xff0c;在用到将视频分帧保存为图片时&#xff0c;图片可以保存&#xff0c;但是会出现(-215:Assertion failed) !_img.empty() in function cv::imwrite问题而不能正常运行&#xff0c;在检查代码、检查路径等措施均无果后&…...

说说对React refs 的理解?应用场景?

先了解&#xff0c;是什么&#xff1f; React 中的 Refs提供了一种方式&#xff0c;允许我们访问 DOM节点或在 render方法中创建的 React元素。 本质为ReactDOM.render()返回的组件实例&#xff0c;如果是渲染组件则返回的是组件实例&#xff0c;如果渲染dom则返回的是具体的do…...

Pytorch 读取t7文件

Pytorch 1.0以上可以使用&#xff1a; import torchfileth_path r"./path/xx.t7" data torchfile.load(th_path)print(data.shape)若data的尺寸为0&#xff0c;则将torch版本降为0.4.1&#xff0c;并使用以下函数&#xff1a; from torch.utils.serialization im…...

【YOLOV8预测篇】使用Ultralytics YOLO进行检测、分割、姿态估计和分类实践

目录 一 安装Ultralytics 二 使用预训练的YOLOv8n检测模型 三 使用预训练的YOLOv8n-seg分割模型 四 使用预训练的YOLOv8n-pose姿态模型 五 使用预训练的YOLOv8n-cls分类模型 <...

[Linux] MySQL数据库之索引

一、索引的相关知识 1.1 索引的简介 索引是一个排序列表&#xff0c;包含索引值和包含该值的数据行的物理地址&#xff08;类似于 c 语言链表&#xff0c;通过指针指向数据记录的内存地址&#xff09;。 使用索引后可以不用扫描全表来定位某行的数据&#xff0c;而是先通过索…...