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

【RAG】【retrievers08】基于Together.ai长上下文嵌入的混合检索

案例目标

本案例展示如何使用Together.ai的长上下文嵌入模型实现混合检索系统,结合块级别和文档级别的相似度计算,提高RAG系统的检索质量。通过将文档嵌入与块嵌入相结合,利用文档级别的语义信息辅助块级别的检索,从而获得更准确的检索结果。

技术栈与核心依赖

llama-index-embeddings-together

llama-index-llms-openai

llama-index-readers-web

llama-index-readers-file

llama-index-core

BeautifulSoup4

llama-index-vector-stores-chroma

openai

环境配置

# 安装必要的依赖
pip install llama-index-embeddings-together llama-index-llms-openai
pip install llama-index-readers-web llama-index-readers-file
pip install llama-index-core beautifulsoup4
pip install llama-index-vector-stores-chroma openai

# 设置API密钥
import os
os.environ["TOGETHER_API_KEY"] = "your_together_api_key"
os.environ["OPENAI_API_KEY"] = "your_openai_api_key"

案例实现

1. 数据准备

步骤 1

使用BeautifulSoup爬取LlamaIndex文档,获取120个链接的内容:

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin

def get_all_links(url):
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
links = []
for link in soup.find_all('a'):
href = link.get('href')
if href and href.startswith('/') and not href.startswith('//'):
full_url = urljoin(url, href)
links.append(full_url)
return links

步骤 2

使用AsyncHtmlLoader和Html2TextTransformer处理网页内容:

from llama_index.readers.web import AsyncHtmlLoader
from llama_index.core.node_parser import HTML2TextTransformer

loader = AsyncHtmlLoader(urls[:120])
docs = await loader.aload_data()

transformer = HTML2TextTransformer()
transformed_docs = transformer.transform_documents(docs)

2. 混合检索器实现

步骤 3

初始化Together嵌入模型:

from llama_index.embeddings.together import TogetherEmbedding

embed_model = TogetherEmbedding(
model_name="togethercomputer/m2-bert-80M-8k-retrieval",
api_key=os.environ["TOGETHER_API_KEY"]
)

步骤 4

创建自定义混合检索器类:

class HybridRetriever(BaseRetriever):
def __init__(
self,
vector_retriever,
doc_retriever,
alpha=0.5, # 平衡块和文档相似度的权重
):
self.vector_retriever = vector_retriever
self.doc_retriever = doc_retriever
self.alpha = alpha
super().__init__()

def _retrieve(self, query_bundle: QueryBundle):
# 获取块级别的检索结果
vector_nodes = self.vector_retriever.retrieve(query_bundle)

# 获取文档级别的检索结果
doc_nodes = self.doc_retriever.retrieve(query_bundle)

# 创建文档ID到文档节点的映射
doc_id_to_node = {node.node_id: node for node in doc_nodes}

# 计算混合分数
hybrid_nodes = []
for node in vector_nodes:
# 获取节点所属文档的ID
doc_id = node.metadata.get("doc_id")
if doc_id and doc_id in doc_id_to_node:
# 获取文档级别的相似度
doc_node = doc_id_to_node[doc_id]
doc_similarity = doc_node.score

# 计算混合分数
node_score = node.score
hybrid_score = (1 - self.alpha) * node_score + self.alpha * doc_similarity

# 更新节点分数
node.score = hybrid_score

hybrid_nodes.append(node)

# 按混合分数排序
hybrid_nodes.sort(key=lambda x: x.score, reverse=True)

return hybrid_nodes

3. 构建检索系统

步骤 5

创建文档级别的向量存储:

from llama_index.core import Document, VectorStoreIndex, StorageContext
from llama_index.core.node_parser import SentenceSplitter

# 创建文档对象
documents = [Document(text=doc.text, metadata={"doc_id": str(i)}) for i, doc in enumerate(transformed_docs)]

# 创建文档级别的节点解析器(不分割文档)
doc_parser = SentenceSplitter(chunk_size=1000000) # 设置一个很大的值,确保不分割

# 创建文档级别的索引
doc_index = VectorStoreIndex.from_documents(documents, embed_model=embed_model, transformations=[doc_parser])
doc_retriever = doc_index.as_retriever(similarity_top_k=10)

步骤 6

创建块级别的向量存储:

# 创建块级别的节点解析器
chunk_parser = SentenceSplitter(chunk_size=512)

# 创建块级别的索引
chunk_index = VectorStoreIndex.from_documents(documents, embed_model=embed_model, transformations=[chunk_parser])
vector_retriever = chunk_index.as_retriever(similarity_top_k=10)

步骤 7

创建混合检索器:

# 创建混合检索器
hybrid_retriever = HybridRetriever(
vector_retriever=vector_retriever,
doc_retriever=doc_retriever,
alpha=0.5 # 平衡块和文档相似度的权重
)

4. 查询与评估

步骤 8

执行查询并比较结果:

from llama_index.core.query_engine import RetrieverQueryEngine

