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

(附实例代码及图示)混合策略实现 doc-doc 对称检索

HyDE 混合策略

在前面的文章中,学习的优化策略都是将对应的 查询 生成 新查询,通过 新查询 来执行相应的检索,但是在数据库中存储的数据一般都是 文档 层面上的,数据会远远比 查询 要大很多,所以 querydoc 之间是不对称检索,能找到的相似性文档相对来说也比较少。

例如:**今天回家的路上看到了美丽的风景,非常开心!想学习 python 该怎么办?**这个请求中,前面的风景、开心等词语均为无关信息。会对真实的请求学习 python 产生干扰。如果直接搜索用户的请求,可能会产生不正确或无法回答的 LLM 响应。因此,有必要使得用户查询的语义空间与文档的语义空间保持一致。

资料推荐

  • 💡大模型中转API推荐
  • ✨中转使用教程
  • ✨模型优惠查询

特别是 query 和对应的相关内容(答案)可能只存在弱相关性,导致难以找到最相关的文档内容。

在这篇论文《Precise Zero-Shot Dense Retrieval without Relevance Labels》中提出了一个 HyDE混合策略 的概念,首先利用 LLM 将问题转换为回答问题的假设性文档/假回答,然后使用嵌入的 假设性文档 去检索真实文档,前提是因为 doc-doc 这个模式执行相似性搜索可以尝试更多的匹配项。

论文地址:https://arxiv.org/pdf/2212.10496

假回答和真回答虽然可能存在事实错误,但是会比较像,因此能更容易找到相关内容。

简单来说,就是先根据 query 生成一个 doc,然后根据 doc 生成对应的 embedding,再执行相应的检索,运行流程如下:
在这里插入图片描述
LangChain 中,并没有封装基于 HyDE混合策略 的检索器,所以需要自定义一个检索器,并实现 _get_relevant_documents() 方法,具象化代码如下:

from typing import Listimport dotenv
import weaviate
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.documents import Document
from langchain_core.language_models import BaseLanguageModel
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.retrievers import BaseRetriever
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_weaviate import WeaviateVectorStore
from weaviate.auth import AuthApiKeydotenv.load_dotenv()class HyDERetriever(BaseRetriever):"""HyDE混合策略检索器"""retriever: BaseRetrieverllm: BaseLanguageModeldef _get_relevant_documents(self, query: str, *, run_manager: CallbackManagerForRetrieverRun) -> List[Document]:"""传递检索query实现HyDE混合策略检索"""# 1.构建生成假设性文档的promptprompt = ChatPromptTemplate.from_template("请写一篇科学论文来回答这个问题。\n""问题: {question}\n""文章: ")# 2.构建链应用chain = ({"question": RunnablePassthrough()}| prompt| self.llm| StrOutputParser()| self.retriever)return chain.invoke(query)# 1.构建向量数据库与检索器
db = WeaviateVectorStore(client=weaviate.connect_to_wcs(cluster_url="https://mbakeruerziae6psyex7ng.c0.us-west3.gcp.weaviate.cloud",auth_credentials=AuthApiKey("ZltPVa9ZSOxUcfafelsggGyyH6tnTYQYJvBx"),),index_name="DatasetDemo",text_key="text",embedding=OpenAIEmbeddings(model="text-embedding-3-small"),
)
retriever = db.as_retriever(search_type="mmr")# 2.创建HyDE检索器
hyde_retriever = HyDERetriever(retriever=retriever,llm=ChatOpenAI(model="gpt-3.5-turbo-16k", temperature=0),
)# 3.检索文档
documents = hyde_retriever.invoke("关于LLMOps应用配置的文档有哪些?")
print(documents)
print(len(documents))

输出内容:

[Document(metadata={'source': './项目API文档.md', 'start_index': 0.0}, page_content='LLMOps 项目 API 文档\n\n应用 API 接口统一以 JSON 格式返回,并且包含 3 个字段:code、data 和 message,分别代表业务状态码、业务数据和接口附加信息。\n\n业务状态码共有 6 种,其中只有 success(成功) 代表业务操作成功,其他 5 种状态均代表失败,并且失败时会附加相关的信息:fail(通用失败)、not_found(未找到)、unauthorized(未授权)、forbidden(无权限)和validate_error(数据验证失败)。\n\n接口示例:\n\njson { "code": "success", "data": { "redirect_url": "https://github.com/login/oauth/authorize?client_id=f69102c6b97d90d69768&redirect_uri=http%3A%2F%2Flocalhost%3A5001%2Foauth%2Fauthorize%2Fgithub&scope=user%3Aemail" }, "message": "" }'), Document(metadata={'source': './项目API文档.md', 'start_index': 1621.0}, page_content='id -> uuid:应用 id,类型为 uuid。\n\nname -> string:应用名称。\n\nicon -> string:应用图标。\n\ndescription -> string:应用描述。\n\npublished_app_config_id -> uuid:已发布应用配置 id,如果不存在则为 null。\n\ndrafted_app_config_id -> uuid:草稿应用配置 id,如果不存在则为 null。\n\ndebug_conversation_id -> uuid:调试会话记录 id,如果不存在则为 null。\n\npublished_app_config/drafted_app_config -> json:应用配置信息,涵盖草稿配置、已发布配置,如果没有则为 null,两个配置的变量信息一致。\n\nid -> uuid:应用配置 id。\n\nmodel_config -> json:模型配置,类型为 json。\n\ndialog_round -> int:携带上下文轮数,类型为非负整型。'), Document(metadata={'source': './项目API文档.md', 'start_index': 5818.0}, page_content='json { "code": "success", "data": { "list": [ { "id": "1550b71a-1444-47ed-a59d-c2f080fbae94", "conversation_id": "2d7d3e3f-95c9-4d9d-ba9c-9daaf09cc8a8", "query": "能详细讲解下LLM是什么吗?", "answer": "LLM 即 Large Language Model,大语言模型,是一种基于深度学习的自然语言处理模型,具有很高的语言理解和生成能力,能够处理各式各样的自然语言任务,例如文本生成、问答、翻译、摘要等。它通过在大量的文本数据上进行训练,学习到语言的模式、结构和语义知识'), Document(metadata={'source': './项目API文档.md', 'start_index': 490.0}, page_content='带有分页数据的接口会在 data 内固定传递 list 和 paginator 字段,其中 list 代表分页后的列表数据,paginator 代表分页的数据。\n\npaginator 内存在 4 个字段:current_page(当前页数) 、page_size(每页数据条数)、total_page(总页数)、total_record(总记录条数),示例数据如下:')]
4

资料推荐

  • 💡大模型中转API推荐
  • ✨中转使用教程
  • ✨模型优惠查询
http://www.xdnf.cn/news/12684.html

相关文章:

  • FreeRTOS任务调度过程vTaskStartScheduler()任务设计和划分
  • redis分布式锁
  • Python训练营打卡DAY47
  • 4G物联网模块提升智慧农业的自动化生产效率
  • 【CSS-5】深入理解CSS复合选择器:提升样式表的精确性与效率
  • 第三章支线二 ·函数幻阶:语法召唤与逻辑封印
  • A Execllent Software Project Review and Solutions
  • 函数式接口实现分页查询
  • AI开发 | 生成式AI在企业软件中的演进形态:从嵌入式到智能体
  • nodejs:用 nodemailer 发送一封带有附件的邮件
  • 【JavaSE】集合学习笔记
  • C++ 对 C 的兼容性
  • 基于Scala实现Flink的三种基本时间窗口操作
  • 跨平台资源下载工具:res-downloader 的使用体验
  • Vue3中computed和watch的区别
  • OpenLayers 导航之运动轨迹
  • 深入剖析 RocketMQ 中的 DefaultMQPushConsumerImpl:消息推送消费的核心实现
  • Docker基础(二)
  • TTL简述
  • Unity基础-欧拉角和四元数
  • 【Elasticsearch】映射:Join 类型、Flattened 类型、多表关联设计
  • 基于springboot的藏文古籍系统
  • Nature子刊:16S宏基因组+代谢组学联动,借助MicrobiomeGS2建模揭示IBD代谢治疗新靶点
  • Java高级 | 【实验六】Springboot文件上传和下载
  • Python 中的MVC与MVP 框架与示例
  • LVGL对显示接口的要求
  • 闲庭信步使用SV搭建图像测试平台:第一课——图片的读写
  • 【商城saas和商城源码的区别】
  • 【Zephyr 系列 13】BLE Mesh 入门实战:构建基础节点通信与中继组播系统
  • 类型别名与类型自动推导