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

【原创】使用ElasticSearch存储向量实现大模型RAG

一、概述

检索增强生成(Retrieval-Augmented Generation,RAG)已成为大型语言模型(LLM)应用的重要架构,通过结合外部知识库来增强模型的回答能力,特别是在处理专业领域知识、最新信息或企业私有数据时。本报告将系统梳理使用 Elasticsearch(ES)作为向量数据库实现 RAG 系统的优缺点,与传统向量数据库及其他存储解决方案的对比,以及基于 Deepseek V3 和 Qwen2.5 大模型的实现方案。

二、Elasticsearch 作为 RAG 向量数据库的优缺点分析

1. 优点

低门槛的独立技术栈
  • 一站式解决方案:ES 能够一站式完成向量生成、存储、索引和检索,通过配置即可实现大部分功能
  • 成熟的生态系统:作为成熟的搜索引擎,拥有丰富的文档、社区支持和工具集
  • 简化的部署和维护:相比需要部署多个组件的解决方案,ES 可以作为单一系统处理所有 RAG 相关任务
高性能和扩展性
  • 分布式架构:支持百万级 QPS 和千亿级数据量
  • 灵活的扩展能力:可以通过添加节点水平扩展,满足不断增长的数据需求
  • 高可用性:内置的分片和复制机制确保系统的可靠性
混合检索能力
  • 文本与向量的结合:同时支持传统的全文检索和向量相似性搜索
  • 提高检索精度:混合检索策略能够显著提升搜索结果的准确性和多样性
  • 处理短查询优势:对于短查询,传统关键词搜索可以弥补纯向量搜索的不足
丰富的数据处理能力
  • 强大的文本分析:内置多种语言分析器,支持分词、同义词、停用词等处理
  • 结构化和非结构化数据支持:可以同时处理结构化字段和非结构化文本
  • 聚合和分析功能:提供丰富的聚合功能,可用于数据分析和可视化
多种相似度计算算法支持
  • 余弦相似度(Cosine Similarity):适用于文本语义搜索,不受向量长度影响
  • 点积(Dot Product):适用于推荐系统,考虑向量长度和方向
  • 欧几里得距离(L2 Norm):适用于图像特征、地理位置等场景
  • 脚本评分(Script Score):支持自定义脚本实现更复杂的相似度计算
  • 函数评分(Function Score):允许结合衰减函数、字段值等因素调整相似度分数
与大模型的无缝集成
  • 简化的集成流程:提供 API 和工具,便于与各种大模型集成
  • 灵活的检索配置:可以根据不同大模型的特点调整检索策略

2. 不足

向量搜索性能限制
  • 非专用架构:ES 的架构不是专为向量搜索设计的,在大规模向量搜索时性能可能不如专用向量数据库
  • 延迟问题:在大规模向量集上,搜索延迟通常为毫秒级,而专用向量数据库可达微秒级
  • 资源消耗较高:向量操作可能需要更多的内存和计算资源
向量功能相对有限
  • 算法支持有限:支持的向量索引和搜索算法相对较少,主要是 HNSW
  • 缺乏专业优化:缺少针对向量操作的专门优化,如 GPU 加速
  • 向量维度限制:在处理超高维向量时可能存在效率问题
学习和配置复杂性
  • 配置复杂:需要正确配置索引映射、分片策略等
  • 调优难度:优化 ES 性能需要专业知识和经验
  • 维护成本:需要定期维护和监控集群状态
存储效率问题
  • 存储开销:存储向量数据可能需要更多空间
  • 索引大小:包含向量的索引通常比纯文本索引大得多

三、Elasticsearch 向量存储与检索原理

1. 向量数据存储原理

Elasticsearch 使用 dense_vector 字段类型来存储向量数据,其工作原理如下:

基本存储结构
  • 文档结构:向量被存储为文档的一个字段,与其他字段(如文本、数字等)一起构成完整的文档。
  • 向量表示:向量以浮点数数组的形式存储,每个数组元素对应向量的一个维度。
  • 索引映射:通过索引映射定义向量字段的属性,包括维度大小、索引方式和相似度计算方法。

存储过程简述
  1. 1. 向量生成:通过嵌入模型将文本、图像等内容转换为固定维度的向量。

  2. 2. 文档创建:创建包含向量字段的文档,将向量数据与其他元数据一起存储。

  3. 3. 分片分配:ES 将文档分配到不同的分片中,每个分片可以位于不同的节点上。

  4. 4. 磁盘存储:向量数据最终以 Lucene 索引格式存储在磁盘上,同时部分热数据会缓存在内存中。

2. 向量检索原理

Elasticsearch 主要使用 HNSW(Hierarchical Navigable Small World)算法进行向量检索,这是一种近似最近邻(ANN)搜索算法:

HNSW 算法简介
  • 多层图结构:HNSW 构建一个多层的图结构,顶层包含少量节点,底层包含所有节点。
  • 导航原理:搜索从顶层开始,通过"贪心"策略快速找到大致方向,然后在下层进行更精细的搜索。
  • 近似搜索:通过牺牲一定的精确度来换取显著的性能提升。

检索过程
  1. 1. 查询向量生成:将用户查询转换为向量表示。

  2. 2. 分片搜索:在每个相关分片上执行向量搜索。

  3. 3. 相似度计算:根据配置的相似度方法(余弦、点积或 L2 范数)计算查询向量与索引向量的相似度。

  4. 4. 结果合并:将各分片的搜索结果合并,并按相似度排序。

  5. 5. 返回结果:返回最相似的文档作为搜索结果。

性能优化参数
  • ef_construction:构建索引时的精度参数,值越大索引质量越高但构建越慢。
  • ef_search:搜索时的精度参数,值越大搜索结果越精确但速度越慢。
  • m:每个节点的最大连接数,影响图的连通性和搜索效率。

3. 多模态向量存储支持

Elasticsearch 不仅可以存储文本向量,还可以存储来自图片、音频和视频等多模态数据的向量表示:

图像向量存储
  • 实现原理:使用图像嵌入模型(如 ResNet、ViT 等)将图像转换为向量表示。
  • 存储方式:与文本向量相同,使用 dense_vector 字段存储图像向量。
  • 应用场景:图像相似度搜索、以图搜图、视觉内容检索。

音频向量存储
  • 实现原理:使用音频嵌入模型(如 Wav2Vec、CLAP 等)将音频转换为向量表示。
  • 存储方式:同样使用 dense_vector 字段,维度根据音频嵌入模型而定。
  • 应用场景:音乐推荐、语音搜索、音频内容分类。

