GenAI 客户支持 — 第 3 部分:为人类设计聊天机器人的聊天界面

news2024/9/21 12:39:38

作者:Ian Moersen

本博客系列揭示了我们的现场工程团队如何使用 Elastic stack 和生成式 AI 开发出一款可爱而高效的客户支持聊天机器人。如果你错过了本系列的其他文章,请务必查看第一部分、第二部分和第四部分。

通过 Web 应用聊天的想法已经存在了很长时间。因此,你可能会认为这意味着 GenAI 聊天机器人将是一个标准的、无聊的界面。但事实证明,AI 聊天机器人提出了一些有趣而新颖的挑战。我将在这里提到其中的一些,希望如果你希望构建自己的聊天界面,你可以使用这些技巧和窍门来帮助你。

作为一名 UI 设计师,我喜欢对小事大惊小怪。头像的十六进制颜色是否太暗?我肯定会抱怨。此工具提示上的动画是否没有正确缓动?让我们花时间寻找正确的贝塞尔曲线。不,不,相信我,这绝对值得。新页面上的字体渲染是否略有不同?哦,是的,你肯定会从 Ian(本文作者) 那里听到这个消息。

因此,当我的团队开始开发新的自动化支持助手时,我们必须决定:我们是否从架子上取下一个库来处理聊天界面?我们要从头开始开发自己的聊天机器人吗?对我来说,我几乎不想考虑前者。为我们的聊天机器人做好每一个小事是设计师的梦想。让我们开始吧。

1. 选择库

因此,当我之前说 “从头开始开发我们自己的” 时,我的意思并不是从头开始。抱歉,现在是公元 2024 年,大多数人不再从头开始开发 UI 组件。许多开发人员依靠组件库来构建新事物,在 Elastic 我们也不例外。虽然我们在一个方面非常出色:我们有自己的 Elastic UI 组件库,任何人都可以免费使用。

EUI 目前没有 “ChatBot” 组件,但它确实提供了头像、“面板”、文本区域等,可能需要创建一个漂亮的小聊天窗口。

如果你想继续阅读这篇文章的其余部分,请随时在另一个选项卡中打开我制作的这个示例 EUI 聊天界面,你可以自己试用一下。玩得开心!

2. 动画……借助一些意想不到的帮助

在设计和组装聊天界面的主要构建块(你可以在上面的沙盒链接中查看)之后,我们面临的下一个挑战是如何在聊天机器人响应的漫长时间内保持用户的参与度。更糟糕的是,我们使用的第一个 LLM 端点(用于内部 alpha 测试)没有流式传输其响应;它只是生成并将整个答案以单个 HTTP 响应主体的形式发送回给我们。这花了很长时间。不太好。

操作从 -> 到观察到的近似延迟
Initial requestClient -> server100 - 500ms
RAG searchServer -> cluster1 - 2.5s
Call to LLMServer -> LLM1 - 2.5s
First streamed byteLLM -> server -> client3 - 6s
5.1 - 11.5 seconds

我们的第一道防线是引人注目的 “加载” 动画。我想要一些自定义的、看起来有趣的东西,但同时也要非常符合 Elastic 的整体品牌指导方针。为此,我决定使用 Elastic 现有的 EuiIcon 组件来显示三个点,然后使用 Elastic 品牌颜色和 EUI 的默认动画贝塞尔曲线(这些数学描述动画如何加速和减速)来让事物在脉动、闪烁和改变颜色时感觉 “Elastic”。

在 CSS 中编排弹跳、颜色变化和不透明度淡化有点超出我的舒适范围。因此,与其花一整天时间猜测要使用的值,我突然想到我可以问坐在我面前的人。没错,我要求聊天机器人(早期版本)编写自己的加载动画。

它在第一次尝试时就得出了近乎完美的结论。经过一些微调和代码重构后,结果如下:

