Press "Enter" to skip to content

我如何将ChatGPT转变为图像和视频数据集的类SQL翻译器

即时工程、软件工程、试错和刻苦努力的过程

VoxelGPT使用自然语言查询图像数据集。图片由作者提供。

与表格数据不同,计算机视觉任务的数据集是非结构化的,想象一下大量像素、大量标签、大量标记和有时结构化的元数据。尽管如此,我们在计算机视觉领域工作的人仍需要能够有效地筛选这些数据,以了解数据集、准备训练和测试集、找到模式、识别边缘情况和评估模型性能。

当我需要理解视觉数据时(基本上是所有时间),我使用开源库FiftyOne,它定义了一个强大的Python语法,用于查询计算机视觉数据。它有点像针对计算机视觉数据非结构化世界的SQL,它允许我以编程方式过滤、排序和语义地切分由图像、视频甚至3D点云组成的数据集。

几个月前,在ChatGPT风靡全球时,我在OpenAI的网站上看到了一个将自然语言输入转换为SQL查询的示例应用程序。尽管此应用程序非常基本,而计算机视觉数据要复杂得多,但它让我想到:是否可以将类似的事情用于图像和视频数据集?换句话说:

我们能否利用大型语言模型(LLMs)的多功能性,将自然语言查询转换为过滤视觉计算机数据集的视图?

答案是肯定的!

在将LLM应用于FiftyOne的查询语言的情况下,我们在Voxel51团队建立了开源AI助手VoxelGPT:它使您可以全面查询计算机视觉数据集,而无需编写一行代码!

我们使用langchain,tiktoken和fiftyone实现了这一点。

您可以在gpt.fiftyone.ai上免费尝试它!

本文将为您介绍构建特定领域LLM应用程序所需的即时工程、软件工程和大量试错。

在整个过程中,我们多次遇到了困难,并担心这项任务不可行。如果您正在尝试并努力构建LLM驱动的应用程序,我希望本文能为您提供所需的灵感,帮助您突破自己的困境!

本文结构如下:

  • 图像和视频的类似SQL查询
  • 定义总体任务
  • 给模型提供上下文
  • 生成和利用示例
  • 分解问题
  • 进入生产

查询语言

VoxelGPT使用自然语言查询图像数据集。图片由作者提供。

在我们深入介绍如何使用LLM生成查询之前,值得花一些时间描述我们希望模型翻译的查询语言。这里是您需要了解的基本信息。有关更详细的概述,请参阅FiftyOne用户指南。如果您已经熟悉该语言,请随时跳到下一节。

  • 数据集:Dataset是计算机视觉中的Table或pandas中的DataFrame的类比。它包含与某个媒体文件集合相关的所有信息。
  • 样本:Sample类比于数据表中的行。样本是Dataset的原子元素。每个样本都有一个filepath,指向一个媒体文件,并存储与该数据相关的所有其他信息。
  • 字段:Field类比于数据表中的列,因为它定义了样本的属性(例如,图像宽度、高度和文件路径)。但是,字段是灵活的,因为它们可以包含其他字段(请参见下面的Label)。
  • 标签:Label是存储语义基本事实或预测信息的Field。例如,对象检测存储在 Detections 标签字段中,而分类存储在Classification标签字段中。

与 SQL 或 pandas 类似,您可以使用查询操作过滤数据。例如,您可能想要查询数据表以获取:

所有在列“A”中具有大于0.5的条目的行

但是,尽管数据表适用于数字切片和过滤,但非结构化的计算机视觉数据则适用于语义切片,例如:

检索在至少具有3个非“dog”地面真实检测的图像中具有大边界框的高置信度“dog”预测

语义切片非结构化数据需要更高的灵活性。

为了实现这种灵活性,FiftyOne定义了一组ViewStage方法,这些方法封装了允许的查询操作,例如过滤、匹配、选择、排序和排除。这些方法松散地类似于SQL中的SELECT,WHERE和ORDER BY,但由于查询空间更大,因此有更多的方法,而且每个方法都有许多用例。有关详细讨论,请参见此Views Cheat Sheet。

