如何在 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 中的实现方式。 第一部分重…...
DeepSeek的出现会对百度有多大影响?
当DeepSeek与ChatGPT等大模型接管搜索入口,我们正见证百年一遇的信息革命。 01 传统搜索已死?AI助手正在重写游戏规则! 当DeepSeek与ChatGPT等大模型接管搜索入口,我们正见证百年一遇的信息革命。 就像汽车淘汰马车、触屏终结按键…...
【C#】条件运算符
1.逻辑与(&&) Console.WriteLine(true && true);//true Console.WriteLine(true && false);//false Console.WriteLine(false && false);//false2.逻辑或(||) Console.WriteLine(true || true);//true Console.WriteLine(true || false);//t…...
单例模式详解(Java)
单例模式详解(Java) 一、引言 1.1 概述单例模式的基本概念和重要性 单例模式是一种常用的软件设计模式,它确保一个类在整个应用程序中只有一个实例,并提供一个全局访问点来访问这个唯一实例。这种模式在资源管理、配置设置和日志记录等方面非常有用,因为它们通常只需要…...
PyQt学习记录01——加法计算器
目录 PyQt学习记录01——加法计算器 PyQt学习记录02——串口助手 0. 安装配置 0.1 安装相关库 首先打开你的PyCharm程序,然后新建一个目录用于学习,其次在terminal中输入 pip install pyqt5如果你不具有科学上网能力,请改为国内源 pip …...
笔记:蓝桥杯python搜索(3-2)——DFS剪支和记忆化搜索
目录 一、DFS剪支 二、例题 P2942 数字王国之军训军队 P3075 特殊的多边形 三、记忆化搜索 四、例题 例题 P3820 混境之地 P216 地宫取宝 一、DFS剪支 在搜索过程中,如果需要完全遍历所有情况可能需要很多时间在搜索到某种状态时,根据当前状态判断…...
k8s启空容器用于排查问题
如果 Pod 一会儿就销毁了,可能是由于 Pod 配置、节点状态或容器运行时问题导致的。 此时想进容器排查,但是pod一会儿就销毁了,不利于排查。 为了排查问题,可以启动一个空容器来临时保留 Pod,进而进入 Pod 内部进行调…...
jenkins备份还原配置文件
下载ThinBackup插件 方式1 从插件市场直接下载 Manage Jenkins->Manage Plugins->可选插件搜索 注意:有时可能因为网络或者版本问题下载不了,好像是默认下载最新版本,可选择手动安装! 方式二 手动安装插件 点击查看手…...
02.11 数据库
1.思维导图 2.题目 将 epoll 服务器、客户端拿来用客户端:写一个界面,里面有注册登录服务器:处理注册和登录逻辑,注册的话将注册的账号密码写入数据库,登录的话查询数据库中是否存在账号,并验证密码是否正…...
物联网(IoT)如何与人工智能(AI)的结合
物联网(IoT)与人工智能(AI)的结合是当前技术发展的重要趋势,通常被称为 AIoT(人工智能物联网)。这种结合通过将AI的计算能力和数据分析能力与物联网的海量设备连接能力相结合,实现了…...
嵌入式硬件篇---原码、补码、反码
文章目录 前言简介八进制原码、反码、补码1. 原码规则示例问题 2. 反码规则示例问题 3. 补码规则示例优点 4. 补码的运算5. 总结 十六进制原码、反码、补码1. 十六进制的基本概念2. 十六进制的原码规则示例 3. 十六进制的反码规则示例 4. 十六进制的补码规则示例 5. 十六进制补…...
PHP函数fgetc(): 从文件中读取一个字符
在PHP中,有许多用于文件操作的函数,其中之一就是fgetc()函数。fgetc()函数用于从打开的文件中读取一个字符,并将指针移动到下一个字符的位置。本文将介绍fgetc()函数的用法,并提供一些示例来帮助读者更好地理解和使用这个函数。 …...
Spring Boot整合DeepSeek实现AI对话(API调用和本地部署)
本篇文章会分基于DeepSeek开放平台上的API,以及本地私有化部署DeepSeek R1模型两种方式来整合使用。 本地化私有部署可以参考这篇博文 全面认识了解DeepSeek利用ollama在本地部署、使用和体验deepseek-r1大模型 Spring版本选择 根据Spring官网的描述 Spring AI是一…...
苹果转型独立AR眼镜:一场技术与创新的深度探索
在科技日新月异的今天,增强现实(AR)技术正逐渐从科幻电影走进我们的日常生活。作为科技界的领头羊,苹果公司的每一步动向都备受关注。近期,苹果宣布暂停原定的Mac连接式AR眼镜计划,转而全力研发一款独立的AR眼镜。这一战略调整不仅反映了苹果对AR市场的深度洞察,也预示着…...
Java小白入门基础知识(一)
1.初识Java java源程序通过javac 编译生成字节码文件,通过java命令运行java程序 总结: 1)在一个Java文件中,只能有一个public class 2)public class一定要和文件名一致 3)类里面包含方法 4)…...
通过 Docker 安装和部署 KeyDB v6.3.4 的详细步骤
KeyDB 是一种高性能的开源内存数据库,最初是基于 Redis 项目开发的,但在性能、特性和功能上进行了许多增强和改进。它兼容 Redis 的大部分命令和数据结构,因此可以作为 Redis 的替代品使用,尤其是在需要更高性能和多线程支持的场景…...
【JavaEE进阶】依赖注入 DI详解
目录 🌴什么是依赖注入 🎄依赖注入的三种方法 🚩属性注⼊(Field Injection) 🚩Setter注入 🚩构造方法注入 🚩三种注⼊的优缺点 🌳Autowired存在的问题 🌲解决Autowired存在的…...
Avnet RFSoC基于maltab得5G 毫米波 开发工具箱
使用 MATLAB 连接到 AMD Zynq™ RFSoC 评估板。使用 RF 附加卡执行 OTA 测试。使用 HDL Coder 部署算法 版本要求: 大于 2023b 需要以下支持包之一: 适用于 Xilinx 基于 Zynq 的无线电(R2023b 及更早版本)的通信工具箱支持包适…...
掌握 PHP 单例模式:构建更高效的应用
在 PHP 应用开发中,资源的高效管理至关重要。单例模式是一种能够帮助我们实现这一目标的设计模式。本文将深入探讨单例模式的概念、工作原理以及在 PHP 项目中何时应该(或不应该)使用它。 什么是单例模式? 单例模式是一种设计模…...
neo4j-解决导入数据后出现:Database ‘xxxx‘ is unavailable. Run :sysinfo for more info.
目录 问题描述 解决方法 重新导入 问题描述 最近在linux上部署了neo4j,参照之前写的博客:neo4j-数据的导出和导入_neo4j数据导入导出-CSDN博客 进行了数据导出、导入操作。但是在进行导入后,重新登录网页版neo4j,发现对应的数据库状态变…...
卷积神经网络(CNN)池化层的最大池化(Max Pooling)和 平均池化(Average Pooling)
在 卷积神经网络(CNN) 中,池化层(Pooling Layer) 是用来 减少特征图的空间尺寸、减少计算量、控制过拟合 的关键层。池化层通过 窗口操作 将输入特征图中一定区域的信息压缩成一个单一的值,常见的池化方式有 最大池化(Max Pooling) 和 平均池化(Average Pooling)。这…...
Mac(m1)本地部署deepseek-R1模型
1. 下载安装ollama 直接下载软件,下载完成之后,安装即可,安装完成之后,命令行中可出现ollama命令 2. 在ollama官网查看需要下载的模型下载命令 1. 在官网查看deepseek对应的模型 2. 选择使用电脑配置的模型 3. copy 对应模型的安…...
第六届MathorCup高校数学建模挑战赛-A题:淡水养殖池塘水华发生及池水自净化研究
目录 摘要 1 问题的重述 2 问题的分析 2.1 问题一的分析 2.2 问题二的分析 2.3 问题三的分析 2.4 问题四的分析 2.5 问题五的分析 3. 问题的假设 4. 符号说明 5. 模型的建立与求解 5.1 问题一的建模与求解 5.1.1 分析对象与指标的选取 5.1.2 折线图分析 5.1.3 相关性分析 5.1.4…...
【分布式理论9】分布式协同:分布式系统进程互斥与互斥算法
文章目录 一、互斥问题及分布式系统的特性二、分布式互斥算法1. 集中互斥算法调用流程优缺点 2. 基于许可的互斥算法(Lamport 算法)调用流程优缺点 3. 令牌环互斥算法调用流程优缺点 三、三种算法对比 在分布式系统中,多个应用服务可能会同时…...
第一财经对话东土科技 | 探索工业科技新边界
当前以ChatGPT、Sora等为代表的生成式人工智能快速发展,越来越多面向垂直场景的行业大模型涌现出来,并成为推动制造业智能化改造与数字化转型、加快推进新型工业化,进而培育发展新质生产力的新引擎。 在垂类场景的应用落地,是AI发…...
深入理解Java对接DeepSeek
其实,整个对接过程很简单,就四步,获取key,找到接口文档,接口测试,代码对接。 1.获取 KEY https://platform.deepseek.com/transactions 直接付款就是了(现在官网暂停充值2025年2月7日…...
如何设置爬虫的延时避免频繁请求?
在Python爬虫开发中,合理设置延时是避免频繁请求、降低被封禁风险的关键策略之一。以下是一些常见的延时设置方法和建议: 1. 使用 time.sleep() 设置固定延时 time.sleep() 是最简单直接的延时方法,通过暂停程序的执行来控制请求频率。例如…...
线段平移 实战笔记
目录 pingyi2.py pingyi2.py import numpy as np import cv2# 画线段的函数 def draw_line(img, p1, p2, color, thickness=2):cv2.line(img, tuple(p1), tuple(p2), color, thickness)# 创建图像并初始化 def create_image():# 创建一个黑色背景图像img = np.zeros((500, 50…...
【计算机毕业设计】Spring Boot教师人事档案管理系统功能说明
🎉**欢迎来到琛哥的技术世界!**🎉 📘 博主小档案: 琛哥,一名来自世界500强的资深程序猿,毕业于国内知名985高校。 🔧 技术专长: 琛哥在深度学习任务中展现出卓越的能力&a…...
WinForm 防破解、反编译设计文档
一、引言 1.1 文档目的 本设计文档旨在阐述 WinForm 应用程序防破解、反编译的设计方案,为开发团队提供详细的技术指导,确保软件的知识产权和商业利益得到有效保护。 1.2 背景 随着软件行业的发展,软件破解和反编译现象日益严重。WinForm…...