// An animation cycle will have three "keyframes", describing how the animation
// will look at the beginning, middle and end of a cycle.
@keyframes loadingPulsate {
  // Beginning
  0% {
    opacity: 0.85;
    color: #0077cc;
  }

  // Middle
  50% {
    transform: scale(0.5);
    opacity: 0.55;
    color: #00bfb3;
  }

  // End
  100% {
    opacity: 0.85;
    color: #f04e98;
  }
}

// A class applied to each "dot": it calls the animation with an appropriate
// bezier curve to describe how to animate the properties between keyframes
.typing-dots-animation {
  animation: loadingPulsate 1.2s cubic-bezier(0.694, 0.0482, 0.335, 1) infinite;
}

// A class applied to the second "dot"—it just delays the start of the animation
.typing-dots-animation1 {
  animation-delay: -0.4s;
}

// A class applied to the third and final "dot", delaying the start as well
.typing-dots-animation2 {
  animation-delay: -0.2s;
}

如果你能找出在上面的沙盒链接中要编辑哪些属性以亲自查看这些加载点,则可以获得加分。所有代码都在那里!)

这产生了一个令人愉悦的小加载动画,我仍然喜欢一次看几秒钟;这正是我们所需要的!现在,聊天机器人编程本身是否存在令人担忧的问题?......这个问题我将留给哲学家。但作为一名网络开发人员,我需要关注更实际的问题。比如,如果 LLM 的回复时间太长或完全中断,我们应该怎么做。

3. Killswitch 启动

在大多数传统 Web 应用中,处理网络超时和故障非常简单。只需检查响应的错误代码并进行适当处理即可。任何额外的超时处理都可以在 try/catch 块或类似块中捕获。通常,典型的 HTTP 提取将知道如何处理超时,超时通常配置为在相当短的时间后发生,并且发生的频率相对较低。

生成式 AI API 端点的当前状态并不完全如此。是的,偶尔,你会收到带有错误代码的快速故障响应,但请记住,我们在这里流式传输 LLM 的响应。很多时候,我们会快速从 API 端点收到 200 OK,这告诉我们大型语言模型已准备好开始流式传输其响应……但随后可能需要非常长的时间才能接收任何数据。或者,在流式传输过程中,路径变冷,连接挂起。

无论哪种情况,我们都不想依赖传统的网络超时来为用户提供重试问题的选项。在尝试失败时设置短暂的超时时间,然后快速、成功地重试,这比花费太长时间的成功响应要好得多。

因此,在我们发现大多数失败的流需要一分钟以上的时间才能解决后,我们开始寻找最短的时间,以确保流可能会失败(或需要过多的时间来解决)。我们不断地缩短时间,直到我们发现,在仅仅 10 秒的无线电静默之后,我们几乎可以肯定流最终会失败,或者需要一分钟以上的时间才能恢复。

以下是一些说明这一概念的伪代码。这是你可能在用户提出问题后调用流式 LLM API 的主要函数中找到的代码类型的示例。只要巧妙地使用 AbortController 信号和 setTimeout,你就可以在 fetch() 函数上实现 “killswitch”,以便在流停止超过 10 秒时快速向用户返回错误:

const KILLSWITCH_TIMEOUT_IN_SECONDS = 10;
const abortController = new AbortController();

const firstGenerationTimeoutId = setTimeout(() => {
  abortController.abort();
}, KILLSWITCH_TIMEOUT_IN_SECONDS * 1000); // Convert seconds to milliseconds for setTimeout()

return {
  promise: fetchStreamingAPI("/api/streaming-ai-endpoint", {
    body: JSON.stringify(request),
    method: "POST",
    onmessage: ({ event, data }) => {
      clearTimeout(firstGenerationTimeoutId);
      // Handle actual streaming response data here
    },
    openWhenHidden: true,
    signal: abortController.signal,
  }),
  stopGeneration: () => abortController.abort(),
};

因此,在解决了这些问题以及大约一百个其他问题之后,是时候关注站点范围的生成 AI 界面所独有的另一个挑战:上下文。

4. 聊天历史上下文

在与 AI 助手聊天时,你希望它了解你之前消息的上下文。例如,如果你要求它澄清答案,它需要 “记住” 你问它的问题以及它自己的回答。你不能只将 “你能澄清一下吗?”单独发送给 LLM 并期望得到有用的回复。