视频向量存储
  • 实现原理:可以通过两种方式处理:
    1. 将视频分解为关键帧,然后使用图像嵌入模型处理每个关键帧。
    2. 使用专门的视频嵌入模型(如 Video Transformers)直接生成视频向量。
  • 存储方式:可以存储单个视频的整体向量,或者存储多个关键帧的向量序列。
  • 应用场景:视频内容搜索、相似视频推荐、视频分类。

多模态向量存储的简单示例
# 图像向量存储示例
from PIL import Image
from transformers import AutoFeatureExtractor, AutoModel
import torch# 加载图像嵌入模型
image_model = AutoModel.from_pretrained("openai/clip-vit-base-patch32")
feature_extractor = AutoFeatureExtractor.from_pretrained("openai/clip-vit-base-patch32")# 处理图像
image = Image.open("example.jpg")
inputs = feature_extractor(images=image, return_tensors="pt")
with torch.no_grad():image_features = image_model.get_image_features(**inputs)
image_vector = image_features[0].tolist()# 存储到Elasticsearch
doc = {"title": "示例图片","description": "这是一张示例图片","image_path": "example.jpg","image_vector": image_vector  # 使用dense_vector字段存储
}es.index(index="image-vectors", document=doc)

四、Elasticsearch 与其他向量存储解决方案的对比

1. 各向量存储解决方案综合对比

特性ElasticsearchPGVector (PostgreSQL)Redis VectorMongoDB AtlasFAISSMilvusPineconeQdrantChroma
架构类型分布式搜索引擎关系型数据库扩展内存数据库扩展文档数据库扩展库/嵌入式分布式向量数据库托管向量数据库向量数据库嵌入式向量数据库
部署模式自托管/云服务自托管/云服务自托管/云服务自托管/云服务嵌入式自托管/云服务仅云服务自托管/云服务嵌入式/自托管
向量索引算法HNSWHNSW, IVFHNSWHNSWHNSW, IVF, PQ 等多种HNSW, IVF, FLAT 等多种HNSW 变体HNSWHNSW
查询性能毫秒级毫秒级亚毫秒级毫秒级微秒-毫秒级微秒-毫秒级毫秒级毫秒级毫秒级
扩展性优秀有限有限优秀有限优秀优秀良好有限
混合查询原生支持支持 SQL+向量有限支持支持文档+向量不支持支持有限支持支持支持
元数据过滤强大强大(SQL)有限强大(文档查询)有限支持支持支持支持
GPU 加速不支持不支持不支持不支持支持支持内部支持不支持不支持
存储容量TB-PB 级TB 级GB-TB 级TB-PB 级受内存限制TB 级TB 级TB 级GB-TB 级
全文搜索优秀基础良好基础不支持有限不支持有限有限
相似度算法余弦、点积、L2 范数余弦、L2 范数余弦、L2 范数余弦、点积、欧几里得多种(余弦、内积、L2 等)多种(余弦、内积、L2 等)余弦、点积余弦、点积、欧几里得余弦
事务支持有限完整 ACID有限文档级事务不支持有限不支持不支持不支持
易用性中等高(SQL 熟悉度)高(MongoDB 用户)复杂中等简单简单简单
维护成本中等中等低(嵌入式)低(托管)
社区支持强大强大强大强大活跃活跃有限活跃活跃
成本开源,自托管开源,自托管开源+商业版开源+商业版开源,免费开源+商业版商业版,按量付费开源+商业版开源,免费
适用场景混合搜索结构化数据+向量高性能、低延迟半结构化数据+向量高性能向量搜索大规模向量管理简单部署、高可用中小规模应用快速原型开发

2. 不同相似度计算方法对比

相似度方法数学表达式值域适用场景特点支持的存储系统
余弦相似度cos(θ) = A·B / (‖A‖·‖B‖)[-1, 1]文本语义搜索不受向量长度影响,只考虑方向全部
点积A·B = ∑(A_i × B_i)无限制推荐系统考虑向量长度和方向,通常需要归一化ES, MongoDB, FAISS, Milvus, Pinecone, Qdrant
欧几里得距离‖A-B‖ = √(∑(A_i - B_i)²)[0, ∞)图像特征、地理位置值越小表示越相似,需要转换为相似度ES, PGVector, Redis, MongoDB, FAISS, Milvus, Qdrant
曼哈顿距离∑|A_i - B_i|[0, ∞)网格空间、特征差异计算简单,对异常值不敏感FAISS, Milvus
杰卡德相似度J(A,B) = |A∩B| / |A∪B|[0, 1]集合比较、文档相似度适用于二进制特征或集合ES(脚本), PGVector(SQL)
汉明距离H(A,B) = ∑(A_i ⊕ B_i)[0, dim]二进制特征、错误检测计算二进制向量中不同位的数量FAISS

3. 适用场景对比总结

解决方案最适合场景不适合场景
Elasticsearch需要混合搜索(文本+向量)、已有 ES 基础设施、需要复杂文本处理超大规模纯向量搜索、极低延迟要求、GPU 加速需求
PGVector已有 PostgreSQL 基础设施、需要事务支持、结构化数据+向量超大规模向量集、分布式部署需求
Redis Vector超低延迟需求、缓存层向量搜索、临时数据持久化要求高、复杂查询、大规模数据
MongoDB Atlas半结构化数据、文档+向量混合、MongoDB 用户复杂文本分析、极高性能要求
FAISS纯向量搜索、算法研究、GPU 加速、嵌入式应用需要持久化、分布式部署、元数据过滤
Milvus大规模向量管理、需要丰富索引算法、混合查询简单应用、资源受限环境
Pinecone快速部署、无运维需求、按需扩展自托管需求、成本敏感、复杂查询
Qdrant中小规模应用、需要良好元数据过滤、开源需求超大规模、GPU 加速需求
Chroma快速原型开发、简单应用、本地部署企业级应用、大规模数据、高并发

五、基于 Elasticsearch 的 RAG 实现方案

1. 系统架构设计

基于 Elasticsearch 实现 RAG 系统的整体架构如下:

  1. 1. 数据处理层:负责文档的收集、清洗、分块和向量化

  2. 2. 存储层:使用 Elasticsearch 存储文本内容和向量表示

  3. 3. 检索层:实现混合检索策略,结合文本和向量搜索

  4. 4. 生成层:集成 Deepseek V3 或 Qwen2.5 大模型,基于检索结果生成回答

  5. 5. 应用层:提供用户界面和 API 接口

