使用 Elasticsearch 和 OpenAI 为你的客户成功应用程序构建对话式搜索

news2024/11/12 12:43:11

作者:来自 Elastic Lionel Palacin

在此博客中,我们将探讨如何通过利用大型语言模型 (LLM) 和检索增强生成 (RAG) 等技术实施对话式搜索来增强你的客户成功应用程序。

你将了解对话式搜索在客户成功应用程序环境中的优势,以及如何使用 Elasticsearch 有效地实施它。

简介

什么是客户成功应用程序

客户成功应用程序是一种允许客户自助查找支持信息的工具,这样他们就可以在需要时获得答案,并可以最大限度地提高他们使用的产品或服务的价值,并帮助他们最大限度地提高产品或服务的价值。想象一下,你正在预订网站上计划一次旅行,有一个专门的部分可以帮助你解决有关你计划的旅行的任何问题或疑问,以及联系支持人员以获得进一步帮助的选项。这就是客户成功应用程序的作用 —— 它让客户满意并确保他们对你的服务有成功的体验。

什么是 AI 对话式搜索

AI 对话式搜索允许用户使用自然语言与你的应用程序进行交互,就像与人交谈一样。该技术可以理解用户查询、检索相关信息并实时提供准确的上下文感知响应,使搜索体验更加直观和高效。

从技术角度来看,AI 对话式搜索结合了大型语言模型 (LLMs) 和检索增强生成 (RAG) 的强大功能。LLMs 能够根据大量训练数据理解和生成类似人类的文本。RAG 通过集成检索系统来增强此功能,该系统从预定义、实时和特定领域的数据集中提取相关信息,确保响应既准确又与上下文相关。

AI 对话式搜索对客户成功应用程序的好处

与传统的搜索栏体验相比,AI 对话式搜索使客户成功应用程序更加用户友好且更有帮助。它允许客户自然地提出问题并获得快速、个性化的答案,从而节省他们的时间和挫败感。此外,如果第一个答案不令人满意或他们需要更多解释,他们可以提出后续问题。

总体而言,AI 对话式搜索为客户创造了更好的体验,让他们感到被重视,并根据他们的需求为他们提供规范指导。

AI 对话式搜索的实现

在下一部分中,我们将介绍从头开始构建 AI 对话式搜索应用程序的不同步骤。

高层架构

从高级架构的角度来看,AI 对话式搜索体验的核心是 RAG 应用程序,它具有先进的检索系统(在我们的例子中是 Elasticsearch)和对话式界面。

数据收集和预处理

根据定义,客户成功应用程序环境中的 AI 对话式搜索体验需要访问专有数据。这些数据代表了你所提供的服务所特有的知识。

首先,你需要确定数据的来源,例如内部知识库、常见问题解答和文档。接下来,你需要构建一个数据管道,将这些数据带入检索系统,并准备将其用于 RAG 应用程序。

使用 Elasticsearch,你可以从任何地方提取任何类型的数据,无论是非结构化数据还是非结构化数据。查看此博客,其中解释了根据你使用 Elasticsearch 的情况使用哪种提取方法。

此外,数据需要进行转换才能在我们的 AI 对话式搜索应用中有效使用。我们希望用户使用自然语言提问,因此检索系统需要支持高级搜索技术,例如语义和混合搜索,以检索最相关的信息。这需要在段落中分块长文本并生成密集或稀疏的向量嵌入,然后再将它们索引到 Elasticsearch 中。这一切都可以在 Elasticsearch 中作为数据管道的一部分完成。查看此博客,其中介绍了如何利用 Elasticsearch 中的索引映射自动转换数据。

设置 Elasticsearch

开始使用 Elasticsearch 的最简单方法是创建一个 serverless 项目。按照此处描述的步骤,在几秒钟内即可完成 Elasticsearch 部署。

在接下来的步骤中,你将需要 Elasticsearch API 密钥和 Elasticsearch URL 端点。因此请确保检索它们。

设置数据管道

在此博客中,我们将使用示例数据集来实现我们的 AI 对话式搜索示例,并使用 Python 代码将其提取到索引 search-faq 中。

我们还想准备数据以支持语义搜索。为此,我们将利用 Elasticsearch serverless 开箱即用的 E5 多语言模型来生成向量嵌入。

第一步是准备索引映射以存储我们将提取的数据。请注意,名为 semantic 且类型为 semantic_text 的字段是将从 content 字段的内容自动生成嵌入的字段(请注意 copy_to 选项)。

让我们看看这个的 Python 代码。