在对话中,上下文很容易找到和发送。只需将所有以前的聊天消息转换为 JSON 对象,并将其与最新问题一起发送到 LLM 端点即可。虽然可能需要考虑一些较小的问题(例如如何序列化和存储元数据或 RAG 结果),但相对来说并不复杂。下面是一段伪代码,说明如何使用对话上下文丰富默认提示。

// An example prompt
const defaultPrompt = `Role: Expert Elastic Support Engineer.\
  - Your goal is to help Elastic customers.\
  - Include the relevant url references at the end of your response.\
  - Answer only things you're sure about.\
  // ...etc
`;

// Here's one way to inject that prompt with context from earlier messages in the conversation
const addContextToPrompt = (defaultPrompt: string, chatHistory: ChatMessage[]) => (
  `${defaultPrompt}

  Additionally, this JSON object describes your conversation with the customer to this point: ${JSON.stringify(chatHistory)}`;
)

但是其他类型的上下文呢?例如:当你阅读支持案例并在页面上看到聊天小部件时,询问 AI 助手 “此案例已开庭多久了?” 不是很有意义吗?好吧,为了提供这个答案,我们需要将支持案例本身作为上下文传递给 LLM。但是,如果你正在阅读该支持案例,并且其中一个回复包含你不理解的术语,该怎么办?要求助手解释这个高度技术性的术语是有意义的。好吧,为此,我们需要向 LLM 发送不同的上下文(在我们的例子中,是从我们的知识库中搜索该技术术语的结果)。

我们如何向用户传达像上下文这样复杂而独特的东西,以便在对话中引导他们?我们如何让用户选择发送哪些上下文?也许最难的是,我们如何用如此有限的像素数量完成所有这些工作?

在设计和评估了相当多的选项(面包屑?聊天窗口内的粘性警报栏?小徽章??)之后,我们决定在文本输入区域添加一个 “前置” 元素。这样可以将上下文放在它描述的 “action item - 操作项” 旁边;上下文仅附加到你的下一个问题,而不是你的最后一个答案!

UI Element优点缺点
面包屑(Elastic 图标)占用空间小,易于交互更适合表示 URL 和路径
顶部横幅不碍事,可以进行长描述不易互动,容易迷路
微徽章轻松显示多个上下文难以编辑上下文
带数字标记的前置菜单靠近输入字段,易于交互挤占可用空间

此外,可以使用 EUI 上下文菜单让高级用户编辑他们的上下文。比方说,你想向助手询问一些需要同时参考案例历史记录和彻底搜索 Elastic 知识库的问题;这是两个非常不同的上下文。比如:“How do I implement the changes the Elastic engineer is asking me to make- 我该如何实现 Elastic 工程师要求我进行的更改?”此时,你可以使用上下文菜单,确保这两种信息来源都被用于助手的回答。

这也为我们提供了更大的灵活性。例如,如果我们希望 LLM 本身在回答每个问题后确定上下文,我们可以轻松地将其显示给用户,并且小粉色通知徽章可以在有任何更新时提醒用户。


这些只是我们在开发 GenAI 支持助手界面时需要解决的众多小问题中的一小部分。尽管现在似乎每个人都在发布聊天机器人,但我并没有看到很多在设计界面和体验时可能遇到的实际问题的细分。构建一个无摩擦的界面,重点是让流媒体体验感觉流畅,为意外超时提供便利,并为聊天上下文等复杂概念设计只有几个像素的空闲,这些只是我们需要解决的几个问题。

实现 AI 聊天机器人自然会将大部分工程重点放在 LLM 和后端服务上。但是,重要的是要记住,新工具的 UX/UI 组件也需要足够的时间和注意力。即使我们正在构建使用 AI 技术的产品,为人类设计始终很重要。

准备好自己尝试一下了吗?开始免费试用。

想要获得 Elastic 认证吗?了解下一次 Elasticsearch 工程师培训何时开始!

原文:GenAI with Elastic ELSER for Customer Support — Search Labs

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

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

