本文介绍了 Shortwave 团队开发的“生成式 AI 产品”——一个集成在电子邮件应用程序中的 AI 助手。该助手旨在利用大型语言模型 (LLM) 的推理能力,将用户的电子邮件历史转化为可操作的知识库,并提供类似于“执行助理”的体验。
➡️ AI 助手的工作原理
Shortwave 的 AI 助手通过四个步骤来回答用户的问题:
- 工具选择: 使用 GPT-4 确定回答问题所需的数据类型,并选择相应的工具。
- 工具数据检索: 并行检索每个工具相关的数据,例如电子邮件历史、日历、草稿等。
- 问题解答: 将用户问题和所有工具检索到的数据整合到一个提示中,并使用 GPT-4 生成答案。
- 后处理: 将 LLM 的输出转换为富文本,添加来源引用,并向用户提供操作建议。
➡️ AI 搜索
AI 搜索是 Shortwave AI 助手最重要的工具之一,它允许助手访问用户的整个电子邮件历史。AI 搜索通过以下步骤工作:
- 查询重构: 使用 LLM 将缺乏上下文信息的查询重写为独立的句子,例如将“Jonny 怎么样?”重写为“Jonny 什么时候到达凤凰城?”。
- 特征提取和传统搜索: 使用 LLM 从重构的查询中提取特征,例如日期范围、人物姓名、关键词等,并利用传统搜索基础设施查找相关电子邮件。
- 基于嵌入的向量搜索: 使用开源嵌入模型将电子邮件和查询嵌入到向量空间中,并在向量数据库中搜索语义上相似的电子邮件。
- 快速启发式重新排序: 使用启发式算法对检索到的电子邮件进行重新排序,以优先考虑与查询最相关的电子邮件。
- 交叉编码器重新排序: 使用交叉编码模型对重新排序后的电子邮件片段进行进一步排序,以提高结果的准确性和相关性。
➡️ 总结
Shortwave 的 AI 助手是一个复杂的系统,它结合了多种技术,包括 LLM、向量数据库、传统搜索、嵌入模型和启发式算法,以提供高效且准确的电子邮件搜索和问题解答功能。该系统仍在不断迭代,预计未来将变得更加智能、快速和强大。
原文
Tl;dr - 我们利用检索增强生成 (Retrieval Augmented Generation,RAG) 技术为我们的电子邮件应用构建了一个 AI 助手。为了构建和发布这个超越基础功能的实际解决方案,我们在技术堆栈的每个层面都投入了大量的基础设施工作。以下是我们学到的内容以及我们的系统在深层技术层面的工作方式。
–
2022 年 11 月的一个星期四下午,我们的团队聚集在旧金山一栋维多利亚风格大房子的地下室。我们的投资者和顾问 James Tamplin 把我们叫到这里,但没有解释他要给我们看什么。
“我一直在玩 AI,”他说,然后点击了他刚刚构建的 Chrome 扩展中的“总结”按钮,该扩展将 GPT-3 连接到 Shortwave 应用程序。我被震惊了。虽然我一直在随意关注 AI 的发展,但我没有准备好迎接那个生成的书写良好且正确的电子邮件摘要。显然,AI 现在不仅仅是整理文本了。AI 可以思考。
我们的团队立即看到了潜力。我们每个用户的收件箱都包含大量的文本数据:人类通信、日历邀请、收据、SaaS 通知、新闻通讯等。我们一直希望 Shortwave 能帮助用户将他们的电子邮件历史转变为可操作的知识库,但到目前为止,我们使用传统搜索基础设施的所有尝试都不尽如人意。大语言模型 (Large Language Models,LLM) 可以改变这一点。
我们的目标:一个生活在你收件箱中的执行助理
总结是一个简单且显而易见的用例(我们已经构建并发布了),但我们想要瞄准更高的目标。我们相信 LLM 的推理能力将引起用户与应用程序交互方式的重大变化,我们希望释放这种新变革技术的全部潜力。我们希望构建下一个 Uber,而不是下一个 Hertz 移动应用。
在与 alpha 用户测试了许多概念后,我们为我们的 AI 确定了一个简单的心理模型,我们认为用户会直观地理解:“一个生活在你收件箱中的 AI 执行助理”。告诉用户将我们的 AI 视为一个坐在他们旁边、对他们的电子邮件历史有完美了解的人,有助于他们推理它能做什么以及如何最好地使用它。
标准已经设定——但构建它将不是一件容易的事。人类助理极其聪明且非常多才多艺。我们面临艰巨的任务。
它是如何工作的——四个步骤
我们需要一个架构,使我们的 AI 助手随着时间的推移能够回答几乎任何问题。因此,我们设计的核心原则是所有关于如何回答问题的推理都应由 LLM 自己处理。我们的工作是找到合适的数据并将其填入提示中。
当我们看到其他团队使用长链 LLM 调用构建助手时,将推理分解为多个阶段,我们发现这种方法不切实际。根据我们的经验,长链 LLM 调用在每个阶段都会引入数据丢失和错误,导致低质量的响应。相反,我们决定采用一种设计,其中响应是使用单个 LLM 生成的,该 LLM 包含回答问题所需的所有上下文。这种方法依赖于一个极其强大的大模型和一个大的上下文窗口来工作。幸运的是,GPT-4 达到了标准。我们还预计推理能力和上下文窗口将迅速改善,因此这感觉像是正确的赌注。
有了这些原则和最终目标,我们倒推确定了最终 LLM 调用的提示中需要包含的内容。例如:要回答用户当前电子邮件线程或草稿的问题,我们应该在提示中包含这些内容;要回答用户日程安排的问题,我们应该包含他们日历中的数据。如果我们有一个具有无限上下文窗口和完美推理能力的 LLM,并且如果从我们的后端加载数据是瞬时的,我们可以在每次 LLM 调用中包含所有信息。然而,在现实系统中,我们必须非常聪明地选择包含哪些数据以及不包含哪些数据。
为了使我们的系统模块化并更容易推理,我们引入了一种称为“工具”的抽象。每种类型的数据(如日历、电子邮件历史、草稿等)将来自不同的工具,工具将内部负责决定要向最终提示添加哪些具体数据。
在高层次上,我们的 AI 助手通过四个步骤回答问题:工具选择、工具数据检索、问题回答和后处理。
第一步:工具选择
当你向 Shortwave AI 提问时,它会立即将查询传递给一个 LLM。然而,这次 LLM 调用的目的是不是回答问题,而是确定我们需要收集哪些类型的数据来回答问题。我们称这一步为“工具选择”。
工具选择需要先进的推理能力(如区分一般知识问题和需要电子邮件搜索的更个性化的问题)和对问题上下文的深刻理解。我们在这一步使用 GPT-4,并在我们的提示中包括了大量关于世界状态的细节,如当前应用程序状态(如用户正在查看的当前线程)、可用的工具、对话历史等。
我们允许工具选择返回零个、一个或多个相关工具。下表列出了一些示例用户查询,以及 LLM 可能为它们选择的工具:
查询 | 工具 |
---|---|
总结这个 | CurrentThread |
像过去那样回复 | CurrentThread、EmailHistory、Compose |
世界上最长的河是什么? | 无 |
下周有空的时间包括哪些 | Calendar、Compose、CurrentDraft |
工具选择为我们提供了一个简单且结构化的架构,便于构建和迭代。最重要的是,它使我们能够以模块化和可扩展的方式与多个异构数据源集成。
第二步:工具数据检索
一旦我们知道需要哪些工具,我们就让所有工具并行检索它们的数据。每个工具都是不同的。有些非常简单(如“总结”工具只是我们在提示中包含的自定义指令),而另一些则由复杂的分布式系统支持。我们最强大和最复杂的工具是 EmailHistory(在产品中我们称之为“AI 搜索”)。我将在本文后面详细讨论 AI 搜索。
Shortwave AI 助手中的大部分繁重工作(实际上大部分 AI 技术)实际上都是在这些模块化工具内部完成的。工具可以进行自己的 LLM 调用,运行向量数据库查询,在我们的云 GPU 集群上运行模型,访问我们的全文搜索基础设施等。
以下是我们提供的一些工具:
我们最受欢迎的功能之一是“以你的语气写作”功能。此功能由我们的 Compose 工具启用。当我们的工具选择步骤确定用户正在尝试撰写电子邮件时,我们加载再现其语气和语调所需的信息,包括其风格的预先计算文本描述和相关示例电子邮件用于少样本提示。
第三步:问题回答
在这一步,我们已经收集了回答用户问题所需的所有信息。我们要做的就是创建一个包含原始用户问题和使用各种工具获取的所有上下文信息的提示,并将其传递给 LLM(
在我们的案例中是 GPT-4)以生成答案。提示还包含许多专门的指令,如如何格式化输出和引用来源。
这一步通常需要我们在不同工具之间分配 Token 时进行权衡。例如,上述的 EmailHistory 工具通常会生成比我们能放入提示中的更多内容。我们在这里使用启发式方法在需要时做出这些权衡。
第四步:后处理
我们快完成了!我们的后处理步骤将 LLM 的输出转换为富文本,添加来源引用,并向用户建议操作(如“插入草稿”),这样他们就可以获得干净且易于使用的用户界面。
现在你已经在高层次上了解了我们的 AI 助手,让我们深入了解我们最重要且最复杂的工具。AI 搜索使我们的助手能够完全了解你的电子邮件历史。它也是让 Shortwave 的 AI 助手区别于其他电子邮件 AI 助手产品的关键。
AI 搜索的工作是从整个电子邮件历史中找到与回答用户问题相关的电子邮件,并按有用性进行排名,以便在回答问题时可以做出聪明的权衡。
AI 搜索在你提出的每个问题上投入大量的 CPU 和 GPU 计算能力,并使用 AI 和非 AI 基础设施的组合:LLM、嵌入、向量数据库、全文搜索、基于元数据的搜索、交叉编码模型和基于规则的启发式方法。它是一个庞大的系统。
让我们通过跟踪查询被引入 AI 搜索工具后的过程来了解这个系统是如何工作的。
第一步:查询改写
在我们开始寻找相关的电子邮件之前,我们需要先弄清楚用户真正想问什么。例如,考虑以下对话:
用户:我什么时候在凤凰城降落?
AI 助手:你周五飞往凤凰城的航班将于下午 6:30 到达。
用户:Jonny 呢?
这里的最后一个用户问题“Jonny 呢?”作为独立问题没有意义。但在上下文中,很明显用户在问“Jonny 什么时候在凤凰城降落?”。
查询改写解决了这个问题。它将缺乏必要上下文的查询改写为一个单独有意义的问题。查询改写会考虑用户可能引用的屏幕上可见的任何内容,包括聊天历史、当前可见的线程和任何当前草稿。因此,例如,你可以问“查找类似的电子邮件”,而查询改写会将其转化为“查找与这封关于我飞往凤凰城的航班的电子邮件类似的邮件”。
第二步:特征提取和传统搜索
通常,找到相关电子邮件的最佳方式是使用传统的全文或基于元数据的查询。如果我们能弄清楚要运行哪些查询,我们可以简单地使用我们的传统搜索基础设施来找到相关电子邮件。
幸运的是,LLM 可以在这里帮助我们。我们可以将改写后的查询与一组描述问题中可能产生有用查询的属性的特征提取相结合。我们寻找日期范围、人名、关键词、电子邮件地址、标签等。我们通过大量并行调用快速 LLM 来完成这项工作,每个 LLM 都被优化以提取特定特征。让这些 LLM 调用彼此独立,提供了一定程度的模块化,使其更容易测试和演化。每个提取的特征还会被分配一个置信度评分,表示我们对结果的确定程度。
例如,查询“Alex 昨天在做什么?”可能会产生一个覆盖昨天的日期范围特征和一个包含“Alex”的姓名特征。特征提取器可以访问相关上下文,如当前系统时间,因此它们可以解析模糊术语(如“昨天”和“上周”)。
第三步:基于嵌入的向量搜索
在许多情况下,关键词和基于元数据的搜索不足以找到我们要找的电子邮件。幸运的是,我们有一种更强大的语义感知搜索技术,可以在这些情况下帮助我们:向量嵌入搜索。
当我们将电子邮件引入 Shortwave 时,我们使用一个开源的嵌入模型(Instructor)对电子邮件进行嵌入。我们在自己的服务器上使用 GPU 加速进行此操作,以提高性能、安全性和成本。然后,我们将该嵌入存储在我们的向量数据库(Pinecone)中,每个用户命名空间(命名空间是我们选择 Pinecone 的主要原因之一)。
当使用 AI 搜索工具时,我们会嵌入用户改写后的查询,并在我们的向量数据库中搜索语义相似的电子邮件。这种技术非常强大,因为它可以让我们找到在概念上与问题相似的电子邮件,即使它们没有共享任何关键词,也不符合我们提取的任何特征。然而,当可能时,我们会使用我们之前提取的一些特征(例如日期范围)来更好地将我们的语义搜索范围限定在用户电子邮件历史的较小子集。
第四步:快速启发式重新排序
一旦我们确定了来自传统和嵌入搜索的所有电子邮件,并加载了它们的元数据,我们最终会得到一大堆电子邮件要筛选。通常,这会产生一千封以上的结果——远远超过我们能放入提示中的数量。我们需要将其缩减到只有几十个结果,而且我们需要快速完成。
这就是重新排序的作用。它帮助我们从大量低质量的潜在结果中找到一些非常有用的电子邮件来回答用户的问题。我们通过两个阶段重新排序电子邮件:第一阶段使用快速启发式方法将列表从大量缩减到更容易管理的数量,以便进行下一阶段的机器学习重新排序。
在第一阶段,我们尝试根据它们的语义相似性得分对检索到的电子邮件进行排序。这一得分对于所有通过嵌入搜索检索到的电子邮件来说是现成的。对于其他电子邮件,我们直接从 Pinecone 获取相关的嵌入向量,并在本地计算余弦相似度距离。
然而,语义相似性得分只是电子邮件内容中包含知识的表示。它不会捕捉到其他特定于元数据的关注点,如标签、日期和联系人,而用户问题可能会提到这些。语义相似性得分对我们的嵌入模型中可能固有的各种不一致也很敏感。我们通过应用一系列基于先前提取特征的本地启发式方法来克服这些限制:
- 如果我们之前从查询中提取了日期范围特征,我们会应用高斯滤波器来增强在日期范围内的电子邮件,并惩罚其他所有电子邮件。高斯滤波器的确切参数与日期范围特征的置信度评分相关。这种方法使我们能够优先考虑特定时间段内的电子邮件,但继续以一定的容忍度考虑该时间段外的电子邮件。
- 如果我们从查询中提取了任何人名或电子邮件地址,提到这些联系人的电子邮件会得到提升。同样,提升的幅度由特征的置信度评分决定。
- 如果我们从查询中提取了任何标签名,带有这些标签的电子邮件会得到提升。
- 如果查询有高时效性偏向(这是我们提取的另一个特征),我们会提升较新的电子邮件,而不是较旧的电子邮件。这对于正确处理诸如“我们上次的集体活动在哪里举行?”这样关注最近集体活动而不是旧的集体活动的问题是必要的。
- 我们优先考虑促销和更新,偏向其他高价值电子邮件。
一旦我们的启发式方法确定了电子邮件的大致排序,我们开始加载它们的全部内容(不仅仅是它们的元数据)。为了更快地执行,我们分批加载电子邮件,在进行时将它们分成长度受限的片段,并将它们流入我们的第二阶段、更昂贵的重新排序步骤。
第五步:交叉编码重新排序
我们最强大的重新排序技术是一个专门为此任务构建的开源交叉编码模型。我们使用 MS Marco MiniLM,在我们自己的 GPU 上运行。该模型比我们的启发式方法更聪明,但也更慢。因此,我们只从上一步的顶级电子邮件线程片段中挑选,并通过交叉编码模型处理它们。
交叉编码器将我们的改写查询和预先选择的电子邮件片段作为输入。它根据与问题的相关性对每个片段进行评分。然后,我们将本地启发式方法(与上一阶段使用的相同)重新应用于交叉编码器生成的评分。这有助于根据提取的特征提升或惩罚片段,并解决评分中的任何不一致。结果是一个更强健的排序,考虑了语义相关性和元数据兼容性。我们将最终排序的片段列表返回给 AI 助手,助手用它来生成对用户问题的回答。
综合起来
尽管系统复杂,但我们已经对其进行了优化,可以在 3-5 秒内回答几乎所有问题。这种端到端延迟包括多次 LLM 调用、向量数据库查找、ElasticSearch 查询、调用开源 ML 模型等。该系统大量使用并发、流式传输和流水线来实现这一目标。我们也只是向问题投入了大量计算:高端 GPU 的强大服务器和集群。
如你所见,构建一个深度集成到真实应用数据中的真实世界、生产就绪的 AI 助手是一项复杂的任务。你在这里看到的是我们的 v1。我们的团队正在继续快速迭代我们的设计,因此预计我们的助手将在未来迅速变得更聪明、更快、更强大。
我希望你喜欢这个快速概述我们助手工作方式的介绍!如果你想看看它的实际操作,请查看我们的发布视频或亲自试试看:Shortwave 是免费的。