落地运行老本及照应提前优化 LLM 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 是什么影响了经常使用老本和照应提前?

撰写本文时,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 运行程序时,除了初始揭示词模板之外,至少还须要以下组件:

从技术上讲,咱们可以参与恣意数量的工具,但假设依赖最便捷的 Agent\&Tools 架构,或者系统的裁减性就会很差。关于每一种可用的工具,都须要在每次调用 Agents 时发送诸如 API 文档之类的详细说明。

在预备新系统组件时,须要思考每次调用参与多少个 tokens 是值得的。 假设经常使用的是 OpenAI 的模型,可以极速评价新工具或额外的指点性揭示词的"tokens 消耗"状况,方法如下:

import tiktokendef 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 的环节中,我发现以下一些通用技巧特意有用。我将在未来几周内撰写后续文章解说其中的大少数通用技巧,因此,假设你想不错过这些内容,欢迎您在此(​ ​)​ ​ 订阅我的团体主页,以便在文章颁布时接纳到通知。

4.1 将大段揭示词拆分红多层而后再调用

软件工程的关键准则之一是模块化和笼统化。试图用单个揭示词来处置更复杂的疑问,就似乎编写难以保养的"意大利面条式"代码(Spaghetti code)(译者注:这个比喻起源于意大利面(spaghetti)缠绕不清、难分难解的笼统。当一段代码不足明晰的结构、正确的模块划分和正当的逻辑顺序,而是充满着少量的嵌套条件语句、无序的跳转、重复的代码块时,就被视为"意大利面式代码"。)一样低效。

在构建 Mieszko 时,性能清楚优化的一个关键点是将揭示词拆分为两个局部:

分层决策与口头架构图

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

这种架构使得咱们能够在每次调用时,首先选取须要经常使用的特定义务揭示词,而无需随附繁重的、消耗少量 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 langchainlangchain.debug=True

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

在经常使用 LLMs 时,最大的误区是遗记你依然可以应用编程来处置疑问。 以我为例,一些最大的性能优化,就是经过经常使用 Python 函数在 LLMs 调用的高低游处置一些极为便捷的义务。

在经常使用 LangChain 时,这一点尤为有效,咱们可以轻松地将 LLMs 的调用与传统的 Python 函数启动链式处置。上方是一个简化的示例,我曾用它来处置一个难题:即使批示 LLMs 坚持回答与用户发送的信息相反的言语,LLMs 仍自动回复英文。

咱们无需借助 LLMs 来检测目前的对话经常使用的是什么言语,应用 Google Translate API 或甚至是一个便捷的 Python 库(如 langdetect ),可以更快、更准确地成功这项义务。一旦咱们确定了输入言语,就可以明白地将其传入指点性揭示词中,从而缩小在 LLMs 的调用环节中须要处置的上班量。

from langdetect import detectprompt = """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_messagedetect_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,供其间接了解、剖析。

宿愿本文引见的这些通用技巧,能够协助各位读者更好地了解 LLMs 运行中经常使用老本和照应提前的关键影响起因,以及如何优化它们。我宿愿尽或者多地分享我在开发基于 LLM 的消费级运行中学到的关键阅历经验。在本系列接上去的文章中,我将从更详细、通常性更强的通常案例着手:

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

Thanks for reading!

Jan Majewski

Leveraging LLMs to transform Real Estate search.>

原文链接:

您可能还会对下面的文章感兴趣: