提示工程自动化实践

news/2024/9/18 14:48:20/ 标签: 自动化, 运维

提示工程很糟糕。

这是使用大型语言模型最乏味的部分。这些模型非常挑剔,对提示进行看似无害的更改可能会导致截然不同的结果。我厌倦了手动调整、不系统的变化以及与手动提示工程相关的头痛……

首先让我们统一认识,提示工程是指对 AI 模型给出的指令(提示)进行精心设计和改进,以引出所需的响应。它需要深入了解模型的行为,并进行大量的反复试验才能获得一致和准确的输出。

但传统的手动改进提示的过程很糟糕。所以我正在制作一个自动提示优化器。

本文将分为多个部分。本文的前半部分将概述我的一般方法。我将讨论我为获得基本事实所做的工作,这是优化过程中的重要部分。

本文的下一部分将介绍优化阶段。它将讨论我计划如何改进我的“AI 股票筛选器”,这是 NexusTrade 平台内由 LLM 提供支持的功能。

我们将改进的由 AI 提供支持的股票筛选器

这项工作很重要,因为它可以让我们花更少的时间进行手动提示调整(这并不能保证提高性能),而花更多的时间专注于大型语言模型的实际业务用例。

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - AI模型在线查看 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割

1、我的方法概述:自动快速优化

我的方法受到一篇名为 EvoPrompt 的论文的启发,这是一个自动快速优化的框架。该框架使用受进化启发的算法,模仿自然选择的过程来迭代改进解决方案。

进化算法是一类受查尔斯·达尔文进化论启发的优化算法。它们有五个阶段:

  • 初始化:如何生成初始种群
  • 选择:如何“选择”种群中的个体进行繁殖,更适合的个体更有可能被选中
  • 交叉(或重组):我们如何选择结合父母的“基因”来创造新的后代(或解决方案)
  • 突变:后代的意外变化可能对其适应性产生积极或有害的影响
  • 评估:我们如何计算后代的适应性

为了利用此算法进行快速优化,我们需要一个可以在过程中使用的输入/输出对种群。一个部分用于训练模型,另一个部分用于评估模型。

2、获取基本事实

模型输入示例

我将优化的提示是我的 AI 驱动的股票筛选器。给定自然语言输入,筛选器将找到符合拟标准的股票。

NexusTrade 中的 AI 股票筛选器

一些示例输入是:

  • (简单)IBM 的最新毛利润是多少?
  • (中等)前 5 大软件公司的总股本是多少?
  • (困难)2021 年 6 月 16 日,市值 1000 亿美元或以上的 10 家公司的价格与自由现金流比率最低?

我的方法相对简单。我收集了 60 个问题的列表并检索了这些问题的答案。我将使用以下目录结构将问题/答案对保存到我的计算机上:

./
├── output/
│   ├── easy_apple_price_today/
│   │   ├── input.txt
│   │   └── output.txt
│   ├── easy_nvidia_latest_revenue/
│   │   ├── input.txt
│   │   └── output.txt
│   ├── medium_top_10_ai_stocks/
│   │   ├── input.txt
│   │   └── output.txt
│   ├── hard_lowest_price_fcf_ratio/
│   │   ├── input.txt
│   │   └── output.txt
│   ├── easy_ford_pe_ratio_ttm/
│   │   ├── input.txt
│   │   └── output.txt
│   ├── hard_ev_stocks_highest_volume/
│   │   ├── input.txt
│   │   └── output.txt
│   ├── medium_semiconductor_stocks_revenue/
│   │   ├── input.txt
│   │   └── output.txt
│   ├── medium_avg_revenue_top_25_biotech/
│   │   ├── input.txt
│   │   └── output.txt
└── main.ts

3、用于填充输入/输出对的脚本

为了从输入生成所有输出,我还使用了 AI 驱动的方法:

import NexusGenAIServiceClient, {AIModeEnum,
} from '../services/NexusGenAIServiceClient';import { BigQueryDataManager } from '../../services/BigQueryClient';
import DB from '../../services/db';
import fs from 'fs';
import inputs from './inputs';
import readline from 'readline';async function evaluateResponse(response: any) {const result = await new NexusGenAIServiceClient({process.env.NEXUSGENAI_API_KEY}).chatWithPrompt({model: 'AI Stock Screener Output Evaluator',prompt: 'AI Stock Screener: Content: JSON.stringify(response) }',AIModeEnum.four0m,});console.log('Score:', result[result.length - 1].data.score);return result;
}async function run() {const db = new DB('cloud');await db.connect();const rl = readline.createInterface({input: process.stdin,output: process.stdout,});async function askQuestion(question: string): Promise<string> {return new Promise((resolve) => {rl.question(question, (answer) => {resolve(answer);});});}function isAffirmative(response: string): boolean {const affirmatives = ['yes', 'yeah', 'ya', 'yea'];return affirmatives.includes(response);}function isNegative(response: string): boolean {const negatives = ['no', 'nah', 'nope'];return negatives.includes(response);}async function getUpdatedMessages({messages,sql: string,content: string}) {return await new NexusGenAIServiceClient({process.env.NEXUSGENAI_API_KEY}).chatWithPrompt({model: 'AI Stock Screener',prompt: `User: ${content}`,AIModeEnum.four0,});}for (const input of inputs) {const { text, filename } = input;const outputDir = `./output/${filename}`;const outputFilePath = `${outputDir}/output.txt`;if (!fs.existsSync(outputDir)) {fs.mkdirSync(outputDir, { recursive: true });}const sql = `SQL QUERY BASED ON ${text}`;const messages = await getUpdatedMessages({messages: [{sender: 'user',content: text,AIModeEnum.four0,},],sql,content: text,});let isCorrect = false;let retryCount = 0;const maxRetries = 5;console.log('Thought Process:', messages[messages.length - 1].content);while (!isCorrect) {const sql = messages[messages.length - 1].data.sql;console.log('SQL:', sql);await BigQueryDataManager.createInstance().executeQuery(sql);console.log('Manual review required for $filename }');let userResponse = await askQuestion('Is this query correct after manual review? (yes/no): ');while (!isAffirmative(userResponse) && !isNegative(userResponse)) {userResponse = await askQuestion('Please enter a valid response (yes/no): ');}if (isAffirmative(userResponse)) {isCorrect = true;} else {const issueDescription = await askQuestion('Explain in detail what’s wrong with the query: ');messages = await getUpdatedMessages({messages,sql,issueDescription,});}if (++retryCount >= maxRetries) {console.log('Max retries reached. Manual review required.');break;}}const outputContent = JSON.stringify(messages[messages.length - 1].data, null, 2);fs.writeFileSync(outputFilePath, outputContent);}rl.close();
}(async () => {await run();process.exit(0);
})();

更具体地说,我正在使用脚本来帮助我填充模型的基本事实。它执行以下操作:

  • 将请求发送到 OpenAI
  • 从 OpenAI 响应执行查询
  • 询问用户输出是否正确。如果不正确,他们可以添加有关答案看起来错误的原因的背景信息,并引导模型找到正确答案。

执行脚本时,输出如下所示:

Input: What is the average price to sales ratio of the top 5 cloud computing stocks?
Thought Process: To find the average price to sales ratio of the top 5 cloud computing stocks, we need to:
1. Generate a subquery to get the most recent price to sales ratio for each cloud computing stock.
2. Filter for companies classified under cloud computing.
3. Order the results by market cap in descending order to identify the top 5 companies.
4. Calculate the average price to sales ratio for these top 5 companies.
5. Ensure the query avoids common errors such as division by zero by not performing any division operations.
6. Group the results by company symbol to avoid duplicates.
7. Use appropriate timestamp operations to handle the date filtering.
8. Limit the number of results to 5 to focus on the top companies.
Now I will generate the query:
SQL:WITH CloudComputingStocks AS (SELECT si.symbol, si.name, pd.date, pd.priceToSalesRatioTTM,pd.marketCap FROM `nexustrade-io.stockindustries.current` si JOIN `nexustrade-io.universalstockfundamentals.price_data` pd ON si.symbol = pd.symbol WHERE si.cloudComputing = TRUE AND pd.date = (SELECT MAX(date) FROM `nexustrade-io.universalstockfundamentals.price_data` WHERE symbol = si.symbol) ORDER BY pd.marketCap DESC LIMIT 5) SELECT AVG(priceToSalesRatioTTM) AS average_price_to_sales_ratio FROM CloudComputingStocksJob ef860d9c-cdd3-4313-9b11-c5d54877127f started.
[ { average_price_to_sales_ratio: 14.710944000000001 } ]
Manual review required for medium_avg_ps_ratio_cloud_computing.What is the average price to sales ratio of the top 5 cloud computing stocks?Is this query correct after manual review? (yes/no): no
Explain in detail what’s wrong with the query: the stock names are not populated

