在您的Gen AI项目中使用的十个技巧和窍门
十个Gen AI项目技巧和窍门
从一个生产就绪的生成式AI应用中学到的教训
今天在生产中使用的生成式AI应用并不多,我是指那些已经部署并被最终用户积极使用的应用。(演示、POC和抽取式AI不计算在内。)目前在生产中使用的生成式AI应用(例如Google Workspace中的Duet,Salesforce的Einstein GPT中的销售电子邮件生成)都是闭源的,因此你无法从中学习。
因此,当defog.ai开源了他们一直在客户端自动化多个生成式AI工作流程中使用的NLP-to-SQL模型SqlCoder时,我感到非常兴奋。他们还详细介绍了他们的方法和思考过程。这为我提供了一个具体的例子来指导。

在本文中,我将使用SqlCoder来展示在你自己的生成式AI项目中可能会做的具体示例。
1. 设计一个根据生成的文本使用方式计算的评估指标。
与传统机器学习一样,用于优化LLM的损失指标并不能捕捉到其在现实世界中的效用。分类模型使用交叉熵损失进行训练,但使用指标如AUM/F分数进行评估,或者将经济成本分配给假阳性等。
同样,基础LLM使用BLEU或ROUGE等指标进行训练优化。在某种程度上,这些指标只是衡量生成的文本与标签之间的标记重叠。显然,这对于SQL生成来说是不太好的——标签“SELECT list_price”和生成的文本“SELECT cost_price”并不是特别接近(LLM中的标记是子词,所以这两个字符串只相差一个标记!)。
Defog解决这个问题的方法在他们的博客文章中有解释,他们是如何进行评估的。基本上,他们不直接比较SQL字符串,而是在一个小数据集上运行生成的SQL并比较结果。这使得他们可以接受等效的SQL,只要生成的SQL最终执行的操作与标签相同。然而,如果列的别名不同怎么办?如何处理无序的结果?如果生成的SQL是标签的超集会怎样?需要解决很多特殊情况和细微差别。如果你对这个具体问题感兴趣,请阅读他们关于评估的博客文章。然而,更重要的是,这个问题在所有类型的生成式AI问题中都是适用的——设计一个评估指标,不是根据生成的字符串,而是根据生成的字符串的使用方式进行计算。
许多研究论文使用LLM(通常是GPT-4)对生成的文本进行“评分”,并将其作为指标。这并不像设计一个合适的评估指标那样好,因为LLM得分对于GPT算法有很大的偏见,并且对于你可以进行的许多智能优化是不利的。此外,回想一下Open AI不得不关闭他们试图检测AI生成文本的服务;如果他们无法使LLM生成的分数起作用,你为什么认为你会成功呢?
2. 建立实验追踪
在你开始做任何事情之前,请确保你有一个记录和共享实验结果的系统。你将进行很多实验,你希望确保你记录了你尝试过的一切。
这可以是一个简单的电子表格,其中包含以下列:实验、实验描述(方法、参数、数据集等)、训练成本、推理成本、指标(按子任务切片:见下文)、定性注释。或者它可以更复杂一些,利用ML实验追踪框架,如Vertex AI、Sagemaker、neptune.ai、Databricks、Datarobot等。
如果你不以一种可重复的方式记录实验,而且这种方式在你团队的所有成员之间保持一致,那么在后续做决策时将会很困难。
3. 将问题细分为子任务
您经常希望在整个评估数据集上进行评估,而不是在任务拆分的数据子集上进行评估。例如,看看defog如何报告不同类型查询的性能:

