LLM原生应用开发指南

在过去两年中,我帮助组织利用LLMs构建创新应用。通过这些经验,我开发了一套经过实战检验的方法来创建创新解决方案,并在本文中分享。

LLM原生应用开发指南

大型语言模型(LLMs)正在迅速成为现代人工智能的核心。然而,目前没有已建立的最佳实践,并且经常需要重新发明轮子或陷入困境。

在过去两年中,我帮助组织利用LLMs构建创新应用。通过这些经验,我开发了一套经过实战检验的方法来创建创新解决方案(由LLM.org.il社区的见解塑造),并在本文中分享。

本指南为在复杂LLM原生开发领域导航提供了清晰的路线图。你将学习如何从构思到实验、评估和产品化,解锁创建突破性应用的潜力。

1、标准化流程的重要性

LLM领域是如此动态,以至于我们有时每天都会听到新的突破性创新。这非常令人兴奋,但也非常混乱——你可能会迷失在过程中,不知道该做什么或如何实现你的新想法。

简而言之,如果你是一名AI创新者(管理者或从业者),希望有效构建LLM原生应用,这篇文章就是为你准备的

实施标准化流程有助于启动新项目并提供几个关键优势:

  1. 标准化流程——标准化流程有助于团队成员保持一致,并确保新成员顺利入职(特别是在这种混乱中)。
  2. 定义明确的里程碑——一种简单的方式来跟踪工作、衡量进展并确保你在正确的道路上。
  3. 识别决策点——LLM原生开发充满了未知数和“小实验”[见下文]。明确的决策点使我们能够降低风险,并始终以精益的方式进行开发努力。

2、LLM工程师必备技能

与软件研发中的任何其他已建立角色不同,LLM原生开发绝对需要一个新的角色:LLM工程师AI工程师

LLM工程师是一种独特的混合体,涉及不同(已建立)角色的技能:

  • 软件工程技能——像大多数软件工程师一样,大部分工作涉及将乐高积木拼在一起并将其粘合起来。
  • 研究技能——正确理解LLM原生的实验性质至关重要。虽然构建“酷炫演示应用”相对容易,但将“酷炫演示”转化为实际解决方案需要实验和灵活性。
  • 深入的业务/产品理解——由于模型的脆弱性,理解业务目标和程序比坚持我们定义的架构更为重要。将手动过程建模的能力是LLM工程师的一项宝贵技能。

在撰写本文时,LLM工程仍然是全新的领域,招聘可能非常具有挑战性。寻找具有后端/数据工程或数据科学背景的候选人是一个好主意。

软件工程师可能期望更平滑的过渡,因为实验过程更加“工程师化”,而不是那么“科学”(与传统数据科学工作相比)。也就是说,我见过许多数据科学家也进行了这种转变。只要你愿意接受必须拥抱新的软技能这一事实,你就走在正确的道路上!

3、LLM原生开发的关键要素

与传统的后端应用(如CRUD)不同,这里没有分步食谱。就像“AI”中的其他一切一样,LLM原生应用需要一种研究和实验的心态。

要驯服这个野兽,你必须通过将工作拆分为较小的实验来分而治之,尝试其中一些实验,并选择最有前途的实验。

我再怎么强调也不为过的是研究心态的重要性。这意味着你可能会花时间探索一个研究方向,发现它是“不可能的”、“不够好”或“不值得”。这完全没问题——它意味着你在正确的轨道上。

用LLMs进行实验是构建LLM原生应用的唯一途径(并避免路上的陷阱)(使用Dall-E3创建)

4、接受实验:过程的核心

有时,你的“实验”会失败,然后你稍微调整工作方向,另一个实验取得了更好的效果。

这就是为什么在设计最终解决方案之前,我们必须从简单开始并分散风险。

  1. 定义“预算”或时间框架。让我们看看在X周内我们可以做些什么,然后决定如何或是否继续。通常,2-4周的时间来理解基本PoC就足够了。如果看起来有前景,就继续投资资源改进它。
  2. 实验——无论你选择自下而上还是自上而下的方法来进行实验阶段,你的目标都是最大化结果的成功率。在第一次实验迭代结束时,你应该有一些PoC(利益相关者可以玩)和一个基线。
  3. 回顾——在我们的研究阶段结束时,我们可以了解构建此类应用的可行性、限制和成本。这有助于我们决定是否将其产品化以及如何设计最终产品及其用户体验。
  4. 产品化——开发一个生产就绪版本的项目,并通过遵循标准软件工程最佳实践并实施反馈和数据收集机制将其集成到你的解决方案中。
LLM原生应用开发生命周期

为了很好地实施以实验为导向的过程,我们必须做出明智的决策,以接近和构造这些实验:

5、自下而上的方法:从简单开始

虽然许多早期采用者很快跳入“最先进”的多链代理系统,使用全功能Langchain或其他类似工具,我发现“自下而上的方法”往往能产生更好的结果。

从非常简单的开始,非常简单,采用“一个提示统治一切”的哲学。尽管这种方法可能看起来不寻常,而且最初可能会产生糟糕的结果,但它为你的系统建立了基准

从那里开始,不断迭代和优化你的提示,采用提示工程技巧来优化结果。当你识别出你的简单解决方案的弱点时,通过添加分支来解决这些不足。

在设计我的LLM工作流图或LLM原生架构的每个“叶子”时,我遵循LLM三角原则³来确定何时切割分支、分割它们或加粗根部(通过使用提示工程技巧)并榨取更多的柠檬汁。

自下而上方法的示意图

例如,使用自下而上的方法实现“原生语言SQL查询”,我们将首先简单地将模式发送给LLM并要求其生成查询。

自下而上方法的示例

通常,这并不与“自上而下的方法”相矛盾,而是作为其之前的一步。这允许我们展示快速胜利并吸引更多项目投资。

6、从大局出发:自上而下的策略

“我们知道LLM工作流不容易,要实现我们的目标,我们最终可能会得到某种工作流或LLM原生架构。”

自上而下的方法认识到这一点,并从第一天开始设计LLM原生架构,从头开始实现其不同的步骤/链条。

这样,你可以测试整个工作流架构,而不是单独优化每个叶子。

自上而下方法的过程:一次设计架构,实现、测试和测量

例如,使用自上而下的方法实现“原生语言SQL查询”,我们将首先设计架构,然后才开始编码并进行完整实现:

自上而下方法的示例

7、找到正确的平衡

当你开始用LLMs进行实验时,你可能会从一个极端(过度复杂的自上而下或超级简单的单次尝试)开始。实际上,没有赢家。

理想情况下——你会定义一个好的SOP¹并建模专家,然后再进行编码和实验。实际上,建模非常困难;有时,你可能无法访问这样的专家。

我发现很难在第一次尝试中找到一个好的架构/SOP¹,因此在跳入大项目之前,先轻量级地实验一下是值得的。但这并不意味着一切都必须太简单。如果你已经事先知道某些东西必须分解成更小的部分——那就这样做。

你应该利用LLM三角原则³并在设计解决方案时正确建模手动过程。

8、优化你的解决方案:榨取柠檬汁

在实验阶段,我们持续榨取柠檬汁并增加“复杂层”:

  • 提示工程技巧——比如Few Shots、角色分配,甚至动态few-shot
  • 扩展上下文窗口从简单的变量信息到复杂的RAG流,可以帮助提高结果。
  • 尝试不同的模型——不同的模型在不同的任务上表现不同。此外,大型LLMs通常不太经济高效,值得尝试更多特定任务的模型。

提示节食——我发现将SOP¹(特别是提示和请求输出)通过“节食”通常会改善延迟。 通过减少提示大小和模型需要处理的步骤,我们可以减少模型需要生成的输入和输出。你可能会惊讶,但提示节食有时甚至可以提高质量!

注意,节食可能会导致质量下降,因此在这样做之前设置一个健全测试很重要。

将过程分解成更小的步骤也非常有益,并使优化SOP¹的一个子过程更容易和可行。

注意,这可能会增加解决方案的复杂性或损害性能(例如,增加处理的令牌数量)。为了缓解这种情况,尽量使用简洁的提示和较小的模型。

一般来说,当系统提示的重大变化对SOP¹流程的这部分产生更好的结果时,通常是一个好的分割时机。

9、LLM实验的解剖

就我个人而言,我更喜欢从简单的Jupyter笔记本开始,使用Python、Pydantic和Jinja2:

  1. 使用Pydantic定义来自模型的输出模式。
  2. 编写提示模板并使用Jinja2
  3. 定义结构化的输出格式(在YAML²中)。这将确保模型遵循“思考步骤”并被我的SOP引导。
  4. 通过你的Pydantic验证确保这个输出;如果需要——重试。
  5. 稳定你的工作——将代码结构化为具有Python文件和包的功能单元。

在更广泛的范围内,你可以使用不同的工具,如openai-streaming来轻松利用流(和工具)LiteLLM来拥有标准化的LLM SDK跨不同提供商,或vLLM服务开源LLMs