2. 实现步骤详解

2.1 环境准备

首先,我们需要安装必要的依赖:

# 安装必要的库
pip install elasticsearch langchain langchain-elasticsearch langchain-community langchain-openai
pip install deepseek-ai qwen-api
2.2 Elasticsearch 配置

设置 Elasticsearch 集群并创建适合 RAG 的索引,展示不同相似度计算方法:

from elasticsearch import Elasticsearch# 连接到Elasticsearch
es = Elasticsearch(hosts=["http://localhost:9200"],basic_auth=("user", "password"),  # 如果有认证request_timeout=60
)# 创建索引映射,使用cosine相似度
cosine_index_mapping = {"mappings": {"properties": {"title": {"type": "text", "analyzer": "standard"},"content": {"type": "text", "analyzer": "standard"},"source": {"type": "keyword"},"content_vector": {"type": "dense_vector","dims": 1536,  # 根据嵌入模型调整维度"index": True,"similarity": "cosine"  # 余弦相似度}}},"settings": {"number_of_shards": 2,"number_of_replicas": 1}
}# 创建使用余弦相似度的索引
es.indices.create(index="rag-knowledge-cosine", body=cosine_index_mapping)# 创建索引映射,使用dot_product相似度
dot_product_index_mapping = {"mappings": {"properties": {"title": {"type": "text", "analyzer": "standard"},"content": {"type": "text", "analyzer": "standard"},"source": {"type": "keyword"},"content_vector": {"type": "dense_vector","dims": 1536,"index": True,"similarity": "dot_product"  # 点积相似度}}},"settings": {"number_of_shards": 2,"number_of_replicas": 1}
}# 创建使用点积相似度的索引
es.indices.create(index="rag-knowledge-dot-product", body=dot_product_index_mapping)# 创建索引映射,使用l2_norm相似度
l2_norm_index_mapping = {"mappings": {"properties": {"title": {"type": "text", "analyzer": "standard"},"content": {"type": "text", "analyzer": "standard"},"source": {"type": "keyword"},"content_vector": {"type": "dense_vector","dims": 1536,"index": True,"similarity": "l2_norm"  # 欧几里得距离(L2范数)}}},"settings": {"number_of_shards": 2,"number_of_replicas": 1}
}# 创建使用L2范数相似度的索引
es.indices.create(index="rag-knowledge-l2-norm", body=l2_norm_index_mapping)

2.3 文档处理与索引

实现文档的处理、分块和向量化,并分别存储到不同相似度计算方法的索引中:

import os
from langchain_community.document_loaders import DirectoryLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings  # 也可以使用其他嵌入模型# 加载文档
loader = DirectoryLoader("./documents", glob="**/*.txt", loader_cls=TextLoader)
documents = loader.load()# 文档分块
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000,chunk_overlap=200,length_function=len,
)
chunks = text_splitter.split_documents(documents)# 初始化嵌入模型
embeddings = OpenAIEmbeddings()  # 可替换为其他嵌入模型# 处理文档并索引到不同的Elasticsearch索引
for i, chunk in enumerate(chunks):# 生成向量嵌入vector = embeddings.embed_query(chunk.page_content)# 准备索引文档doc = {"title": f"Chunk {i} from {chunk.metadata.get('source', 'unknown')}","content": chunk.page_content,"source": chunk.metadata.get("source", "unknown"),"content_vector": vector}# 索引文档到不同相似度计算方法的索引es.index(index="rag-knowledge-cosine", document=doc)# 对于dot_product,通常需要归一化向量es.index(index="rag-knowledge-dot-product", document=doc)# 对于l2_norm,直接使用原始向量es.index(index="rag-knowledge-l2-norm", document=doc)# 刷新索引
es.indices.refresh(index="rag-knowledge-cosine")
es.indices.refresh(index="rag-knowledge-dot-product")
es.indices.refresh(index="rag-knowledge-l2-norm")

2.4 使用 LangChain 与 Elasticsearch 实现 RAG

下面是使用 LangChain 与 Elasticsearch 结合实现 RAG 的代码,支持不同相似度计算方法:

from langchain_elasticsearch import ElasticsearchStore
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
from langchain.schema import Document# 初始化不同相似度计算方法的Elasticsearch向量存储
es_store_cosine = ElasticsearchStore(es_url="http://localhost:9200",index_name="rag-knowledge-cosine",embedding=embeddings,es_user="user",  # 如果有认证es_password="password"  # 如果有认证
)es_store_dot_product = ElasticsearchStore(es_url="http://localhost:9200",index_name="rag-knowledge-dot-product",embedding=embeddings,es_user="user",es_password="password"
)es_store_l2_norm = ElasticsearchStore(es_url="http://localhost:9200",index_name="rag-knowledge-l2-norm",embedding=embeddings,es_user="user",es_password="password"
)# 创建不同相似度计算方法的检索器
retriever_cosine = es_store_cosine.as_retriever(search_type="similarity",search_kwargs={"k": 5}
)retriever_dot_product = es_store_dot_product.as_retriever(search_type="similarity",search_kwargs={"k": 5}
)retriever_l2_norm = es_store_l2_norm.as_retriever(search_type="similarity",search_kwargs={"k": 5}
)# 创建多相似度混合检索器
def multi_similarity_retriever(query, top_k=5):# 从三种不同相似度方法获取结果cosine_docs = retriever_cosine.get_relevant_documents(query)dot_product_docs = retriever_dot_product.get_relevant_documents(query)l2_norm_docs = retriever_l2_norm.get_relevant_documents(query)# 合并结果all_docs = cosine_docs + dot_product_docs + l2_norm_docs# 去重unique_docs = list({doc.page_content: doc for doc in all_docs}.values())# 限制返回数量return unique_docs[:top_k]# 定义提示模板
template = """
你是一个专业的AI助手。请基于以下提供的上下文信息,回答用户的问题。
如果你无法从上下文中找到答案,请直接说"我无法从提供的信息中找到答案",不要编造信息。上下文信息:
{context}用户问题: {question}回答:
"""prompt = PromptTemplate(template=template,input_variables=["context", "question"]
)# 格式化文档函数
def format_docs(docs):return "\n\n".join([doc.page_content for doc in docs])

2.5 集成 Deepseek V3 模型

from langchain_deepseek import DeepseekChat# 初始化Deepseek模型
deepseek_llm = DeepseekChat(model_name="deepseek-ai/deepseek-v3",api_key="your_api_key",temperature=0.1
)# 构建RAG链(使用余弦相似度)
deepseek_rag_chain_cosine = ({"context": retriever_cosine | format_docs, "question": RunnablePassthrough()}| prompt| deepseek_llm| StrOutputParser()
)# 构建RAG链(使用点积相似度)
deepseek_rag_chain_dot_product = ({"context": retriever_dot_product | format_docs, "question": RunnablePassthrough()}| prompt| deepseek_llm| StrOutputParser()
)# 构建RAG链(使用L2范数相似度)
deepseek_rag_chain_l2_norm = ({"context": retriever_l2_norm | format_docs, "question": RunnablePassthrough()}| prompt| deepseek_llm| StrOutputParser()
)# 构建RAG链(使用多相似度混合检索)
def answer_with_deepseek_multi_similarity(question):# 获取多相似度混合检索结果docs = multi_similarity_retriever(question)context = format_docs(docs)# 构建RAG链chain = ({"context": RunnablePassthrough(), "question": RunnablePassthrough()}| prompt| deepseek_llm| StrOutputParser())# 生成回答return chain.invoke({"context": context, "question": question})# 示例
response = answer_with_deepseek_multi_similarity("什么是向量数据库?")
print(response)

2.6 集成 Qwen2.5 模型

from langchain_community.llms import QianfanLLMEndpoint# 初始化Qwen模型
qwen_llm = QianfanLLMEndpoint(model_name="qwen-2.5",api_key="your_api_key",secret_key="your_secret_key",temperature=0.1
)# 构建RAG链(使用余弦相似度)
qwen_rag_chain_cosine = ({"context": retriever_cosine | format_docs, "question": RunnablePassthrough()}| prompt| qwen_llm| StrOutputParser()
)# 构建RAG链(使用点积相似度)
qwen_rag_chain_dot_product = ({"context": retriever_dot_product | format_docs, "question": RunnablePassthrough()}| prompt| qwen_llm| StrOutputParser()
)# 构建RAG链(使用L2范数相似度)
qwen_rag_chain_l2_norm = ({"context": retriever_l2_norm | format_docs, "question": RunnablePassthrough()}| prompt| qwen_llm| StrOutputParser()
)# 构建RAG链(使用多相似度混合检索)
def answer_with_qwen_multi_similarity(question):# 获取多相似度混合检索结果docs = multi_similarity_retriever(question)context = format_docs(docs)# 构建RAG链chain = ({"context": RunnablePassthrough(), "question": RunnablePassthrough()}| prompt| qwen_llm| StrOutputParser())# 生成回答return chain.invoke({"context": context, "question": question})# 示例
response = answer_with_qwen_multi_similarity("Elasticsearch的主要优势是什么?")
print(response)

3. 高级功能实现

3.1 实现混合搜索策略
def enhanced_hybrid_search(query, es_client, index_name, embedding_model, similarity_type="cosine"):# 生成查询向量query_vector = embedding_model.embed_query(query)# 根据不同相似度类型构建脚本if similarity_type == "cosine":similarity_script = "cosineSimilarity(params.query_vector, 'content_vector') + 1.0"elif similarity_type == "dot_product":similarity_script = "dotProduct(params.query_vector, 'content_vector')"elif similarity_type == "l2_norm":# 对于L2范数,较小的值表示更相似,所以我们使用负值或倒数similarity_script = "1 / (1 + l2Norm(params.query_vector, 'content_vector'))"else:raise ValueError(f"不支持的相似度类型: {similarity_type}")# 构建混合查询hybrid_query = {"query": {"bool": {"should": [# 向量搜索部分{"script_score": {"query": {"match_all": {}},"script": {"source": similarity_script,"params": {"query_vector": query_vector}}}},# 文本搜索部分{"match": {"content": {"query": query,"boost": 0.5  # 调整文本搜索的权重}}}]}},"size": 5}# 执行搜索response = es_client.search(index=index_name, body=hybrid_query)# 处理结果results = []for hit in response["hits"]["hits"]:results.append({"score": hit["_score"],"title": hit["_source"]["title"],"content": hit["_source"]["content"],"source": hit["_source"]["source"]})return results

3.2 实现自适应相似度选择
def adaptive_similarity_search(query, es_client, embedding_model):# 分析查询特征,决定使用哪种相似度方法query_length = len(query.split())# 短查询(1-3个词)可能更适合关键词搜索if query_length <= 3:# 使用混合搜索,但给文本搜索更高权重results = enhanced_hybrid_search(query, es_client, "rag-knowledge-cosine", embedding_model,similarity_type="cosine")# 中等长度查询(4-10个词)elif query_length <= 10:# 使用余弦相似度,适合一般语义搜索results = enhanced_hybrid_search(query, es_client, "rag-knowledge-cosine", embedding_model,similarity_type="cosine")# 长查询(>10个词)else:# 对于长查询,点积可能更适合捕捉更多语义信息results = enhanced_hybrid_search(query, es_client, "rag-knowledge-dot-product", embedding_model,similarity_type="dot_product")return results

3.3 实现多步检索策略
def multi_step_retrieval(query, es_client, embedding_model):# 第一步:使用文本搜索获取初步结果text_query = {"query": {"match": {"content": query}},"size": 20}text_response = es_client.search(index="rag-knowledge-cosine", body=text_query)# 提取文档ID和内容candidate_docs = []for hit in text_response["hits"]["hits"]:candidate_docs.append({"id": hit["_id"],"content": hit["_source"]["content"]})# 如果文本搜索没有足够结果,添加向量搜索if len(candidate_docs) < 10:# 生成查询向量query_vector = embedding_model.embed_query(query)# 向量搜索vector_query = {"query": {"script_score": {"query": {"match_all": {}},"script": {"source": "cosineSimilarity(params.query_vector, 'content_vector') + 1.0","params": {"query_vector": query_vector}}}},"size": 20 - len(candidate_docs)}vector_response = es_client.search(index="rag-knowledge-cosine", body=vector_query)# 添加到候选文档for hit in vector_response["hits"]["hits"]:# 避免重复if not any(doc["id"] == hit["_id"] for doc in candidate_docs):candidate_docs.append({"id": hit["_id"],"content": hit["_source"]["content"]})# 第二步:对候选文档进行重新排序# 生成查询向量query_vector = embedding_model.embed_query(query)# 为每个候选文档计算相似度分数for doc in candidate_docs:# 生成文档向量doc_vector = embedding_model.embed_query(doc["content"])# 计算余弦相似度similarity = cosine_similarity([query_vector],[doc_vector])[0][0]doc["similarity_score"] = similarity# 按相似度排序ranked_docs = sorted(candidate_docs, key=lambda x: x["similarity_score"], reverse=True)# 返回前5个最相关文档return ranked_docs[:5]

3.4 实现查询扩展和改写
def query_expansion(original_query, llm):# 使用大模型扩展查询expansion_prompt = f"""请基于以下原始查询,生成3个不同的扩展查询,以便更全面地搜索相关信息。每个扩展查询应该保留原始查询的核心意图,但可以添加相关术语、同义词或上下文。原始查询: {original_query}扩展查询(每行一个):"""# 获取扩展查询response = llm.invoke(expansion_prompt)# 解析响应expanded_queries = [q.strip() for q in response.split("\n") if q.strip()]# 过滤掉可能的空行或无关行expanded_queries = [q for q in expanded_queries if len(q) > 5]# 确保至少有一个查询(原始查询)if not expanded_queries:expanded_queries = [original_query]else:# 添加原始查询expanded_queries.append(original_query)return expanded_queriesdef multi_query_retrieval(original_query, es_client, embedding_model, llm):# 扩展查询expanded_queries = query_expansion(original_query, llm)# 对每个扩展查询执行搜索all_results = []for query in expanded_queries:results = enhanced_hybrid_search(query, es_client, "rag-knowledge-cosine", embedding_model)all_results.extend(results)# 去重unique_results = []seen_contents = set()for result in all_results:if result["content"] not in seen_contents:unique_results.append(result)seen_contents.add(result["content"])# 重新排序(可以基于原始查询的相似度)query_vector = embedding_model.embed_query(original_query)# 为每个结果计算与原始查询的相似度for result in unique_results:# 假设我们可以从ES获取内容的向量content_vector_query = {"query": {"term": {"_id": result["id"]}},"_source": ["content_vector"]}vector_response = es_client.search(index="rag-knowledge-cosine", body=content_vector_query)content_vector = vector_response["hits"]["hits"][0]["_source"]["content_vector"]# 计算相似度similarity = cosine_similarity([query_vector],[content_vector])[0][0]result["final_score"] = similarity# 按最终分数排序ranked_results = sorted(unique_results, key=lambda x: x["final_score"], reverse=True)# 返回前5个最相关结果return ranked_results[:5]

六、总结与结论

1. Elasticsearch 作为 RAG 向量数据库的优势总结

  1. 1. 全栈解决方案:Elasticsearch 提供了从数据索引到检索的完整解决方案,无需集成多个系统。

  2. 2. 混合检索能力:结合传统文本搜索和向量搜索的能力是其最大优势,能够显著提高检索质量。

  3. 3. 成熟的生态系统:作为成熟的搜索引擎,拥有丰富的文档、工具和社区支持。

  4. 4. 多模态支持:能够存储和检索文本、图像、音频和视频的向量表示,支持多模态 RAG 应用。

  5. 5. 灵活的相似度计算:支持多种相似度计算方法(余弦、点积、L2 范数),适应不同应用场景。

2. 实施建议

  1. 1. 选择合适的相似度计算方法:

    • 文本语义搜索:优先使用余弦相似度
    • 推荐系统:考虑使用点积
    • 图像或地理位置搜索:考虑使用 L2 范数
  2. 2. 优化索引配置:

    • 根据数据量和查询频率调整分片数量
    • 为频繁查询的索引配置足够的副本
    • 合理设置 HNSW 参数,平衡搜索精度和性能
  3. 3. 实现混合检索策略:

    • 结合向量搜索和关键词搜索
    • 根据查询特征动态调整搜索策略
    • 考虑使用查询扩展和多步检索提高召回率
  4. 4. 性能优化:

    • 对于大规模部署,考虑使用专用节点
    • 监控和调整 JVM 堆大小
    • 定期优化索引

3. 未来发展方向

  1. 1. 与专用向量数据库的集成:

    • 考虑 Elasticsearch 与专用向量数据库(如 FAISS、Milvus)的混合架构
    • 利用 ES 的文本处理和混合查询能力,结合专用向量数据库的高性能向量搜索
  2. 2. 知识图谱增强:

    • 将向量搜索与知识图谱结合,实现 GraphRAG
    • 利用实体关系增强检索结果的相关性和可解释性
  3. 3. 多模态 RAG 应用:

    • 扩展到图像、音频和视频内容的检索增强生成
    • 实现跨模态检索,如以文搜图、以图搜文
  4. 4. 自适应检索策略:

    • 开发能够根据查询特征和上下文自动选择最佳检索策略的系统
    • 利用强化学习优化检索参数

4. 结论

Elasticsearch 作为 RAG 系统的向量数据库具有显著优势,特别是在需要混合检索、多模态支持和成熟生态系统的场景下。虽然在纯向量搜索性能上可能不如专用向量数据库,但其全面的功能和灵活性使其成为构建企业级 RAG 系统的有力选择。

通过合理配置和优化,结合本报告提供的实现方案,可以充分发挥 Elasticsearch 在 RAG 系统中的潜力,为大模型应用提供高质量的知识检索支持。

对于需要构建 RAG 系统的团队,建议根据具体需求和现有技术栈选择合适的向量存储解决方案,Elasticsearch 特别适合已有 ES 基础设施、需要混合检索能力以及处理多模态数据的场景。

 


【大模型介绍电子书】

快速揭秘DeepSeek背后的AI工作原理

要获取本书全文PDF内容,请在VX后台留言:“AI大模型基础” 或者 “大模型基础” 就会获得电子书的PDF。

相关文章:

【原创】使用ElasticSearch存储向量实现大模型RAG

一、概述 检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;RAG&#xff09;已成为大型语言模型&#xff08;LLM&#xff09;应用的重要架构&#xff0c;通过结合外部知识库来增强模型的回答能力&#xff0c;特别是在处理专业领域知识、最新信息或企业私有数…...

Gymnasium Cart Pole 环境与 REINFORCE 算法 —— 强化学习入门 2

Title: Gymnasium Cart Pole 环境与 REINFORCE 算法 —— 强化学习入门 2 文章目录 I. Gymnasium Cart Pole 环境II. REINFORCE 算法1. 原理说明2. REINFORCE 算法实现 I. Gymnasium Cart Pole 环境 Gymnasium Cart Pole 环境是一个倒立摆的动力学仿真环境. 状态空间: 0: Ca…...

响应式数据 和 Pinia 状态

响应式数据 和 Pinia 状态 是 Vue.js 应用中用于管理数据的两种重要机制&#xff0c;它们之间有密切的关系。以下是它们的定义、特点以及关系&#xff1a; 1. 响应式数据 定义 响应式数据 是 Vue.js 的核心特性之一&#xff0c;指的是当数据发生变化时&#xff0c;视图会自动…...

在大数据开发中hive是指什么?

hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在大数据技术的浩瀚星空中&#xff0c;Apache Hive犹如一座桥梁&#xff0c;连接着传统数据仓库理念…...

LeRobot源码剖析——对机器人各个动作策略的统一封装:包含ALOHA ACT、Diffusion Policy、VLA模型π0

前言 过去2年多的深入超过此前7年&#xff0c;全靠夜以继日的勤奋&#xff0c;一天当两天用&#xff0c;抠论文 抠代码 和大模型及具身同事讨论&#xff0c;是目前日常 而具身库里&#xff0c;idp3、π0、lerobot值得反复研究&#xff0c;故&#xff0c;近期我一直在抠π0及l…...

Python生成requirements.txt的两种方法

Python生成requirements.txt的两种方法 方法一&#xff1a;导出当前环境的依赖包 使用pipreqs --encodingutf8为使用utf8编码&#xff0c;避免编码报错 --force 强制执行覆盖生成目录下的requirements.txt # 安装 python3 -m pip install pipreqs # 在当前目录生成 pipreqs . …...

如何判断 MSF 的 Payload 是 Staged 还是 Stageless(含 Meterpreter 与普通 Shell 对比)

在渗透测试领域&#xff0c;Metasploit Framework&#xff08;MSF&#xff09;的 msfvenom 工具是生成 Payload&#xff08;载荷&#xff09;的核心利器。然而&#xff0c;当我们选择 Payload 时&#xff0c;经常会遇到一个问题&#xff1a;这个 Payload 是 Staged&#xff08;…...

HTML5与CSS3新特性详解

一、HTML5新特性 1.概述 HTML5 的新增特性主要是针对于以前的不足&#xff0c;增加了一些新的标签、新的表单和新的表单属性等。 这些新特性都有兼容性问题&#xff0c;基本是 IE9 以上版本的浏览器才支持&#xff0c;如果不考虑兼容性问题&#xff0c;可以大量使用这些新特…...

Redis常用进阶 存储原理和主从思路

Redis常用进阶 存储原理和主从思路 简介 此篇用于需要时随时查阅的知识. 由于不断的学习总是会忘记一些 所以用于记录 笔记对应视频为黑马redis https://www.bilibili.com/video/BV1Pu411Y7bq 单点redis的问题 : 数据丢失问题 持久化并发能力弱 主从集群存储能力问题 ES故…...

本地部署DeepSeek-R1(Dify升级最新版本、新增插件功能、过滤推理思考过程)

下载最新版本Dify Dify1.0版本之前不支持插件功能&#xff0c;先升级DIfy 下载最新版本&#xff0c;目前1.0.1 Git地址&#xff1a;https://github.com/langgenius/dify/releases/tag/1.0.1 我这里下载到老版本同一个目录并解压 拷贝老数据 需先停用老版本Dify PS D:\D…...

分治-快速排序系列一>快速排序

目录 题目方法&#xff1a;优化方法&#xff1a;代码&#xff1a; 题目方法&#xff1a; 忘记快速排序看这里&#xff1a;链接: link 优化方法&#xff1a; 代码&#xff1a; public int[] sortArray(int[] nums) {qsort(nums,0,nums.length-1);return nums;}private void qso…...

【spring对bean Singleton和Prototype的管理流程】

在 Spring 框架中&#xff0c;Bean 的作用域决定了 Bean 的生命周期和创建方式。Spring 支持多种作用域&#xff0c;其中最常用的是 单例&#xff08;Singleton&#xff09; 和 原型&#xff08;Prototype&#xff09;。以下是 Spring 对单例和原型 Bean 的管理流程详解&#x…...

【Java】grpc-java在IDEA中build不成功的相关问题,Android,codegen C++语言排除

一、解决Android依赖问题 在当前grpc-java项目根目录下创建gradle.properties文件,输入以下内容: skipAndroid=true或者 android.useAndroidX=true二、com.google.cloud.tools.appengine插件找不到的问题 Plugin [id: ‘com.google.cloud.tools.appengine’, version: ‘…...

十七、实战开发 uni-app x 项目(仿京东)- 后端指南

前面我们已经用uniappx进行了前端实战学习 一、实战 开发uni-app x项目(仿京东)-规划-CSDN博客 二、实战 开发uni-app x项目(仿京东)-项目搭建-CSDN博客 三、实战开发 uni-app x 项目(仿京东)- 技术选型-CSDN博客 四、实战开发 uni-app x 项目(仿京东)- 页面设计-C…...

SpringSecurity——基于角色权限控制和资源权限控制

目录 基于角色权限控制 1.1 自定义 UserDetailsService 1.2 加载用户角色 1.3. 给角色配置能访问的资源&#xff08;使用切面拦截&#xff0c;使用注解&#xff09; 总结 资源权限控制 2.2. 需要有一个用户&#xff1b;&#xff08;从数据库查询用户&#xff09; 2.2 基…...

经历过的IDEA+Maven+JDK一些困惑

注意事项&#xff1a;由于使用过程中是IDEA绑定好另外2个工具&#xff0c;所以报错统一都显示在控制台&#xff0c;但要思考和分辨到底是IDEA本身问题导致的报错&#xff0c;还是maven导致的 标准配置 maven Java Compiler Structure 编辑期 定义&#xff1a;指的是从open pr…...

基于Arduino控制的温室蔬菜园环境监控系统(论文+源码)

2.1系统总体方案设计 本课题为基于Arduino控制的温室蔬菜园环境监控系统&#xff0c;在硬件上结合Arduino 控制器&#xff0c;土壤湿度传感器&#xff0c;ESP8266模块&#xff0c;环境温湿度传感器&#xff0c;光敏电阻&#xff0c;液晶等来构成整个系统&#xff0c;其可以实现…...

关于HAL库的知识1----MSP函数

在 HAL 库中&#xff0c;大部分外设在初始化时都会调用一个对应的 MSP 初始化函数&#xff0c;这个函数的主要作用就是配置与外设相关的底层硬件资源&#xff0c;比如时钟、GPIO、中断、DMA 等。常见的外设及其对应的 MSP 函数包括&#xff1a; UART/USART&#xff1a;对应 HA…...

QT 磁盘文件 教程04-创建目录、删除目录、遍历目录

【1】新建目录 bool CreateDir(QString name){QString fileName name ;QDir dir(fileName);if (dir.isEmpty()) {dir.mkdir(fileName);return true;}else{qDebug()<<"文件夹已存在";return false;} } 【2】删除目录 bool DeleteDir(QString fileName){if (…...

高级java每日一道面试题-2025年3月06日-微服务篇[Eureka篇]-Eureka Server和Eureka Client关系?

如果有遗漏,评论区告诉我进行补充 面试官: Eureka Server和Eureka Client关系? 我回答: 在微服务架构中&#xff0c;Eureka作为Netflix开源的服务发现组件&#xff0c;由Eureka Server&#xff08;服务端&#xff09;和Eureka Client&#xff08;客户端&#xff09;两大部分…...

MAC-在使用@Async注解的方法时,分布式锁管理和释放

在使用 @Async 注解的异步方法中管理分布式锁时,需要特别注意 ​锁的获取、释放与异步执行的生命周期匹配。以下是结合 Spring Boot 和 Redis 分布式锁的实践方案: 1. 为什么需要分布式锁? 异步方法可能被多个线程/服务实例并发执行,若访问共享资源(如数据库、缓存),需…...

Kafka 八股文

一、基础概念 1. Kafka 是什么&#xff1f;它的核心组件有哪些&#xff1f; Kafka 的定义 Kafka 是一个 分布式流处理平台&#xff0c;最初由 LinkedIn 开发&#xff0c;后成为 Apache 顶级项目。它主要用于 高吞吐量的实时数据流处理&#xff0c;支持发布-订阅模式的消息传递…...

现代前端开发框架对比:React、Vue 和 Svelte 的选择指南

引言 在当今快速发展的 Web 开发领域&#xff0c;前端框架的选择往往直接影响项目的开发效率、维护成本和用户体验。React、Vue 和 Svelte 作为当前最受关注的三大框架&#xff0c;各自拥有独特的设计哲学与技术实现。本文将通过 5000 字的深度解析&#xff0c;从架构设计、开…...

ffmpeg(库编译) 01 搭建环境和安装依赖

创建目录在home目录下创建 ffmpeg_sources:用于下载源文件 ffmpeg_build: 存储编译后的库文件 bin:存储二进制文件(ffmpeg,ffplay,ffprobe,X264,X265等) mkdir ffmpeg_sources ffmpeg_build bin安装依赖 先执行sudo apt-get update进行更新,再往下走sudo apt-get -…...

Java后端开发技术详解

Java作为一门成熟的编程语言&#xff0c;已广泛应用于后端开发领域。其强大的生态系统和广泛的支持库使得Java成为许多企业和开发者的首选后端开发语言。随着云计算、微服务架构和大数据技术的兴起&#xff0c;Java后端开发的技术栈也不断演进。本文将详细介绍Java后端开发的核…...

Python高级:GIL、C扩展与分布式系统深度解析

文章目录 &#x1f4cc; **前言**&#x1f527; **第一章&#xff1a;Python语言的本质与生态**1.1 **Python的实现与版本演进**1.2 **开发环境与工具链** &#x1f527; **第二章&#xff1a;元编程与动态特性**2.1 **描述符协议&#xff08;Descriptor Protocol&#xff09;*…...

数学之握手问题

问题描述 小蓝组织了一场算法交流会议&#xff0c;总共有 50人参加了本次会议。在会议上&#xff0c;大家进行了握手交流。按照惯例他们每个人都要与除自己以外的其他所有人进行一次握手 (且仅有一次)。但有 7 个人&#xff0c;这 7 人彼此之间没有进行握手 (但这 7 人与除这 …...

【Nodejs】2024 汇总现状

之前已经调研了容器、nexus-public&#xff0c;实现了本地构建应用镜像和基础设施的镜像。为实现分布式一体化协作开发的目标&#xff0c;还需要配套的线上协作开发环境。故而重回前端调研现状&#xff0c;比较 5 年前的 nodejs 快好的啊。 以下是针对 Node.js 工具链的深度解析…...

人工智能之数学基础:矩阵的降维

本文重点 在现实世界中,我们经常会遇到高维数据。例如,图像数据通常具有很高的维度,每个像素点都可以看作是一个维度。高维数据不仅会带来计算和存储上的困难,还可能会导致 “维数灾难”,即随着维度的增加,数据的稀疏性和噪声也会增加,从而影响数据分析的效果。因此,我…...

数仓开发那些事(10)

某神州优秀员工&#xff1a;&#xff08;没错&#xff0c;这个diao毛被评为了优秀员工&#xff09;一闪&#xff0c;听说你跑路了&#xff0c;不做零售行业了 一闪&#xff1a;没错&#xff0c;老东家的新it总监上任后大家都开始躺平&#xff0c;失去了当年的动力&#xff0c;所…...

【手工】早教游戏:下楼的猴子

一、效果 二、准备材料 吸管: 10.4 c m 10.4cm 10.4cm&#xff1b;棉签&#xff1a; 6 6 6 根双头棉签&#xff1b;硬币&#xff1a;1角&#xff1b;纸皮人: 2.0 c m 4.0 c m 2.0cm4.0cm 2.0cm4.0cm&#xff1b;纸板&#xff1a; 12.0 c m 30.0 c m 12.0cm30.0cm 12.0cm30…...

力扣刷题46. 全排列

46. 全排列 - 力扣&#xff08;LeetCode&#xff09; 使用dfs搜索&#xff0c;查找所有的情况&#xff0c;首先定义所有的链表集合list&#xff0c;在定义每一种情况的链表res&#xff0c;在主函数中遍历所有的初始元素&#xff0c;首先初始化res&#xff0c;并且添加到res中&…...

【工作记录】pytest使用总结

1、 fixture夹具 可参考&#xff1a; python3.x中 pytest之fixture - 漂泊的小虎 - 博客园 fixture是指夹具&#xff08;把用例夹在中间&#xff09;&#xff0c;它包括前置工作和后置工作&#xff0c;前置是用例代码的准备阶段&#xff0c;后置是用例执行之后的清理阶段,用…...

linux 命令 mkdir

以下是 Linux mkdir 命令的简明总结&#xff0c;适合快速查阅和实际场景应用&#xff1a; 基础语法 mkdir [选项] 目录名... 常用选项速查 选项作用-p自动创建父目录&#xff08;解决多级目录问题&#xff09; mkdir -p a/b/c-m直接设置权限&#xff08;替代chmod&#xff0…...

浏览器对一个资源设置了缓存,如何清除缓存,且后续请求不命中缓存

方式1、浏览器端强制刷新 方式2、修改资源url eg&#xff1a;如下图&#xff0c;添加了查询参数 <link rel"stylesheet" href"style.css?v1.2.1"> <script src"app.js?t20231010"></script> 原理&#xff1a;1、在资源的…...

k8s的存储

一 configmap 1.1 configmap的功能 configMap用于保存配置数据&#xff0c;以键值对形式存储。 configMap 资源提供了向 Pod 注入配置数据的方法。 镜像和配置文件解耦&#xff0c;以便实现镜像的可移植性和可复用性。 etcd限制了文件大小不能超过1M 1.2 configmap的使用…...

[JavaScript]如何利用作用域块避免闭包内存泄漏?

出自《你不知道的JavaScript》上卷 以下是本书给出的反例: function process (data) {...} var bigdata{...} process(bigdata); var btn document.getElementById(x); btn.addEventListener(click, function click{...});click会被回调在其他位置, 在addEventListener函数内…...

Pytorch使用手册—扩展 TorchScript 使用自定义 C++ 操作符(专题五十三)

提示 本教程自 PyTorch 2.4 起已弃用。有关 PyTorch 自定义操作符的最新指南,请参阅 PyTorch 自定义操作符。 PyTorch 1.0 版本引入了一种名为 TorchScript 的新编程模型。TorchScript 是 Python 编程语言的一个子集,可以被 TorchScript 编译器解析、编译和优化。此外,编译后…...

CellOracle|基因扰动研究基因功能|基因调控网络+虚拟干预

在gzh“生信小鹏”同步文章 论文来源: 发表期刊:Nature发表时间:2023年2月23日论文题目:Dissecting cell identity via network inference and in silico gene perturbation研究团队:Kenji Kamimoto 等,华盛顿大学医学院1. 研究背景与问题提出 细胞身份(Cell Identit…...

深入探索JVM字节码增强技术与调优实践

引言 Java虚拟机(JVM)是Java程序运行的基石,而字节码增强技术则是JVM生态中一项强大的工具。通过字节码增强,开发者可以在不修改源代码的情况下,动态地修改或增强类的行为。本文将深入探讨字节码增强技术的原理、常用工具,并结合JVM调优和排错实践,帮助开发者更好地理解…...

vue 中常用操作数组的方法

操作数组方法 记录一下自己常用到的操作数组的方法 1.forEach() 遍历数组 在回调函数中对原数组的每个成员进行修改&#xff08;不用 return&#xff09; 方法接收一个回调函数 回调函数接收两个参数 第一个是遍历的当前元素 第二个是元素的索引 const arr [{name: 张三},…...

envoy 源码分析

整体架构 Envoy 的架构如图所示: Envoy 中也可能有多个 Listener&#xff0c;每个 Listener 中可能会有多个 filter 组成了 chain。 Envoy 接收到请求后&#xff0c;会先走 FilterChain&#xff0c;通过各种 L3/L4/L7 Filter 对请求进行微处理&#xff0c;然后再路由到指定的集…...

c++基础知识--返回值优化

在 C 中&#xff0c;Named Return Value Optimization&#xff08;NRVO&#xff0c;具名返回值优化&#xff09; 是一种编译器优化技术&#xff0c;用于消除函数返回一个局部对象时的拷贝或移动操作。它是 返回值优化&#xff08;RVO&#xff09; 的一种更复杂的变体&#xff0…...

【第14节】windows sdk编程:进程与线程介绍

目录 一、进程与线程概述 1.1 进程查看 1.2 何为进程 1.3 进程的创建 1.4 进程创建实例 1.5 线程查看 1.6 何为线程 1.7 线程的创建 1.8 线程函数 1.9 线程实例 二、内核对象 2.1 何为内核对象 2.2 内核对象的公共特点 2.3 内核对象句柄 2.4 内核对象的跨进程访…...

实测 Gemini 2.0 Flash 图像生成:多模态 AI 的创作力边界

近日&#xff0c;Google 发布了 Gemini 2.0 Flash 的实验性图像生成功能&#xff08;Gemini 2.0 Flash (Image Generation) Experimental&#xff09;。我也第一时间体验了这一功能&#xff0c;再次感受到 AI 技术对传统图像处理工具的颠覆性冲击。 引言 Gemini 2.0 Flash 的…...

每日一题——买卖股票的最佳时机

买卖股票的最佳时机 问题描述示例示例 1示例 2 提示 问题分析难点分析 算法设计思路 代码实现复杂度分析测试用例测试用例 1测试用例 2测试用例 3 总结 问题描述 给定一个数组 prices&#xff0c;其中第 i 个元素 prices[i] 表示一支给定股票在第 i 天的价格。你可以选择某一天…...

以太坊节点间通信机制 DEVp2p 协议

文章目录 概要1. 协议概述2. 协议栈与关键技术3. RLPx 协议核心机制3.1 数据包结构3.2 加密握手流程 4. 核心子协议与消息类型4.1 基础控制消息4.2 以太坊子协议示例4.3 网络 ID 列表 5. 安全与防攻击机制6. 节点标识与声誉管理7. 对比其他区块链通信协议8. 总结 概要 1. 协议…...

YOLO+OpenCV强强联手:高精度跌倒检测技术实战解析

目录 关于摔倒检测 摔倒检测核心逻辑 摔倒检测:联合多种逻辑判断 原理详细解释 1. 导入必要的库 2. 定义函数和关键点连接关系 3. 筛选有效关键点并计算边界框 4. 计算人体上下半身中心点和角度 5. 绘制关键点和连接线 6. 绘制角度标注和检测跌倒 7. 返回处理后的图…...

HyperAD:学习弱监督音视频暴力检测在双曲空间中的方法

文章目录 速览摘要1. 引言2. 相关工作弱监督暴力检测双曲空间中的神经网络 3. 预备知识双曲几何切空间&#xff08;Tangent Space&#xff09;指数映射与对数映射&#xff08;Exponential and Logarithmic Maps&#xff09;3.1 双曲图卷积网络&#xff08;Hyperbolic Graph Con…...

网络协议抓取与分析(SSL Pinning突破)

1. 网络协议逆向基础 1.1 网络协议分析流程 graph TD A[抓包环境配置] --> B[流量捕获] B --> C{协议类型} C -->|HTTP| D[明文解析] C -->|HTTPS| E[SSL Pinning突破] D --> F[参数逆向] E --> F F --> G[协议重放与模拟] 1.1.1 关键分析目标…...