构建LLM应用清晰的分步指南
构建LLM原生应用的综合步骤:从初始想法到实验、评估和产品化
大型语言模型(LLMs)正迅速成为现代AI的基石。然而,目前尚无公认的最佳实践,先行者往往面临无明确路线图的困境,需要重新发明轮子或陷入僵局。
在过去两年中,我协助多家组织利用LLMs构建创新应用。通过这一经历,我开发了一套经过实战检验的方法(受LLM.org.il 社区洞察启发),将在本文中分享。
本指南为LLM原生开发这一复杂领域提供了一条清晰的路线图。你将学习如何从构思到实验、评估,再到产品化,释放你的潜力,创造突破性应用。
为何标准化流程至关重要
LLM领域日新月异,我们几乎每天都能听到新的突破性创新。这固然令人振奋,但也异常混乱——你可能会在过程中迷失方向,不知该如何行动或如何将你的新颖想法付诸实践。
简而言之,如果你是一位希望高效构建LLM原生应用的AI创新者(无论是管理者还是从业者),这篇文章正是为你而写。
实施标准化流程有助于启动新项目,并带来以下几个关键好处:
- 流程标准化 — 标准化流程有助于团队成员对齐,确保新成员顺利融入(尤其是在这种混乱中)。
- 明确里程碑 — 一种直接的方式来跟踪工作进度,衡量成果,并确保你走在正确的道路上。
- 识别决策点 — LLM原生开发充满未知和“小规模实验”[见下文]。清晰的决策点使得我们能够轻松降低风险,始终保持开发工作的精简高效。
LLM工程师的核心技能
与软件研发中的其他既定角色不同,LLM原生开发绝对需要一个新的角色:LLM工程师或AI工程师。
LLM工程师是一种独特的混合型人才,融合了来自不同(既定)角色的技能:
- 软件工程技能——与大多数软件工程师一样,大部分工作涉及将乐高积木拼装在一起并将其粘合起来。
- 研究技能——充分理解LLM原生的实验性质是至关重要的。虽然构建“酷炫的演示应用”相当容易,但“酷炫的演示”与实际解决方案之间的距离需要实验和敏捷性。
- 深入的业务/产品理解——由于模型的脆弱性,理解业务目标和流程比坚持我们定义的架构更为重要。对LLM工程师来说,能够建模手动流程是一项宝贵的技能。
在撰写本文时,LLM工程仍然是一个全新的领域,招聘可能会非常具有挑战性。寻找具有后端/数据工程或数据科学背景的候选人可能是一个好主意。
软件工程师可能会期待一个更平滑的过渡,因为实验过程更加“工程师化”,而不是那么“科学化”(与传统数据科学工作相比)。话虽如此,我也见过许多数据科学家成功完成这一转变。只要你愿意接受必须掌握新软技能的事实,你就走在了正确的道路上!
LLM原生开发的关键要素
与传统的后端应用(如CRUD)不同,这里没有一步一步的食谱。就像“AI”领域的其他一切,LLM原生应用需要一种研究与实验的思维方式。
要驯服这头猛兽,你必须通过将工作分解成更小的实验,尝试其中一些,并选择最有希望的实验来分而治之。
我无法强调研究思维的重要性。这意味着你可能会投入时间去探索一个研究方向,并发现它是“不可能的”、“不够好”或“不值得”。这完全没问题——这意味着你走在正确的轨道上。
拥抱实验:过程的核心
有时,你的“实验”会失败,然后你稍微调整工作方向,这个新的实验取得了更好的成功。
这正是为什么,在设计最终解决方案之前,我们必须从简单开始并规避风险。
- 设定“预算”或时间框架。 让我们看看在X周内能做些什么,然后决定是否继续。通常,2-4周来理解基本PoC就足够了。如果看起来有希望——继续投入资源来改进它。
- 实验—— 无论你选择自下而上还是自上而下的方法进行实验阶段,你的目标都是最大化结果成功率。在第一次实验迭代结束时,你应该有一些PoC(利益相关者可以操作)和已达到的基准。
- 回顾—— 在我们的研究阶段结束时,我们可以理解构建这样一个应用的可行性、限制和成本。这有助于我们决定是否将其产品化以及如何设计最终产品和其用户体验。
- 产品化—— 开发一个生产就绪版本的项目,并通过遵循标准SWE最佳实践并实施反馈和数据收集机制,将其与解决方案的其余部分集成。