from elasticsearch_serverless import Elasticsearch
import json
import os

client = Elasticsearch(
  os.getenv("ELASTICSEARCH_URL"),
  api_key=os.getenv("ES_API_KEY"),
  request_timeout=600
)

mappings={"properties":{"semantic":{"type":"semantic_text","inference_id":"e5-small"},"content":{"type":"text","copy_to":"semantic"}}}

# Create index
client.indices.create(index="search-faq", mappings=mappings)

接下来,我们需要创建一个 inference service 来操作 E5 多语言 ML 模型。

inference_config={"service":"elasticsearch","service_settings":{"num_allocations":1,"num_threads":1,"model_id":".multilingual-e5-small"}}

# Create inference
client.inference.put(inference_id="e5-small", task_type="text_embedding", inference_config=inference_config)

现在数据管道已准备就绪。它将在摄取时自动为每个文档生成向量嵌入。

with open("faq.json") as f:
    documents = json.load(f)
    
def generate_docs():
    index_name = "search-faq"
    for row in documents:
        yield { "index" : { "_index" : index_name } }
        yield row

client.bulk(operations=generate_docs())

使用 Next.Js 创建应用程序

现在我们的检索系统已经准备就绪,我们将构建一个简单的聊天界面供用户交互。

此应用程序的灵感来自此处记录的 Vercel RAG 示例。

首先,初始化 Next.JS 应用程序。

pnpm create next-app@latest chat-example --ts --tailwind --app --no-eslint --no-src-dir --no-import-alias

然后导航到应用程序文件夹 chat-example。

cd chat-example

让我们添加一个 API 路由来实现 RAG 应用程序的逻辑。聊天前端将使用用户问题调用此 API。接下来,使用语义搜索从 Elasticsearch 检索相关文档。从返回的文档生成上下文窗口,OpenAI 使用该窗口向用户提供有意义的答案。

创建一个新文件 app/api/chat/route.ts 并开始编辑它。

首先让我们添加导入并初始化 Elasticsearch 客户端连接

import { openai } from '@ai-sdk/openai';
import { convertToCoreMessages, streamText, tool } from 'ai';
const { Client } = require('@elastic/elasticsearch-serverless')
import { z } from 'zod';

const client = new Client({
  node: process.env.ELASTICSEARCH_URL, // serverless project URL
  auth: { apiKey: process.env.ES_API_KEY }, // project API key
})

然后我们声明一个使用语义搜索查询 Elasticsearch 的函数。

// Retrieve relevant content from the knowledge base
async function findRelevantContent(question: string) {
	
  // Semantic search query
  const body = await client.search({
    size: 3,
    index: 'search-faq',
    body: {
      query: {
        semantic: {
            field: "semantic",
            query: question
          }
      }
    }
  });
  return body.hits.hits.map((hit: any) => ({
    content: hit._source.content
  }));
}

最后,我们声明处理路由 POST 调用的主函数。此函数检索用户问题,使用 findRelevantContent 函数从 Elasticsearch 检索文档,然后构建上下文窗口,将其传递给 LLM,然后将答案流回客户端。

export async function POST(req: Request) {

  const { messages } = await req.json();
  const result = await streamText({
    model: openai('gpt-4-turbo'),
    system: `You are a customer service assistant, please be concise in your answer. Check your knowledge base before answering any questions.
    Only respond to questions using information from tool calls.
    if no relevant information is found in the tool calls, respond, "Sorry, I don't know."`,
    messages: convertToCoreMessages(messages),
    tools: {
      getInformation: tool({
        description: `get information from your knowledge base to answer questions.`,
        parameters: z.object({
          question: z.string().describe('the users question'),
        }),
        execute: async ({ question }: { question: string }) => findRelevantContent(question),
      }),
    },
  });

  // Respond with the stream
  return result.toAIStreamResponse();
}

现在让我们编辑前端以显示一个简单的聊天界面。打开文件 app/page.tsx 并将现有内容替换为以下内容:

'use client';

import { useChat } from 'ai/react';

export default function Chat() {
  const { messages, input, handleInputChange, handleSubmit } = useChat({
    maxToolRoundtrips: 2,
  });
  return (
    <div className="flex flex-col w-full max-w-md py-24 mx-auto stretch">
      <div className="space-y-4">
        {messages.map(m => (
          <div key={m.id} className="whitespace-pre-wrap">
            <div>
              <div className="font-bold">{m.role}</div>
              <p>
                {m.content.length > 0 ? (
                  m.content
                ) : (
                  <span className="italic font-light">
                    {'calling tool: ' + m?.toolInvocations?.[0].toolName}
                  </span>
                )}
              </p>
            </div>
          </div>
        ))}
      </div>

      <form onSubmit={handleSubmit}>
        <input
          className="fixed bottom-0 w-full max-w-md p-2 mb-8 border border-gray-300 rounded shadow-xl"
          value={input}
          placeholder="Ask your question..."
          onChange={handleInputChange}
        />
      </form>
    </div>
  );
}

