关于生成式AI产品的思考

在过去的六个月里,我们 LinkedIn 的团队一直在努力开发一种新的人工智能体验。我们希望重新构想我们的会员如何进行求职和浏览专业内容。

生成式人工智能的爆炸式增长让我们停下来思考一年前不可能实现的事情。我们尝试了许多想法,但都没有真正实现,最终发现了将每个信息流和招聘信息转化为跳板的力量:

  • 更快地获取信息,例如从帖子中获取要点或了解公司的最新动态。
  • 连接各个点,例如评估你是否适合某个职位。
  • 接受建议,例如改善你的个人资料或准备面试。
  • 还有更多……

构建起来容易吗?哪些进展顺利,哪些进展不顺利?在生成式AI的基础上进行构建并非一帆风顺,我们在很多地方都遇到了障碍。我们想拉开“工程”的帷幕,分享哪些事情很容易,哪些地方遇到了困难,以及接下来会发生什么。

1、概述

让我们通过一个真实场景来展示系统是如何工作的。

想象一下,你正在浏览 LinkedIn 信息流,偶然发现了一篇关于设计无障碍的有趣帖子。在帖子旁边,你会看到一些入门问题,以便更深入地探讨该主题。你很好奇,点击了“无障碍在科技公司中推动商业价值的例子有哪些?”

以下是后台发生的事情:

  • 选择合适的代理(agent):这是你的旅程的开始。我们的系统会接受你的问题,并决定哪个 AI 代理最适合处理它。在这种情况下,它会识别出你对科技公司无障碍的兴趣,并将你的查询路由到专门从事一般知识搜索问题的 AI 代理。
  • 收集信息:是时候做一些准备工作了。AI 代理调用内部 API 和 Bing 的组合,搜索具体示例和案例研究,重点介绍设计无障碍如何为科技的商业价值做出贡献。我们正在创建一个档案来为我们的回应打下基础。
  • 制定回应:有了必要的信息,代理现在可以写回应了。它会过滤和综合数据,形成一个连贯、信息丰富的答案,为你提供清晰的示例,说明无障碍计划如何为科技公司带来商业价值。为了避免生成大量文本并使体验更具交互性,会调用内部 API 来用附件(如文章链接或帖子中提到的人的个人资料)来修饰响应。

你可能会接着问“我如何将我的职业转向这个领域?”,我们会重复这个过程,但现在会将你引导到职业和工作 AI 代理。只需点击几下,你就可以深入研究任何主题,获得可行的见解或找到下一个重大机会。

其中大部分都是通过大型语言模型 (LLM) 的出现实现的,我们认为分享我们在它们的基础上构建时面临的挑战的幕后故事会很有趣。

2、容易实现的部分

图 1:处理用户查询的简化管道。KSA 代表“知识共享代理”,是数十个可以处理用户查询的代理之一

有些人可能从上面的解释中注意到,我们的管道遵循所谓的检索增强生成 (RAG),这是生成式 AI 系统的常见设计模式。构建管道出乎意料地比我们预期的要轻松。短短几天内,我们就启动并运行了基本框架:

  • 路由:决定查询是否在范围内,以及将其转发给哪个 AI 代理。代理的示例包括:工作评估、公司理解、帖子要点等。
  • 检索:面向回忆的步骤,AI 代理决定调用哪些服务以及如何调用(例如LinkedIn 人员搜索、Bing API 等)。
  • 生成:面向精确度的步骤,筛选检索到的嘈杂数据,过滤数据并生成最终响应。

考虑到“路由”和“检索”的分类性质,调整它们感觉更自然:我们构建了开发集,并用提示工程和内部模型对其进行了调整。现在,生成,这是一个不同的故事。它遵循 80/20 规则;获得 80% 很快,但最后 20% 花费了我们大部分的工作。当你对产品的期望是 99% 以上的答案应该很棒时,即使使用最先进的模型,仍然需要大量的工作和创造力才能获得每 1%。

对我们有用的方法:

  • 固定的 3 步管道
  • 用于路由/检索的小模型,用于生成的大模型
  • 基于嵌入的检索 (EBR) 由内存数据库提供支持,作为我们的“穷人的微调”,将响应示例直接注入我们的提示
  • 每步特定的评估管道,特别是用于路由/检索

我们希望在多个团队之间快速行动,因此决定将任务拆分为由不同人员开发的独立代理(即 AI 代理):一般知识、工作评估、发布要点等。

但是,这种方法带来了重大妥协。通过并行化任务,我们在速度方面获得了好处,但代价是碎片化。当与助手的后续交互可能由不同的模型、提示或工具管理时,保持统一的用户体验变得具有挑战性。