您可以通过按顺序组合多个ViewStage操作来获得Dataset的任意子集,称为DatasetView

以下是查询语言的实际应用:假设有一个名为my_dataset的数据集,如果我们想要获取所有包含“cat”(在它们的"ground_truth”标签字段中)的10个随机图像中的“dog”检测结果(在"predictions”标签字段中),则可以使用以下查询:

view = my_dataset.match(        F("ground_truth.detections.label").contains(["cat"])    ).filter_labels(        "predictions",         F("label") == "dog"    ).take(10)

match()限制了具有“ground_truth”检测字段中的“cat”的图像,然后filter_labels()到达"predictions”字段并仅检索“dog”检测结果,最后take()随机选择一个子集。

定义任务

当我们开始这个旅程时,我们不知道LLMs可能性有多大。在2022年12月,我曾尝试使用ChatGPT玩耍,甚至写了一篇题为“计算机视觉中的隧道视觉:ChatGPT能看到吗?”的文章,探究了聊天机器人对计算机视觉概念的理解。当时,一个通用语言模型能够为基本的图像处理任务编写大多正确的Python代码已经令人印象深刻,但是在计算机视觉应用中使用GPT生成的代码(没有人类验证)似乎是不切实际的。

看到文本到SQL的示例,并阅读有关GPT-4据报通过了BAR(以及其他考试)的报道后,我决定再次尝试GPT-for-CV。我要求GPT-4为几个简单的查询生成Python代码,并对其响应感到愉快。GPT-4的开箱即用结果的真实性还有很大的提升空间,这是可以理解的,因为我没有提供有关FiftyOne库的任何信息。但是使这项工作成功的前景令人神往。

要求一致性

随着我们尝试提示技术(稍后我们将讨论),很快就显然,如果我们想将其纳入更大的管道中,我们需要明确定义任务。

如果由GPT模型自己决定,从提示到提示,其响应的格式会有很大的差异。

以下仅是两个示例,稍后我们将对其进行分析:

提示1:

您的任务是将输入的自然语言查询转换为Python代码,以为计算机视觉库FiftyOne生成ViewStages。

这是您的第一个自然语言查询:“仅包含狗的图像”

给我FiftyOne代码。

响应1:

好的,这是生成仅包含狗的图像的ViewStage的FiftyOne代码:

import fiftyone as foimport fiftyone.zoo as foz# Load the datasetdataset = foz.load_zoo_dataset(    "open-images-v6",    split="validation",    label_types=["detections"],    classes=["Dog"],)# Create a view stage that filters out images without any dog detectionsview_stage = fo.ViewStage("detections", fo.FilterField("detections", "label", "Dog"))# Apply the view stage to the datasetdataset = dataset.add_stage(view_stage)# View the datasetsession = fo.launch_app(dataset)

这段代码载入了Open Images v6验证数据集,只使用“detections”标签类型来检测狗。然后创建一个视图阶段,过滤掉没有检测到狗的任何图像。最后,将视图阶段应用于数据集,并在FiftyOne App中启动。

Prompt 2:

你的任务是将输入的自然语言查询转换为Python代码,以生成FiftyOne机器学习库的ViewStages。

这是你的第一个自然语言查询:“最独特的带有误报检测的图像”

给我FiftyOne代码。

Response 2:

好的,这是使用Python中的FiftyOne库生成自然语言查询“最独特的带有误报检测的图像”的ViewStages的FiftyOne代码:

import fiftyone as foimport fiftyone.zoo as foz# Load your datasetdataset = fo.load_dataset("your_dataset_name")# Define your false positive detection modelmodel = foz.load_zoo_model("your_model_name")# Define your pipelinepipeline = [    {"$set": {"predictions": {"$predict": model}}},    {"$match": {"predictions.mistakes.false_positive": True}},    {"$group": {"_id": "$filepath"}},    {"$count": "num_images"},    {"$sort": {"num_images": -1}},]# Run your pipeline and display the results in a view stageview = dataset.aggregate(pipeline).limit(10).display()

在此代码中,我们首先加载FiftyOne库和任何必要的依赖项。然后使用fo.load_dataset()加载数据集。