为了很好地实施以实验为导向的过程,我们必须做出明智的决定,如何接近和构建这些实验:
从简出发:自底向上方法
尽管许多早期采用者迅速投入“最前沿”的多链代理系统,如全功能的Langchain或其他类似系统,我发现“自底向上方法”往往能带来更好的结果。
从简开始,非常简,秉持“一个提示统领一切”的理念。虽然这一策略看似非传统,且最初可能产生不良结果,但它为你的系统建立了基准。
在此基础上,持续迭代并精炼你的提示,运用提示工程技术优化结果。当你发现简解决方案中的弱点时,通过增加分支来拆分流程,以解决这些不足。
在设计我的LLM工作流图或LLM原生架构的每个“叶”时,我遵循魔法三角³来决定何时何地修剪分支、拆分它们,或通过使用提示工程技术加固根基(即通过提示工程技术)并榨取更多价值。

例如,要通过自底向上方法实现“原生语言SQL查询”,我们将从简单地将模式发送给LLM并要求其生成查询开始。

通常,这并不与“自顶向下方法”相矛盾,而是作为其前的一个步骤。这使我们能够展示快速成果并吸引更多项目投资。
全局概览先行:自顶向下的策略
“我们知道LLM工作流程并不简单,为了达成目标,我们可能会最终采用某种工作流程或LLM原生架构。”
自顶向下的方法认识到这一点,从一开始就着手设计LLM原生架构,并从最初阶段就实施其不同的步骤/链条。
这样,你可以整体测试你的工作流程架构,而不是单独细化每个环节。

例如,要通过自顶向下的方法实现“原生语言SQL查询”,我们会先设计架构,然后再进入全面实施阶段:

寻找合适的平衡点
当你开始尝试使用大型语言模型(LLMs)时,可能会从一个极端开始(过于复杂的自上而下或超级简单的一次性尝试)。实际上,并不存在绝对的胜者。
理想情况下——你会先定义一个好的标准操作程序(SoP¹),并在编码和实验模型之前模拟专家行为。但在现实中,建模非常困难;有时,你可能无法接触到这样的专家。
我发现第一次就确定一个好的架构/SoP¹颇具挑战,因此,在采取重大举措之前进行轻量级实验是值得的。然而,这并不意味着所有事情都必须过于精简。如果你已经有了先验知识,认为某些部分必须分解成更小的单元——那就这样做。
无论如何,在设计解决方案时,你应该利用魔法三角³范式,并正确地模拟手动流程。
优化您的解决方案:挤柠檬
在实验阶段,我们不断“挤柠檬”并增加更多的“复杂层”:
- 提示工程技术 — 如Few Shots、角色分配,甚至是动态Few-shot
- 扩展上下文窗口,从简单的变量信息到复杂的RAG流程,有助于提升结果。
- 尝试不同的模型 — 不同模型在不同任务上的表现各异。此外,大型LLM往往成本效益不高,尝试更多任务特定的模型是值得的。
- 提示瘦身 — 我发现将SOP¹(特别是提示和请求的输出)进行“瘦身”通常能改善延迟。
通过减少提示大小和模型需要经历的步骤,我们可以减少模型需要生成的输入和输出。令人惊讶的是,提示瘦身有时甚至能提高质量!
需要注意的是,瘦身也可能导致质量下降,因此在进行之前设置一个健全性测试很重要。
- 将流程拆分为更小的步骤也能非常有益,并使优化SOP¹的子流程更容易和可行。
需要注意的是,这可能会增加解决方案的复杂性或损害性能(例如,增加处理的令牌数量)。为了缓解这一点,目标是简洁的提示和较小的模型。
作为经验法则,通常在系统提示发生显著变化能为此部分SOP¹流程带来更好结果时进行拆分是个好主意。
LLM实验的结构解析
个人而言,我倾向于从简单的Jupyter Notebook开始,使用Python、Pydantic和Jinja2来保持精简:
- 利用Pydantic定义模型输出的架构。
- 使用Jinja2编写提示模板。
- 定义结构化输出格式(采用YAML²)。这将确保模型遵循“思考步骤”并受我的SOP引导。
- 通过Pydantic验证确保输出;如有必要,进行重试。
- 稳定你的工作——将代码结构化为功能单元,使用Python文件和包。
在更广泛的范围内,你可以使用不同的工具,如openai-streaming 来轻松利用流式处理(及工具),LiteLLM 以实现跨不同提供商的标准化LLM SDK,或vLLM 来服务开源LLMs。
确保质量:健全性测试与评估
健全性测试用于评估项目的质量,确保不会降低你设定的某个成功率基线。
可以把你的解决方案/提示看作是一条短毯子——如果过度拉伸,它可能会突然无法覆盖某些原本能覆盖的使用场景。
为此,定义一组你已经成功覆盖的案例,并确保保持这种状态(或至少值得这样做)。将其视为表驱动测试 可能会有所帮助。
评估“生成式”解决方案(例如,撰写文本)的成功与否,比使用LLMs进行其他任务(如分类、实体提取等)要复杂得多。对于这类任务,你可能需要引入更智能的模型(如GPT4、Claude Opus或LLAMA3–70B)来充当“评判者”。在生成式输出之前尝试包含“确定性部分”也是一个好主意,因为这类输出更容易测试:
1 | cities: |
有几种前沿且极具潜力的解决方案值得研究。我发现它们在评估基于RAG的解决方案时尤为相关:可以看看DeepChecks 、Ragas 或ArizeAI 。
明智决策:回顾会议的重要性
每次重大或时间框架内的实验或里程碑之后,我们都应停下来,就如何以及是否继续采用此方法做出明智的决策。
此时,你的实验将有一个明确的成功率基线,并且你将对需要改进的地方有所了解。
这也是一个讨论此解决方案产品化影响并开始“产品工作”的好时机:
- 这在产品中会是什么样子?
- 有哪些限制/挑战?你将如何缓解它们?
- 你目前的延迟是多少?是否足够好?
- 用户体验应如何设计?可以使用哪些界面技巧?流式处理 能有所帮助吗?
- 预计在令牌上的花费是多少?我们能否使用更小的模型来减少开支?
- 优先级是什么?是否有任何挑战是阻碍因素?
假设我们达到的基线是“足够好”的,并且我们相信可以解决提出的问题。在这种情况下,我们将继续投资并改进项目,同时确保它不会退步,并使用健全性测试。
从实验到产品:将您的解决方案落地
最后但同样重要的是,我们需要将工作产品化。与任何其他生产级解决方案一样,我们必须实施生产工程概念,如日志记录、监控、依赖管理、容器化、缓存等。
这是一个庞大的领域,但幸运的是,我们可以借鉴许多经典生产工程的机制,甚至采用许多现有工具。
尽管如此,对于涉及LLM原生应用的细微差别,我们需要格外小心:
- 反馈循环 — 我们如何衡量成功?仅仅是“点赞/踩”机制,还是更复杂的方法,考虑我们解决方案的采用情况?收集这些数据也很重要;未来,这可以帮助我们重新定义我们的“基准”,或通过动态少样本 微调我们的结果,或微调模型。
- 缓存 — 与传统软件工程不同,当我们的解决方案涉及生成方面时,缓存可能非常具有挑战性。为了缓解这一问题,可以探索缓存相似结果(例如,使用RAG)和/或减少生成输出(通过设定严格的输出模式)的选项。
- 成本跟踪 — 许多公司发现从“强大模型”(如GPT-4或Opus)开始非常诱人,然而在生产环境中,成本可能迅速上升。避免在最终账单上感到惊讶,并确保测量输入/输出令牌,跟踪您的工作流程影响(没有这些实践——祝您后续分析好运)。
- 可调试性和追踪 — 确保您设置了正确的工具来跟踪“有问题的”输入,并追踪整个过程。这通常涉及保留用户输入以供后续调查,并设置追踪系统 。记住:“与传统软件不同,AI失败时是无声的!”
结束语:你在推进LLM原生技术中的角色
这可能是本文的结尾,但绝不是我们工作的终点。LLM原生开发是一个涵盖更多使用场景、挑战和特性的迭代过程,并持续改进我们的LLM原生产品。
在继续你的AI开发之旅时,保持敏捷,大胆实验,并始终关注终端用户。与社区分享你的经验和见解,我们一起推动LLM原生应用的边界。继续探索、学习和构建——可能性是无穷的。
希望这份指南在你的LLM原生开发旅程中是一份宝贵的伴侣!我很想听听你的故事——在下方评论区分享你的成功和挑战。💬
如果你觉得这篇文章有帮助,请在Medium上给它一些掌声 👏,并分享给你的AI爱好者朋友们。你的支持对我意义重大!🌍
让我们继续对话——欢迎通过电子邮件 或LinkedIn联系 🤝
特别感谢Yonatan V. Levin 、Gal Peretz 、Philip Tannor 、Ori Cohen 、Nadav 、Ben Huberman 、Carmel Barniv 、Omri Allouche 和Liron Izhaki Allerhand 提供的见解、反馈和编辑建议。
¹SoP- 标准操作程序,借用自魔法三角³的概念
²YAML- 我发现使用YAML来构建输出与LLMs配合得更好。为什么?我的理论是它减少了不相关的标记,行为更接近原生语言。本文深入探讨了这一主题。
³魔法三角- LLM原生开发的蓝图;敬请关注,并关注我以在发布时阅读蓝图。
- 标题: 构建LLM应用清晰的分步指南
- 作者: Barry
- 创建于 : 2024-06-10 20:02:32
- 更新于 : 2024-08-31 06:59:45
- 链接: https://wx.role.fun/2024/06/10/79b3b8e654f441459da6a3b8590f7a94/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。