相关文章

[AHK]ListBox的增删改移等操作示范

ahk v1 中对ListBox的操作:增、删、改、上移、下移等操作。 #singleinstance forcetitle ListBox 例子gui,add,listbox,xm ym w100 r20 vLB choose1 gLBevent,电话|聊天|拍拖|表白|订婚|礼金|礼盒 gui,add,edit ,xm yp250 w200 vEDT -background gui,add,butto…

c++数据结构算法题讲解

那么从本期文章开始&#xff0c;会尽量带大家一起刷题 第一题 题目 关键词 思路 源代码 class MinStack { public: void push(int val) { _st.push(val); if(_minst.empty() || val < _minst.top()) { _minst.push(val); } } void pop() { if(_st.top() _minst.top()) {…

ld_addr + UAF漏洞修复

文章目录 ciscn 2023中一条新的IO链例题&#xff1a;思路&#xff1a;分析&#xff1a;利用&#xff1a; 如何修复UAF漏洞 ciscn 2023中一条新的IO链 如果vtable check不通过&#xff0c;会走_dl_addr&#xff0c;在 _dl_addr中会调用到 在exit_hook中利用的那个函数指针&#…

LCD彩条显示——FPGA学习笔记10

部分素材来自原子哥 一、LCD简介 基本原理&#xff1a;在两块平行玻璃板中填充液晶材料&#xff0c;通过电场控制液晶分子旋转从而达到透光和遮光的目的。 LCD屏幕重要参数&#xff1a;分辨率、像素格式、驱动时序 分辨率&#xff1a; 像素格式&#xff1a; RGB&#xff1a;…

C++第四节课 - 内联函数 + 初认类

一、auto关键字 C中可以使用typeid打印变量的类型 #include<iostream> using namespace std;int main() {int a 0;int b a;auto c a;auto d 1 1.11;cout << typeid(c).name() << endl;cout << typeid(d).name() << endl;return 0; } 但是上…

ActiveMQ 的网络连接及消息回流机制

1、ActiveMQ 的网络连接 activeMQ 如果要实现扩展性和高可用性的要求的话&#xff0c;就需要用用到网络连接模式。 NetworkConnector&#xff1a;主要用来配置 broker 与 broker 之间的通信连接 如上图所示&#xff0c;MQ 服务器1 和MQ 服务器2 通过 NewworkConnector 相连&…

PhotoZoom 9安装包下载-图片无损放大编辑PhotoZoom 9 Pro软件安装

PhotoZoom 9 Pro是一款专业的图像放大软件&#xff0c;旨在提供高质量的图像放大和改进功能。适用于摄影师、设计师、印刷专业人员以及任何需要将图像放大到更大尺寸并保持高质量的用户。它使用先进的放大算法&#xff0c;能够有效地处理不同类型的图像&#xff0c;并在保持细节…

使用切换 JDK 的方式优化部署微服务占用内存过高的问题

使用切换 JDK 的方式优化部署微服务占用内存过高的问题 一、前言二、下载 J9 虚拟机的JDK三、切换 JDK1、上传到服务器2、解压3、修改 JDK 路径4、解决 JDK 没有切换成功的问题 一、前言 前段时间在服务器部署了微服务项目&#xff0c;但即使限制了每个服务的堆&#xff0c;内…

苹果首款AI手机发布!iPhone 16全新AI功能体验感拉满

苹果于2024年秋季盛大发布iPhone 16系列&#xff0c;带来前所未有的AI智能体验。iPhone 16系列不仅硬件全面升级&#xff0c;更融入了尖端的AI技术&#xff0c;为用户带来更加智能化的生活体验。 在科技春晚的舞台上&#xff0c;苹果不负众望地揭开了iPhone 16系列的神秘面纱。…

【贪心算法】(一)贪心算法理论及基础习题

【贪心算法】贪心算法理论及基础习题&#xff08;一&#xff09; 理论基础简单例题分发饼干K次取反后最大化的数组和柠檬水找零买卖股票的最佳时机 Ⅱ单调递增的数字摆动序列 两个纬度权衡问题分发糖果根据身高重建队列 理论基础 什么是贪心&#xff1a; 贪心的本质是选择每一…