请注意,这是一种半自动化方法。由于我们还没有基本事实,因此我们必须照看模型并确保它生成正确的输出。这非常重要,因为我们不想针对错误的答案进行优化。

获得输入/输出对列表后,我们可以继续执行第 2 步。

4、数据拆分和优化

在下一节中,我将讨论优化技术的下一阶段。如果拟对训练神经网络或遗传优化很熟悉,那么拟会觉得这很熟悉。我计划执行的程序如下:

准备数据

数据准备对于消除结果中的偏差非常重要。最好的方法是随机化。具体来说:

  • 我们将随机化问题/答案对的群体。
  • 然后我们将拆分数据:前 80% 将放在训练集中,20% 将放在验证集中。

训练集直接用于改进模型,而验证集仅用于查看我们的优化技术是否能很好地泛化样本。我们的目标是,尽管没有直接对其进行训练,但我们的验证集性能仍会提高。

从数据准备到初始种群生成

就像遗传优化一样,我需要使用训练集创建初始提示种群。

在我的平台中,提示对象不仅仅是您可能习惯的系统提示。它由以下属性组成:

  • 系统提示:我们给模型的直接指令
  • 模型:GPT-4o mini 和 Claude 3.5 Sonnet 等模型是您可以使用的一些模型。
  • 示例:示例听起来就是它们的样子:它们是模型可以预期的对话示例

所有内容的组合构成了一个“提示对象”。在这个实验中,我们不会尝试优化模型——我们将专注于优化系统提示和示例。

以下是我们将如何生成初始种群。

  • 原始提示修改:获取原始提示对象并删除现有示例。
  • 提示变体生成:使用具有成本效益的模型(如 GPT-4o mini)生成提示的 x 个变体,GPT-4o mini 是最新(且最便宜)的大型语言模型,其性能优于 GPT-3.5 Turbo。首先,我们可以生成 10 个变体
  • 示例生成:为每个变体生成 8 个随机示例。
通过适者生存提示进行进化

接下来,我将使用语言模型作为优化器来优化我的提示。这是该过程最酷的部分之一——每个优化组件都是一个语言模型。让我解释一下这个过程。

  • 评估:使用 GPT-4o mini 作为我们的事实上的模型,我们将使用来自训练集的示例子集来测试我们的初始种群。获得输出后,我们将使用特殊的“提示评分器”提示将输出与我们今天合成的地面真相进行比较。提示评分器将为每个提示给出 0 到 1 的分数。然后我们将分数相加,因此每个提示都会有一个最终分数。
  • 选择:我们将执行所谓的“轮盘选择”来选择父母,其中表现更好的提示更有可能被选为父母。对于每个父母,我们将随机挑选将传递给后代的示例。
  • 交叉:取一对父母,我们将使用“提示组合器”提示来合并选定的提示。在创建新的后代时,我们还将组合来自每个父代的随机示例
  • 变异:为了保持种群的多样性,我们将随机选择一个提示并对其进行“变异”。虽然我们可以通过多种方式来实现这一点,但我们将首先使用一个简单的“提示变异器”提示,它只是重新表述系统提示。我们还可以有一个“示例重新排列器”,它会影响示例保存到提示对象的顺序。
  • 替换:最后,我们将评估每个新提示的性能,根据提示的性能对其进行排名,并剔除性能较差的提示。

如拟所见,这种方法完全由大型语言模型支持。随着 GPT-4o mini 的发布,执行这种类型的优化从未如此便宜。

“提示分级器”、“提示组合器”和“提示变异器”的具体实现将在下一篇文章中详细介绍。总结一下,它们将是自己的提示,并被赋予专门的任务以促进优化过程。

例如,提示评分者将获得模型的输出和基本事实,并被告知输出一个从 0 到 1 的数字,其中 1 表示模型输出了正确的响应(类似于基本事实),而 0 表示模型输出了错误的响应。

提示组合器和提示修改器将根据其角色被赋予类似的任务。

找到最好的提示

最后,在每个循环结束时,我们将运行以下两个步骤:

  • 验证:在验证集上测试优化的提示,以评估与基本事实相比的准确性。
  • 迭代:重复整个过程一定次数,以迭代方式改进提示。首先,我们只需重复该过程 10 次,然后查看验证集性能随时间的变化