默认情况下,项目使用深色主题创建。为了便于示例,我们来简化一下,打开文件 app/globals.css 并仅保留以下内容:

@tailwind base;
@tailwind components;
@tailwind utilities;

让我们测试一下我们的应用程序。在运行应用程序之前,导出以下环境变量:

# Export the URL of your Elasticsearch deployment
export ELASTICSEARCH_URL=<es_url>
# Export your Elasticsearch API Key
export ES_API_KEY=<es_api_key>
# Export your OpenAI API Key
export OPENAI_API_KEY=<openai_api_key>

安装项目依赖项:

pnpm install ai @ai-sdk/openai zod @elastic/elasticsearch-serverless

最后,在本地运行该应用程序:

yarn dev

就这样,你构建了第一个 AI 对话搜索!

该示例的工作代码可以在 Github 中找到。

结论

在本文中,你了解了在构建客户成功应用程序时使用 AI 对话式搜索相对于传统搜索体验的优势。然后,你看到了有关如何使用 Elasticsearch、OpenAI 和 Next.JS 构建 AI 对话式搜索的端到端指南。使用本教程开始使用生成式 AI 和 Elasticsearch 增强客户体验。你还可以查看 Kibana 中的 Playground 以快速开始对话式搜索。

准备好自己尝试了吗?开始免费试用。
希望将 RAG 构建到你的应用程序中?想要尝试使用矢量数据库的不同 LLM?
在 Github 上查看我们针对 LangChain、Cohere 等的示例笔记本,并立即加入 Elasticsearch Relevance Engine 培训。

原文:Build a Conversational Search for your Customer Success Application with Elasticsearch and OpenAI — Search Labs

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

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

相关文章

复制配置,多个端口号一起开启。

选择 输入&#xff1a;-Dserver.port8082

安卓原生聊天面板开发(一)整体规划

系列文章 安卓原生聊天面板开发&#xff08;一&#xff09;整体规划 安卓原生聊天面板开发&#xff08;二&#xff09;emoji功能实现 安卓原生聊天面板开发&#xff08;三&#xff09;录音交互实现 安卓原生聊天面板开发&#xff08;四&#xff09;整体交互实现 背景 产品喝…

Android 小白菜鸟从入门到精通教程

前言 Android一词最早出现于法国作家利尔亚当&#xff08;Auguste Villiers de l’Isle-Adam&#xff09;在1886年发表的科幻小说《未来的夏娃》&#xff08;L’ve future&#xff09;中。他将外表像人的机器起名为Android。从初学者的角度出发&#xff0c;通过通俗易懂的语言…

记录通过SSH连接Linux(VM)过程

记录通过SSH连接Linux&#xff08;VM&#xff09;过程 打开VM的虚拟网络编辑器&#xff0c; 点击NAT 设置&#xff0c;记录一下子网和网关 进入虚拟机&#xff0c;输入&#xff1a;vim /etc/sysconfig/network-scripts/ifcfg-ens*; 网关改成和上面一样的网关&#xff0c;IP…

Zabbix介绍和架构

目录 一.Zabbix简介 1.为什么需要监控 2.需要监控什么 3.常见的监控工具 4.Zabbix使用场景及系统概述 5.Zabbix 架构 6.Zabbix工作流程 7.Zabbix 术语 二. 部署安装zabbix 三.zabbix 配置文件 一.Zabbix简介 1.为什么需要监控 运维行业有句话:“无监控、不运维”&am…

朋友圈运营分享干货

朋友圈运营技巧对于提升个人或品牌的曝光度、增强用户粘性以及实现营销目标至关重要。 本篇是一些清晰、实用的朋友圈运营技巧~ 目标定位 明确目标群体&#xff1a;了解目标用户的年龄、兴趣、需求等特征以便精准定位内容。 竞争对手分析&#xff1a;观察和分析竞争对手的运…

echarts图表