# 创建查询引擎
query_engine = RetrieverQueryEngine(hybrid_retriever)
base_query_engine = chunk_index.as_query_engine(similarity_top_k=10)

# 执行查询
query_str = "What is the LLM interface in LlamaIndex?"
response = query_engine.query(query_str)
base_response = base_query_engine.query(query_str)

# 打印结果
print("混合检索结果:")
print(str(response))
print("\n基础检索结果:")
print(str(base_response))

案例效果

混合检索系统相比仅使用块级别检索的基线系统,在检索质量和答案相关性方面有明显提升。通过结合文档级别的语义信息,混合检索器能够更好地理解查询意图,并返回更相关的文档块。

混合检索器的优势

  • 更准确的排序:文档级别的相似度信息帮助调整块级别的检索结果排序
  • 上下文感知:考虑整个文档的语义,而不仅仅是单个块的局部信息
  • 减少噪声:过滤掉来自不相关文档的高分块
  • 灵活性:通过alpha参数可以灵活调整块级别和文档级别相似度的权重

案例实现思路

本案例的核心思路是通过结合两种不同粒度的检索策略来提高检索质量:

  1. 双粒度索引:同时构建文档级别和块级别的向量索引,分别捕获整体文档语义和局部文本细节
  2. 相似度融合:通过加权平均的方式融合两种粒度的相似度分数,平衡局部和全局信息
  3. 动态权重调整:通过alpha参数可以灵活调整两种相似度的权重,适应不同场景的需求
  4. 长上下文嵌入:利用Together.ai的长上下文嵌入模型,更好地处理长文档的语义表示

这种混合检索方法特别适用于处理长文档集合,其中单个文档包含多个相关但不连续的主题。通过考虑文档级别的语义,可以避免检索到来自不相关文档的高分块,从而提高整体检索质量。

扩展建议

  • 多级混合检索:扩展到更多粒度级别,如段落级别、句子级别等
  • 动态权重调整:根据查询类型或内容动态调整alpha参数
  • 重排序集成:在混合检索结果基础上应用重排序模型进一步优化结果
  • 查询扩展:结合查询扩展技术提高检索覆盖率
  • 多模态混合:扩展到多模态内容,结合文本、图像等多种信息的检索
  • 自适应检索:根据文档特征自动选择最适合的检索策略组合

总结

基于Together.ai长上下文嵌入的混合检索系统通过结合块级别和文档级别的检索策略,有效提高了RAG系统的检索质量。这种方法特别适用于处理长文档集合,能够同时考虑局部文本细节和整体文档语义,从而返回更相关的检索结果。

混合检索的核心优势在于它能够克服单一检索策略的局限性,通过多粒度信息的融合获得更全面的语义理解。随着长上下文嵌入模型的发展,这种混合检索方法将在处理复杂文档集合和多样化查询需求方面发挥越来越重要的作用。

http://www.jsqmd.com/news/862041/

相关文章:

  • 4 类国产企业即时通讯平台推荐榜:如何为安全协同构建私有化底
  • AI 大模型技术架构演进与应用落地瓶颈分析
  • 西门子PLC对接须知:从通信到编程的实战指南
  • 用LLM从零搭3D小世界编辑器|小白也能搞定的AI Native开发实录
  • 【RHCA+】info命令(模块化的命令帮助文档)
  • 【RAG】【retrievers09】Pathway检索器:实时数据索引与检索
  • 适配多层级组织管理,科学运用 360 度反馈打造公平高效绩效文化
  • 2026年整箱榨菜厂家精选合集 - 行业平台推荐
  • 第2章:文档加载与智能分块——RAG的第一步
  • HTTP状态码与请求方式全解析【个人八股】
  • VGG16猫狗二分类
  • 工程实战:基于 GPIO 物理旁路极速部署机器人电梯调度系统的设计
  • 微波遥感杂谈五(微波辐射计)
  • 仪式感,从来与你无关
  • 慢驴效应(懒驴效应)
  • 3.url编码
  • Spec-Kit + Superpowers 实战:Go语言博客论坛系统的规范驱动开发
  • VisionPro 中 验证工具 ID Verfiction
  • 性价比高的国产PLM软件公司
  • 关于 ops-transformer 和它背后那套系统,几个我见过最常见的误解
  • 数采网关的应用与特点
  • 2025-2026年国内跨境电商TRO解冻机构:五大机构产品好的产品下架风险应对注意事项
  • 本科论文不用熬大夜?paperxie 智能写作,把万字初稿的时间从 30 天压到 3 小时
  • LeetCode 27 · 移除元素——双指针一次遍历搞定,O(n²) 暴力解瞬间不香了
  • 11.三层网络VXLAN
  • 【SSD】闪存1
  • VGG16猫狗二分类数据集处理
  • ops-transformer 基础设施性能实验报告:GE 融合边界与 Runtime 调度效率实测
  • 机器学习之逻辑回归算法
  • 远程技术面试的潜规则:摄像头角度可能影响你的录用