接下来,使用foz.load_zoo_model()定义您的误报检测模型。此函数从FiftyOne Zoo Model Zoo加载预训练模型,其中包括计算机视觉的各种最先进的模型。

之后,我们使用$set、$match、$group、$count和$sort聚合阶段定义了我们的管道。该管道首先使用$set为数据集中的每个样本添加包含模型预测的字段。然后,我们使用$match筛选样本,只包括具有误报检测的样本。

接下来,我们使用$group将样本按其文件路径分组,使用$count计算每个组中的图像数量。最后,我们使用$sort按图像数量降序排序组。

最后,我们在数据集上运行管道,并使用limit()将结果限制为最多有10个误报检测的图像。然后使用display()在视图阶段中显示结果。

即使这两个示例的提示方式相同,但响应在几个关键方面有所不同。响应1尝试通过向数据集添加ViewStage来创建DatasetView。响应2定义并应用MongoDB聚合管道,然后使用limit()方法(应用Limit阶段)将视图限制为10个样本,以及不存在的(也就是幻想的)display()方法。此外,虽然响应1加载了实际数据集(Open Images V6),但响应2实际上是模板代码,因为需要填写“your_dataset_name”和“your_model_name”。

这些示例还突出了以下问题:

  1. 样板代码:某些响应包含用于导入模块、实例化数据集(和模型)以及可视化视图(session = fo.launch_app(dataset))的代码。
  2. 解释性文本:在许多情况下,包括教育环境在内,模型解释其“推理”的事实是积极的。然而,如果我们想代表用户执行查询,则此解释性文本只会妨碍。有些查询甚至会导致多个代码块,由文本分割。

我们真正想要的是LLM以不带所有额外负担的方式响应代码,该代码可以复制并粘贴到Python进程中。作为提示模型的第一次尝试,我开始将以下文本作为前缀给出,以便将任何自然语言查询转换为Python代码:

你的任务是将输入的自然语言查询转换为Python代码,以生成计算机视觉库FiftyOne的ViewStages。这些规则如下:- 避免所有头代码,例如导入包,以及所有尾部代码,例如保存数据集或启动FiftyOne App。- 只给我最终的Python代码,没有中间代码片段或说明。- 始终假设数据集存储在Python变量“dataset”中- 您可以使用以下ViewStages以任何组合来生成响应:exclude、exclude_by、exclude_fields、exclude_frames等

关键是,我定义了一个任务,并设置了规则,告诉模型它允许和不允许做什么。

注意:由于响应以更统一的格式到来,因此在这一点上,我从 ChatGPT 聊天界面转向使用通过 OpenAI 的 API 进行的 GPT-4。

限制范围

我们团队还决定,至少在开始时,我们将限制我们要求 LLM 进行的范围。虽然 fiftyone 查询语言本身是全面的,但要求一个预训练的模型在没有任何微调的情况下执行任意复杂的任务是一种失望的做法。从简单的开始,逐渐增加复杂性。

对于这个实验,我们强加了以下限制:

  • 只处理图像和视频:不要指望 LLM 查询 3D 点云或分组数据集。
  • 忽略不稳定的 ViewStages:大多数 ViewStages 遵循相同的基本规则,但有一些不遵循。`Concat` 是唯一一个需要输入第二个 DatasetViewViewStagesMongo 使用 MongoDB 聚合语法;GeoNear 有一个 query 参数,该参数接受一个 fiftyone.utils.geojson.geo_within() 对象;GeoWithin 需要一个 2D 数组来定义“within”应用的区域。我们决定忽略 ConcatMongoGeoWithin,并支持除 query 参数外的所有 GeoNear 用法。
  • 只使用两个阶段:虽然让模型组合任意数量的阶段会很好,但在我看到的大多数工作流程中,一个或两个 ViewStages 足以创建所需的 DatasetView。这个项目的目标不是被卡在草丛里,而是为计算机视觉从业者构建有用的东西。

提供上下文

VoxelGPT using natural language to query an image dataset. Image courtesy of the author.

