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

BGE-M3模型结合Milvus向量数据库强强联合实现混合检索

在基于生成式人工智能的应用开发中,通过关键词或语义匹配的方式对用户提问意图进行识别是一个很重要的步骤,因为识别的精准与否会影响后续大语言模型能否检索出合适的内容作为推理的上下文信息(或选择合适的工具)以给出用户最符合预期的回答。

在本篇文章中,我将尽可能详细地介绍想达成准确识别用户提问意图的解决方案之一,即基于功能强大的BGE-M3模型和Milvus向量数据库实现混合检索(稠密向量 dense vector 和 稀疏向量 sparse vector)。

下面会先对混合检索,BGE-M3以及Milvus向量数据库做一个介绍,后面再对BGE-M3官方提供的使用Milvus的示例代码进行讲解,并基于自定义数据进行混合检索的实验效果进行呈现和分析。

何为混合检索

其实就是将多种单一检索技术结合起来使用的一种检索方式,目的是充分利用不同检索技术各自的优势,以达到更好的检索效果。接下来介绍两种比较常用的检索技术,嵌入检索(稠密检索)和 以BM25算法为代表的稀疏检索

嵌入检索 (embedding retrieval)

指的是使用稠密向量(dense vector)表示来进行信息检索的方法。

稠密向量有以下特点:

  1. 向量中大部分元素非零,是高维的实数向量,通常由深度学习模型生成;
  2. 重点在于向量空间中的相似性计算,一般使用余弦相似度、点积等计算方法。这允许语义上相似的文本可以被较好理解,即使它们的词语重叠较少;
  3. 能够捕捉文本的语义信息,而不是仅仅匹配关键词,但计算成本较高,需要更强大的计算资源。
稀疏检索 (sparse retrieval)

指的是使用稀疏向量(sparse vector)表示来进行信息检索的方法。

稀疏向量有以下特点:

  1. 通常由词袋模型 (Bag-of-Words, BoW)、TF-IDF 等传统方法生成,向量维度通常对应词汇表中的词语,其值表示词频或 TF-IDF 权重,向量中大部分元素为零;
  2. 主要基于关键词匹配,使用余弦相似度等方法计算向量之间的相似性;
  3. 计算效率高,对语义理解能力有限。

区别总结(Gemini 1.5 Flash回答):

特性嵌入检索稀疏检索
向量表示稠密向量 (dense vector)稀疏向量 (sparse vector)
表示方法使用深度学习模型生成使用词袋模型 (BoW)、TF-IDF 等传统方法生成
捕捉信息语义信息关键词信息
计算复杂度
应用场景语义搜索,问答系统基于关键词的搜索引擎

总之,嵌入检索和稀疏检索是两种不同的信息检索方法,它们各有优缺点,实际应用中常常结合使用,形成混合检索系统,以达到更好的检索效果。

BGE-M3 模型

BAAI/bge-m3 是一个由北京人工智能研究院(BAAI)开源的嵌入模型,主要用于生成文本嵌入(text embeddings)。它是一个多功能、多语言、多粒度的模型。M3指的就是多功能性(Multi-Functionality)、多语言性(Multi-Linguality)和多粒度(Multi-Granularity)。

  1. 多功能性 (Multi-Functionality): 该模型可以同时执行嵌入式模型的三个常见检索功能:稠密检索、多向量检索和稀疏检索。这意味着它能够灵活地应对不同的检索需求,并结合不同检索方法的优势。

  2. 多语言性 (Multi-Linguality): 该模型支持100多种语言。 这意味着它可以处理多种语言的文本,并进行跨语言检索。

  3. 多粒度性 (Multi-Granularity): 该模型能够处理不同粒度的输入,从短句到长达8192个词元的长文档。 这意味着它可以处理各种长度的文本,而不会受到输入长度的限制。

Milvus开源向量数据库介绍

官网介绍:https://milvus.io/intro

Github: https://github.com/milvus-io/milvus

Milvus 是一个以高效检索和高扩展性为特点的开源向量数据库,支持对大量的非结构化数据(如文本,图像还有多模态数据信息等)进行组织和检索。