进行切片评估的原因有三个:
- 您最终会在模型大小、性能和成本之间陷入困境。打破这个困局的一种方法是拥有多个机器学习模型,每个模型在不同的子任务上进行调优。许多人怀疑GPT-4本身就是一组GPT 3.5质量的模型的集成。[顺便说一句,这也是单个LLM对抗GPT-4表现不佳的原因之一 – 您需要构建一个模型集合来击败它。]
- 如果您有多个利益相关者,他们可能对不同的事物感兴趣。在这种情况下,请确保设计和跟踪与每个目标相关的指标。您也可以将这些不同的目标视为子任务,并开始跟踪它们。最终,您可能需要创建多个模型,为每个利益相关者创建一个模型。同样,您现在可以将这些模型视为集合的成员。
- 对子任务进行切片评估的第三个原因是,机器学习评估的黄金标准是将其呈现给一组人类专家。这往往太昂贵了。但是,如果您确实进行人工评估,请确保以这样的方式进行,以便您以后可以使用计算的度量来“预测”人工评估可能是什么样的。在进行此类校准时,拥有更多的问题属性可能会有所帮助。
4. 应用提示工程技巧
使用Gen AI的所有方法最终都需要向经过训练的LLM发送文本提示。随着时间的推移,社区已经学到了很多关于创建良好提示的技巧。通常,LLM的文档会告诉您哪些方法有效(例如:OpenAI cookbook,Lllama2,Google PaLM)-请确保阅读并采用建议的技巧!
defog的提示是:
prompt = """### Instructions:Your task is convert a question into a SQL query, given a Postgres database schema.Adhere to these rules:- **Deliberately go through the question and database schema word by word** to appropriately answer the question- **Use Table Aliases** to prevent ambiguity. For example, `SELECT table1.col1, table2.col1 FROM table1 JOIN table2 ON table1.id = table2.id`.- When creating a ratio, always cast the numerator as float### Input:Generate a SQL query that answers the question `{question}`.This query will run on a database whose schema is represented in this string:CREATE TABLE products ( product_id INTEGER PRIMARY KEY, -- Unique ID for each product name VARCHAR(50), -- Name of the product price DECIMAL(10,2), -- Price of each unit of the product quantity INTEGER -- Current quantity in stock);CREATE TABLE customers ( customer_id INTEGER PRIMARY KEY, -- Unique ID for each customer name VARCHAR(50), -- Name of the customer address VARCHAR(100) -- Mailing address of the customer);...-- sales.product_id can be joined with products.product_id-- sales.customer_id can be joined with customers.customer_id-- sales.salesperson_id can be joined with salespeople.salesperson_id-- product_suppliers.product_id can be joined with products.product_id### Response:Based on your instructions, here is the SQL query I have generated to answer the question `{question}`:```sql"""
这说明了几个技巧:
- 任务输入。前言(“您的任务是将问题转换为SQL查询,给定一个Postgres数据库架构。”)被称为任务输入。这是LLM训练方案的指令模型阶段的输入。请记住,基本上,LLM是一个文本补全机器。任何可以增加正确部分单词概率的事物都将有所帮助。因此,如果您的前言指导LLM进入您关心的单词空间的部分,许多LLM的效果会更好。defog在前言中使用SQL,Postgres等单词在这里至关重要。
- 系统提示。规则(“逐字阅读问题和架构,使用表别名等。”)形成所谓的系统提示。这用于指导和限制行为。 [我对defog团队的建议是避免使用“遵守”等10美元的词汇,而使用“始终”和“永远”等10美分的词汇-它们往往效果更好。] LLM经过训练以遵守系统提示(这是它们防止有毒内容的方式)。利用它们。
- 上下文的开始和结束。要回答的问题出现了两次。一次在输入部分,一次在响应部分。这种放置-在开始和结束处-并非偶然。LLM倾向于降低上下文的中间部分的权重,特别是如果您的提示(如此处)非常长。将最重要的内容放在开头和结尾。重复可能有所帮助(请进行实验以查看是否有效)。
- 结构化输入。LLM权重由与每个“头”相关的注意机制修改。因此,使用一致且唯一的令牌序列(如**Input**)有助于训练LLM以不同方式使用后续的单词。
- 上下文中的规则(?)。defog在输入上放置了关于哪些列可以与其他列连接的规则的部分。这非常有趣,他们将规则放在了输入上下文的一部分。我以前没有见过这种做法(也不确定为什么会有效),但这是我将开始注意的事情。这始终是一个学习过程:阅读有效的提示,以便掌握新技巧。
- 句子补全。注意提示以“这是我生成的SQL查询…”结尾。这是一种帮助LLM完成提示的技巧。基于聊天的LLM经过训练以接受问题并生成相应的答案,但如果您正在进行微调,则通常会微调没有此功能的基本LLM。为句子补全设定提示是个好主意。
- 上下文长度。所有LLM都有一个上下文长度。例如,Llama2的上下文长度默认为2K,但您可以通过更改源代码或在微调期间增加此窗口来增加它。现代LLM使用一个叫做sentencepiece的库对子词进行标记化,一个很好的经验法则是将每个令牌视为两个字符。注意您的提示的长度,并确保它保持在LLM的上下文长度之下。否则,LLM将截断您的请求!如果截断的提示中不包含句子补全,LLM将继续生成问题!
- 结构化响应。有几种技巧可以让LLM生成一个可解析的响应。一种方法是使用系统提示要求它生成YAML。这是凭运气的。另一种方法是在上下文中使用少量示例来说明所需的响应格式。这往往效果更好。第三个技巧是最可靠的:在提示的句子补全部分添加一系列特殊字符(defog正在使用三个反引号),然后在后处理中仅保留遵循特殊序列的响应部分。
顺便提一下,在Google Workspace Duet中,您可以看到第7和第8项。除非该错误已修复,否则请尝试选择一个过长的段落(超过上下文)并要求它进行摘要。结果将包含“Instruction”一词,这是系统提示的一部分。您之所以能看到它,是因为在响应中不存在用于界定输出的特殊字符。许多对LLM的红队黑客攻击都始于对响应的过度填充-截断会暴露很多错误和意外行为。
5. 在架构中智能混合不同的方法
现在有五种在生成AI之上构建的方法:
- 零样本:仅向LLM发送提示。您完全依赖LLM的训练数据。
- 少样本:在上下文中包含1-2个示例输入和响应。这些示例可以是固定的,也可以是基于与查询最相关的示例检索而来的。这通常只是引导LLM的一种方式,而不是教会它新的信息或新的任务。
- 检索增强生成(RAG):从相似性搜索的向量数据库中提取相关数据,并将其包含在上下文中。这是教LLM新信息的一种方式(当今的LLM无法使用RAG学习新技能)。
- 微调。通常,这是以参数高效的方式(PEFT)进行的,使用低秩适应(LoRA)的方法训练一个单独的神经网络,修改LLM的权重,使LLM能够处理新任务。在微调中,您教LLM如何处理新的指令(当今的LLM无法通过微调学习新信息)。
- 代理框架。让LLM生成您将传递给外部API的参数。这可以用于为LLM添加更多的技能和知识,但在没有人参与的情况下可能会有危险。
正如您所见,每种方法都有其优点和缺点。所以,Defog所做的是几种方法的混合。最终,他们正在执行第5项(生成将发送到数据库的SQL),但将SQL放置在由人类用户指导的复杂工作流程中。他们根据查询提取必要的模式和连接规则(第3项)。他们通过微调(第4项)一个小型模型以高效管理成本。他们以零样本的方式调用经过微调的模型(第1项)。
这种智能混合方法的目的是充分利用各种方法的优势,并防范它们的弱点。
6. 清理和组织数据集
在生成AI中,数据的数量和质量都变得越来越重要。Defog设定了一个目标,即获取10,000个训练示例,以便对定制模型进行微调(似乎他们为每个客户微调模型:请参阅前面关于子任务的讨论),而他们的努力的一大部分是清理数据集。
以下是确保数据集最佳的快速检查清单:
- 正确性。确保所有标签都是正确的。Defog通过确保所需的SQL运行并生成可以与生成文本创建的数据帧进行比较的数据帧来确保这一点。
- 策划数据。Platypus能够通过从训练数据集中删除重复项、删除灰色区域的问题等来改进Llama2。
- 数据多样性。在明智地使用这10,000个示例,并向LLM展示它在生产中将看到的各种情况非常重要。请注意Platypus如何使用大量开放数据集,或者defog如何使用10个不同的模式集,而不仅仅是训练一个表集。
- Evol-instruct。“教科书是你所需的一切”一文展示了选择简单示例并逐渐增加难度的重要性。defog使用LLM将一组指令适应为更复杂的指令。
- 对示例分配难度级别。有很多情况下,通过难度对训练数据集进行分割是有用的。您可以使用分割评估指标(参见提示#3),为较简单的任务训练较简单的模型,将其用作有效的集成机制,以难度阶段教授模型等。
到目前为止,这是能够为您提供最大性能提升的提示。
7. 根据具体情况决定建造与购买
大型模型的服务成本很高。通过在精选数据集上进行微调较小的模型,您可以获得具有竞争力的结果。这些成本可能只有原来的1/10或更少。此外,您可以在本地、边缘等地方提供微调后的模型。在计算投资回报率时,不要忽视拥有模型的财务和战略利益。
话虽如此,Open AI的GPT-4通常能够在初始状态下提供出色的性能。如果您可以预估您在生产环境中调用Open AI API的规模,您就可以估算出它将给您带来的成本。如果您的请求量足够小,由于开发成本的原因,微调可能没有经济意义。即使您开始采用微调的方法,也需要与当时的最先进模型进行基准测试,并准备好在必要时调整您的方法。
您不太可能有足够的资源为所需的一切创建定制模型。因此,您可能会同时拥有购买的模型和自建的模型。不要陷入总是自建或总是购买的陷阱。
8. 抽象出特定的LLM
OpenAI并不是唯一的选择。谷歌一直在暗示他们即将推出的Gemini模型比GPT-4更好。每隔几个月就会出现一种新的最先进模型(SoTA)。您的评估组合肯定应该包括目前为止最先进的模型(GPT-4、Gemini或GPT-5)。然而,确保您还与其他接近最先进模型(如Cohere或Anthropic)以及上一代模型(如GPT 3.5和PaLM2)的性能和成本进行比较。
购买哪个LLM主要是一项商业决策。在成本上的微小差异很少能够抵消大的差距。因此,应该对几个选项的性能和成本进行比较。
使用langchain来抽象出LLM,并将成本效益纳入您的实验框架中。这将帮助您有效地进行谈判。
9. 以API形式部署
即使是您的“小型”13GB参数微调LLM,加载时间也很长,需要一组GPU来提供服务。将其作为API提供服务,即使是对内部用户,使用网关服务进行计量和监控。
如果您的最终用户是应用程序员,记得记录API接口,并且如果您支持不同的提示,也要记录它们,并提供单元测试以确保不会破坏使用这些特定提示的下游工作流程。
如果您的最终用户是非技术人员,仅提供API是不够的。正如defog所示,提供一个带有示例查询(“chips”)的游乐场界面是一个好主意,可以使用类似streamlit的工具;如果您的最终用户是ML开发人员,可以使用HuggingFace来提供游乐场功能。
10. 自动化您的训练过程
确保您的微调流程是完全自动化的。
默认情况下,使用您通常用于云端ML平台的超级计算机,但确保计算成本和GPU/TPU在您所在地区是可用的。还有一些初创公司提供“LLMops”作为服务,通常比大型云提供商更具成本效益,因为它们使用竞价实例、拥有自己的硬件,或者是使用他人的资金。
在这里保留选择的一个好方法是将整个流程容器化。这样,您就可以轻松地将(重新)训练流程移植到任何有GPU的地方。
总结

参考资料
- https://defog.ai/
- SqlCoder: https://defog.ai/blog/open-sourcing-sqlcoder/
- SQL Evaluation metric: https://github.com/defog-ai/sql-eval
- Can foundation models label data like humans https://huggingface.co/blog/llm-leaderboard
- OpenAI cookbook, Lllama2, Google PaLM
- Lost in the middle: how language models use long contexts. https://arxiv.org/abs/2307.03172
- Platypus AI: https://www.geeky-gadgets.com/platypus-ai/
- Evol-Instruct, from WizardLM: Empowering Large Language Models to Follow Complex Instructions. https://arxiv.org/abs/2304.12244