优化LLM Prompt:降低使用成本和响应延迟的实用技巧

编者按: LLMs 被视为 AI 领域的一个里程碑式的突破,但要将其应用于实际生产环境,并且还能用对、用好并非易事。模型的使用成本和响应延迟是目前将大语言模型(LLMs)应用于生产环境中的核心难题之一。

在本期刊载的这篇文章中,作者从自身项目的实践经验出发,分享了一系列实用技巧,帮助优化 LLM Prompt ,能够一定程度上降低大模型的使用成本和响应延迟。

文章首先解析了导致高成本和高延迟的根源在于输入输出 tokens 的数量,而非任务本身的复杂度。接下来,作者逐一阐述了包括提示词拆分、模块化设计、与传统编程技术结合使用等多种优化策略。这些策略体现了作者对大模型应用本质的深刻理解,注重发挥 LLMs 在复杂推理方面的优势,同时将数学计算、数据聚合等工作外包给 SQL/Python 等更高效的工具。

本文贯穿了一种务实的方法论 ------ 理性看待 LLMs 技术,扬长避短,与其他技术工具形成合力,而非将其视为解决一切问题的"灵丹妙药"。这种观点和方法论对于企业更好地将 LLMs 技术应用于生产实践至关重要。

作者: Jan Majewski

编译: 岳扬

image generated by author with GPT-4o

高成本和延迟是将大语言模型应用于生产环境中的主要障碍之一,二者均与提示词信息的体量(prompt size)紧密相连。

鉴于大语言模型(LLM)展现出极强的广泛适用性,不少人视其为解决各类问题的灵丹妙药。通过与诸如检索增强生成技术(RAG)及 API 调用等在内的工具整合,并配以精细的指导性提示词,LLM 时常能展现出逼近人类水平的工作能力。

然而,这种无所不包的应用策略,其潜在隐患在于可能会导致提示词的信息量迅速膨胀,直接引发高昂的使用成本以及较大的响应延迟,令 LLMs 在生产环境的实际部署面临重重困难。

针对高价值任务(如代码优化任务)使用 LLMs 时,成本这方面的考量或许会退居其次 ------ 一段平常半小时才能编写完成的代码现在等待半分钟即完成,花费一定的成本尚可接受。但转至 To C 领域,面对成千上万次的即时对话需求,成本控制与响应速度便成为决定项目成败的关键。

本文将分享为 Resider.pl 构建由 LLM 支持的房地产搜索助手 “Mieszko” 这一过程的心得。本文的重点是:如何跨越从吸引眼球的概念验证(impressive POC)在实操中有效运用 LLMs 的鸿沟。

01 Prompt is all you have

在构建 “Mieszko” 时,我非常倚重 LangChain这一个出色的框架。该框架以一种有序且清晰的方式,将复杂的逻辑或组件抽象化,并配备了高效易用的提示词模板,仅需寥寥数行代码即可实现调用。

LangChain 的易用性或许会让我们不经意间忘却一个核心要点:不论我们的解决方案有多么繁琐,实质上所有组件都会汇总成一条长长的文本信息------“指令性提示词”------传递给LLM。接下来将要展示的内容是一个概括性的示例说明,用于展示 LLM Agent 在接收指令性提示词或执行任务前,其输入提示词的基本结构和主要组成部分。

使用 LLM Agent 中的指令性提示词模板时所采用的基本结构

02 是什么影响了使用成本和响应延迟?

LLMs(大语言模型)是有史以来构建的最复杂的人工智能模型之一,但其响应延迟和使用成本主要取决于输入和输出处理的 tokens 数量,而非任务本身的难度。

撰写本文时,OpenAI 旗舰模型 GPT-4 Turbo 的定价公式大致如下:

响应延迟的相关计算方法则并不那么直接,但根据 “Mieszko” 的应用场景,可简单归结为以下这个公式:

从成本角度看,input tokens 通常是 LLMs 使用成本的"大头",其价格仅为 output tokens 的三分之一,但对于更复杂的任务,提示词长度会远超面向用户的 output tokens 长度。

然而,延迟主要受 output tokens 影响,处理 output tokens 的时间大约是 input tokens 的 200 倍。

在使用 LLM Agents 时,约 80% 的 tokens 来自 input tokens ,主要是初始的提示词和 Agents 推理过程中的消耗。这些 input tokens 是使用成本的关键组成部分,但对响应时间的影响有限。

03 监控和管理 tokens 的消耗

在构建任何 LLMs 应用程序时,除了初始提示词模板之外,至少还需要以下组件:

  • 记忆库(每次与 LLMs 的交互(每次调用)中,都需要包含之前所有的对话消息或历史上下文。)
  • 工具箱 (如供 LLMs 调用的API),及其详细的指导性提示词
  • 检索增强生成(RAG)系统及其产生的上下文

从技术上讲,我们可以添加任意数量的工具,但如果依赖最简单的 Agent&Tools 架构,可能系统的扩展性就会很差。对于每一种可用的工具,都需要在每次调用 Agents 时发送诸如 API 文档之类的详细说明。

在准备新系统组件时,需要考虑每次调用增加多少个 tokens 是值得的。 如果使用的是 OpenAI 的模型,可以快速评估新工具或额外的指导性提示词的"tokens 消耗"情况,方法如下:

  • 直接访问网站:https://platform.openai.com/tokenizer
  • 如果你更喜欢使用 Python,可以使用 tiktoken 库,通过以下简单函数实现:
 import tiktoken
def num_tokens_from_string(string: str, model_name: str) -> int:
 try:
        encoding = tiktoken.encoding_for_model(model_name)
 except KeyError as e:
 raise KeyError(f"Error: No encoding available for the model '{model_name}'. Please check the model name and try again.")

    num_tokens = len(encoding.encode(string))
 return num_tokens

04 如何在保持提示词精简的同时不牺牲准确性

初次接触时,大语言模型(LLMs)可能令人感到无所适从,但归根结底,重要的是要记住我们打交道的仍是软件。这意味着我们应当事先预料到会出现错误,管理和控制软件系统设计中的抽象层次和模块化程度,并寻找更高效的解决方案来处理子任务。