为了解决这个问题,我们采用了一种简单的组织结构。

一个小型的“水平”工程舱,处理通用组件并专注于整体体验。这包括:

  • 托管产品的服务
  • 用于评估/测试的工具
  • 所有垂直行业使用的全局提示模板(例如代理的全局身份、对话历史记录、越狱防御等)
  • 为我们的 iOS/Android/Web 客户端共享 UX 组件
  • 一个服务器驱动的 UI 框架,用于发布新的 UI 更改而无需客户端代码更改或发布。

几个“垂直”工程小组,其代理具有自主权,例如:

  • 个性化岗位总结
  • 工作适合度评估
  • 面试技巧

对我们有用的方法:

  • 分而治之但限制代理数量
  • 具有多轮对话的集中评估管道
  • 共享提示模板(例如“身份”定义)、UX 模板、工具和仪表

3、我们遇到的困难

评估我们答案的质量比预期的要困难得多。这些挑战大致可以分为三个方面:制定指导方针、扩展注释和自动评估。

  • 制定指导方针是第一个障碍。让我们以工作评估为例:点击“评估我是否适合这份工作”并得到“你不适合这份工作”的答案并不是很有用。我们希望它既真实又富有同情心。一些成员可能正在考虑转行到他们目前不太适合的领域,需要帮助了解差距和下一步。确保这些细节一致是确保我们的注释者分数统一的关键。
  • 扩展注释是第二步。最初,团队中的每个人都参与其中(产品、工程、设计等),但我们知道我们需要一种更有原则的方法,以及一致且多样化的注释者。我们的内部语言学家团队构建了工具和流程,通过这些工具和流程,我们可以评估多达 500 次日常对话并获得以下指标:总体质量得分、幻觉率、负责任的人工智能违规、连贯性、风格等。这成为我们了解趋势、迭代提示和确保我们已准备好上线的主要路标。
  • 自动评估是圣杯,但仍在进行中。没有它,工程师只能目测结果和在有限的示例集上进行测试,并且需要 1 天以上的时间才能知道指标。我们正在构建基于模型的评估器来估计上述指标并允许更快的实验,并且在幻觉检测方面取得了一些成功(但这并不容易!)。
图 2:我们执行的评估步骤。工程师进行快速、粗略的评估以获得方向性指标。注释者提供更细致的反馈,但周转时间约为 1 天。成员是最终评判者,并为我们提供衡量标准,但某些指标可能需要 3 天以上的时间才能完成一次更改

我们正在研究的内容:端到端自动评估管道,以实现更快的迭代。

3.1 调用内部 API

LinkedIn 拥有大量关于人员、公司、技能、课程等的独特数据,这些数据对于构建提供独特和差异化价值的产品至关重要。然而,LLM 尚未接受过这些信息的培训,因此无法按原样使用它们进行推理和生成响应。解决这个问题的标准模式是设置检索增强生成 (RAG) 管道,通过该管道调用内部 API,并将其响应注入后续的 LLM 提示中,以提供额外的上下文来支持响应。

许多此类独特数据通过各种微服务的 RPC API 在内部公开。虽然这对于人类以编程方式调用非常方便,但它对 LLM 不太友好。我们通过将“技能”包装在这些 API 周围来解决这个问题。每个技能都有以下组成部分:

  • 对 API 的作用以及何时使用它的人类(因此对 LLM)友好的描述。
  • 调用 RPC API 的配置(端点、输入架构、输出架构等)
  • LLM 友好型输入和输出架构:原始类型(字符串/布尔值/数字)值、JSON 架构样式输入和输出架构描述
  • 在 LLM 友好架构和实际 RPC 架构之间进行映射的业务逻辑。

此类技能使 LLM 能够执行与我们的产品相关的各种操作,例如查看个人资料、搜索文章/人员/职位/公司,甚至查询内部分析系统。同样的技术也用于调用非 LinkedIn API,例如 Bing 搜索和新闻。

图 3:使用技能调用内部 API

我们编写提示,要求 LLM 决定使用哪种技能来解决特定工作(通过规划选择技能),然后输出调用该技能的参数(函数调用)。由于调用的参数必须与输入模式匹配,因此我们要求 LLM 以结构化的方式输出它们。大多数 LLM 都使用 YAML 和 JSON 进行训练,以实现结构化输出。我们选择 YAML 是因为它不太冗长,因此比 JSON 消耗的令牌更少。

我们遇到的挑战之一是,虽然大约 90% 的时间里,LLM 响应包含正确格式的参数,但大约 10% 的时间里,LLM 会出错,并且经常输出与提供的模式不符的数据,或者更糟的是,甚至不是有效的 YAML。这些错误虽然对于人类来说微不足道,但却导致解析它们的代码崩溃。大约 10% 是一个足够高的数字,我们不能轻易忽略,因此我们着手解决这个问题。