除了为模型提供明确的“任务”和清晰的指示之外,我们发现通过提供更多关于 FiftyOne 查询语言如何工作的信息,可以提高性能。没有这些信息,LLM 是盲目的。它只是在黑暗中摸索。

例如,在提示 2 中,当我要求假阳性预测时,响应尝试使用 predictions.mistakes.false_positive 引用这些假阳性。就 ChatGPT 而言,这似乎是一种存储和访问有关假阳性信息的合理方式。

模型不知道在 FiftyOne 中,检测预测的真实/假的情况是通过 dataset.evaluate_detections() 进行评估的,运行完评估后,您可以通过与 eval_fp>0 匹配来检索所有具有假阳性的图像:

images_with_fp = dataset.match(F("eval_fp")>0)

我试图通过提供其他规则来澄清任务,例如:

- 当用户要求最“独特”的图像时,他们是指样本上存储的“独特性”字段。- 当用户要求最“错误”的图像时,他们是指样本上存储的“错误性”字段。- 如果用户没有指定要应用某些操作的标签字段,例如“predictions”或“ground_truth”,则假定如果数据上存在“ground_truth”字段,则它们意味着“ground_truth”。

我还提供了有关标签类型的信息:

- 对象检测包围框采用 [左上-x、左上-y、宽度、高度] 格式,所有相对于图像宽度和高度的范围都在 [0, 1] 范围内- 可能的标签类型包括分类、分类、检测、检测、分割、关键点、回归和折线

此外,尽管通过为模型提供允许的视图阶段列表,我能够促使它使用它们,但它并不知道:

  • 何时给定阶段是相关的,或者
  • 如何以句法上正确的方式使用该阶段

为了填补这个空白,我想给LLM提供有关每个视图阶段的信息。我编写了代码来循环遍历视图阶段(您可以使用fiftyone.list_view_stages()列出它们),存储docstring,然后将docstring的文本分成描述和输入/参数。

然而,我很快遇到了一个问题:上下文长度。

使用OpenAI API通过基础GPT-4模型,我已经接近8,192个令牌上下文长度的限制。而这还没有添加任何关于数据集本身的示例或信息!

理论上,OpenAI确实有一个具有32,768个令牌上下文长度的GPT-4模型,我本可以使用它,但我通过简单的估算发现这可能会变得很昂贵。如果我们填满整个32k令牌上下文,根据OpenAI的定价,每次查询的成本将约为2美元!

相反,我们的团队重新思考了我们的方法,并采取了以下措施:

  • 切换到GPT-3.5
  • 最小化令牌计数
  • 更加选择性地选择输入信息

切换到GPT-3.5

没有免费的午餐-这确实导致了略低的性能,至少最初是如此。在项目的过程中,我们通过提示工程成功地恢复并大大超越了这一点!在我们的情况下,这样做的努力值得成本节省。在其他情况下,可能不是这样。

最小化令牌计数

随着上下文长度成为一个限制因素,我采用了以下简单的技巧:使用ChatGPT来优化提示!

一次只有一个ViewStage,我将原始描述和输入列表,与提示一起传递给ChatGPT,要求LLM最小化文本的令牌计数,同时保留所有语义信息。使用tiktoken计算原始版本和压缩版本的令牌数,我能够将令牌数量减少约30%。

更加选择性

虽然为模型提供上下文很棒,但某些信息对于手头的任务更有帮助。如果模型只需要生成包含两个ViewStages的Python查询,那么它可能不会从其他ViewStages的输入信息中受益。

我们知道需要一种方法来根据输入的自然语言查询选择相关信息。然而,这不像在描述和输入参数上执行相似性搜索那样简单,因为前者通常用不同的语言描述。我们需要一种将输入和信息选择联系起来的方法。

结果证明,这种联系是例子。

例子

生成例子

如果您曾经玩过ChatGPT或其他LLM,您可能已经亲身体验到即使提供了单个相关示例,模型的性能也会显着提高。

作为起点,我想出了10个完全合成的示例,并通过将它们添加到我的输入提示中的任务规则和ViewStage描述之后将它们传递给GPT-3.5:

A)“文件路径以'/ Users'开头”B)`dataset.match(F(“ filepath”).starts_with(“ / Users”))`A)“置信度>0.95的预测”B)`dataset.filter_labels(“ predictions”,F(“ confidence”)> 0.95)`…

仅使用这10个示例,模型的响应质量有了明显的改善,因此我们的团队决定对此进行系统化处理。

  1. 首先,我们查看了我们的文档,找到了通过组合ViewStages创建的所有视图的任何示例。
  2. 然后,我们遍历了ViewStages列表,并添加了示例,以便我们尽可能地覆盖使用语法。为此,我们确保每个参数或关键字至少有一个示例,以给模型一个遵循的模式。
  3. 使用语法完成后,我们根据需要在示例中变化字段和类的名称,以便模型不会生成任何关于名称与阶段相关的错误假设。例如,我们不希望模型仅因为所有match_labels()的示例都包含“person”类而强烈将“person”类与match_labels()方法相关联。

选择相似的案例

在这个案例生成过程的末尾,我们已经有了数百个案例——远远超出了上下文长度的范围。幸运的是,这些案例包含了(作为输入)自然语言查询,我们可以直接将其与用户的自然语言查询进行比较。

为了进行这种比较,我们使用OpenAI的text-embedding-ada–002模型预先计算了这些示例查询的嵌入。在运行时,用户的查询会使用相同的模型进行嵌入,并选择最相似的自然语言查询的案例-通过余弦距离。最初,我们使用ChromaDB构建了一个内存向量数据库。但是,考虑到我们处理的是数百或数千个向量,而不是数百万个向量,实际上更有意义的是切换到精确的向量搜索(加上我们限制了依赖项)。

管理这些示例和提示组件变得越来越困难,因此我们开始使用LangChain的Prompts模块。最初,我们能够使用它们的Similarity ExampleSelector选择最相关的示例,但最终我们不得不编写一个自定义的ExampleSelector,以便我们更好地控制预过滤。

过滤适当的示例

在计算机视觉查询语言中,查询的适当语法可能取决于数据集中样本的媒体类型:例如,视频有时需要与图像不同地处理。我们决定只提供对于给定数据集而言语法上正确的示例,而不是通过给出看似冲突的示例来混淆模型,或者通过强制模型根据媒体类型推断来使任务变得更加复杂。在向量搜索的上下文中,这被称为预过滤。

这个想法效果很好,我们最终将相同的考虑应用于数据集的其他特征。在某些情况下,差异仅仅是句法上的——当查询标签时,访问Detections标签的语法与访问Classification标签的语法不同。其他过滤器更具策略性:有时我们不希望模型知道查询语言的某个特定特性。

例如,我们不希望给出利用它无法访问的计算的LLM示例。如果没有为特定数据集构建文本相似性索引,那么向模型提供搜索自然语言查询的最佳视觉匹配的示例就没有意义。同样,如果数据集没有任何评估运行,则查询真正的正例和假例会产生错误或空结果。

您可以在GitHub repo的view_stage_example_selector.py中看到完整的示例预过滤管道。

根据示例选择上下文信息

对于给定的自然语言查询,我们然后使用我们的ExampleSelector选择的示例来决定在上下文中提供什么额外信息。

特别地,我们统计这些选定示例中每个ViewStage的出现次数,确定最常见的五个ViewStages,并将这些ViewStages的描述和输入参数的信息作为上下文添加到我们的提示中。这样做的理由是,如果一个阶段在类似的查询中频繁出现,它很可能(但不是保证)与这个查询相关。

如果不相关,则描述将帮助模型确定它不相关。如果相关,则有关输入参数的信息将帮助模型生成符合语法要求的ViewStage操作。

分而治之

VoxelGPT使用自然语言查询图像数据集。图片由作者提供。

直到这一点,我们的重点是尽可能多地挤入一个提示中的所有相关信息,而只是相关信息。但这种方法已经到达了极限。

即使不考虑每个数据集都有自己的字段和类别名称,可能的Python查询空间也太大了。