在开发 Mieszko 的过程中,我发现以下一些通用技巧特别有用。我将在未来几周内撰写后续文章讲解其中的大多数通用技巧,因此,如果你想不错过这些内容,欢迎您在此(https://medium.com/@janekmajewski/subscribe) 订阅我的个人主页,以便在文章发布时接收到通知。

4.1 将大段提示词拆分成多层然后再调用

软件工程的关键原则之一是模块化和抽象化。试图用单个提示词来处理更复杂的问题,就如同编写难以维护的"意大利面条式"代码(Spaghetti code)(译者注:这个比喻来源于意大利面(spaghetti)缠绕不清、难分难解的形象。当一段代码缺乏清晰的结构、正确的模块划分和合理的逻辑顺序,而是充斥着大量的嵌套条件语句、无序的跳转、重复的代码块时,就被视为"意大利面式代码"。)一样低效。

在构建 Mieszko 时,性能显著提升的一个关键点是将提示词拆分为两个部分:

  • 用于决策的 Agent (Decision Agent):对下一步可以采取的措施以及如何处理提示词输出的一般指导原则。
  • 用于执行任务的 Agent / 对话型 LLMs 系统:含有针对具体步骤(如房源搜索、数据比较或房地产知识查询)的详细指导性提示词。

分层决策与执行架构图

分层决策和执行调用架构图,图片由原文作者提供

这种架构使得我们能够在每次调用时,首先选取需要使用的特定任务提示词,而无需随附沉重的、消耗大量 tokens 的执行指令(execution instructions),从而平均减少了超过 60% 的 tokens 使用量。

4.2 务必监控每次调用时的最终提示词

LLM 接收到的最终提示词(final prompt)可能与最初的提示词模板相去甚远。通过工具(tools)、记忆库(memory)、上下文(context)及 Agent 的内部推理来丰富提示词模板这一过程,可能会使提示词的规模激增数千个 tokens 。

此外,LLMs 有时会展现出如洛奇·巴尔博亚(Rocky Balboa)(译者注:洛奇·巴尔博亚(Rocky Balboa),美国电影《洛奇》系列的主角,业余拳击手出身,凭借自身的努力,登上拳坛最高峰。)般的韧性,即使面对存在错误和矛盾的提示词,也能"站起来"给出合理的答案。

通过仔细审查数十次 LLMs 的调用,并深入了解大语言模型(LLM)实际上接收到了什么信息,能为关键突破(key breakthroughs)和消除漏洞(bug elimination)提供宝贵洞见。我强烈推荐使用 LangSmith 来进行深入分析。

如果想要寻求最简便的方案,也可以启用 LangChain 中的调试功能,它将为我们提供每次调用时确切发送的提示词,以及大量有用信息,帮助我们更好地监控和优化提示词内容。

import langchain
langchain.debug=True

4.3 如只需几行代码即可处理的事,向 LLMs 提交前请三思

在使用 LLMs 时,最大的误区是忘记你仍然可以利用编程来解决问题。 以我为例,一些最大的性能提升,就是通过使用 Python 函数在 LLMs 调用的上下游处理一些极为简单的任务。

在使用 LangChain 时,这一点尤为有效,我们可以轻松地将 LLMs 的调用与传统的 Python 函数进行链式处理。下面是一个简化的示例,我曾用它来解决一个难题:即便指示 LLMs 保持回答与用户发送的消息相同的语言,LLMs 仍默认回复英文。

我们无需借助 LLMs 来检测目前的对话使用的是什么语言,利用 Google Translate API 或甚至是一个简单的 Python 库(如 langdetect ),可以更快、更准确地完成这项任务。一旦我们确定了输入语言,就可以明确地将其传入指导性提示词中,从而减少在 LLMs 的调用过程中需要处理的工作量。

from langdetect import detect

prompt = """
Summarize the following message in  {language}:
Message: {input} 
"""

prompt = ChatPromptTemplate.from_template(prompt)

def detect_language(input_message):
    input_message["language"] = detect(input_message["input"])
 return input_message

detect_language_step= RunnablePassthrough.assign(input_message=detect_language)

chain_summarize_in_message_language = (
    detect_language_step
 * RunnablePassthrough.assign(
            language=lambda x: x["input_message"]["language"]
 ) 
 * prompt 
 * llm )

4.4 在设计 Agent 的提示词时要精打细算,因为它们通常至少会被调用两次

集成了工具的 Agent 能够将 LLMs 的能力提升到新的层次,但同时它们也非常消耗 tokens(计算资源)。 下面的图表展示了 LLM Agent 针对 query 提供答案的一般逻辑流程。

AI Agent 两次调用 LLM,图片由原文作者提供

如上图所示,Agent 通常至少需要调用 LLM 两次:第一次是为了规划如何使用工具,第二次则是解析这些工具的输出以便给出最终答案。这一特点意味着,我们在设计提示词时节省的每一个 token,实际上都会带来双倍的效益。

对于某些较为简单的任务,采用 Agent 的方式可能是"用牛刀杀鸡",而直接使用带有 Completion 的简单指导性提示词(译者注:模型接收到 instruction prompt 后的内容生成过程。)可能就能够达到相似的结果,且速度甚至还能快上一倍。以 Mieszko 项目为例,我们决定将大部分任务从 Multi-Agent 架构转变为基于特定任务的 Agent+Completion 模式。

4.5 将大语言模型和传统编程工具结合使用,发挥各自的优势(Use LLMs for reasoning but calculate and aggregate with SQL or Python)

相较于早期的 GPT-3.5,最新顶尖大语言模型已经有了很大的进步,那时它们在处理基础数学公式时都还会出错。现在,在诸如计算 segment averages (译者注:在一组数据中,将数据分成若干个段或区间,然后计算每个段内数据的平均值。)任务上,LLMs 已经能够轻松处理数百个数字。

但它们更擅长编写 Python 或 SQL,无需数以万亿计的模型参数,就能以 100% 的准确率执行复杂的数学运算。然而,向 LLMs 传递大量数字会消耗大量 tokens ,在最好的情况下,每 3 位数字都会转换为一个 token ;若数值庞大,单个数字就可能占用多个 tokens 。

想要更低成本、更高效率地分析数学运算,获得运算结果,窍门在于如何运用 LLMs 理解问题及手头数据,继而将之转译为 SQL 或 Python 这类更适合进行数学分析的编程语言。

实践中,可将编写的代码嵌入一个函数内执行,此函数负责连接数据源并仅将最终分析结果呈现给 LLM,供其直接理解、分析。

05 Summary

希望本文介绍的这些通用技巧,能够帮助各位读者更好地了解 LLMs 应用中使用成本和响应延迟的主要影响因素,以及如何优化它们。我希望尽可能多地分享我在开发基于 LLM 的生产级应用中学到的关键经验教训。在本系列接下来的文章中,我将从更具体、实践性更强的实践案例着手:

  • 使用 Python guardrails (译者注:使用 Python 编写基于规则的验证函数。)提升 LLM 输出内容的可靠性
  • 通过模块化和抽象化(Modularity and Abstraction)增强 LLM Agents
  • 利用 LangSmith 了解、监控基于 LLMs 的应用(预计六月中旬发布)

最后,特别感谢 Filip Danieluk ,并向 Filip Danieluk 致以崇高的敬意,他是 Mieszko 引擎的 co-creator 。无数个昼夜的深入讨论和结对编程(pair-programming)催生了本系列文中阐述的内容,这些见解既属于我,也属于 Filip 。

Thanks for reading!

————
Jan Majewski

https://medium.com/@janekmajewski

Leveraging LLMs to transform Real Estate search. Data Scientist passionate about NLP, geo-analytics and price-benchmarking

END

本文经原作者授权,由 Baihai IDP 编译。如需转载译文,请联系获取授权。

原文链接:

https://towardsdatascience.com/streamline-your-prompts-to-decrease-llm-costs-and-latency-29591dd0e9e4

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何使用C++ STL标准模板库中的算法函数(附源码)

目录 1、概述 2、调用sort函数对列表元素进行排序 3、调用count_if查找满足条件的元素个数 4、调用find_if函数找到目标元素的信息 5、调用remove_copy_if函数搜索满足条件的多个元素 6、总结 VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.…

香港服务器的正确维护指南:确保稳定运行的实用策略

很多人使用香港服务器,很清楚即使它们可以全天候运行而不会出现问题,您仍然需要进行适当的维护以确保效率。原因很简单,香港服务器的正确维护对于保证网站或应用的正常运行时间、数据安全以及系统性能至关重要。以下本文将讨论一些有关如何维…

【开源】医院电子病历管理系统 SSM+JSP+MySQL

目录 一、项目介绍 科室模块 医生模块 预约挂号模块 就诊记录模块 就诊评价模块 二、项目界面 三、核心代码 一、项目介绍 经典老框架SSM打造入门项目《医院电子病历管理系统》,分为用户网页和管理后台,包括科室模块、医生模块、预约挂号模块、…

AI网络爬虫:批量获取post请求动态加载的json数据

网站https://www.futurepedia.io/ai-innovations的数据是通过post请求动态加载的: 查看几页的请求载荷: {"companies":[],"startDate":"2023-12-01T00:00:00.000Z","endDate":"2024-06-09T12:25:08.525Z&…

wireshark 标记自己想要的数据包

1:点击视图 2:点击视图-着色规则 点击新增一行,双击名称-进行编辑 过滤器规则-编辑自己想要看到的 点击前景-选择凸出显示颜色 点击背景--选择凸出显示颜色 点击确定按钮

提升易用性,OceanBase生态管控产品的“从小到大”

2022年,OceanBase发布4.0版本“小鱼”,并首次公开提出了单机分布式一体化这一理念,旨在适应大小不同规模的工作负载,全面满足用户数据库“从小到大”全生命周期的需求。当时,我们所说的“从小到大”主要聚焦于数据库的…

Linux系统之smem命令的基本使用

Linux系统之smem命令的基本使用 一、smem命令介绍二、smem命令的使用帮助2.1 smem命令的help帮助信息2.2 smem命令的语法解释 三、smem工具安装3.1 安装epel3.2 搜索smem包3.3 安装smem 四、smem命令的基本使用4.1 查看内存概览4.2 查看内存占用百分比4.3 查看系统内存使用情况…

JDKCGLIB实现动态代理

1.代理模式 代理模式是23中设计模式中的一种。简单来说就是我们使用代理对象来替代真实对象,这样就可以实现在不修改原目标对象的前提下,提供额外的功能操作,以达到扩展目标对象的功能。 代理模式的功能主要是扩展目标对象的功能,比如说在目…

35、matlab设置字体、查看工具包版本、窗口默认布局和程序发布

1、matlab设置字体 1)找到预设并点击预设 2)设置流程:字体——>自定义——>编辑器——>选择字体及格式——>确定 如图序号所示 2、matlab查看工具包版本:ver命令 1)命令行窗口输入命令 即可查看工具包…

