ChatGPT 和 Elasticsearch:分面、过滤和更多上下文

news2024/11/26 5:47:29

作者:Luca Wintergerst

在最近的一篇博客文章中,我们讨论了 ChatGPT 和 Elasticsearch® 如何协同工作以帮助更有效地管理专有数据。 通过利用 Elasticsearch 的搜索功能和 ChatGPT 的上下文理解,我们演示了如何改进结果。

在这篇文章中,我们讨论如何通过添加分面(facets)、过滤和附加上下文来进一步增强用户体验。 通过提供 ChatGPT 等工具附加上下文,你可以增加获得更准确结果的可能性。 了解 Elasticsearch 的分面和过滤框架如何允许用户优化搜索并降低使用 ChatGPT 的成本。

比较 ChatGPT 和 Elasticsearch 结果

为了改善示例应用程序的用户体验,我们添加了一项功能,可以在 ChatGPT 创建的响应旁边显示原始结果。 这将帮助用户更好地了解 ChatGPT 的工作原理。

由于我们的源数据集仅是爬行的,因此文档中的结构使得人类难以阅读。 为了显示这种差异以及 ChatGPT 可以带来的价值,我们在 GPT 创建的响应旁边添加了原始结果。

目前,此示例应用程序仅返回单个结果。 即使我们使用向量搜索和 BM25 进行混合评分,这个结果也可能并不完美。 如果我们将这个不完美的结果传递给 ChatGPT,我们得到的响应很可能也不会很好,因为上下文缺少重要信息。

理想情况下,我们只需将更多上下文传递到 ChatGPT 中,但当前的 GPT 3.5-turbo 模型仅限于 4,096 个 tokens(这包括你期望获得的响应,因此实际限制要低得多)。 未来的模型可能会有更大的限制,但这也是有代价的。

截至目前,GPT-3.5-turbo 的成本为 0.002 美元/1K 代币,而即将推出的具有 32K 上下文的 GPT-4 成本为 0.06 美元/1K 代币 — 这是 30 倍以上。 即使未来几年出现更强大的模型,对于所有用户案例来说,这样做在经济上也可能不可行。

因此,我们现在不会使用 GPT-4,而是通过发送多个并发请求并为用户提供更灵活的过滤结果来解决 GPT-3.5 的最大 token 限制。

聚合、分面(facets)和过滤

为了解决这一限制,Elasticsearch 的最大优势之一是其强大的分面和过滤框架。 当用户搜索某些内容时,他们可能会提供额外的偏好或上下文,以显着增加获得正确结果的可能性。 通过利用 Elasticsearch 的分面和过滤框架,我们可以允许用户根据各种参数(例如日期、位置或其他相关条件)优化搜索。

同样重要的是要注意,许多用户已经习惯在搜索某些内容时使用分面过滤选项。 让我们看一个例子。

搜索 “How can I parse a message with Grok(如何使用 Grok 解析消息)?” 导致摄取管道的文档作为顶部结果返回。 这并没有错,因为摄取管道也支持 Grok 表达式,但是如果用户有兴趣使用 Logstash 解析他的数据怎么办?

使用简单的术语聚合作为获取点击的请求的一部分,我们可以获得前 10 个产品类别的列表,并将其作为用户的过滤选项提供。

 

如果用户现在选择左侧的 “Logstash”,则所有结果都将针对 Logstash 进行过滤。 值得注意的是,这一切都可以在仍然使用我们在上一篇博客中讨论过的相同混合查询模型的情况下实现。 我们仍然使用 BM25 和 kNN 搜索的组合来匹配我们的文档。

 

 

并行加载多个结果

我们之前简要提到了最大 token 限制。 简而言之,你发送到 API 的提示及其响应不能超过 4,096 个 tokens。 在搜索你的专有数据时,你希望提供尽可能多的具体上下文,以便模型可以为你提供最佳答案。 然而,4,096 个 token 并不算多,尤其是当你包含代码片段之类的内容时。

减轻限制的一个非常简单的第一步就是并行多次询问,每次给出不同的上下文。 使用我们的 Elasticsearch 方法,我们可以更改应用程序以加载前 10 个命中,然后使用相应的上下文提出问题,而不是仅获取前 1 个结果并将其发送到 OpenAI。

这为我们的问题提供了 10 个独特的答案,并大大增加了我们向最终用户提供相关答案的机会。 虽然我们增加了用户查看结果的负担,但它仍然为他们提供了更大的灵活性。