解决此问题的标准方法是检测它,然后重新提示 LLM,要求它通过一些额外的指导来纠正错误。虽然这种技术有效,但它会增加相当多的延迟,并且由于额外的 LLM 调用而消耗宝贵的 GPU 容量。为了规避这些限制,我们最终编写了一个内部防御性 YAML 解析器。

通过对各种有效载荷的分析,我们确定了 LLM 常犯的错误,并编写了代码来在解析之前检测和适当修补这些错误。我们还修改了我们的提示,在这些常见错误周围注入提示,以提高修补的准确性。我们最终能够将这些错误的发生率降低到约 0.01%。

3.2 始终如一的质量

团队在第一个月内就实现了我们计划提供的基本体验的 80%,然后又花了四个月的时间试图超过我们完整体验的 95% 的完成度——我们努力改进、调整和提高各个方面。我们低估了检测和缓解幻觉的挑战,以及质量分数提高的速度——最初急剧上升,然后迅速趋于平稳。

对于容忍这种错误程度的产品体验,使用生成式AI进行构建非常简单。但它也创造了无法实现的期望,最初的速度让人产生一种“几乎完成”的虚假感觉,随着随后每增加 1%,改进速度就会显著放缓,这种感觉变得令人沮丧。

构建助手感觉就像背离了更“有原则的”机器学习,更像是在专家系统中调整规则。因此,虽然我们的评估变得越来越复杂,但我们的“训练”主要是提示工程,这更像是一门艺术而不是一门科学。

我们正在开展的工作:微调大型语言模型 (LLM),以使我们的管道更加以数据为驱动。

3.3 容量和延迟

容量和感知成员延迟始终是首要考虑因素。一些维度:

  • 质量 vs.延迟:思想链 (CoT) 等技术在提高质量和减少幻觉方面非常有效。但它们需要成员从未见过的token,因此增加了他们的感知延迟。
  • 吞吐量与延迟:在运行大型生成模型时,通常情况下,TimeToFirstToken (TTFT) 和 TimeBetweenTokens (TBT) 会随着利用率的增加而增加。在 TBT 的情况下,它有时可能是线性的。如果你愿意牺牲这两个指标,获得 2 倍/3 倍的 TokensPerSecond (TPS) 并不罕见,但我们最初必须将它们限制得非常严格。
  • 成本:GPU 集群并不容易获得,而且成本高昂。一开始,我们甚至必须设置时间表来确定何时可以测试产品或不可以测试产品,因为它会消耗太多token并阻止开发人员工作。
  • 端到端流式传输:完整的答案可能需要几分钟才能完成,因此我们让所有请求流式传输以减少感知延迟。更重要的是,我们实际上在管道内端到端地进行流式传输。例如,决定调用哪些 API 的 LLM 响应被逐步解析,并且我们在参数准备就绪后立即触发 API 调用,而无需等待完整的 LLM 响应。最终合成的响应也使用我们的实时消息传递基础架构一路流式传输到客户端,并对诸如信任/负责任的 AI 分类之类的内容进行增量处理。
  • 异步非阻塞管道:由于 LLM 调用可能需要很长时间才能处理,我们通过构建完全异步的非阻塞管道来优化我们的服务吞吐量,该管道不会因为 I/O 上的线程阻塞而浪费资源。

这些有时之间会产生有趣的相互作用。例如,我们最初只将 TTFT 限制为直接映射到我们初始产品的成员延迟。当我们处理幻觉并且思维链在我们的提示中变得突出时,我们忽略了 TBT 会对我们造成更大的伤害,因为任何“推理”令牌都会增加成员延迟(例如,对于 200 个令牌的推理步骤,即使 10ms 的 TBT 增加也意味着额外的 2s 延迟)。这导致我们的一个公共坡道突然发出警报,提示某些任务正在超时,我们不得不迅速增加容量以缓解该问题。

我们正在做什么:

  • 将更简单的任务转移到内部微调模型。
  • LLM 部署的更可预测的部署基础设施。
  • 减少每一步浪费的令牌。

4、结束语

说得够多了,为什么不让产品说话呢?


这还不错!尤其是后续建议,可以让你陷入维基百科式的好奇心。

随着我们继续改进质量、开发新功能和优化管道以提高速度,我们将很快向更多用户推出。

到达这里是一群优秀人员付出的巨大努力,随着我们不断学习,我们将很快分享更多技术细节。敬请期待!


原文链接:Musings on building a Generative AI product

BimAnt翻译整理,转载请标明出处