记一个简单的关于轴线和toolip图表配置 getEcharts(xAxisData, analysisData) {// console.log(analysisData,"数据");var chart this.$echarts.init(this.$refs.classEcharts)let option {tooltip: {trigger: axis,className: echarts-tooltip,backgroundColor:…

vue+element的table合并单元格(竖着合并行)及合计行添加并计算

1 效果: 代码分析: 1 表格头配置: 2 懒得写的:自己复制吧 <el-table:data"tableData"style"width: 98%":height"height"v-loading"isLoading"stripe"false" :span-method"objectSpanMethod"show-summary:summ…

Redis之Zset

目录 一.介绍 二.命令 三.编码方式 四.应用场景 Redis的学习专栏&#xff1a;http://t.csdnimg.cn/a8cvV 一.介绍 ZSET&#xff08;有序集合&#xff09;是 Redis 提供的一种数据结构&#xff0c;它与普通集合&#xff08;SET&#xff09;类似&#xff0c;不同之处在于每个…

【Node】node的fs模块介绍及使用(一)

文章目录 简言File systemPromise example 承诺示例Callback example 回调示例Synchronous example 同步示例Promises API 承诺APIClass: FileHandleEvent: close 关闭文件filehandle.appendFile(data[, options]) 添加数据filehandle.chmod(mode) 修改权限filehandle.chown(ui…

安全防御---防火墙双击热备与带宽管理

目录 一、实验拓扑 二、实验需求 三、实验的大致思路 四、实验过程 4、基础配置 4.1 FW4的接口信息 4.2 新建办公&#xff0c;生产&#xff0c;游客&#xff0c;电信&#xff0c;移动安全区域 4.3 接口的网络配置 生产区:10.0.1.2/24 办公区:10.0.2.2/24 4.4 FW4的…

word的进阶

Word的基本操作 这里主要用到的软件是WPS软件。 一、创建一个文档 第一种&#xff1a;快捷键&#xff1a;ctrln第二种&#xff1a;通过界面鼠标点击 二、设置文档背景 更换过的背景如下&#xff1a; 三、章节、目录导航的设置 四、插入目录页 五、对历史文档进行管理 六、…

Unity UGUI 之EventSystem

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 1.EventSystem是什么&#xff1f; 有需要请查看手册&#xff1a;Unity - 手册&#xff1…

业务架构、数据架构、应用架构和技术架构分析

一文看懂&#xff1a;什么是业务架构、数据架构、应用架构和技术架构 TOGAF&#xff08;开放集团架构框架&#xff09;是企业广泛应用的架构设计和管理利器。其核心在于四大架构领域&#xff1a;业务、数据、应用和技术&#xff0c;助力组织高效运作。TOGAF&#xff0c;让架构设…

python计算PMF、PDF、CDF、PPF、KDE介绍

目录 1. 总括1.1 绘图示例1.2 概念介绍1. PMF (Probability Mass Function)2. PDF (Probability Density Function)3. CDF (Cumulative Distribution Function)4. PPF (Percent Point Function)5. KDE (Kernel Density Estimation)1. 总括 1.1 绘图示例 上图展示了PMF、PDF、C…

关于css中flex布局垂直居中失效问题的原因

项目中遇到用flex进行页面布局后&#xff0c;使用上下居中设置&#xff1a;align-item: center; 目标效果如下&#xff1a; 但是失效&#xff0c;不起作用&#xff0c;如下图所示&#xff1a; 各种排查过后发现设置了子模块 align-self 属性&#xff0c;这会覆盖容器上的 al…

科研绘图系列:R语言微生物堆积图(stacked barplot)

介绍 堆叠条形图是一种数据可视化图表,它通过将每个条形分割成多个部分来展示不同类别的数值。每个条形代表一个总体数据,而条形内的每个部分则代表该总体数据中不同子类别的数值。这种图表特别适合展示整体与部分的关系,以及各部分在整体中的比例。 特点: 多部分条形:每…

laravel为Model设置全局作用域

如果一个项目中存在这么一个sql条件在任何情况下或大多数情况都会被使用&#xff0c;同时很容易被开发者遗忘&#xff0c;那么就非常适用于今天要提到的这个功能&#xff0c;Eloquent\Model的全局作用域。 首先看一个示例&#xff0c;有个数据表&#xff0c;结构如下&#xff1…

【HarmonyOS】HarmonyOS NEXT学习日记:四、布局与容器组件

【HarmonyOS】HarmonyOS NEXT学习日记&#xff1a;四、布局与容器组件 学习了基础组件之后&#xff0c;想要利用基础组件组装成一个页面&#xff0c;自然就要开始学习布局相关的知识。我理解的ArkUI的布局分为两个部分 一、组件自身的通用属性&#xff0c;诸如weight、height、…