为了取得进展,我们需要将问题分解为更小的部分。从最近的方法中汲取灵感,包括 “思路链”提示 和 “选择推理”提示,我们将生成 DatasetView 的问题分为四个不同的选择子问题:

  1. 算法
  2. 算法运行
  3. 相关字段
  4. 相关类名

然后我们将这些选择“链接”链接在一起,并将它们的输出传递到最终的 DatasetView 推理模型中。

对于每个子任务,都应遵循统一性和简单性的原则。我们尽可能地尝试回收现有示例的自然语言查询,但是对于每个选择任务的所有输入和输出格式都进行了简化。对于一个链接最简单的输入可能不是对于另一个链接最简单的输入!

算法

在 FiftyOne 中,数据集上的计算结果被存储为一个“运行”。这包括像 uniqueness 这样的计算,它测量每个图像相对于数据集中其他图像的唯一性,以及 hardness,它量化模型在试图学习此样本时会遇到的困难。它还包括与每个样本相关联的嵌入的向量索引生成的 similarity 计算,甚至是我们之前提到的 evaluation 计算。

每个计算都生成不同类型的结果对象,该对象具有自己的 API。此外,ViewStages 与这些计算之间没有任何一对一的对应关系。我们以唯一性为例。

唯一性计算结果存储在每个图像上的浮点型字段(默认为 "uniqueness")。这意味着,根据情况,您可能希望按照唯一性进行排序:

view = dataset.sort_by("uniqueness")

检索唯一性大于某个阈值的样本:

from fiftyone import ViewField as Fview = dataset.match(F("uniqueness") > 0.8)

甚至只显示唯一性字段:

view = dataset.select_fields("uniqueness")

在这一选择步骤中,我们要求 LLM 预测哪些可能的计算可能与用户的自然语言查询相关。这项任务的示例如下:

Query: "most unique images with a false positive"Algorithms used: ["uniqueness", "evaluation"]

算法运行

一旦确定了可能相关的计算算法,我们就会让 LLM 选择每个计算的最适合运行。这是必要的,因为某些计算可以在相同的数据集上使用不同的配置多次运行,而 ViewStage 可能只有正确的“运行”才有意义。

相似性运行是一个很好的例子。假设您正在测试两个模型(InceptionV3 和 CLIP)的数据,并针对每个模型在数据集上生成了一个向量相似性索引。当使用 SortBySimilarity 视图阶段时,被确定为与哪个其他图像最相似的图像可能会相当大地依赖于嵌入模型,因此以下两个查询需要生成不同的结果:

## query A:"show me the 10 most similar images to image 1 with CLIP"## query B:"show me the 10 most similar images to image 1 with InceptionV3"

此运行选择过程针对每种类型的计算单独处理,因为每种类型需要修改的任务规则和示例不同。

相关字段

这个链接涉及识别与自然语言查询相关的所有字段名称,这些字段名称与计算运行无关。例如,不是所有具有预测的数据集都将这些标签存储在名称为 "predictions" 的字段下。根据个人、数据集和应用程序的不同,预测可能存储在名为 "pred""resnet""fine-tuned""predictions_05_16_2023" 或其他名称下。

这项任务的示例包括查询、数据集中所有字段的名称和类型,以及相关字段的名称:

查询:“从所有样本中排除model2的预测”可用字段:“[id: string,filepath: string,tags: list,ground_truth: Detections,model1_predictions: Detections,model2_predictions: Detections,model3_predictions: Detections]”所需字段:“[model2_predictions]”

相关类名

对于像分类和检测这样的标签字段,将自然语言查询转换为Python代码需要使用数据集中实际类的名称。为此,我让GPT-3.5执行标签类别中的命名实体识别。

在查询“至少有一个牛预测且没有马”的情况下,模型的任务是识别"horse""cow"。然后将这些已识别的名称与先前步骤中选择的标签字段的类名进行比较-首先是区分大小写的,然后是不区分大小写的,然后是不区分单复数的。

如果在命名实体和数据集中的类名之间没有匹配,则退回到语义匹配:"people""person""table""dining table""animal" [“cat”, “dog", “horse", …]