可以这样想:如果你尝试调试问题并在 Google 上搜索异常,你可以快速扫描 Google 显示的前四或五个结果列表,然后单击似乎最适合你的问题的结果。 向用户显示问题的多个答案与此类似。

虽然有一个正确答案是理想的选择,但一开始有多个答案可供选择也是一个很好的起点。 正如之前提到的,与使用更昂贵的模型(例如 GPT-4)相比,它可以更便宜。

我们还可以通过提示发挥更多创意,并要求 ChatGPT 在无法使用提供的上下文回答问题时向我们发送特定响应。 这将使我们能够稍后从 UI 中删除结果。

在我们的用例中效果很好的一个提示是:

prompt = f"Answer this question: {query}\n. Don’t give information not mentioned in the CONTEXT INFORMATION. If the CONTEXT INFORMATION contains code or API requests, your response should include code snippets. If the context does not contain relevant information, answer 'The provided page does not answer the question': \n {body}"

 

解决 ChatGPT 的最大 token 限制:从一组答案中回答一个问题

由于我们现在对问题有多个答案,因此我们可以尝试将它们总结为一个答案。 为此,我们将主要遵循与之前相同的方法,但我们不会在 Elasticsearch 中搜索上下文,而是将迄今为止收到的各个答案连接起来,排除模型响应但根据所提供的上下文无法回答的任何位置 。

请注意,此运行的提示与之前的提示略有不同,因此模型对上下文的处理略有不同。 这里提供的提示并不完美,还需要根据数据进一步调整和优化。

concatResult = ""
        for resultObject in results:
            if resultObject['choices'][0]["message"]["content"] != "The provided page does not answer the question.":
                concatResult += resultObject['choices'][0]["message"]["content"]
        if st.session_state['summarizeResults']['state']:
            results = [None] * 1
            tasks = []
            prompt = f"I will give you {numberOfResults} answers to this question.: \"{query}\"\n. They are ordered by their likelyhood to be correct. Come up with the best answer to the original question, using only the context I will provide you here. If the provided context contains code snippets or API requests, half of your response must be code snippets or API requests. \n {concatResult}"
            element = None
            with st.session_state['topResult']:
                with st.container():
                    st.markdown(f"**Summary of all results:**")
                    element = st.empty()

            with elasticapm.capture_span("top-result", "openai"):
                task = loop.create_task(achat_gpt(prompt, results, counter, element))
                tasks.append(task)
                loop.set_exception_handler(handle_exception)
                loop.run_until_complete(asyncio.wait(tasks))
	      loop.close()

有了这个额外的 “减少阶段(reduce phase)”,我们的应用程序现在将:

  • 在 Elasticsearch 中搜索前 10 名点击
  • 10 次并行要求 OpenAI 回答问题,每次提供不同的上下文
  • 连接 OpenAI 的回复并再次要求 OpenAI 回答问题

通过这种设置,我们可以使用近 40,000 个上下文令牌,同时只需支付相当便宜的 GPT-3.5 模型的费用。 在另一篇博客文章中,我们将更详细地探讨成本,并使用 Elastic APM 来跟踪我们的支出以及其他指标。

应该注意的是,GPT-4 的性能可能仍然比上述方法好得多,因此请使用最适合你和你期望的流量的方法。

Elasticsearch 及 ChatGPT - 搜索 summary frozen index

ChatGPT 结果的引用

大型语言模型(LLM)的缺点之一是过度自信和产生幻觉的倾向。 你提出问题,你就会得到答案。 答案是否正确由你决定。 该模型很少承认它不知道某些事情。 正如我们上面所做的那样,提供上下文并告诉它以特定答案进行响应有助于在一定程度上缓解这种情况。

但是,所提供的上下文以及让模型承认它无法回答问题的同时,也使我们能够为回答提供更准确的引用。

在上一节中,我们将 10 个答案总结为一个全局答案。 除了提供这个全局答案之外,我们还可以提供用于编译结果的所有源文档页面的列表 - 基本上是模型未响应 “The provided page does not answer the question(提供的页面未回答问题)” 的任何页面。

在此屏幕截图中,你可以看到 Elasticsearch 的一组 10 个结果的摘要答案。 尽管我们检查了 10 个结果,但我们仅显示与回答问题实际相关的三个文档链接。 在这种情况下,Elasticsearch 返回的其他七个文档与文档或索引有关,但他们没有具体讨论如何索引某些内容。

 

搜索专有数据