[N-152]基于java贪吃蛇游戏5

开发工具eclipse,jdk1.8 文档截图&#xff1a; N-152基于java贪吃蛇游戏5

通过Python调用Excel VBA宏:扩展自动化能力的深度探索

目录 1. 引言 1.1 自动化办公的重要性 1.2 Python与Excel VBA的结合优势 2. Python调用Excel VBA宏的基本原理 2.1 Excel VBA宏的基本概念 2.2 Python调用VBA宏的方法 3. 安装与准备 3.1 安装pywin32库 3.2 配置Excel以允许宏运行 4. Python调用VBA宏的实例 4.1 导出…

基于单片机的室内装修环境检测系统设计

基于单片机的室内装修环境检测系统&#xff0c;该系统可实现苯、甲醛、氨气等有害气体的浓度检测和超标报警。该系统以STC89C52RC单片机为核心&#xff0c;由传感器检测室内装修环境中苯、甲醛、氨气的浓度以及温湿度&#xff0c;将以上测量出来的数据传送到PCF8591转换器&…

Java+vue的医药进出口交易系统(源码+数据库+文档)

外贸系统|医药进出口交易系统 目录 基于Javavue的服装定制系统 一、前言 二、系统设计 三、系统功能设计 仓储部门功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设…

15.2 JDBC数据库编程2

15.2.1 数据库访问步骤 使用JDBC API连接和访问数据库&#xff0c;一般分为以下5个步骤: (1) 加载驱动程序 (2) 建立连接对象 (3) 创建语句对象 (4) 获得SQL语句的执行结果 (5) 关闭建立的对象&#xff0c;释放资源 下面将详细描述这些步骤 15.2.2 加载驱动程序 要使…

开发中的网络问题逻辑推理分析

基于TCP/IP的逻辑推理&#xff0c;大部分软件从业人员都不是很懂&#xff0c;导致很多问题都被误认为诡异问题。有些人是惧怕TCP/IP网络书籍中的复杂知识内容&#xff0c;有的是被wireshark[1]显示的深红色内容所干扰。 经典案例1&#xff1a; 例如有一个DBA遇到了性能问题&a…

基于SpringBoot+Vue+MySQL的流浪猫狗宠物救助救援网站管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 在当今社会&#xff0c;随着宠物数量的激增及人们关爱动物意识的提升&#xff0c;流浪猫狗问题日益严峻。为解决这一问题&#xff0c;构建一套高效、便捷的流浪猫狗宠物救助救援网站管理系统显得尤为重要。本系统基于SpringBoot…

在VB.net中,TimeSpan有什么属性与方法

标题 在VB.net中&#xff0c;TimeSpan有什么属性与方法 正文 在 VB.NET 中&#xff0c;TimeSpan 结构表示时间间隔&#xff0c;即一段时间&#xff0c;而不表示特定的时间点。TimeSpan 提供了多种属性来获取时间间隔的各个组成部分&#xff0c;以及一些方法来操作这些时间间隔。…

Linux下载新版火狐浏览器,替换默认火狐浏览器,保留桌面任务栏图标快捷方式

Linux下载新版火狐浏览器&#xff0c;替换默认火狐浏览器&#xff0c;保留桌面任务栏图标快捷方式 方式一 替换默认程序入口 下载官方浏览器 火狐浏览器下载地址【官网】 &#xff08;搞清楚你的Linux系统是32位还是64位&#xff09; 解压下载的程序包&#xff0c;建议放到/o…

Leetcode面试经典150题-74.搜索二维矩阵

解法都在代码里&#xff0c;不懂就留言或者私信 二分查找&#xff0c;比较简单 class Solution {/**解题思路&#xff1a;每一行有序、每一列也有序&#xff0c;只是整体不是严格有序的&#xff0c;那我们需要找一个点&#xff0c;只能往两个方向走&#xff0c;往一个方向走是…