Milvus 使用 GoC++ 编程语言开发实现, 并通过CPU/GPU指令级优化,以实现最佳的向量搜索性能。

Milvus 提供多种本地部署方式,以适应不同规模和需求的应用场景(引导Gemini 1.5 Flash回答如下):

1. 基于 Kubernetes (K8s) 的全分布式架构:

  • 适用场景: 处理数万甚至数十万每秒查询请求,向量数据规模达到数十亿级别的大规模应用。需要高可扩展性和实时数据更新能力。
  • 关键特性: 水平扩展性强,高可用性,实时数据处理。
  • 主要差异: 部署最复杂,但性能和可扩展性最高。需要预先配置好 Kubernetes 集群。

安装部署参考:官方文档

2. 单机模式 (Docker或者Docker Compose):

  • 适用场景: 小型应用、测试、开发和概念验证项目。相比全分布式模式,部署更简单。
  • 关键特性: 使用 Docker 简化部署。适用于单节点环境。
  • 主要差异: 可扩展性比分布式模式低。不适合高吞吐量或大型数据集。

安装部署参考:官方文档

3. Milvus Lite:

  • 适用场景: 快速入门、学习和小型实验项目,尤其是在 Python 环境中。强调易用性和极简的设置。
  • 关键特性: 通过 pip install 命令轻松安装。轻量级,快速上手。
  • 主要差异: 可扩展性和功能最受限制。主要用于学习和原型设计,不适合生产环境部署或大型数据集。

安装部署参考:官方文档

总结表格:

部署模式可扩展性数据规模实时更新部署复杂度使用场景
基于 K8s 的全分布式架构数十亿大规模生产环境,高吞吐量
单机模式 (Docker)中等是 (受限)中等小型应用,测试,开发
Milvus Lite极低小型极低快速入门,学习,小型原型设计

简而言之,选择哪种部署模式取决于应用的规模和需求。对于海量数据集和高查询量,基于 Kubernetes 的部署是必要的。对于小型需求,单机模式或 Milvus Lite 提供更简单快速的设置。

本地实验前准备

下载 BGE-M3
git lfs install
git clone https://huggingface.co/BAAI/bge-m3

模型大小 total 2.2G

以Docker Compose方式部署Milvus & 下载 pymilvus 和 FlagEmbedding

在后续结合bge-m3模型实现基于语义的混合检索实验中,我们使用docker compose安装部署Milvus的方式,并搭配 pymilvus 第三方python库进行使用。

官方文档:Run Milvus with Docker Compose

运行命令如下

# 安装
wget https://github.com/milvus-io/milvus/releases/download/v2.5.0-beta/milvus-standalone-docker-compose.yml -O docker-compose.yml
# 运行
sudo docker-compose up -d
# 终端显示
Creating milvus-etcd  ... done
Creating milvus-minio ... done
Creating milvus-standalone ... done

pymilvus和FlagEmbedding(此库方便我们加载bge模型)安装命令:

pip install -U pymilvus
pip install -U FlagEmbedding
数据准备

因为我后期想搭一个基于提问内容自动匹配合适的api去调用并将返回结果作为大语言模型推理上下文信息的问答机器人小应用,所以我准备了对不同api调用功能目进行描述的几条**中文**短文本作为检索知识库内容。

我在聚合数据平台申请了三个api,分别是:

  1. 黄金数据:提供黄金品种查询服务,支持黄金现货、黄金期货等品种查询;提供黄金价格查询服务,支持查询最新价、开盘价、最高价、最低价等价格信息。
  2. 股票数据:根据股票编号查询股票信息,包括涨跌额、股票名称、开盘价、收盘价、当前价格、最高最低价、竞买价等信息;支持沪深、香港、美国三个市场的股票数据查询,覆盖全球各地的股票信息。
  3. 新闻头条:提供最新的新闻头条信息,包括国内、国际、体育、娱乐、科技等各类资讯,让用户获取及时的新闻报道;支持按照不同的新闻分类进行查询,用户可以选择感兴趣的领域,如体育、科技、娱乐等,获取相关的新闻内容。

根据api的功能描述,建立检索知识库列表如下:

docs = ["提供黄金品种查询服务,支持黄金现货、黄金期货等品种查询;提供黄金价格查询服务,支持查询最新价、开盘价、最高价、最低价等价格信息。","根据股票编号查询股票信息,包括涨跌额、股票名称、开盘价、收盘价、当前价格、最高最低价、竞买价等信息;支持沪深、香港、美国三个市场的股票数据查询,覆盖全球各地的股票信息。","提供最新的新闻头条信息,包括国内、国际、体育、娱乐、科技等各类资讯,让用户获取及时的新闻报道;支持按照不同的新闻分类进行查询,用户可以选择感兴趣的领域,如体育、科技、娱乐等,获取相关的新闻内容。"]

代码实现

Milvus team 提供了使用 bge-m3 模型生成稀疏&稠密向量搭配Milvus向量数据库实现混合检索的示例代码,本次实验将以该代码作为参考,在其基础上进行适当修改调整。

  1. 导入相关库;(本次实验不试用reranker进行精筛所以 use_reranker 设置为 False
# A demo showing hybrid semantic search with dense and sparse vectors using Milvus.
#
# You can optionally choose to use the BGE-M3 model to embed the text as dense
# and sparse vectors, or simply use random generated vectors as an example.
#
# You can also use the BGE CrossEncoder model to rerank the search results.
#
# Note that the sparse vector search feature is only available in Milvus 2.4.0 or
# higher version. Make sure you follow https://milvus.io/docs/install_standalone-docker.md
# to set up the latest version of Milvus in your local environment.# To connect to Milvus server, you need the python client library called pymilvus.
# To use BGE-M3 model, you need to install the optional `model` module in pymilvus.
# You can get them by simply running the following commands:
#
# pip install pymilvus
# pip install pymilvus[model]# If true, use BGE-M3 model to generate dense and sparse vectors.
# If false, use random numbers to compose dense and sparse vectors.
use_bge_m3 = True
# If true, the search result will be reranked using BGE CrossEncoder model.
use_reranker = False# The overall steps are as follows:
# 1. embed the text as dense and sparse vectors
# 2. setup a Milvus collection to store the dense and sparse vectors
# 3. insert the data to Milvus
# 4. search and inspect the result!
import random
import string
import numpy as npfrom FlagEmbedding import BGEM3FlagModelfrom pymilvus import (utility,FieldSchema, CollectionSchema, DataType,Collection, AnnSearchRequest, RRFRanker, connections, WeightedRanker
)
  1. 指定bge-m3模型路径并以fp32精度(全精度浮点数)加载模型;
model_dir = "bge-m3"
model = BGEM3FlagModel(model_dir) 
  1. 定义检索文本内容列表和用户提问示例;
docs = ["提供黄金品种查询服务,支持黄金现货、黄金期货等品种查询;提供黄金价格查询服务,支持查询最新价、开盘价、最高价、最低价等价格信息。","根据股票编号查询股票信息,包括涨跌额、股票名称、开盘价、收盘价、当前价格、最高最低价、竞买价等信息;支持沪深、香港、美国三个市场的股票数据查询,覆盖全球各地的股票信息。","提供最新的新闻头条信息,包括国内、国际、体育、娱乐、科技等各类资讯,让用户获取及时的新闻报道;支持按照不同的新闻分类进行查询,用户可以选择感兴趣的领域,如体育、科技、娱乐等,获取相关的新闻内容。"
]
# 用户提问示例
query = "请问黄金品种AU99.99价格如何?"
  1. 将检索文本列表编码为稀疏和稠密向量;
passage_embeddings = model.encode(docs, return_dense=True, return_sparse=True, return_colbert_vecs=False)

passage_embeddings 变量打印出来看看

{'dense_vecs': array([[-0.05132515,  0.0243751 , -0.06081232, ..., -0.03952702,0.02319626, -0.03473093],[-0.07099452, -0.01123387, -0.05009558, ..., -0.00663427,0.05279079,  0.01525173],[-0.03272525, -0.00253467, -0.04763371, ..., -0.00828949,0.0147302 , -0.05601017]], dtype=float32), 'lexical_weights': [defaultdict(<class 'int'>, {'6': 0.20276982, '2212': 0.17947777, '78563': 0.27358395, '182114': 0.24308087, '115106': 0.25357044, '3367': 0.19385284, '4': 0.17282556, '7499': 0.17129068, '15895': 0.11740263, '24781': 0.07431586, '153133': 0.18931584, '844': 0.06803232, '74': 0.10644381, '16806': 0.14869832, '16677': 0.054120254, '14498': 0.116243124, '4185': 0.07396346, '27964': 0.13261327, '37': 0.056129213, '14812': 0.059598763, '36315': 0.082842745, '5412': 0.09079999, '30': 0.011220258}), defaultdict(<class 'int'>, {'80476': 0.13337892, '50653': 0.23055996, '30862': 0.24856994, '5730': 0.24488933, '115106': 0.2854578, '5412': 0.22158799, '4': 0.17879836, '5384': 0.09052652, '85266': 0.091248944, '44040': 0.12723388, '22878': 0.106443286, '37': 0.06931204, '108279': 0.10546562, '4185': 0.05373253, '27964': 0.12790793, '14498': 0.093488105, '6633': 0.05225729, '36563': 0.106637016, '16806': 0.10283494, '14812': 0.045356337, '36315': 0.081632964, '97954': 0.14599079, '11795': 0.08332152, '844': 0.018887743, '74': 0.1779946, '7499': 0.18943872, '206056': 0.08312804, '6728': 0.12673198, '6665': 0.11565392, '3893': 0.115120836, '41953': 0.10232154, '60114': 0.1253739, '12833': 0.22091916, '78868': 0.14010657, '7153': 0.11074717, '40727': 0.100175254, '43': 0.08830682, '30': 0.025547896}), defaultdict(<class 'int'>, {'6': 0.21939242, '2212': 0.21460007, '110004': 0.16313581, '21606': 0.2181344, '3878': 0.15887201, '7781': 0.21819039, '5412': 0.19437945, '4': 0.15980814, '5384': 0.13158405, '13853': 0.108550005, '5559': 0.08813208, '28788': 0.17125762, '23942': 0.15054022, '7355': 0.15029378, '844': 0.0729285, '62335': 0.095689975, '144343': 0.23023936, '3933': 0.0954708, '10501': 0.16799492, '95579': 0.13417137, '32292': 0.12720525, '27835': 0.17556949, '74': 0.18231188, '7499': 0.20008457, '17236': 0.10246284, '13647': 0.12076213, '136229': 0.2379455, '115106': 0.23003161, '1441': 0.04709647, '8827': 0.11257933, '123701': 0.1811453, '17010': 0.15106374, '3322': 0.003149774, '84492': 0.07179478, '8105': 0.079666495, '30': 0.075698406})], 'colbert_vecs': None}

passage_embeddings 变量是一个dict数据结构,有三个key值,分别是 dense_vecs, lexical_weights, colbert_vecs

passage_embeddings.keys()
# dict_keys(['dense_vecs', 'lexical_weights', 'colbert_vecs'])
passage_embeddings["dense_vecs"].shape
# (3, 1024) 3x1024维的一个dense vector
passage_embeddings["lexical_weights"]
# 生成的稀疏向量,sparse vector,存在一个list当中,有三个元素,元素类型是 collections.defaultdict
passage_embeddings["colbert_vecs"]
# colbert_vecs 这个Multi-Vector没生成,所以对应的值为 None
  1. 将用户提问 query 编码为稀疏和稠密向量;
query_embeddings_raw = model.encode([query], return_dense=True, return_sparse=True, return_colbert_vecs=False)
  1. 连接 Milvus(确保docker compose是up的状态)并创建 collection和index;
connections.connect("default", host="localhost", port="19530")
# 列出当前所有collection
utility.list_collections()
# 输出显示为空列表

基于schema创建一个新的名为 hybrid_demo 的collection

# Specify the data schema for the new Collection.
fields = [# Use auto generated id as primary keyFieldSchema(name="pk", dtype=DataType.VARCHAR,is_primary=True, auto_id=True, max_length=100),# Store the original text to retrieve based on semantically distanceFieldSchema(name="text", dtype=DataType.VARCHAR, max_length=512),# Milvus now supports both sparse and dense vectors, we can store each in# a separate field to conduct hybrid search on both vectors.FieldSchema(name="sparse_vector", dtype=DataType.SPARSE_FLOAT_VECTOR),# 注意这个的dim要和dense vector的维度保持一致,即1024# 注意dtype也是要和dense vector的精度保持一致,即fp32FieldSchema(name="dense_vector", dtype=DataType.FLOAT_VECTOR,dim=1024),
]
schema = CollectionSchema(fields, "")
col_name = 'hybrid_demo'
# Now we can create the new collection with above name and schema.
col = Collection(col_name, schema, consistency_level="Strong")

接着我们需要为每一个向量字段创建index,创建的indices会被加载到内存中以实现高效检索。

# We need to create indices for the vector fields. The indices will be loaded into memory for efficient search.
sparse_index = {"index_type": "SPARSE_INVERTED_INDEX", "metric_type": "IP"}
col.create_index("sparse_vector", sparse_index)
dense_index = {"index_type": "FLAT", "metric_type": "IP"}
col.create_index("dense_vector", dense_index)
col.load()
  1. 将生成的表示检索文本内容的稀疏&稠密向量加入到创建的collection中;
docs_embeddings = {}
docs_embeddings["dense"] = passage_embeddings["dense_vecs"]
docs_embeddings["sparse"] = passage_embeddings["lexical_weights"]
# 3. insert text and sparse/dense vector representations into the collection
entities = [docs, docs_embeddings["sparse"], docs_embeddings["dense"]]
col.insert(entities)
col.flush()
  1. 开始混合检索
query_embeddings = {}
query_embeddings["dense"] = query_embeddings_raw["dense_vecs"]
query_embeddings["sparse"] = [dict(query_embeddings_raw["lexical_weights"][0])]

因为检索文档数量较少只有三条,所以top k中k的值设置为1

# 4. search and inspect the result!
k = 1 # we want to get the top 1 docs closest to the query# Prepare the search requests for both vector fields
sparse_search_params = {"metric_type": "IP"}
sparse_req = AnnSearchRequest(query_embeddings["sparse"],"sparse_vector", sparse_search_params, limit=k)
dense_search_params = {"metric_type": "IP"}
dense_req = AnnSearchRequest(query_embeddings["dense"],"dense_vector", dense_search_params, limit=k)# Search topK docs based on dense and sparse vectors and rerank with RRF.
res = col.hybrid_search([sparse_req, dense_req], rerank=RRFRanker(),limit=k, output_fields=['text'])# Currently Milvus only support 1 query in the same hybrid search request, so
# we inspect res[0] directly. In future release Milvus will accept batch
# hybrid search queries in the same call.
res = res[0]

打印出最为匹配的文档内容,检索正确:

print(res)
["id: 454220910858869856, distance: 0.032786883413791656, entity: {'text': '提供黄金品种查询服务,支持黄金现货、黄金期货等品种查询;提供黄金价格查询服务,支持查询最新价、开盘价、最高价、最低价等价格信息。'}"]

再试两个query:

Query 一:

query = "请问科技圈发生了什么热点事件?"
print(res)
["id: 454220910858869858, distance: 0.032786883413791656, entity: {'text': '提供最新的新闻头条信息,包括国内、国际、体育、娱乐、科技等各类资讯,让用户获取及时的新闻报道;支持按照不同的新闻分类进行查询,用户可以选择感兴趣的领域,如体育、科技、娱乐等,获取相关的新闻内容。'}"]

Query 二:

query = "请问股票代码为CSCO的美股今日走势如何?"
print(res)
["id: 454220910858869857, distance: 0.032786883413791656, entity: {'text': '根据股票编号查询股票信息,包括涨跌额、股票名称、开盘价、收盘价、当前价格、最高最低价、竞买价等信息;支持沪深、香港、美国三个市场的股票数据查询,覆盖全球各地的股票信息。'}"]

效果还是不错的。

相关文章:

BGE-M3模型结合Milvus向量数据库强强联合实现混合检索

在基于生成式人工智能的应用开发中&#xff0c;通过关键词或语义匹配的方式对用户提问意图进行识别是一个很重要的步骤&#xff0c;因为识别的精准与否会影响后续大语言模型能否检索出合适的内容作为推理的上下文信息&#xff08;或选择合适的工具&#xff09;以给出用户最符合…...

鸿蒙NEXT开发案例:文字转拼音

【引言】 在鸿蒙NEXT开发中&#xff0c;文字转拼音是一个常见的需求&#xff0c;本文将介绍如何利用鸿蒙系统和pinyin-pro库实现文字转拼音的功能。 【环境准备】 • 操作系统&#xff1a;Windows 10 • 开发工具&#xff1a;DevEco Studio NEXT Beta1 Build Version: 5.0.…...

CTF之密码学(栅栏加密)

栅栏密码是古典密码的一种&#xff0c;其原理是将一组要加密的明文划分为n个一组&#xff08;n通常根据加密需求确定&#xff0c;且一般不会太大&#xff0c;以保证密码的复杂性和安全性&#xff09;&#xff0c;然后取每个组的第一个字符&#xff08;有时也涉及取其他位置的字…...

修改插槽样式,el-input 插槽 append 的样式

需缩少插槽 append 的 宽度 方法1、使用内联样式直接修改&#xff0c;指定 width 为 30px <el-input v-model"props.applyBasicInfo.outerApplyId" :disabled"props.operateCommandType input-modify"><template #append><el-button click…...

UPLOAD LABS | PASS 01 - 绕过前端 JS 限制

关注这个靶场的其它相关笔记&#xff1a;UPLOAD LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;过关流程 本关的目标是上传一个 WebShell 到目标服务器上&#xff0c;并成功访问&#xff1a; 我们直接尝试上传后缀为 .php 的一句话木马&#xff1a; 如上&#xff0c;靶场弹…...

【css实现收货地址下边的平行四边形彩色线条】

废话不多说&#xff0c;直接上代码&#xff1a; <div class"address-block" ><!-- 其他内容... --><div class"checked-ar"></div> </div> .address-block{height:120px;position: relative;overflow: hidden;width: 500p…...

缓存方案分享

不知道大家平常更新缓存是怎么做的&#xff0c;但是大部分时候都是更新数据的同时更新缓存&#xff0c;今天和同事一起聊到一个缓存方案的问题&#xff0c;感觉很有趣、非常精妙&#xff0c;记录一下。 基于此本文将介绍几种常见的缓存更新策略&#xff0c;包括简单的缓存覆盖…...

第四十篇 DDP模型并行

摘要 分布式数据并行(DDP)技术是深度学习领域中的一项重要技术,它通过将数据和计算任务分布在多个计算节点上,实现了大规模模型的并行训练。 DDP技术的基本原理是将数据和模型参数分割成多个部分,每个部分由一个计算节点负责处理。在训练过程中,每个节点独立计算梯度,…...

软件测试面试之常规问题

1.描述一下测试过程 类似题目:测试的生命周期 思路:这是一个“范围”很大的题目&#xff0c;而且回答时间一般在3分钟之内&#xff0c;不可能非常详细的描述整个过程&#xff0c;因此答题的思路要从整体结构入手&#xff0c;不要过细。为了保证答案的准确性&#xff0c;可以引…...

《图像形态学运算全解析:原理、语法及示例展示》

简介&#xff1a; 本文详细介绍了图像形态学中的多种运算&#xff0c;包括腐蚀、膨胀、开运算、闭运算、形态学梯度运算、礼帽运算以及黑帽运算。分别阐述了各运算的原理、语法格式&#xff0c;并通过 Python 代码结合具体示例图片&#xff08;如erode.JPG、dilate.JPG、close.…...

双十一线上服务调用链路追踪SkyWalking实战分析

序言 随着电商行业的飞速发展&#xff0c;双十一购物节已成为全球最大的购物狂欢节之一。在双十一期间&#xff0c;电商平台需要处理海量的用户请求和订单&#xff0c;这对系统的稳定性和性能提出了极高的要求。为了确保系统在高并发环境下的稳定运行&#xff0c;对线上服务的…...

网络安全究竟是什么? 如何做好网络安全

网络安全是如何工作的呢? 网络安全结合多层防御的优势和网络。每个网络安全层实现政策和控制。授权用户访问网络资源,但恶意参与者不得进行攻击和威胁。 我如何受益于网络安全? 数字化改变了我们的世界。我们的生活方式、工作、玩耍,和学习都发生了变化。每个组织希望提供…...

【C++】入门【一】

本节目标 一、C关键字&#xff08;C98&#xff09; 二、命名空间 三、C的输入输出 四、缺省函数 五、函数重载 六、引用 七、内联函数 八、auto关键字&#xff08;C11&#xff09; 九、范围for&#xff08;C11&#xff09; 十、指针空值nullptr&#xff08;C11&#xff09; 一.…...

【ArcGIS Pro实操第11期】经纬度数据转化成平面坐标数据

经纬度数据转化成平面坐标数据 数据准备ArcGIS操作步骤-投影转换为 Sinusoidal1 投影2 计算几何Python 示例 另&#xff1a;Sinusoidal (World) 和 Sinusoidal (Sphere) 的主要区别参考 数据准备 数据投影&#xff1a; 目标投影&#xff1a;与MODIS数据相同&#xff08;Sinu…...

python学opencv|读取图像

【1】引言 前序学习了使用matplotlib模块进行画图&#xff0c;今天开始我们逐步尝试探索使用opencv来处理图片。 【2】学习资源 官网的学习链接如下&#xff1a; OpenCV: Getting Started with Images 不过读起来是英文版&#xff0c;可能略有难度&#xff0c;所以另推荐一…...

ffmpeg RTP PS推流

要实现 CRtpSendPs 类&#xff0c;使其能够将 H264 数据通过 RTP PS 流推送到指定的 URL&#xff0c;并支持 TCP 和 UDP 传输方式&#xff0c;您需要使用 FFmpeg 库。以下是该类的实现示例&#xff0c;包括必要的初始化、推流和退出函数。 步骤 初始化 FFmpeg 库&#xff1a;…...

Rust语言俄罗斯方块(漂亮的界面案例+详细的代码解说+完美运行)

tetris-demo A Tetris example written in Rust using Piston in under 500 lines of code 项目地址: https://gitcode.com/gh_mirrors/te/tetris-demo 项目介绍 "Tetris Example in Rust, v2" 是一个用Rust语言编写的俄罗斯方块游戏示例。这个项目不仅是一个简单…...

NUMA架构及在极速网络IO场景下的优化实践

NUMA技术原理 NUMA架构概述 随着多核CPU的普及&#xff0c;传统的对称多处理器&#xff08;SMP&#xff09;架构逐渐暴露出性能瓶颈。为了应对这一问题&#xff0c;非一致性内存访问&#xff08;NUMA, Non-Uniform Memory Access&#xff09;架构应运而生。NUMA架构是一种内存…...

Brain.js 用于浏览器的 GPU 加速神经网络

Brain.js 是一个强大的 JavaScript 库&#xff0c;它允许开发者在浏览器和 Node.js 环境中构建和训练神经网络 。这个库的目的是简化机器学习模型的集成过程&#xff0c;使得即使是没有深厚机器学习背景的开发者也能快速上手 。 概述 Brain.js 提供了易于使用的 API&#xff…...

Linux——用户级缓存区及模拟实现fopen、fweite、fclose

linux基础io重定向-CSDN博客 文章目录 目录 文章目录 什么是缓冲区 为什么要有缓冲区 二、编写自己的fopen、fwrite、fclose 1.引入函数 2、引入FILE 3.模拟封装 1、fopen 2、fwrite 3、fclose 4、fflush 总结 前言 用快递站讲述缓冲区 收件区&#xff08;类比输…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

FFmpeg avformat_open_input函数分析

函数内部的总体流程如下&#xff1a; avformat_open_input 精简后的代码如下&#xff1a; int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...