最终结果应该是一组比原始提示更好的提示。我们还将有一个图表来查看训练和验证集性能是否确实随着时间的推移而提高。当然,我的所有结果都将在本系列的下一篇文章中详细记录。

5、结束语

关于如何改进这种方法,我有很多疯狂的想法。例如,我可以执行一种更复杂的优化技术,称为多目标优化,它可以同时改善多个因素。这包括速度和成本等传统因素,但也包括模型的个性或他们使用的语气等不太常见的因素。

但首先,我从一个非常简单的单目标优化问题开始。为什么?因为我讨厌提示工程。

如果我能证明,花 2 个小时的时间开发完整的基本事实可以消除我再次修改这些提示的需要,那么你敢打赌我会珍惜这笔投资。


原文链接:我讨厌提示工程 - BimAnt


http://www.ppmy.cn/news/1516946.html

相关文章

Elasticsearch 8 RAG 技术分享

Tech Day 本文由Elastic 中国区首席架构师 Jerry Zhu 在【AI搜索 TechDay】上的分享整理而成。【AI搜索 TechDay】 是 Elastic 和阿里云联合主办的 AI 技术Meetup系列&#xff0c;聚焦企业级 AI 搜索应用和开发者动手实践&#xff0c;旨在帮助开发者在大模型浪潮下升级 AI搜索…

探索Facebook的AI算法:如何优化用户体验

在数字化时代&#xff0c;社交媒体平台不断引领着技术创新的潮流。作为全球领先的社交平台之一&#xff0c;Facebook在人工智能&#xff08;AI&#xff09;算法的应用上取得了显著进展&#xff0c;极大地提升了用户的社交体验。本文将探讨Facebook如何通过先进的AI算法优化用户…

第4章 汇编语言和汇编软件

第4章 汇编语言和汇编软件 该章主要介绍了汇编语言和汇编语言编译器的安装和使用。 汇编语言程序 该小节主要介绍了为什么要有汇编语言和汇编语言程序的一些基础写法。 书中有提到CPU有不同的架构&#xff0c;汇编语言有不同的风格&#xff0c;那么不同的CPU架构和不同的汇…

RPA自动化流程机器人在企业财务中的安全与合规性考虑

随着企业对数字化转型的需求不断增加&#xff0c;财务系统变得更加复杂和集成&#xff0c;而新技术的应用将改变企业财务管理传统的运营模式&#xff0c;帮助企业提质增效的同时也可能带来系统安全性的挑战。RPA自动化流程机器人作为最受企业欢迎的数字化转型工具之一&#xff…

【C语言】深入理解指针3(附转移表源码)

深入理解指针3 1.字符指针变量2.数组指针变量2.1是什么2.2应用 3.二维数组传参的本质4.函数指针变量4.1函数指针变量的创建和使用4.2 typedef关键字 5.函数指针数组6.转移表 1.字符指针变量 上⾯代码的意思是把⼀个常量字符串的⾸字符 h 的地址存放到指针变量 pstr 中。 《剑指…

WITH (NOLOCK) 是 SQL Server 中的一个提示

WITH (NOLOCK) 是 SQL Server 中的一个提示&#xff08;hint&#xff09;&#xff0c;它告诉 SQL Server 在读取数据时不要获取共享锁。这个提示通常用于优化读取操作的性能&#xff0c;特别是在读取大量数据时&#xff0c;因为它可以减少锁的竞争&#xff0c;从而可能加快查询…

Mac M1 Max配置torch-geometric等深度学习库

前提&#xff1a;此电脑中已经安装好了Anaconda环境 &#xff08;一&#xff09;查看创建的虚拟环境中torch的版本 import torch torch.__version__&#xff08;二&#xff09;针对安装的 torch 版本&#xff0c;去官网下载torch-geometric 依赖的对应版本 torch-sparse、tor…

Mysql 集群技术

目录 一、MySQL在服务器中的部署方法 1、MySQL的源码编译安装 2、MySQL部署 二、MySQL的主从复制 1、配置master 2、配置slave 当有数据时添加node3 4、延迟复制 5、慢查询日志 6、MySQL的并行复制 7、原理剖析 8、架构缺陷 三、半同步模式 1、原理 2、gtid模式…

vue2前端阿里云oss断点续传