Halcon 多相机统一坐标系

小杨说事-基于Halcon的多相机坐标系统一原理个人理解_多相机标定统一坐标系-CSDN博客 一、概述 最近在搞多相机标定等的相关问题,对于很大的场景,单个相机的视野是不够的,就必须要统一到一个坐标系下,因此我也用了4个相机&#…

指挥中心操作台在轨道交通中的作用

随着城市化进程的加速和交通需求的日益增长,轨道交通作为高效、便捷、环保的出行方式,在城市交通体系中扮演着越来越重要的角色。而在轨道交通系统的运行中,指挥中心操作台则发挥着至关重要的作用。本文将详细探讨指挥中心操作台在轨道交通中…

龙气万象-大麗和和「腾龙图」翡翠高级珠宝系列

泠泠龙吟,气象万千。大麗和和诚献「腾龙图」翡翠高级珠宝系列,以贯穿上下五千年的龙图腾纹样为主轴,融入现代高级珠宝设计,集雅列珍,见证龙纹嬗变,探讨美学的传承与创新。 这一系列从探讨构思到惊艳呈现历时20个月,龙纹原型跨越从战国早期至明清两代的漫长岁月,设计团队自青铜…

ttkbootstrap的icon图标自定义

前言 在使用ttkbootstrap库时,发现icon参数使用报错,错误代码 root ttk.Window(themename"superhero",size(1400, 700),resizable(True, True),iconphoto"1.png" )结果报错:iconphoto path is bad; using default ima…

STM32存储左右互搏 模拟U盘桥接SPI总线FATS读写FLASH W25QXX

STM32存储左右互搏 模拟U盘桥接SPI总线FATS读写FLASH W25QXX STM32的USB接口可以模拟成为U盘,通过FATS文件系统对连接的存储单元进行U盘方式的读写。 这里介绍STM32CUBEIDE开发平台HAL库模拟U盘桥接SPI总线FATS读写W25Q各型号FLASH的例程。 FLASH是常用的一种非易失…

【八股系列】react里组件通信有几种方式,分别怎样进行通信?

文章目录 1. props传递(父向子通信):2. 回调函数作为props(子向父通信):3. Context API:4. Redux或MobX等状态管理库:4.1 Redux使用示例 5. refs: 1. props传递(父向子通信&#xff…

netty内存马探究

0x01 前言 基于netty动态创建pipeline的特性,其内存马的构造思路与tomcat有一定的区别,目前网上有关netty内存马的文章都围绕CVE-2022-22947和XXL-JOB两种场景展开,并未对其做更为详细的分析。本文就以上述两种场景为始,尝试从源码…

打造智能饲料工厂:全自动生产线设备

全自动饲料生产线设备实现了从原料投放到成品包装的全程自动化操作。通过传感器和控制系统,设备能够精确控制原料的配比和混合均匀度,确保饲料的质量稳定可靠。同时,自动化生产线还具备智能调节功能,能够根据生产需求自动调节生产…

四季变换,制氮机使用注意事项

随着四季的轮回变换,大自然展现着不同的风貌。对于制氮机而言,季节的变换同样会带来不同的使用挑战和注意事项。本文将为您揭示四季变换对制氮机使用的影响,帮助您更好地掌握制氮机的季节使用须知。 春季 温湿度变化:春季温湿度逐…

Shell脚本从入门到实战

一、概述 shell 是一个命令行解释器,它接受应用程序、用户命令,然后调用操作系统内核。 shell 还是一个功能强大编程语言,易调试,易编写,灵活性强。 二、mac 怎么重启docker 1.如何重启 Docker on Mac 在 macOS 上…

Flutter笔记:关于WebView插件的用法(上)

Flutter笔记 关于WebView插件的用法(上) - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:htt…