每当匹配不完全相同时,我们使用匹配的类的名称来更新传递给最终推理步骤的查询:

查询:“20个带有桌子的随机图像”  ## 变成:查询:“20个带有餐桌的随机图像”

ViewStage推理

一旦进行了所有这些选择,相似的示例、相关的描述和相关的数据集信息(选择的算法运行、字段和类)将与(可能修改过的)查询一起传递给模型。

与最初的方法要求模型以dataset.view1().view2()…viewn()的形式返回代码不同,我们取消了dataset部分,而是要求模型将ViewStages作为列表返回。当时,我很惊讶这会提高性能,但回想起来,它符合这样的见解:任务分得越多,LLM就越好。

使其可用

创建一个由LLM驱动的玩具很酷,但将同样的内核转换为LLM驱动的应用程序更酷。以下是我们如何做到的简要概述。

单元测试

将其从概念验证转换为牢固设计的系统时,我们使用单元测试来测试管道并确定弱点。链中的链接的模块化性质意味着可以单独对每个步骤进行单元测试、验证和迭代,而无需运行整个链。

这导致了更快的改进,因为提示工程团队内的不同个体或团体可以并行地在链中的不同链接上工作。此外,它会降低成本,因为理论上,您只需要运行一步LLM推理来优化链中的单个链接。

评估LLM生成的代码

我们使用Python的eval()函数将GPT-3.5的响应转换为DatasetView。然后,我们将FiftyOne App的session状态设置为显示此视图。

输入验证

垃圾输入→垃圾输出。为了避免这种情况,我们运行验证以确保用户的自然语言查询是合理的。

首先,我们使用OpenAI的审查端点。然后,我们将任何提示分类为以下四种情况之一:

1:合理且完整:该提示可以合理地转换为用于查询数据集的Python代码。

所有带狗检测的图像

2:合理但不完整:该提示是合理的,但如果没有附加信息就不能转换为DatasetView。例如,如果我们有两个对数据进行预测的模型,则以下提示仅指“我的模型”是不足的:

找回我的模型的错误预测

3: 超出范围:我们正在构建一个应用程序,可以生成对计算机视觉数据集进行查询的视图。虽然基础的 GPT-3.5 模型是一个通用的 LLM,但我们的应用程序不应该成为与你的数据集旁边的断开的 ChatGPT 会话。以下提示应该被消除:

像我五岁的时候解释量子计算

4: 不合理:对于一个随机字符串,尝试生成数据集的视图是没有意义的——甚至不知道从哪里开始!

Azlsakjdbiayervbg

在尝试将用户的输入查询转换为视图阶段序列之前,我们将输入传递到模型中,并提供验证说明和示例。根据响应,我们要么提示用户提供更多信息或更合理的查询,要么继续进行数据集视图生成管道。

总结

VoxelGPT 的运行!视频由作者提供。

一个简单的想法引发了一个疯狂的想法,这个旅程将这个疯狂的想法变成了现实。通过提示工程、一些真正的软件工程、大量的肘部油脂和一剂黑色魔法,我们的团队创建了一个由 LLM 驱动的应用程序,将自然语言查询转换为计算机视觉数据集的过滤视图。

要点很简单:定义任务、用规则指导、限制范围、简化、选择一致性、分解问题并保持相关性。

当我们将所有的组成部分放在一起,它看起来像这样:

  1. 验证查询
  2. 查找相似示例
  3. 检索相关文档
  4. 确定潜在的算法/计算
  5. 选择最可能运行这些算法的运行
  6. 确定在查询中访问/使用哪些字段(属性)
  7. 为每个标签字段推断类名
  8. 生成查询的视图阶段列表
  9. 组合视图阶段并返回数据集中的过滤视图

VoxelGPT 远非完美。但这从来不是目标。每一步都有改进的空间——更不用说更多的例子!人们也可以将其用作构建计算机视觉任务的 AutoGPT 风格委托者的基础。

欢迎任何和所有对 VoxelGPT 的贡献。它是免费和开源的!🙂

Leave a Reply

Your email address will not be published. Required fields are marked *