Kibana 控制台中提供语义、向量和混合搜索
作者:来自 Elastic Mark_Laney
想要将常规 Elasticsearch 查询与新的 AI 搜索功能结合起来吗?那么,你不需要连接到某个第三方的大型语言模型(LLM)吗?不。你可以使用 Elastic 的 ELSER 模型来改进现有搜索,以创建语义向量,并将其与常规搜索相结合,以获得更相关的搜索结果!
介绍
当谈到使用 AI 并将向量搜索应用于 Elastic 上的数据时,我看到很多教程和文章,它们可能变得相当复杂。我想表明,你可以利用今天正在运行的现有搜索,并通过语义和向量搜索来增强它们。你无需连接任何外部 LLM 或付费给任何大公司来处理你的数据。仅在 Elasticsearch 和 Kibana 中,你就可以下载 Elastic 的语义模型 ELSER,处理你的数据以添加描述向量,并增强你的搜索以探索改进。你不需要 LangChain、Python、chatGPT 或任何其他外部工具。
注:目前 ELSER 只提供对英文的支持。它是一种稀疏向量的搜索方式。更多阅读,请参阅 “Elasticsearch:使用 ELSER 释放语义搜索的力量:Elastic Learned Sparse EncoderR”。
平台
我们将运行的搜索是在 Elasticsearch 和 Kibana 8.13.4 版本上完成的。你可以在任何你喜欢的平台上运行它们,无论是在本地还是在云端。
数据
我们将搜索的数据来自 Kaggle 的一组称为 “recipes” 的开放许可数据集。原始数据集可以从这里下载(在《使用 Elastic 的从业者向量搜索》第 173 页中讨论)。我下载了该文件并将其命名为 “allrecipes.csv”。
或者你可以从我的 GitHub 下载数据集。请打开该链接以在后续说明中下载其他文件。
删除重复数据
原始数据集中存在重复的条目。我编写了一个小型 Python 脚本来对它们进行重复数据删除。该脚本位于 GitHub 项目文件夹中,名为 dedupecsv.py。去重的结果文件叫做 allrecipes_dedupe.csv,它也在项目文件中。如果要自己运行 dedupecsv.py,则需要安装 python 库 pandas。 (例如 pip install pandas)。但是你不必执行这个重复数据删除,因为它已经完成,结果是 allrecipes_dedupe.csv。下载该文件。
索引数据
我能够使用 Filebeat 和(甚至更简单的)Kibana 中的文件上传器将数据导入 Elasticsearch 中的索引,最近使用的是 8.13.4 版本,但旧版本也可以使用。如果你使用 Filebeat 将 allrecipes_dedupe.csv 导入 Elasticsearch,则配置文件为 filebeat.yml ,并且副本位于项目文件夹中。我按照 “快速安装” 文档安装并使用 filebeat 作为 “自托管” 系统。如果你正在使用远程系统(如 Cloud 或 Strigo),请将 filebeat.yml 和 allrecipes_dedupe.csv 都 scp 到你的实例。
但使用文件上传器更容易,只需下载 allrecipes_dedupe.csv 并将其拖放到 Kibana 中。
使用任一方法,创建一个名为 “recipes” 的 Elasticsearch 索引。 Filebeat 将为你完成此操作。你在文件上传器中输入该名称。
Kibana
步骤 1:让我们验证食谱索引是否已成功导入 Elasticsearch。
在 Kibana 控制台(Kibana 主菜单 -> Management -> Dev Tools)中运行此命令:
GET _cat/indices?v&s=index
_cat API 提供行和列的输出。问号 (?v&s=index) 后面的字符是显示标题标签 (v) 和按 “index” 列排序 (&s=index) 的选项。
验证 recipes 索引的另一种方法是使用 _count API。
GET recipes/_count
步骤 2:下载 ELSER
Kibana UI 让我们可以在机器学习区域下载模型。转到主菜单-> Machine Learning。找到并点击 “Trained Models”。你应该会看到一个可用模型的简短列表。对于非英特尔环境,请下载 .elser_model_2。如果你的平台使用的是Intel x86 芯片,请下载专门准备的.elser_model_2_linux-x86_64。
步骤 3:启动模型
开始部署该模型进行推理。使用一个分配和四个线程。大多数情况下,分配会消耗一个核心,而线程就是该核心上的线程。下面的 API 调用为模型提供了一个名称 “elser_model”。
如果你运行的是 Intel x86 芯片:
POST _ml/trained_models/.elser_model_2_linux-x86_64/deployment/_start?deployment_id=elser_model&number_of_allocations=1&threads_per_allocation=4
否则:
POST _ml/trained_models/.elser_model_2/deployment/_start?deployment_id=elser_model&number_of_allocations=1&threads_per_allocation=4
如果需要启动和停止模型,可以执行以下操作:
POST _ml/trained_models/elser_model/deployment/_stop
如果管道正在调用模型(我们稍后会讲到):
POST _ml/trained_models/elser_model/deployment/_stop?force=true
确保模型处于启动状态:
GET _ml/trained_models/_stats/
GET _ml/trained_models/_stats?filter_path=trained_model_stats.deployment_stats.state
步骤 4:浏览食谱索引
运行这些命令来检查 recipes 索引的内容和属性。
检查索引中的某些文档:
GET recipes/_search
要查看字段及其数据类型:
GET recipes/_mapping
要查看索引的所有属性(映射、设置、别名),实际上更容易:
GET recipes
步骤 5:改进映射
如果我们运行这个:
GET recipes/_search?filter_path=hits.hits._source.id
请注意,所有 ID 都是小整数。然而,如果我们回过头来检查映射,我们会发现 ID 的数据类型可能是文本/关键字或长整型(取决于我们用来索引配方的工具)。
还要注意,summary 字段是数据类型 text,默认使用标准分析器。如果有英语分析器结果(提供词干结果),这将对我们的搜索很有用。这样,如果我们搜索“stewed” 西红柿的 summary,结果就会是 stewed、stew、stews、stewing等,这可能有助于更轻松地获得相关食谱。
此外,我们还需要创建一个字段来保存数据向量化的结果。稍后我们将配置一个摄取节点管道处理器来指示模型将结果写入名为 ml.tokens 的字段。正如这里所解释的,ELSER 模型结果应该存储为我们的向量嵌入的数据类型 “稀疏向量”。
考虑到这些改变,让我们创建一个具有所有改进的映射属性的不存在的索引。
PUT recipes_embeddings
{"mappings": {"properties": {"id": {"type": "short"},"group": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"ingredient": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"n_rater": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"n_reviewer": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"name": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"process": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"rating": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"summary": {"type": "text","analyzer": "english","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"ml.tokens": {"type": "sparse_vector"}}}
}
步骤 6:其他文档修复
让我们再次检查一些有关食谱的文件。
GET recipes/_search
{"size": 2000,"_source": ["ingredient"]
}
如果你在控制台的右侧按 cntr+f find,你可能会注意到有些文档带有双引号或三引号。
在这里,我们创建一个摄取节点管道,将三重引号替换为单引号。
我们将我们的管道称为 “doublequotes”。
PUT _ingest/pipeline/doublequotes
{"processors": [{"gsub": {"field": "ingredient","pattern": "\"(.*?)","replacement": ""}}]
}
为了测试我们的管道,我们可以使用_simulate API。
POST _ingest/pipeline/doublequotes/_simulate
{"docs": [{"_index": "recipes","_id": "id","_source": {"ingredient": """shredded cheese, and even some cilantro for a great-tasting breakfast burrito that will keep your appetite curbed all day long.","prep: 15 mins,cook: 5 mins,total: 20 mins,Servings: 2,Yield: 2 burritos","2 (10 inch) flour tortillas + 1 tablespoon butter + 4 medium eggs + 1 cup shredded mild Cheddar cheese + 1 Hass avocado - peeled, pitted, and sliced + 1 small tomato, chopped + 1 small bunch fresh cilantro, chopped, or to taste (Optional) + 1 pinch salt and ground black pepper to taste + 1 dash hot sauce, or to taste (Optional)""","tags": 2342}}]
}
步骤 7:带推理的管道
下面我们创建一个管道来清理引文并应用推理处理器。推理处理器是我们用来针对索引中的成分字段运行我们的模型(在本例中为 ELSER)的工具。回想一下,我们部署的名称是 else_model,我们在这里看到它被称为 model_id。我们将此管道称为 else_clean_recipes。
PUT _ingest/pipeline/elser_clean_recipes
{"processors": [{"pipeline": {"name": "doublequotes"},"inference": {"model_id": "elser_model","target_field": "ml","field_map": {"ingredient": "text_field"},"inference_config": {"text_expansion": {"results_field": "tokens"}}}}]
}
请注意,模型默认对 “text_field” 字段进行向量化。在“field_map”行中,我们配置推理处理器以使用不同的字段(在本例中为成分)。
一定要测试。
POST _ingest/pipeline/elser_clean_recipes/_simulate
{"docs": [{"_index": "recipes","_id": "id","_source": {"ingredient": """prep: 20 mins,cook: 20 mins,total: 40 mins,Servings: 4,Yield: 4 servings","½ small onion, chopped + ½ tomato, chopped + 1 jalapeno pepper, seeded and minced + 1 sprig fresh cilantro, chopped + 6 eggs, beaten + 4 (10 inch) flour tortillas + 2 cups shredded Cheddar cheese + ¼ cup sour cream, for topping + ¼ cup guacamole, for topping""","tags": 2342}},{"_index": "recipes","_id": "id","_source": {"ingredient":""""shredded cheese, and even some cilantro for a great-tasting breakfast burrito that will keep your appetite curbed all day long.","prep: 15 mins,cook: 5 mins,total: 20 mins,Servings: 2,Yield: 2 burritos","2 (10 inch) flour tortillas + 1 tablespoon butter + 4 medium eggs + 1 cup shredded mild Cheddar cheese + 1 Hass avocado - peeled, pitted, and sliced + 1 small tomato, chopped + 1 small bunch fresh cilantro, chopped, or to taste (Optional) + 1 pinch salt and ground black pepper to taste + 1 dash hot sauce, or to taste (Optional)"""}},{"_index": "recipes","_id": "id","_source": { "ingredient": """shredded cheese, and even some cilantro for a great-tasting breakfast burrito that will keep your appetite curbed all day long.","prep: 15 mins,cook: 5 mins,total: 20 mins,Servings: 2,Yield: 2 burritos","2 (10 inch) flour tortillas + 1 tablespoon butter + 4 medium eggs + 1 cup shredded mild Cheddar cheese + 1 Hass avocado - peeled, pitted, and sliced + 1 small tomato, chopped + 1 small bunch fresh cilantro, chopped, or to taste (Optional) + 1 pinch salt and ground black pepper to taste + 1 dash hot sauce, or to taste (Optional)"""}}]
}
步骤 8:通过管道处理数据
现在我们有了管道,是时候处理我们的索引了。我们将使用 _reindex API 将数据从 recipes 索引发送到 recipes_embeddings。在此过程中,数据将通过我们的管道来创建嵌入。
重新索引可能需要很长时间,因此我们在这里使用一个名为 wait_for_completion=false 的选项进行运行。
当我们运行命令时,它将生成一个 ID 号,我们可以使用它来检查进度。确保将此 ID 复制并粘贴到某处。
此外,重新索引正在使用选项......
requests_per_second=-1&timeout=60m
...分别以尽可能快的速度运行并且不会太快超时。
警告:可能需要大约 15-30 分钟
POST _reindex?wait_for_completion=false&requests_per_second=-1&timeout=60m
{"conflicts": "proceed", "source": {"index": "recipes","size": 500},"dest": {"index": "recipes_embeddings","pipeline": "elser_clean_recipes"}
}
复制并使用任务编号来跟踪重新索引过程。
GET _tasks/< paste task number here >
例如,我复制并粘贴了这个ID:LAV3l8oZTmaR9p8VUVqO3g:373447
如果需要,你可以像这样删除 recipes_embeddings 索引。
DELETE recipes_embeddings
步骤 9:检查已处理的文件
至少一批文档完成后,检查结果。
GET _cat/indices?v&s=iGET recipes_embeddings/_search
冗长的 ml.tokens 字段使得输出看起来不太好看。你可以像这样抑制它。
GET recipes_embeddings/_search
{ "_source": { "excludes": "ml"} }
GET recipes_embeddings/_count
4808 documents
我们可以运行这个聚合来找到我们可以查询的 “group” 中的所有不同值。
GET recipes_embeddings/_search?size=0
{"aggs": {"all the groups": {"terms": {"field": "group.keyword","size": 200}}}
}
有多少个桶?
GET recipes_embeddings/_search
{"size": 0, "aggs": {"how many buckets": {"cardinality": {"field": "group.keyword","precision_threshold": 200}}}
}
我得到了 174 个不同的组。
为了隔离输出中的组以便我们可以在文档中看到它们,你可以运行以下命令:
GET recipes_embeddings/_search?size=1000&_source=group
搜索
最后,数据准备好了,我们可以在 recipes_embeddings 索引上执行搜索。让我们比较一下没有 ELSER 的运行结果和有 ELSER 的运行结果。
搜索 1:Old fashion(老式鸡尾酒)
首先,我们来寻找一种名为 Old Fashion 的鸡尾酒的配方。下面介绍如何进行此操作。
-- 老式波本鸡尾酒 --
1. 将一到两颗樱桃放入老式老式玻璃杯中,并用捣碎器轻轻捣碎。
2. 取橙皮并擦拭玻璃杯边缘内侧,然后将果皮放在樱桃上。
3. 加入冰块、黑麦威士忌、糖和苦味酒。
4. 搅拌均匀即可食用。
首先,没有 ELSER 的情况下:
GET recipes_embeddings/_search
{"_source": {"excludes": "ml", "includes": ["name","group","summary","ingredient"]},"query": {"bool": {"should": [ { "wildcard": { "group": {"value": "drinks*" }}},{"multi_match": {"type": "phrase", "query": "old fashion","fields": ["summary","name"]}},{"match": {"summary": "delicious sensational"}}]}}
}
在你的控制台中运行它,你将看到热门点击中有一些非常糟糕的结果。
对我来说,它们都不是饮料(尽管我们搜索了饮料*组)。
我的许多搜索结果中都有诸如 “good old fashion meals and dishes...” 这样的短语,但这并不是我们想要的。
现在让我们用 ELSER 搜索...并看看出色的结果!
GET recipes_embeddings/_search
{"_source": {"excludes": "ml","includes": ["name","group","summary","ingredient"]},"sub_searches": [{"query": {"bool": {"should": [{"wildcard": {"group": {"value": "drinks*"}}},{"multi_match": {"query": "old fashioned","type": "phrase","fields": ["summary","name"]}}]}}},{"query": {"text_expansion": {"ml.tokens": {"model_id": "elser_model","model_text": "old fashioned bourbon whiskey whisky drink"}}}}],"rank": {"rrf": {"window_size": 500,"rank_constant": 60}}
}
请注意,所有这些都是成人饮料,并且有几种饮料的名称以 “Old Fashion” 开头。
搜索 2:Shrimp dishes
没有 ELSER:
GET recipes_embeddings/_search
{"_source": {"excludes": "ml"},"query": {"bool": {"should": [{"wildcard": {"group": {"value": "main*"}}},{"multi_match": {"type": "phrase", "query": "tempura shrimp","fields": ["ingredient","name^2"]}},{"match": {"summary": "tasty delightful"}}]}}
}
前五名的结果相当糟糕:我得到了像 pork tenderloin、Spanish sauce、carrot salad 这样的食谱……甚至没有虾。
使用 ELSER:
GET recipes_embeddings/_search
{"_source": {"excludes": "ml"},"sub_searches": [{"query": {"bool": {"should": [{"wildcard": {"group": {"value": "main*"}}},{"multi_match": {"query": "tempura shrimp","type":"phrase","fields": ["ingredient","name^2"]}}/*,{"match": {"summary": "tasty delightful"}}*/]}}},{"query": {"text_expansion": {"ml.tokens": {"model_id": "elser_model","model_text": "tempura shrimp"}}}}],"rank": {"rrf": {"window_size": 500,"rank_constant": 60}}
}
排名前五的菜品要好得多:Shrimp with Pasta、Shrimp Scampis、Penne with Shrimp、Penne with Shrimp、Shrimp Quiche
请注意,Elasticsearch 如何通过语义搜索发现 shrimp 和 scampi 以及 prawns 等其他术语也具有相关性。
搜索 3:Spaghetti dishes
没有 ELSER:
GET recipes_embeddings/_search
{"_source": {"excludes": "ml"},"query": {"bool": {"should": [{"wildcard": {"group": {"value": "main*"}}},{"multi_match": {"type": "phrase", "query": "Spaghetti Bolognese","fields": ["ingredient","name^2"]}},{"match": {"summary": "tasty delightful"}}]}}
}
前五名中又有糟糕的:pork tenderloin, Med. sauce, carrot salad, lime chicken……
我根本不喜欢意大利面。
使用 ELSER:
GET recipes_embeddings/_search?filter_path=hits.hits._source
{"_source": {"excludes": "ml"},"sub_searches": [{"query": {"bool": {"should": [{"wildcard": {"group": {"value": "main*"}}},{"multi_match": {"query": "Spaghetti Bolognese","type":"phrase","fields": ["ingredient","name^2"]}}/*,{"match": {"summary": "tasty delightful"}}*/]}}},{"query": {"text_expansion": {"ml.tokens": {"model_id": "elser_model","model_text": "main Spaghetti Bolognese"}}}}],"rank": {"rrf": {"window_size": 500,"rank_constant": 60}}
}
改进了很多。很多食材都有意大利面或通心粉
再次排在最前面:Pennes, pastas, spaghettis。
搜索 4:巧克力
没有 ELSER:
GET recipes_embeddings/_search
{"_source": {"excludes": "ml"},"query": {"bool": {"should": [{"match": {"name": "dessert"}},{"match": {"ingredient": "chocolate"}},{"match": {"summary": "tasty delightful"}}]}}
}
奶昔和薄饼……?
我找不到任何含巧克力的配料。
使用 ELSER:
GET recipes_embeddings/_search
{"_source": {"excludes": "ml"}, "sub_searches": [{"query": {"bool": {"should": [{"match": {"name": "dessert"}},{"match": {"ingredient": "chocolate"}},{"match": {"summary": "tasty delightful"}}]}}},{"query": {"text_expansion": {"ml.tokens": {"model_id": "elser_model","model_text": "dessert chocolate"}}}}],"rank": {"rrf": {"window_size": 50,"rank_constant": 20}}
}
Peppermint bark 是巧克力的一个晦涩术语。
Nanaimo bars 是一种巧克力顶上的饼干。我还看到hot chocolate, chocolate muffins, chocolate cake, Oreo truffles 和 cake balls,其中的配料包括巧克力。
我看到很多配料都含有巧克力。
我们再看一下我们可以查询的 “groups”。
GET recipes_embeddings/_search?size=0
{"aggs": {"all the groups": {"terms": {"field": "group.keyword","size": 200}}}
}
everyday-cooking 有多少种菜谱?
GET recipes_embeddings/_count
{"query": {"wildcard": {"group.keyword": {"value": "everyday-cooking*"}}}
}
我得到 310。
鱼肉三明治 - Fish Sandwich
让我们在日常烹饪中寻找 “Fish Sandwich”。
没有 ELSER:
GET recipes_embeddings/_search
{"_source": {"excludes": "ml"},"query": {"bool": {"should": [{"wildcard": {"group": {"value": "everyday-cooking*"}}},{"multi_match": {"type": "phrase", "query": "fish sandwich","fields": ["ingredient","name^2"]}}]}}
}
没有!
哇,根本没有鱼肉三明治……?
使用 ELSER 添加嵌入搜索。
GET recipes_embeddings/_search
{"_source": {"excludes": "ml"},"sub_searches": [{"query": {"bool": {"should": [{"wildcard": {"group": {"value": "everyday-cooking*"}}},{"multi_match": {"query": "fish sandwich","type":"phrase","fields": ["ingredient","name^2"]}}]}}},{"query": {"text_expansion": {"ml.tokens": {"model_id": "elser_model","model_text": "fish sandwich"}}}}],"rank": {"rrf": {"window_size": 500,"rank_constant": 60}}
}
在右侧搜索 “三明治”。
我看到 tuna patties, tuna salads - 很多鱼,很多都是三明治。
让我们看看“主菜”类别中有多少食谱?
让我们检查一下 “Main” 类别中有多少个食谱?
GET recipes_embeddings/_search
{"_source": {"excludes": "ml"},"query": {"bool": {"must": [{"match": {"group": "main*"}}]}}
}
我得到了458。
里脊牛排 - Tenderloin Steak
请注意,在美国我们说 “tenderloins or tenderloin steaks”,但在法国它被称为 Chateaubriand。还请注意,“Chateaubriand” 不在任何食谱中。可以使用 multi_match 命令来搜索许多字段,如下所示:
GET recipes_embeddings/_search
{"query": {"multi_match": {"query": "Chateaubriand","fields": ["ingredient","summary","name"]}}
}
零结果
不使用 ELSER:
GET recipes_embeddings/_search
{"_source": {"excludes": "ml", "includes": ["name","group","summary","ingredient"]},"query": {"bool": {"should": [ { "wildcard": { "group": {"value": "main*" }}},{"multi_match": {//"type": "phrase", "query": "tenderloin steak Chateaubriand beef","fields": ["ingredient","name^2"]}},{"match": {"summary": "delicious Chateaubriand"}},{"match": {"ingredient": "beef"}}]}}
}
前十名的成绩相当糟糕。Salt and pepper fries, salt bread, Pork Tenderloin 等等。
使用 ELSER:
GET recipes_embeddings/_search
{"_source": {"excludes": "ml", "includes": ["name","group","summary","ingredient"]},"sub_searches": [{"query": {"bool": {"should": [{"wildcard": {"group": {"value": "main*"}}},{"multi_match": {"query": "tenderloin steak Chateaubriand beef",//"type":"phrase","fields": ["ingredient","name^2"]}},{"match":{"ingredient":{"query": "beef"}}}]}}},{"query": {"text_expansion": {"ml.tokens": {"model_id": "elser_model","model_text": "tenderloin steak Chateaubriand beef"}}}}],"rank": {"rrf": {"window_size": 500,"rank_constant": 60}}
}
更多实际牛排。
恭喜!我们已经研究了许多示例,其中使用 ELSER 对数据进行向量化使我们能够进行语义搜索。我们将常规的、可能预先存在的术语搜索与向量搜索相结合,发现混合搜索结果通常比仅搜索术语本身更相关。
原文:Dec 13th, 2024: [EN] Semantic, Vector, and Hybrid Search all in Kibana Console - Advent Calendar - Discuss the Elastic Stack
相关文章:
Kibana 控制台中提供语义、向量和混合搜索
作者:来自 Elastic Mark_Laney 想要将常规 Elasticsearch 查询与新的 AI 搜索功能结合起来吗?那么,你不需要连接到某个第三方的大型语言模型(LLM)吗?不。你可以使用 Elastic 的 ELSER 模型来改进现有搜索&a…...
设计模式-结构型-装饰器模式
装饰器模式(Decorator Pattern)是结构型设计模式中的一种,它允许你通过将对象封装在一个新的对象中,来动态地添加新的功能,而无需改变原对象的结构。装饰器模式的核心思想是“将功能附加到对象上”,它是一种…...
CAP:Serverless + AI 让应用开发更简单
AI 已被广泛视为推动行业进步的关键力量,其在各行业的落地步伐加快。企业在构建 AI 应用开发过程中经常会面临 AI 技术门槛过高、试错周期过长、GPU 资源昂贵且弹性能力不足、缺乏配套工具、业务与模型的开发运维过于割裂、缺乏定制化能力等挑战,成为企业…...
Redis超详细入门教程(基础篇)
目录 一、什么是Redis 二、安装Redis 1、Windows系统安装 2、Linux系统安装 三、Redis通用命令 四、Redis基本命令 五、五种数据结构类型 5.1、String类型 5.2、List集合类型 5.3、Set集合类型 5.4、Hash集合类型 5.5、Zset有序集合类型 六、总结 一、什么是Redi…...
对话 TDengine 解决方案中心总经理陈肃:构建技术与市场的桥梁
TD 小T导读 他是大数据领域的杰出专家,拥有超过十项一作发明专利,是中国通信行业标准《大数据 消息中间件技术要求与测试方法》的重要编写者,并凭借数据中间件领域的突出成就荣获 2019 年“CJK OSS Award”。他是腾讯云 TVP 专家和 TGO 鲲鹏会…...
Formality:参考设计/实现设计以及顶层设计
相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 Formality存在两个重要的概念:参考设计/实现设计和顶层设计,本文就将对此进行详细阐述。参考设计/实现设计是中两个重要的全局概念&am…...
通过内核模块按fd强制tcp的quickack方法
一、背景 tcp的quickack功能是为了让ack迅速回发,快速响应,减少网络通讯时延,属于一个优化项,但是tcp的quickack是有配额限制的,配置是16个quick,也就是短时间内quickack了16次以后,这个配额为…...
Wi-Fi 7、Wi-Fi 6 与 5G、4G 的全方位对比
随着无线通信技术的飞速发展,Wi-Fi 7、Wi-Fi 6,以及5G、4G 已经成为人们生活和工作中不可或缺的网络技术。无论是家庭网络、高速移动通信,还是工业物联网,这些技术都在发挥各自的作用。那么,它们之间有什么区别&#x…...
【例43.3】 转二进制
目录 描述 输入描述 输出描述 用例输入 1 用例输出 1 来源 类型 知识补充站 代码 C Python3 C 描述 请你把一个整数n转化为二进制并从低位到高位输出。 输入描述 一行,仅含一个正整数 n (1≤n≤109)。 输出描述 从低位到高位输出一个二进制数&a…...
qt vs ios开发应用环境搭建和上架商店的记录
qt 下载链接如下 https://download.qt.io/new_archive/qt/5.14/5.14.2/qt-opensource-mac-x64-5.14.2.dmg 安装选项全勾选就行,这里特别说明下qt5.14.2/qml qt5.14.2对qml支持还算成熟,但很多特性还得qt6才行,这里用qt5.14.2主要是考虑到服…...
安全测评主要标准
大家读完觉得有帮助记得关注和点赞!!! 安全测评的主要标准包括多个国际和国内的标准,这些标准为信息系统和产品的安全评估提供了基础和指导。 一、安全测评的主要标准 1.1、国际标准 可信计算机系统评估准则(TC…...
如何学习数学 | 数学家如何思考
学习数学的关键在哪里? 原创 遇见数学 不少人面对数学都会觉得高深莫测,甚至非常枯燥乏味。 只有当你真正走入它的世界,才会发现里面蕴含着无尽的智慧和美感。要想推开这座数学的大门,需要的不仅仅是背公式,或者做一…...
职场沟通与行为
职场沟通与行为 引言 在职场上,你是否曾遇到过困惑的沟通?是否对同事的行为有过疑虑?这不仅是个别现象,而是我们这个时代工作文化中的普遍问题。许多职场的摩擦,来自沟通不畅或是行为不当。那么,如何才能…...
IIO(Industrial I/O)驱动介绍
文章目录 IIO(Industrial I/O)驱动是Linux内核中用于工业I/O设备的子系统,主要用于处理传感器数据采集和转换。以下是其关键点: 功能 数据采集:从传感器读取数据。数据处理:对原始数据进行滤波、校准等操作…...
关于vite+vue3+ts项目中env.d.ts 文件详解
env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示,特别是在使用一些特定于 Vite 的功能时(如 import.meta.env)。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…...
32单片机综合应用案例——物联网(IoT)环境监测站(四)(内附详细代码讲解!!!)
无论你身处何种困境,都要坚持下去,因为勇气和毅力是成功的基石。不要害怕失败,因为失败并不代表终结,而是为了成长和进步。相信自己的能力,相信自己的潜力,相信自己可以克服一切困难。成功需要付出努力和坚…...
【Flink系列】6. Flink中的时间和窗口
6. Flink中的时间和窗口 在批处理统计中,我们可以等待一批数据都到齐后,统一处理。但是在实时处理统计中,我们是来一条就得处理一条,那么我们怎么统计最近一段时间内的数据呢?引入“窗口”。 所谓的“窗口”ÿ…...
代码随想录算法训练营第三十五天-动态规划-01背包(二维)
动规五部曲 dp数组的含义,注意这是一个二维数组。dp[i][j] 第一维度代表“从0到第i个物品,而且包括选或不选的情况,即这一维度代表物品编号第二维度代表代表背包容量合在一起的意思是当背包容量是j时,从0到i个物品中选择任意物品…...
快速开发:用AI构造AI —— 打造属于个人的Copilot(M-聪明AI)
作品简介: 当今快速发展的AI时代,学会使用AI的同时,也可以融入AI,来打造自己的产品,我给我这个取名M-聪明, 是基于VUE 3 Spring Boot -Redis ChatGML RxJava SSE 的AI 服务平台。然后这款工具旨在为用户…...
Elasticsearch容器启动报错:AccessDeniedException[/usr/share/elasticsearch/data/nodes];
AccessDeniedException 表明 Elasticsearch 容器无法访问或写入数据目录 /usr/share/elasticsearch/data/nodes。这是一个权限问题。 问题原因: 1、宿主机目录权限不足:映射到容器的数据目录 /data/es/data 在宿主机上可能没有足够的权限供容器访问。 …...
用公网服务器实现内网穿透
首先需要一个公网服务器 下载frp 搜索github下载到frp,服务端frps/客户端frpc。。下载的时候要注意自己本地内网机的cpu版本和服务端cpu架构 我的电脑是mac M1PRO版本 下载的是:darwinarm64 比如 服务端一般是Linux(Intel 64位CPU…...
Jmeter如何进行多服务器远程测试
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 JMeter是Apache软件基金会的开源项目,主要来做功能和性能测试,用Java编写。 我们一般都会用JMeter在本地进行测试,但是受到单…...
前端实习第二个月小结
时间飞快,第一次实习已经过去两个多月,作一些简单的总结和分享。 注:文章整体会比较轻松,提及的经历、经验仅作参考。 一、关于实习/工作内容 1、工作内容 近期做的是管理后台方面的业务,技术栈:前端re…...
C# 并发和并行的区别--16
目录 并发和并行 一.并发 定义 特点 代码示例 代码解释 二.并行 定义 特点 在C#中的体现 代码示例 代码解释 三.并发和并行的区别 四 .如何在C#中选择并发还是并行 1.考虑任务类型 2.代码示例 3.注意事项 五.总结 并发和并行 在编程领域,并发和并行是两个密切…...
Python编程与在线医疗平台数据挖掘与数据应用交互性研究
一、引言 1.1 研究背景与意义 在互联网技术飞速发展的当下,在线医疗平台如雨后春笋般涌现,为人们的就医方式带来了重大变革。这些平台打破了传统医疗服务在时间和空间上的限制,使患者能够更加便捷地获取医疗资源。据相关报告显示,中国基于互联网的医疗保健行业已进入新的…...
HBase实训:纸币冠字号查询任务
一、实验目的 1. 理解分布式数据存储系统HBase的架构和工作原理。 2. 掌握HBase表的设计原则,能够根据实际业务需求设计合理的表结构。 3. 学习使用HBase Java API进行数据的插入、查询和管理。 4. 实践分布式数据存储系统在大数据环境下的应用,…...
Java 读取 Windows 设备的唯一性标识及定位
在 Windows 系统中,获取设备唯一性标识及定位信息对设备管理、安全监控等场景意义重大。本文介绍 Java 中几种实现方法,如 JNA 库、WMI4Java 库及通过 JNI 结合 Windows API。 1. 使用 JNA 库读取 DEVPKEY_Device_ContainerId 在 Windows 系统中&…...
UE控件学习
ListView: item设置:使能在list设置为Entry类 Grid Panel: 常用作背包,每个格子大小可不相同 WidgetSwitcher: 用于切换页签 Wrap_Box: 自动横向排版子节点,超过一定范围则自动换行…...
1.Spring AI 从入门到实践
Spring AI 从入门到实践 1.什么是Spring AI 2.使用Spring Boot&Spring AI快速构建AI应用程序 3.ChatClient&Chat Model简化与AI模型的交互 4.Spring AI Prompt:与大模型进行有效沟通 5.结构化输出大模型响应 6.实战:AI聊天机器人 Ben技术站关注Java技术&#x…...
2025年01月蓝桥杯Scratch1月stema选拔赛真题—美丽的图形
美丽的图形 编程实现美丽的图形具体要求: 1)点击绿旗,角色在舞台中心,如图所示; 2)1秒后,绘制一个边长为 140的红色大正方形,线条粗细为 3,正方形的中心为舞台中心,如图所示; 完整题目可点击下…...
FLASK创建下载
html用a标签 <!-- Button to download the image --> <a href"{{ url_for(download_file, filenameimage.png) }}"><button>Download Image</button> </a> 后端:url_for双大括号即是用来插入变量到模板中的语法。也就是绑…...
LDD3学习7--硬件接口I/O端口(以short为例)
1 理论 1.1 基本概念 目前对外设的操作,都是通过寄存器。寄存器的概念,其实就是接口,访问硬件接口,有I/O端口通信和内存映射I/O (Memory-Mapped I/O),I/O端口通信是比较老的那种,都是老的串口并口设备&am…...
MySQL(高级特性篇) 06 章——索引的数据结构
一、为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构,就好比一本教科书的目录部分,通过目录找到对应文章的页码,便可快速定位到需要的文章。MySQL中也是一样的道理,进行数据查找时,首先查看查询条件…...
【FlutterDart】MVVM(Model-View-ViewModel)架构模式例子-http版本(30 /100)
动图更精彩 MVVM(Model-View-ViewModel) 特点 Model:负责数据管理和业务逻辑。 View:负责显示数据,通常是一个UI组件。 ViewModel:负责处理用户交互,更新Model,并将数据转换为View可…...
光谱相机的光谱分辨率可以达到多少?
多光谱相机 多光谱相机的光谱分辨率相对较低,波段数一般在 10 到 20 个左右,光谱分辨率通常在几十纳米到几百纳米之间,如常见的多光谱相机光谱分辨率为 100nm 左右。 高光谱相机 一般的高光谱相机光谱分辨率可达 2.5nm 到 10nm 左右&#x…...
.Net8 Avalonia跨平台UI框架——<vlc:VideoView>控件播放海康监控、摄像机视频(Windows / Linux)
一、UI效果 二、新建用户控件:VideoViewControl.axaml 需引用:VideoLAN.LibVLC.Windows包 Linux平台需安装:VLC 和 LibVLC (sudo apt-get update、sudo apt-get install vlc libvlccore-dev libvlc-dev) .axaml 代码 注…...
【论文阅读】基于空间相关性与Stacking集成学习的风电功率预测方法
文章目录 摘要0. 引言1. 空间相关性分析2. 风电功率预测模型2.1 Stacking 集成策略2.2 基学习器2.2.1 基于机器学习算法的基学习器2.2.2 基于神经网络的基学习器2.2.3 基于粒子群优化算法的超参数优化 2.3 元学习器2.4 基于空间相关性与Stacking集成学习的风电功率预测方法 3 算…...
什么是Spring Boot 应用开发?
一、引言 在当今的软件开发领域,Java 依然占据着重要的地位,而 Spring Boot 作为 Java 生态系统中极具影响力的框架,极大地简化了企业级应用的开发流程,提升了开发效率和应用的可维护性。它基于 Spring 框架构建,通过…...
选择saas 还是源码主要考虑
公司业务规模:小型企业可能会发现SaaS提供的即用型解决方案更符合其需求,而大型企业可能需要源码以实现更高的定制性和控制权。 公司技术专长:缺乏技术团队的企业可能会倾向于使用SaaS,而那些拥有强大IT部门的企业可能更适合管理…...
【JAVA 基础 第(19)课】Hashtable 类用法和注意细节,是Map接口的实现类
Map接口:存放的是具有映射关系的键值对,键映射到值,键必须是唯一的 Hashtable 类,Map接口的实现类,键和值都不能为nullHashtable 是同步的,是线程安全的 public class MapTest {public static void main(String[] arg…...
AI时代下 | 通义灵码冲刺备战求职季
AI时代下 | 通义灵码冲刺备战求职季 什么是通义灵码使用智能编程助手备战求职靠谱吗体验心得 AI时代下,备战求职季有了不一样的方法,使用通义灵码冲刺备战求职季,会有什么样的体验? 什么是通义灵码 在开始话题之前,首…...
如何将 session 共享存储到 redis 中
文章目录 一. 分布式 session 登录1.1 什么是分布式?1.2 Session 共享1.3 为什么服务器 A 登录后,请求发到服务器 B,不认识该用户?1.4 共享存储 二. Session 共享实现Redis三. 测试session共享四. cookie设置4.1 前端4.2 后端 一.…...
智能科技与共情能力加持,哈曼重新定义驾乘体验
2025年1月6日,拉斯维加斯,2025年国际消费电子展——想象一下,当您步入一辆汽车,它不仅能响应您的指令,更能理解您的需求、适应您的偏好,并为您创造一个独特且专属的交互环境。作为汽车科技领域的知名企业和…...
第4章 Kafka核心API——Kafka客户端操作
Kafka客户端操作 一. 客户端操作1. AdminClient API 一. 客户端操作 1. AdminClient API...
Debian 设定 tomcat 定时重启
目录 背景 过程记录 1、编辑sh文件,完成重启功能 2、设置sh的可执行权限 编辑 3、设置定时任务 背景 在Debian 12系统中,原本部署了两个tomcat,结果总是遇到CPU飙升到影响应用正常使用的程度,找了很久原因还是没有找到。 …...
mysql8.0 重要指标参数介绍
MySQL 8.0 引入了许多新的功能和优化,针对性能、可扩展性、可靠性以及安全性方面做出了显著改进。为了确保 MySQL 的高效运行,了解和配置 MySQL 的一些关键指标参数非常重要。以下是 MySQL 8.0 中的一些重要参数和指标,帮助你优化数据库性能。…...
SpringMVC (2)
目录 1. RequestMapping 注解介绍 2. RequestMapping 使用 3. RequestMapping与请求方式 3.1 RequestMapping 支持Get和Post类型的请求 3.2 RequestMapping 指定接收某种请求 3.3 GetMapping和PostMapping 4. 传参 4.1 通过查询字符串传参 4.2 在 Body 中传参 4.2.1 …...
【全面解析】深入解析 TCP/IP 协议:网络通信的基石
深入解析 TCP/IP 协议:网络通信的基石 导语 你是否曾好奇,现代互联网是如何实现全球设备之间的高速、稳定和可靠通信的?无论是浏览网页、发送电子邮件,还是进行视频通话,背后都离不开 TCP/IP 协议 的支撑。作为互联网…...
图数据库 | 19、高可用分布式设计(下)
相信大家对分布式系统设计与实现的复杂性已经有了一定的了解,本篇文章对分布式图数据库系统中最复杂的一类系统架构设计进行探索,即水平分布式图数据库系统(这个挑战也可以泛化为水平分布式图数据仓库、图湖泊、图中台或任何其他依赖图存储、…...
【2024年华为OD机试】 (C卷,200分)- 反射计数(Java JS PythonC/C++)
一、问题描述 题目解析 题目描述 给定一个包含 0 和 1 的二维矩阵,一个物体从给定的初始位置出发,在给定的速度下进行移动。遇到矩阵的边缘时会发生镜面反射。无论物体经过 0 还是 1,都不影响其速度。请计算并给出经过 t 时间单位后&#…...