如何在 Elasticsearch 中设置向量搜索 - 第二部分
作者:来自 Elastic Valentin Crettaz
了解如何在 Elasticsearch 中设置向量搜索并执行 k-NN 搜索。
本文是三篇系列文章中的第二篇,深入探讨了向量搜索(也称为语义搜索)的复杂性以及它在 Elasticsearch 中的实现方式。
第一部分重点介绍了嵌入(又称向量)的基础知识以及向量搜索的底层工作原理。
凭借第一篇文章中学到的所有向量搜索知识,第二部分将指导你了解如何在 Elasticsearch 中设置向量搜索和执行 k-NN 搜索。
在第三部分中,我们将利用前两部分中学到的知识,并在此基础上深入研究如何在 Elasticsearch 中制作强大的混合搜索查询。
首先介绍一些背景
尽管 Elasticsearch 直到 8.0 版(带有 _knn_search API 端点的技术预览)才支持向量搜索,但自 7.0 版发布以来,已经可以使用 dense_vector 字段类型存储向量。那时,向量只是作为二进制文档值存储,但没有使用我们在第一篇文章中介绍的任何算法进行索引。这些密集向量构成了 Elasticsearch 中即将推出的向量搜索功能的前提。
如果你有兴趣深入了解导致 Elasticsearch 中当前实现向量搜索的讨论,你可以参考此问题,其中详细介绍了 Elastic 为将此功能推向市场而必须克服的所有障碍。简而言之,由于 Elasticsearch 已经大量使用 Lucene 作为其底层搜索引擎,我们还决定使用与我们的向量引擎相同的技术,并以非常透明的方式解释了该决定背后的理由。
历史问题已经解决,现在让我们开始工作。
如何设置 k-NN
Elasticsearch 本身就提供向量搜索,无需安装任何特定程序。我们只需要创建一个索引,该索引定义至少一个类型为 density_vector 的字段,向量数据将存储在该字段中并/或被索引。
下面的映射显示了一个名为 title_vector 的 3 维 dense_vector 字段。在此字段中存储和索引的密集向量将使用我们在本系列第一篇文章中介绍的 dot_product 相似度函数。值得注意的是,在 8.11 之前,hnsw(即 Hierarchical Navigable Small Worlds)是 Apache Lucene 支持的唯一用于索引密集向量的算法。从那时起,其他算法被添加,未来,Elasticsearch 可能会提供用于索引和搜索密集向量的其他方法,但由于它完全依赖于 Apache Lucene,因此这将取决于这方面的进展。
"title_vector": {"type": "dense_vector","dims": 3,"index": true,"similarity": "dot_product","index_options": {"type": "hnsw","ef_construction": 128,"m": 24 }
}
下表总结了 Elasticsearch 提供的 dense_vector 字段类型的所有可用配置参数:
参数 | 必需 | 描述 |
---|---|---|
dims | Yes (<8.11) No (8.11+) | 向量维数,在 8.9.2 之前不能超过 1024,在 8.10.0 之后不能超过 2048,在 8.11.0 之后不能超过 4096。此外,从 8.11 开始,此参数不再需要,将默认为第一个索引向量的维数。 |
element_type | No | 向量元素值的数据类型,若不指定,则默认为 `float`(4 个字节),也可以使用 `byte`(1 个字节)和 `bit`。 |
index | No | 指示是否在专用且优化的数据结构中索引向量(如果为 “true”)或仅将其存储为二进制文档值(如果为“false”)。在 8.10 之前,如果未指定,则默认值为“false”。从 8.11 开始,如果未指定,则默认值为 “true”。 |
similarity | Yes (<8.11) No (8.11+) | 直到 8.10 版本,如果 `index` 为 `true`,则此参数是必需的,并定义用于 k-NN 搜索的向量相似度度量。可用的度量包括:a) `l2_norm`:L2 距离 b) `dot_product`:点积相似度 c) `cosine`:余弦相似度 d) `max_inner_product`:最大内积相似度。还请注意,只有当你的向量已经归一化(即,它们是幅度为 1 的单位向量)时,才应使用 `dot_product`,否则使用 `cosine` 或 `max_inner_product`。从 8.11 版本开始,如果未指定,则如果 element_type 为 `bit`,则此参数默认为 `l2_norm`,否则为 `cosine`。 |
index_options | No | 以下是 `type` 参数可能的值(具体取决于版本):a) 直到 8.11,仅支持 `hnsw`。b) 在 8.12 中,标量量化启用了 `int8_hnsw` c) 在 8.13 中,添加了 `flat` 及其标量量化的 `int8_flat` 兄弟 d) 在 8.15 中,添加了 `int4_hnsw` 和 `int4_flat` e) 在 8.18 中,二进制量化启用了 `bbq_hnsw` 和 `bbq_flat`。你可以查看官方文档以了解它们的详细描述(https://www.elastic.co/guide/en/elasticsearch/reference/current/dense-vector.html#dense-vector-params)以及如何配置每个算法。 |
从上表可以看出,自 8.11 版本以来,想量场的定义已大大简化:
关于 8.12 中添加的标量量化支持,请记住,我们在本系列的第一部分中讨论过这种压缩技术。我们不会在本文中深入探讨,但你可以在另一篇 Elastic Search Labs 文章中了解有关如何在 Lucene 中实现这一点的更多信息。同样,我们不会深入研究 8.18 中添加的更好的二进制量化 (BBQ),我们邀请你在本文中了解有关该新突破性算法的更多信息。
就这些了!只需定义和配置一个 dense_vector 字段,我们现在就可以索引向量数据,以便使用 knn 搜索选项或 knn DSL 查询(在 8.12 中引入)在 Elasticsearch 中运行向量搜索查询。Elasticsearch 支持两种不同的向量搜索模式:1) 使用 script_score 查询进行精确搜索和 2) 使用 knn 搜索选项或 knn 查询(8.12+)进行近似最近邻搜索。接下来我们将描述这两种模式。
精确搜索
如果你回想一下本系列的第一篇文章,我们回顾了向量搜索概况,那么精确向量搜索可以归结为在整个向量空间中执行线性搜索或强力搜索(brute-force search)。基本上,查询向量将根据每个存储的向量进行测量,以找到最近的邻居。在此模式下,向量不需要在 HNSW 图中编入索引,而只需存储为二进制文档值,相似度计算由自定义 Painless 脚本运行。
首先,我们需要以不对向量进行索引的方式定义向量场映射,这可以通过在映射中指定 index: false 和 no 相似度度量来实现:
# 1. Create a simple index with a dense_vector field of dimension 3
PUT /my-index
{"mappings": {"properties": {"price": {"type": "integer"},"title_vector": {"type": "dense_vector","dims": 3,"index": false}}}
}# 2. Load that index with some data
POST my-index/_bulk
{ "index": { "_id": "1" } }
{ "title_vector": [2.2, 4.3, 1.8], "price": 23}
{ "index": { "_id": "2" } }
{ "title_vector": [3.1, 0.7, 8.2], "price": 9}
{ "index": { "_id": "3" } }
{ "title_vector": [1.4, 5.6, 3.9], "price": 124}
{ "index": { "_id": "4" } }
{ "title_vector": [1.1, 4.4, 2.9], "price": 1457}
这种方法的优点是向量不需要索引,这大大降低了提取时间,因为不需要构建底层 HNSW 图。但是,根据数据集的大小和硬件,随着数据量的增加,搜索查询可能会很快变慢,因为添加的向量越多,访问每个向量所需的时间就越长(即线性搜索的复杂度为 O(n))。
创建索引并加载数据后,我们现在可以使用以下 script_score 查询运行精确搜索:
POST my-index/_search
{"_source": false,"fields": [ "price" ],"query": {"script_score": {"query" : {"bool" : {"filter" : {"range" : {"price" : {"gte": 100}}}}},"script": {"source": "cosineSimilarity(params.queryVector, 'title_vector') + 1.0","params": {"queryVector": [0.1, 3.2, 2.1]}}}}
}
如你所见,script_score 查询由两个主要元素组成,即查询和脚本。在上面的示例中,查询部分指定了一个过滤器(即 price >= 100),该过滤器限制了将针对其执行脚本的文档集。如果未指定查询,则相当于使用 match_all 查询,在这种情况下,脚本将针对索引中存储的所有向量执行。根据向量的数量,搜索延迟可能会大幅增加。
由于向量未编入索引,因此没有内置算法可以测量查询向量与存储向量的相似性,这必须通过脚本来完成,幸运的是,Painless 提供了我们迄今为止学到的大多数相似性函数,例如:
l1norm(vector, field)
: L1 distance (Manhattan distance)l2norm(vector, field)
: L2 distance (Euclidean distance)hamming(vector, field)
: Hamming distancecosineSimilarity(vector, field)
: Cosine similaritydotProduct(vector, field):
Dot product similarity
由于我们正在编写脚本,因此也可以构建我们自己的相似性算法。 Painless 通过提供对 doc[<field>].vectorValue(允许迭代向量数组)和 doc[<field>].magnitude(返回向量的长度)的访问来实现这一点。
总而言之,尽管精确搜索的扩展性不佳,但它可能仍然适用于某些非常小的用例,但如果你知道数据量会随着时间的推移而增长,则需要考虑改用 k-NN 搜索。 这就是我们接下来要介绍的内容。
近似 k-NN 搜索
大多数情况下,如果你有大量数据并且需要使用 Elasticsearch 实现向量搜索,则你将选择此模式。索引延迟稍高一些,因为 Lucene 需要构建底层 HNSW 图来存储和索引所有向量。它在搜索时的内存要求方面也要求更高一些,之所以称为 “近似”,是因为其准确度永远不可能像精确搜索那样达到 100%。尽管如此,近似 k-NN 的搜索延迟要低得多,并且允许我们扩展到数百万甚至数十亿个向量,前提是你的集群大小合适。
让我们看看它是如何工作的。首先,让我们创建一个具有足够向量场映射的示例索引来索引向量数据(即 index: true + 特定 similarity 定义)并用一些数据加载它:
# 1. Create a simple index with a dense_vector field of dimension 3
PUT /my-index
{"mappings": {"properties": {"price": {"type": "integer"},"title_vector": {"type": "dense_vector","dims": 3,"index": true, # default since 8.11"similarity": "cosine", # default since 8.11"index_options": {"type": "int8_hnsw", # default value since 8.12"ef_construction": 128,"m": 24 }}}}
}# 2. Load that index with some data
POST my-index/_bulk
{ "index": { "_id": "1" } }
{ "title_vector": [2.2, 4.3, 1.8], "price": 23}
{ "index": { "_id": "2" } }
{ "title_vector": [3.1, 0.7, 8.2], "price": 9}
{ "index": { "_id": "3" } }
{ "title_vector": [1.4, 5.6, 3.9], "price": 124}
{ "index": { "_id": "4" } }
{ "title_vector": [1.1, 4.4, 2.9], "price": 1457}
简单的 k-NN 搜索
运行这两个命令后,我们的想量数据现在已在标量量化的 HNSW 图中正确索引,可供搜索。直到 8.11 版,运行简单 k-NN 搜索的唯一方法是使用 knn 搜索选项,该选项与你习惯的 query 部分位于同一级别,如以下查询所示:
POST my-index/_search
{"_source": false,"fields": [ "price" ],"knn": {"field": "title_vector","query_vector": [0.1, 3.2, 2.1],"k": 2,"num_candidates": 100}
}
在上面的搜索负载中,我们可以看到没有像词汇搜索那样的 query 部分,而是 knn 部分。我们正在搜索与指定查询向量最接近的两个(k:2)相邻向量。
从 8.12 开始,引入了新的 knn 搜索查询(knn search query),以允许更高级的混合搜索用例,这是我们将在下一篇文章中讨论的主题。除非你具备将 k-NN 查询与其他查询相结合所需的专业知识,否则 Elastic 建议坚持使用更易于使用的 knn 搜索选项。首先要注意的是,新的 knn 搜索查询没有 k 参数,而是像任何其他查询一样使用 size 参数。第二件值得注意的是,新的 knn 查询通过利用将一个或多个过滤器与 knn 搜索查询相结合的 bool 查询来实现对 k-NN 搜索结果的后过滤,如下面的代码所示:
POST my-index/_search
{"size": 3,"_source": false,"fields": [ "price" ],"query" : {"bool" : {"must" : {"knn": {"field": "title_vector","query_vector": [0.1, 3.2, 2.1],"num_candidates": 100}},"filter" : {"range" : {"price" : {"gte": 100}}}}}
}
上述查询首先检索具有最近邻向量的前 3 个文档,然后过滤掉 price 小于 100 的文档。值得注意的是,使用这种后过滤,如果过滤器过于激进,你可能最终得不到任何结果。还请注意,此行为不同于通常的布尔全文查询,其中首先执行过滤部分以减少需要评分的文档集。如果你有兴趣了解有关 knn 顶级搜索选项和新 knn 搜索查询之间的差异的更多信息,你可以前往另一篇很棒的搜索实验室文章了解更多详细信息。
现在让我们继续了解有关 num_candidates 参数的更多信息。num_candidates 的作用是增加或减少找到真正最近邻候选的可能性。该数字越高,搜索速度越慢,但找到真正最近邻的可能性也越大。每个分片上将考虑 num_candidates 个向量,并将前 k 个向量返回到协调器节点,协调器节点将合并所有分片本地结果并返回全局结果中的前 k 个向量,如下图 1 所示:

向量 id4 和 id2 分别是第一个分片上的 k 个局部最近邻,id5 和 id7 分别是第二个分片上的 k 个局部最近邻。在对它们进行合并和重新排序后,协调器节点将返回 id4 和 id5 作为搜索查询的两个全局最近邻。
多个 k-NN 搜索
如果你的索引中有多个向量字段,则可以发送多个 k-NN 搜索,因为 knn 部分还接受查询数组,如下所示:
POST my-index/_search
{"_source": false,"fields": [ "price" ],"knn": [{"field": "title_vector","query_vector": [0.1, 3.2, 2.1],"k": 2,"num_candidates": 100,"boost": 0.4},{"field": "content_vector","query_vector": [0.1, 3.2, 2.1],"k": 5,"num_candidates": 100,"boost": 0.6}]
}
我们可以看到,每个查询可以采用不同的 k 值以及不同的提升因子。提升因子相当于权重,总得分将是两个得分的加权平均值。
过滤的 k-NN 搜索
与我们之前在 script_score 查询中看到的类似,knn 部分也接受过滤器的规范,以减少近似搜索应运行的向量空间。例如,在下面的 k-NN 搜索中,我们将搜索限制为仅搜索价格大于或等于 100 的文档。
POST my-index/_search
{"_source": false,"fields": [ "price" ],"knn": {"field": "title_vector","query_vector": [0.1, 3.2, 2.1],"k": 2,"num_candidates": 100,"filter" : {"range" : {"price" : {"gte": 100}}}}
}
现在,你可能想知道数据集是否先按 price 过滤,然后对过滤后的数据集运行 k-NN 搜索(预过滤),还是反过来,即先检索最近邻居,然后按 price 过滤(后过滤)。实际上,两者都有一点。如果过滤器过于激进,预过滤的问题在于 k-NN 搜索必须在非常小且可能稀疏的向量空间上运行,并且不会返回非常准确的结果。而后过滤可能会剔除大量高质量的最近邻居。
因此,即使 knn 部分 filter 被视为预过滤器,它也会在 k-NN 搜索期间工作,以确保至少可以返回 k 个邻居。如果你对其工作原理感兴趣,可以查看以下处理此事的 Lucene 问题。
具有预期相似度的过滤 k-NN 搜索
在上一节中,我们了解到,在指定过滤器时,我们可以减少搜索延迟,但我们也冒着将向量空间大幅减少为与查询向量部分或大部分不相似的向量的风险。为了缓解这个问题,k-NN 搜索还可以指定所有返回向量预计具有的最小相似度值(minimum similarity)。重用上一个查询,它看起来会像这样:
POST my-index/_search
{"_source": false,"fields": [ "price" ],"knn": {"field": "title_vector","query_vector": [0.1, 3.2, 2.1],"k": 2,"num_candidates": 100,"similarity": 0.975,"filter" : {"range" : {"price" : {"gte": 100}}}}
}
基本上,它的工作方式是,通过跳过任何与提供的过滤器不匹配或相似度低于指定过滤器的向量来探索向量空间,直到找到 k 个最近邻居。如果算法不能接受至少 k 个结果(由于过滤器过于严格或预期相似度太低),则将尝试进行强力搜索(brute-force),以便至少返回 k 个最近邻居。
关于如何确定最小预期相似度的简短说明。这取决于你在向量场映射中选择了哪种相似度度量。如果你选择了 l2_norm,它是一个距离函数(即相似度随着距离的增加而减小),你将需要在 k-NN 查询中设置最大预期距离,即你认为可接受的最大距离。换句话说,与查询向量的距离介于 0 和最大预期距离之间的向量将被视为足够 “接近” 以相似。
如果你选择了 dot_product 或 cosine,它们是相似度函数(即,相似度随着向量角度变宽而降低),你将需要设置最小预期相似度。与查询向量具有最小预期相似度和 1 之间的相似度的向量将被视为足够 “接近” 以致相似。
应用于上面的示例过滤查询和我们之前已索引的示例数据集,下面的表 1 总结了查询向量和每个索引向量之间的余弦相似度。我们可以看到,向量 3 和 4 被过滤器选中(price >= 100),但只有向量 3 具有最小预期相似度(即 0.975)才能被选中。
Vector | Cosine similarity | Price |
---|---|---|
1 | 0.8473 | 23 |
2 | 0.5193 | 9 |
3 | 0.9844 | 124 |
4 | 0.9683 | 1457 |
k-NN 的局限性
现在我们已经回顾了 Elasticsearch 中 k-NN 搜索的所有功能,让我们看看你需要注意的几个限制:
- 直到 8.11,k-NN 搜索都无法在嵌套文档内的向量字段上运行。从 8.12 开始,此限制已被取消。但是,这种嵌套的 knn 查询不支持指定过滤器。
- search_type 始终设置为 dfs_query_then_fetch,并且无法动态更改它。
- 在使用跨集群搜索跨不同集群进行搜索时,不支持 ccs_minimize_roundtrips 选项。
- 这已经提到过几次了,但由于 Lucene 使用的 HNSW 算法的性质(以及任何其他近似最近邻搜索算法),“近似” 实际上意味着返回的 k 个最近邻并不总是真实的。
调整 k-NN
你可以想象,你可以使用很多选项来优化 k-NN 搜索的索引和搜索性能。我们不会在本文中介绍它们,但如果你真的想在 Elasticsearch 集群中实施 k-NN 搜索,我们强烈建议你在官方文档中查看它们。
超越 k-NN
到目前为止,我们看到的一切都利用了密集(dense)向量模型(因此是致密向量字段类型),其中向量通常包含非零值。Elasticsearch 还提供了使用稀疏(sparse)向量模型执行语义搜索的另一种方法。
Elastic 创建了一个稀疏 NLP 向量模型,称为 Elastic Learned Sparse EncodeR,简称 ELSER,这是一个域外(即未在特定域上训练)稀疏向量模型,不需要任何微调。它是在约 30000 个术语的词汇表上进行预训练的,并且作为一个稀疏模型,这意味着向量具有相同数量的值,其中大多数为零。
它的工作方式非常简单。在索引时,使用推理摄取处理器生成稀疏向量(术语/权重对),并将其存储在 sparse_vector 类型的字段中,这是 dense_vector 向量字段类型的稀疏对应项。在查询时,特定的 DSL 查询(也称为 sparse_vector)将用 ELSER 模型词汇表中的可用术语替换原始查询术语,这些术语已知与它们的权重最相似。
我们不会在本文中深入探讨 ELSER,但如果你渴望了解它的工作原理,你可以查看这篇开创性的文章以及官方文档,其中详细解释了该主题。
快速浏览一些即将推出的相关主题
Elasticsearch 还支持结合词汇搜索和向量搜索,这将是本系列下一篇也是最后一篇文章的主题。
到目前为止,我们必须在 Elasticsearch 之外生成嵌入向量,并将它们明确传递到我们所有的查询中。是否可以只提供查询文本,然后模型就会动态生成嵌入?好消息是,这可以通过 Elasticsearch 来实现,方法是利用名为 query_vector_builder 的构造(用于密集向量)或使用新的 semantic_text 字段类型和 semantic DSL 查询(用于稀疏向量),你可以在这篇文章中了解有关这些技术的更多信息。
让我们总结一下
在本文中,我们深入研究了 Elasticsearch 向量搜索支持。我们首先分享了 Elastic 寻求提供准确向量搜索的一些背景,以及我们决定使用 Apache Lucene 作为向量索引和搜索引擎的原因。
然后,我们介绍了在 Elasticsearch 中执行向量搜索的两种主要方法,即利用 script_score 查询来运行精确的强力搜索,或者通过 knn 搜索选项或 8.12 中引入的 knn 搜索查询使用近似最近邻搜索。
我们展示了如何运行简单的 k-NN 搜索,然后,我们回顾了使用过滤器和预期相似性配置 knn 搜索选项和查询的所有可能方法,以及如何同时运行多个 k-NN 搜索。
总结一下,我们列出了 k-NN 搜索的一些当前限制以及需要注意的事项。我们还邀请你查看可用于优化 k-NN 搜索的所有可能选项。
如果你喜欢你正在阅读的内容,请务必查看本系列的其他部分:
- 第 1 部分:向量搜索快速入门
- 第 3 部分:使用 Elasticsearch 进行混合搜索(敬请期待!)
想要获得 Elastic 认证?了解下一次 Elasticsearch 工程师培训何时开始!
Elasticsearch 包含许多新功能,可帮助你为你的用例构建最佳搜索解决方案。深入了解我们的示例笔记本以了解更多信息,开始免费云试用,或立即在你的本地机器上试用 Elastic。
原文:How to set up vector search in Elasticsearch - Elasticsearch Labs
相关文章:
如何在 Elasticsearch 中设置向量搜索 - 第二部分
作者:来自 Elastic Valentin Crettaz 了解如何在 Elasticsearch 中设置向量搜索并执行 k-NN 搜索。 本文是三篇系列文章中的第二篇,深入探讨了向量搜索(也称为语义搜索)的复杂性以及它在 Elasticsearch 中的实现方式。 第一部分重…...
leetcode 面试经典 150 题:跳跃游戏 II
链接跳跃游戏 II题序号45题型数组题解贪心算法难度中等熟练度✅✅✅ 题目 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向后跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums…...
C++20 新特性解析
1. 概念(Concepts) 概念是 C++20 引入的一项重要特性,它允许程序员定义类型约束,从而在编译时检查模板参数是否符合某些要求。概念提供了模板参数的限制,使得模板代码更加可读和易于维护。 示例代码: #include <iostream> #include <concepts>// 定义一个…...
vue不是内部或外部命令?
问题:当我们在使用脚手架创建项目之前,执行了npm i vue/cli -g或yarn global add vue/cli之后,再执行vue --version无法执行,vue不是内部或外部命令。 前几天在学vue时也是遇到了这个问题,现在来分享一下解决方法。 …...
C#中的Frm_Welcome.Instance.Show(),是什么意思
Frm_Welcome.Instance.Show() 是一种常见的单例模式(Singleton Pattern)实现方式,通常用于在应用程序中确保某个窗体(Form)只有一个实例,并通过该实例显示窗体。以下是对这段代码的详细解释: 代…...
k8s优雅操作pod容器组
k8s优雅操作pod容器组 回退备份 kubectl get deploy deployName -o yaml>>deployName-bak-date "%Y-%m-%d".yaml获取副本数 replicasecho | kubectl get -o template deploy/deployName --template{{.spec.replicas}}停止容器组 kubectl scale deployment …...
【LeetCode: 1760. 袋子里最少数目的球 + 二分】
🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…...
动态规划LeetCode-416.分割等和子集
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 示例 1: 输入:nums [1,5,11,5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和 [11] 。 示例 2&…...
kotlin-kapt
kotlin-kapt kotlin-kapt 是 Kotlin 的一个插件,专门用于处理注解处理器(Annotation Processor)。以下是对该插件的详细解释和指南: kotlin-kapt 是什么? kotlin-kapt 是 Kotlin 官方提供的一个插件,用于在…...
网络安全技术复习总结
1|0第一章 概论 1.网络安全发展阶段包括四个阶段:通信安全、计算机安全、网络安全、网络空间安全。 2.2017年6月1日,我国第一部全面规范网络空间安全的基础性法律《中华人民共和国网络安全法》正式实施。 3.2021年 6月10日,《中华人民共和…...
java 集合
Java集合框架(Java Collections Framework)是一个强大的工具库,旨在简化数据存储和操作的任务。它提供了一组接口、类和算法,帮助开发者高效地管理数据,如列表、集合和映射。下面是Java集合框架的详细介绍:…...
Java常见排序算法及代码实现
1、选择排序算法 选择排序(Selection Sort)是一种简单直观的排序算法,它的工作原理是每次从未排序部分选择最小(或最大)的元素,将其放到已排序部分的末尾。 2、冒泡排序算法 冒泡排序(Bubble…...
130,[1] 攻防世界 very_easy_sql
进入靶场 典型SQL注入页面 先查看源码 访问 试试http://127.0.0.1/ 还尝试了其他都是nonono 回归第一个登录页面 提交的内容不在url处显示,反而第二个url页面会在url处显示 明白第一个页面是通过post方式提交,反正没得到什么信息,去抓…...
Spring Boot从入门到精通:核心知识点+实战指南
目录 一、Spring Boot 是什么?为什么它如此流行? 二、快速创建你的第一个Spring Boot应用 2.1 使用Spring Initializr生成项目 2.2 核心代码示例 三、深度解析Spring Boot核心机制 3.1 自动配置原理揭秘 3.2 自定义Starter实战 四、生产环境必备…...
深入探索现代CSS:从基础到未来趋势
引言:CSS的进化之路 CSS(层叠样式表)自1996年诞生以来,已从简单的样式描述语言发展为构建现代Web体验的核心技术。截至2023年,超过98%的网站使用CSS3技术,其发展历程见证了Web从静态文档到富交互应用的蜕变…...
python-leetcode 23.反转链表
题目: 给单链表的头节点,反转链表,并返回反转后的链表。 方法一:迭代 在遍历链表时,将当前节点的next指针改为指向前一个节点。由于节点没有引用其前一个节点,因此要先存储前一个节点,在更改引…...
Foundation CSS 可见性
Foundation CSS 可见性 引言 在网页设计中,CSS可见性是一个至关重要的概念。它决定了元素在网页上是否可见,以及如何显示。Foundation CSS 是一个流行的前端框架,它提供了丰富的工具和组件来帮助开发者构建响应式和可访问的网页。本文将深入探讨 Foundation CSS 中的可见性…...
DeepSeek模拟阿里面试——java基本语法
为了全面准备阿里Java高级程序员的面试,以下是针对数据类型和变量、运算符、流程控制的系统性复习和准备策略: 数据类型和变量 基本数据类型 整数类型:byte(1字节)、short(2字节)、int…...
大模型基本原理(二)——ChatGPT的工作原理
如何得到一个ChatGPT? 1、无监督预训练:通过大量的文本数据集进行无监督训练,得到一个基座模型(只会续写文本) 2、监督微调:通过一些人类撰写的高质量对话数据对基座模型进行监督微调,得到一个…...
TensorRT 8.6.1教程1-TensorRT简介
区分计算节点和数据节点 视频 TensorRT 教程 | 基于 8.6.1 版本 | 第一部分_哔哩哔哩_bilibili cookbook...
Seaweedfs(master volume filer) docker run参数帮助文档
文章目录 进入容器后执行获取weed -h英文中文 weed server -h英文中文 weed volume -h英文中文 关键点测试了一下,这个-volume.minFreeSpace string有点狠,比如设置值为10(10%),它直接给系统只留下10%的空间࿰…...
深度求索(DeepSeek)的AI革命:NLP、CV与智能应用的技术跃迁
Deepseek官网:DeepSeek 引言:AI技术浪潮中的深度求索 近年来,人工智能技术以指数级速度重塑全球产业格局。在这场技术革命中,深度求索(DeepSeek)凭借其前沿的算法研究、高效的工程化能力以及对垂直场景的…...
探索RDMA技术:从基础到实践
1. 引言 在当今的高性能计算(HPC)和数据中心领域,数据传输的效率和速度至关重要。RDMA(Remote Direct Memory Access,远程直接内存访问)技术作为一种高效的网络通信机制,能够显著减少数据传输的延迟和CPU负载。本文将从基础到实践,详细介绍RDMA技术及其编程模型,帮助…...
Excel 笔记
实际问题记录 VBA脚本实现特殊的行转列 已知:位于同一Excel工作簿文件中的两个工作表:Sheet1、Sheet2。 问题:现要将Sheet2中的每一行,按Sheet1中的样子进行转置: Sheet2中每一行的黄色单元格,为列头。…...
Flutter编译运行android问题之JVM版本问题
错误1: FAILURE: Build failed with an exception. * What went wrong: Execution failed for task :audioplayers_android:compileDebugKotlin. > Inconsistent JVM-target compatibility detected for tasks compileDebugJavaWithJavac (1.8) and compileDebug…...
自动化遇到的问题记录(遇到问题就更)
总结回归下自己这边遇到的一些问题 “EOF错误”,获取不到csv里面的内容 跑多csv文件里的场景,部分场景的请求值为 1、检查csv文件里不能直接是[]开头的参数,把[]改到ms平台的请求参数里 2、有时可能是某个参数值缺了双引号的其中一边 met…...
解决 Flutter Device Daemon 启动失败问题的实践记录
解决 Flutter Device Daemon 启动失败问题的实践记录 最近在使用 Flutter 开发时踩了一个坑。看似是个小问题,但折腾了好久,最终通过日志分析和查阅资料才找到了解决办法。这里记录一下整个问题的排查过程,希望能帮助到遇到类似问题的小伙伴…...
中国通信企业协会 通信网络安全服务能力评定 证书使用说明
中国通信企业协会颁发的通信网络安全服务能力资格证书,是证明证书持有单位符合通信网络安全服务相应能力准则要求。证书持有单位在使用中国通信企业协会颁发的证书时,应遵守以下规定: 评定证书 证书持有单位必须遵守《中国通信企业协会通信网…...
《我在技术交流群算命》(三):QML的Button为什么有个蓝框去不掉啊(QtQuick.Controls由Qt5升级到Qt6的异常)
有群友抛出类似以下代码和运行效果截图: import QtQuick import QtQuick.ControlsWindow {width: 640height: 480visible: truetitle: qsTr("Hello World")Button{anchors.centerIn: parentwidth: 100height: 40background: Rectangle {color: "red…...
多项式插值(数值计算方法)Matlab实现
多项式插值(数值计算方法)Matlab实现 一. 原理介绍二. 程序设计1. 构建矩阵2. 求解矩阵方程3. 作出多项式函数4. 绘制插值曲线5. 完整代码 三. 图例 一. 原理介绍 关于插值的定义及基本原理可以参照如下索引 插值原理(数值计算方法ÿ…...
【AIGC】语言模型的发展历程:从统计方法到大规模预训练模型的演化
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 💯前言💯语言模型的发展历程:从统计方法到大规模预训练模型的演化1 统计语言模型(Statistical Language Model, SLM):统…...
[python]如何安装whl包并解决依赖关系(详细)
一、什么是whl文件? whl是一种预编译的二进制包文件,它主要用于安装python库。简单来讲whl就是一种已经编译好的python库文件。我们可以使用whl包来安装python库。 二、我们为什么需要使用whl文件来安装python库? 有的小伙伴可能会疑惑&…...
Windows中使用Docker安装Anythingllm,基于deepseek构建自己的本地知识库问答大模型,可局域网内多用户访问、离线运行
文章目录 Windows中使用Docker安装Anythingllm,基于deepseek构建自己的知识库问答大模型1. 安装 Docker Desktop2. 使用Docker拉取Anythingllm镜像2. 设置 STORAGE_LOCATION 路径3. 创建存储目录和 .env 文件.env 文件的作用关键配置项 4. 运行 Docker 命令docker r…...
用Kibana实现Elasticsearch索引的增删改查:实战指南
在大数据时代,Elasticsearch(简称 ES)和 Kibana 作为强大的数据搜索与可视化工具,受到了众多开发者的青睐。Kibana 提供了一个直观的界面,可以方便地对 Elasticsearch 中的数据进行操作。本文将详细介绍如何使用 Kiban…...
AI前端开发的国际化发展机遇:ScriptEcho助力全球化布局
在全球化的今天,互联网应用已不再局限于单一市场。高效便捷的前端开发方案成为企业拓展国际市场的关键。得益于人工智能技术的飞速发展,AI代码生成器 正在深刻改变前端开发模式,为国际化应用开发带来前所未有的机遇。然而,国际化开…...
本地基于GGUF部署的DeepSeek实现轻量级调优之一:提示工程(Prompt Engineering)(完整详细教程)
前文,我们在本地windows电脑基于GGUF文件,部署了DeepSeek-1.5B模型,如果想自行对模型进行训练,离线模式下加载本地的DeepSeek模型进行训练时,是不能直接使用GGUF文件进行训练。 请参照我的文章在本地部署好模型之后再继…...
基于 GEE 计算研究区年均地表温度数据
目录 1 代码解析 2 完整代码 3 运行结果 1 代码解析 (1)定义研究区: // 研究区的范围需要自己提前上传 var dataset table;// 将研究区显示在中心,后面的数字为缩放等级,范围从1 - 24 Map.centerObject(dataset,…...
编程语言的深度剖析:从语法到性能优化
引言 随着软件开发的不断进化,编程语言的选择对项目的成功与否具有关键影响。今天的开发者面临着丰富多样的编程语言选择:每一种语言都有独特的优势、特性和适用场景。然而,语言的设计理念、运行机制和优化技巧背后的技术细节却常常被忽视。本…...
设计模式-结构型-外观模式
在软件开发中,随着功能的不断迭代,系统会变得越来越复杂,模块之间的依赖关系也会越来越深。这种复杂性会导致代码难以理解、维护和扩展。而外观模式(Facade Pattern)正是为了解决这一问题而生的。 一、外观模式简介 …...
uniapp中对于文件和文件夹的处理,内存的查询
目录 移动文件到指定文件夹 新增本地文件夹 设定本地文件过期时间,清除超时文件,释放内存 操作本地文件之----删除 uniapp获取设备剩余存储空间的方法 读取本地文件夹下的文件 移动文件到指定文件夹 function moveTempFile(tempFilePath, targetFo…...
计算机网络和操作系统常见面试题目(带脑图,做了延伸以防面试官深入提问)
呜哦~~(✪▽✪)曼波~~~~ 今天我们来聊聊计算机网络和操作系统的面试题目吧!这些题目是面试中经常遇到的,曼波觉得掌握它们对面试非常有帮助哦!(๑✧◡✧๑) --- 1. 计算机网络面试题目 1.1 OSI 七层模型是什么? 回答ÿ…...
C++ Primer 条件语句
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
JAVA安全—Shiro反序列化DNS利用链CC利用链AES动态调试
前言 讲了FastJson反序列化的原理和利用链,今天讲一下Shiro的反序列化利用,这个也是目前比较热门的。 原生态反序列化 我们先来复习一下原生态的反序列化,之前也是讲过的,打开我们写过的serialization_demo。代码也很简单&…...
16.React学习笔记.React更新机制
一. 发生更新的时机以及顺序## image.png props/state改变render函数重新执行产生新的VDOM树新旧DOM树进行diff计算出差异进行更新更新到真实的DOM 二. React更新流程## React将最好的O(n^3)的tree比较算法优化为O(n)。 同层节点之间相互比较,不跨节点。不同类型的节…...
React使用 useImperativeHandle 自定义暴露给父组件的实例方法(包括依赖)
关键词 React useImperativeHandle 摘要 useImperativeHandle 是 React 提供的一个自定义 Hook,用于在函数组件中显式地暴露给父组件特定实例的方法。本文将介绍 useImperativeHandle 的基本用法、常见应用场景,以及如何处理其依赖项,以帮…...
Vue 过渡动画实现全解析:打造丝滑交互体验
Vue 过渡动画实现全解析:打造丝滑交互体验 在当今竞争激烈的 Web 开发领域,用户体验已成为衡量项目成功与否的关键指标。过渡动画作为提升用户体验的利器,能让应用的交互更加丝滑流畅,给用户带来愉悦的使用感受。在 Vue.js 框架中…...
从 0 开始本地部署 DeepSeek:详细步骤 + 避坑指南 + 构建可视化(安装在D盘)
个人主页:chian-ocean 前言: 随着人工智能技术的迅速发展,大语言模型在各个行业中得到了广泛应用。DeepSeek 作为一个新兴的 AI 公司,凭借其高效的 AI 模型和开源的优势,吸引了越来越多的开发者和企业关注。为了更好地…...
Render上后端部署Springboot + 前端Vue 问题及解决方案汇总
有一个 Vue 前端 和 Spring Boot 后端的动态网页游戏,当前在本地的 5173 端口和运行。你希望生成一个公开链接,让所有点击链接的人都能访问并玩这个游戏。由于游戏原本需要在本地执行 npm install 后才能启动,你现在想知道在部署时是选择 Ren…...
Linux——信号的保存与处理
前言:本文主要介绍信号的保存与处理过程。 一、信号阻塞与信号底层逻辑 在linux下面的进程控制块(PCB),存在一个pending变量用于存放接收到的信号,该变量有32位,变量的位代表信号的类别,变量的值代表是否收到信号。进程会根据该变…...
【deepseek-r1本地部署】
首先需要安装ollama,之前已经安装过了,这里不展示细节 在cmd中输入官网安装命令:ollama run deepseek-r1:32b,开始下载 出现success后,下载完成 接下来就可以使用了,不过是用cmd来运行使用 可以安装UI可视化界面&a…...