我们在之前的博客文章中提到,使用 Elasticsearch 和 OpenAI 搜索专有数据非常棒。 但是,我们确实使用网络爬虫来爬取公共文档。 这可能看起来有点违反直觉,但你仔细想想是对的! OpenAI 在网络数据上训练 GPT 模型,因此我们假设它已经知道我们的文档。 那么除了这些数据之外我们为什么还需要 Elasticsearch 呢? 此设置实际上适用于非公开数据吗? 确实如此 —— 让我们证明一下。

使用现有的设置,我们将把有关内部项目的单个超级机密文档推送到我们的索引中。

PUT search-elastic-docs/_doc/1?pipeline=search-elastic-docs@ml-inference
{
  "title": "Project LfQg832p6Jx040809WZc",
  "product_name": "SuperSecret",
  "url": "https://www.example.com",
  "body_content": """What is Project LfQg832p6Jx040809WZc? Project LfQg832p6Jx040809WZc is an internal project that's not public information. This is the plan for the project: Step 1 is writing a blog post about OpenAi and Elasticsearch for private data. Step 2 is noticing that we didn't actually include any private data. Step 3 is including an example about private data
  
  We also have some super secret API requests as part of this project:
  PUT project/_doc/hello-world
  {
    "secret": "don't share this with anyone!" 
  }
  
  """
}

接下来,我们将转到我们的应用程序并搜索 “What are the steps for the internal project(内部项目的步骤是什么)?”

Elasticsearch 及 ChatGPT - 搜索 internal project

总之,对于某些用例,我们使用分面和过滤来减少与 ChatGPT 交互所需的上下文标记数量。 通过在查询时提供额外的上下文,我们表明还可以提高搜索结果的准确性。

详细了解 Elasticsearch 和 AI 的可能性。

在这篇博文中,我们可能使用了第三方生成式人工智能工具,这些工具由其各自所有者拥有和运营。 Elastic 对第三方工具没有任何控制权,我们对其内容、操作或使用不承担任何责任,也不对你使用此类工具可能产生的任何损失或损害负责。 使用人工智能工具处理个人、敏感或机密信息时请务必谨慎。 你提交的任何数据都可能用于人工智能培训或其他目的。 无法保证你提供的信息将得到安全或保密。 在使用之前,你应该熟悉任何生成式人工智能工具的隐私惯例和使用条款。

本文提到的成本基于当前的 OpenAI API 定价以及我们在加载示例应用程序时调用它的频率。

Elastic、Elasticsearch 和相关标志是 Elasticsearch N.V. 在美国和其他国家/地区的商标、徽标或注册商标。 所有其他公司和产品名称均为其各自所有者的商标、徽标或注册商标。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/701312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

制造业数字化转型难?低代码带来曙光

概要:制造业企业在数字化转型中一直面临着许多困难和挑战,中小企业更是如此。天翎低代码平台通过自身可视化设计、私有化部署、灵活性、扩展性和兼容性等特性,帮助制造业企业更好地完成数字化转型目标。不仅如此,天翎还推出了微鳄…

iview tree树形控件多选,自定义内容

项目中需要一个iview框架的树形控件,需要里面包含以下功能 1、控件宽度可展开,可缩小2、树形控件可搜索,并且定位到搜索的节点3、控件可以一键勾选,一键取消4、控件图标自定义5、 点击最后一个节点时可以进入到二级节点,点击上一节点可返回完整代码:listToTree文件 效果图: 具…

标准模版库 知识点总结 C++程序设计与算法笔记总结(八) 北京大学 郭炜

标准模版库 https://blog.csdn.net/shaozheng0503/article/details/129101932?ops_request_misc%257B%2522request%255Fid%2522%253A%2522168802585416800211563089%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id1688025854168…

前端判断img图片未能正确加载时显示一个默认图片。img标签onerror事件设置了本地默认图片还是不显示的问题

前端img标签中引用后端交给的图片地址时,有可能这个路径下图片被删除或者损坏了,那么页面在加载img图片时就显示为,太丑了。 img标签有个onerror事件,就是当图片未被正确加载的时候调用此事件,写的时候在onerror事件里…

安装国产系统Kylin-Desktop实战

前言 随着国产化系统的呼声越来越高,再加上今年6月红帽公司发表声明,只有付费才能拿到代码的通告,学习国产化势在必行。 在众多的国产化系统中,我选择了排名比较高的系统,今天我们就一起来安装下麒麟的操作系统 &…

习题-集合框架

目录 1.打印信息 2.ArrayList的使用 User类 测试类 3.Set的使用 汽车类 测试类 4.ArrayList使用 5.新闻 新闻类 测试类 6.返回索引 7.删除重复QQ 8.Map集合操作 9.成绩排序 学生类 测试类 10.Map基础题 学员类 测试类 11.遍历Map综合-国家名称 12.Collec…