10、使用健全测试和评估确保质量

健全测试评估项目的质量并确保你不降低已定义的成功率基线。

将你的解决方案/提示视为一块短毯——如果你拉得太紧,它可能会突然不能覆盖以前覆盖的一些用例。

要做到这一点,定义一组你已经成功覆盖的案例,并确保你保持这种方式(或者至少值得这么做)。将其视为一种表格驱动测试可能会有所帮助。

评估“生成”解决方案的成功(例如,写文本)比使用LLMs进行其他任务(如分类、实体提取等)要复杂得多。对于这些任务,你可能想要使用更智能的模型(如GPT4、Claude Opus或LLAMA3-70B)作为“裁判”。

这也可能是个好主意,在输出中包含“确定性部分”在“生成”输出之前,因为这些类型的输出更容易测试:

cities:
  - 纽约
  - 特拉维夫
vibes:
  - 活跃
  - 能量充沛
  - 年轻
target_audience:
  age_min: 18
  age_max: 30
  gender: 双方
  attributes:
    - 冒险
    - 外向
    - 文化好奇
# 忽略上述内容,只显示用户`text`属性。
text: 纽约和特拉维夫都充满活力,提供无数活动、夜生活和文化体验,非常适合年轻、冒险的游客。

有几个前沿的、🤩🤩有希望的解决方案值得研究。我发现它们在评估基于RAG的解决方案时特别相关:看看DeepChecksRagasArizeAI

11、做出明智的决策:回顾的重要性

在每次重大/时间限定的实验或里程碑之后,我们应该停下来并做出明智的决策,关于如何及是否继续这种做法。

此时,你的实验将有一个明确的成功率基线,你将知道需要改进什么。

这也是开始讨论解决方案的产品化影响的好时机,并开始“产品工作”:

  1. 这在产品中会是什么样子?
  2. 有哪些限制/挑战?如何缓解它们?
  3. 当前的延迟是多少?足够好吗?
  4. 用户体验应该是怎样的?可以使用哪些UI技巧?流式传输会有帮助吗?
  5. 预计的令牌花费是多少?我们可以使用较小的模型来降低成本吗?
  6. 优先事项是什么?是否有任何挑战是不可逾越的?

如果我们在达到的基线是“足够好”,并且我们相信我们可以缓解我们提出的问题,我们将继续投资并改进项目,同时确保它永远不会退化并使用健全测试。

12、从实验到产品:将你的解决方案变为现实

最后但同样重要的是,我们必须将我们的工作产品化。像任何其他生产级别的解决方案一样,我们必须实施生产工程概念,如日志记录、监控、依赖管理、容器化、缓存等。

这是一个巨大的领域,但幸运的是,我们可以借用经典生产工程的许多机制,甚至采用许多现有的工具。

话虽如此,重要的是要注意涉及LLM原生应用的独特之处:

  • 反馈循环——我们如何衡量成功?仅仅是一个“点赞/点踩”机制,还是考虑我们解决方案采用情况的更复杂的东西? 收集这些数据也很重要;将来,这可以帮助我们重新定义我们的健全“基线”或通过动态few shots微调结果或微调模型。
  • 缓存——与传统软件工程不同,当我们涉及生成方面时,缓存可能会非常具有挑战性。为了缓解这种情况,探索缓存相似结果的选项(例如,使用RAG)和/或减少生成输出(通过严格输出模式)。
  • 成本跟踪——许多公司发现从一开始就使用“强大模型”(如GPT-4或Opus)非常诱人,但在生产中,成本可能会迅速上升。不要被最终账单吓到,确保测量输入/输出令牌并跟踪你的工作流影响(没有这些做法——祝你好运以后再进行性能分析)。
  • 可调试性和跟踪——确保你设置了正确的工具来跟踪“错误”输入并跟踪整个过程。这通常包括保留用户输入以供后续调查并设置跟踪系统。记住:“与传统软件不同,AI会无声地失败!”

13、结束语

这可能是文章的结尾,但我们的工作远未结束。LLM原生开发是一个迭代过程,涵盖更多用例、挑战和功能,并不断改进我们的LLM原生产品。

随着你继续你的AI开发旅程,保持敏捷,无畏地实验,并始终牢记终端用户。分享你的经验和见解与社区,一起,我们可以推动LLM原生应用的可能性边界。继续探索、学习和构建——可能性是无限的。

我希望这篇指南是你LLM原生开发旅程中宝贵的伴侣!


原文链接:Building LLM Apps: A Clear Step-By-Step Guide

汇智网翻译整理,转载请标明出处