官方文档地址&#xff1a;如何通过断点续传上传的方式将文件上传到OSS_对象存储(OSS)-阿里云帮助中心 1、需要后端提供一个接口&#xff0c;接口数据包含&#xff1a; const client new OSS({// yourRegion填写Bucket所在地域。以华东1&#xff08;杭州&#xff09;为例&…

【STM32】PWR电源控制(低功耗模式)

本篇博客重点在于标准库函数的理解与使用&#xff0c;搭建一个框架便于快速开发 目录 PWR简介 修改主频 低功耗模式 睡眠模式 停止模式 待机模式 PWR简介 PWR&#xff08;Power Control&#xff09;电源控制 &#xff0c;负责管理STM32内部的电源供电部分&#xff0c;可…

31套科技风PPT免费分享

目录 部分展示 部分展示 #PPT下载 「科技风模板」链接&#xff1a;https://pan.quark.cn/s/fb2f39a1d343 链接永久有效&#xff0c;点击这里下载&#xff0c;记得给个赞哦

中间件安全

1.中间件 中间件(Middleware)是指一种软件组件&#xff0c;其作用是在不同的系统、应用程序或服务之间传递数据和消息。它通常位于应用程序和操作系统之间&#xff0c;负责在不同的应用程序之间传递数据、协调不同应用程序之间的通信&#xff0c;以及处理网络请求等。 中间件…

Oracle开始严查Java许可!

0x01、 前段时间在论坛里就看到一个新闻&#xff0c;说“Oracle又再次对Java下手&#xff0c;开始严查Java许可&#xff0c;有企业连夜删除JDK”&#xff0c;当时就曾在网上引起了一阵关注和讨论。 这不最近在科技圈又看到有媒体报道&#xff0c;Oracle再次严查&#xff0c;对…

【树的最长路径】

题目 错误代码&#xff08;18过15&#xff09; #include <bits/stdc.h> using namespace std; const int N 1e410, M N << 1; const int null -0x3f3f3f3f; int h[N], e[M], ne[M], w[M], idx; int v[N]; int maxx; int res; int twice; void add(int a, int …

C语言占领游戏

目录 开头程序程序的流程图程序的效果结尾 开头 大家好&#xff0c;我叫这是我58。 程序 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <Windows.h> void pri…

windows核心编程:5章:将一个进程放入一个作业中,以限制此进程具体能够做那些事情

windows核心编程&#xff1a;5章&#xff1a;将一个进程放入一个作业中&#xff0c;以限制此进程具体能够做那些事情 windows核心编程&#xff1a;5章&#xff1a;将一个进程放入一个作业中&#xff0c;以限制此进程具体能够做那些事情 文章目录 windows核心编程&#xff1a;…

Linux的yum包管理工具(在线安装)

Linux的软件从哪里下载&#xff1f; 我们用的Linux系统都是国外的&#xff0c;所以下载软件自然从国外下载。但是访问国外网址太慢了&#xff0c;有没有什么办法快一点呢&#xff1f; 有&#xff01; 啊&#xff0c;还有这么美的事情&#xff1f;快点告诉我&#xff01; 好…

【Redis】RDB和AOF持久化

RDB和AOF持久化 一、什么是持久化&#xff1f;二、RDB三、AOF 一、什么是持久化&#xff1f; 数据一般写在内存上&#xff0c;但是当重新启动计算机内存数据是会丢失的&#xff0c;而硬盘中的数据是不会丢失的&#xff0c;所以&#xff0c;当我们把数据从内存放到硬盘中的话就…

andorid动画之呼吸效果

目录 效果图实现方式一 &#xff1a;使用 ObjectAnimator 实现呼吸效果方式二&#xff1a;使用 ValueAnimator 实现呼吸效果 总结 在 Android 中实现呼吸效果的动画可以通过多种方式来实现&#xff0c;最常见的方法是使用 ObjectAnimator 和 AnimatorSet。呼吸效果通常指的是一…

Vivado 编译固件后时序报告查询

随笔记录 目录 1. 背景介绍 2. 查看时序 2.1 Vivado tcl 模式编译固件&#xff0c;查看时序报告 2.1.1 时序报告路径 2.1.2 查看时序报告内容 2.2 Vivado GUI 模式编译固件&#xff0c;查看时序 1. 背景介绍 硬件源码&#xff0c;需要编译固件生成 bit/bin 文件后&…