1. Linux手写简单的线程池

目录 一、线程池的概念二、线程池的核心组件三、数据结构设计1、任务队列2、线程池 四、接口设计1、创建线程池2、销毁线程池3、抛出任务的接口 五、实现一个线程池及测试1、测试单生成者——多消费者2、测试多生产者——多消费者3、thrd_pool.h4、thrd_pool.c5、main.c6、thrd…

<C语言> 操作符

1.算术操作符 加法():用于将两个操作数相加。减法(-):用于将第一个操作数减去第二个操作数。乘法(*):用于将两个操作数相乘。除法(/):…

使用JavaScript获取随机数序列

使用Javascript 生成随机数 要在 Javascript 中生成随机数,可以使用 Math 对象的 random() 方法。该方法返回一个大于等于 0 小于 1 的伪随机浮点数。 Javascript中的 Math.random() 函数是一个用于生成随机数的内置函数。 MDN 官方解释 Math.random() 函数返回…

idea常用快捷方式,保姆级!图文并茂【建议收藏】

大家好,我是三叔,很高兴这期又和大家见面了,一个奋斗在互联网的打工人。 给大家分享一下idea在开发过程中使用的快捷方式把,可以极大的提升生产力,提高自己的开发速度,需要在开发中不断地使用,…

《Linux操作系统编程》 第十章 线程与线程控制: 线程的创建、终止和取消,detach以及线程属性

🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~&#x1f33…

arcgis-elasticsearch矢量数据导入及索引设计工具

插件说明 插件支持单图层导入和多图层同时导入,依赖elasticsearch包和urlLib包,使用之前请用pip安装,具体的依赖包的requirements.txt文件放在压缩包里面了。 pip install -r requirements.txt插件下载地址:https://download.cs…

DocuSign:在全球电子签名市场具有巨大上涨潜力的SaaS股

来源:猛兽财经 作者:猛兽财经 总结 (1)DocuSign的核心电子签名业务还在持续增长,尽管在疫情后增速有所放缓,但第一季度的收入已经达到了6.61亿美元,增长率为12%。 (2)Do…

Linux:通过wget下载安装mysql数据库(5.7版本)

目前,主要使用的MySQL有5.7和8.0两个版本,在安装上,5.7和8.0版本基本一致,区别只在于配置root密码和远程登陆上不同。本次将以5.7版本作为对象,进行后续安装。 1.wget下载MySQL安装文件 下载完成,得到mysq…

PySpark如何输入数据到Spark中?【RDD对象】

PySpark支持多种数据的输入,在输入完成后,都会得到一个:RDD类的对象RDD全称为弹性分布式数据集(Resilient Distributed Datasets),PySpark针对数据的处理,都是以RDD对象作为载体,即: •数据存储…

ansible实训-Day3(playbook的原理、结构及其基本使用)

一、前言 该篇是对ansible实训第三天内容的归纳总结,主要包括playbook组件的原理、结构及其基本使用方式。 二、Playbook 原理 Playbook是Ansible的核心组件之一,它是用于定义任务和配置的自动化脚本。 Ansible Playbook使用YAML语法编写,可…

Linux 学习记录42(C++篇)

Linux 学习记录42(C篇) 本文目录 Linux 学习记录42(C篇)一、class 类1. 类中的this指针(1. this指针的格式(2. 使用this指针 2. 类中特殊的成员函数(1. 构造函数>1 格式/定义>2 调用构造函数的时机>3 构造函数的初始化列表 (2. 析构函数>1 功能/格式>2 析构函数…

Redis的数据复制到另一台Redis

Redis的数据复制到另一台Redis 最近用到一个问题,需要把Redis的数据复制到另一台Redis,现在总结下解决问题的方法 解决方法一: redis-dump导出 [root ~]# redis-dump -u :password172.20.0.1:6379 > 172.20.0.1.jsonredis-load导入 [ro…

快速打造属于你的接口自动化测试框架

目录 1 接口测试 2 框架选型​​​​​​​ 3 环境搭建 4 需求 5 整体实现架构 6 RF用例实现​​​​​​​ 7 集成到CICD流程 总结: 1 接口测试 接口测试是对系统或组件之间的接口进行测试,主要是校验数据的交换,传递和控制管理过程…

Redis 高可用 RDB AOF

---------------------- Redis 高可用 ---------------------------------------- 在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 但是在Redis语境…