ShiffBot 创建始末:通过 ShiffBot 探索 AI 助力的学习体验,这是一项由 Gemini API 提供支持的 AI 实验

一月 24, 2024
Jasmin Rubinovitz AI Researcher

Google Lab Session 是我们与创新者进行的一系列实验性合作。在本次 Google Lab Session 中,我们与备受欢迎的创意编码教育工作者兼 YouTube 创作者 Daniel Shiffman 合作,共同探讨了 AI(特别是 Gemini API)在学习过程中为教师和学生创造价值的一些方式。

起初,Dan Shiffman 在纽约大学教授 ITP 计划的编程课程,后来他开设了自己的 YouTube 频道 The Coding Train,并将自己的内容分享给了更多的人。学习编码可能会很有挑战性,有时即使是很小的障碍也很难凭一己之力克服。于是我们和 Dan 开始思考:我们能否尝试创建一项 AI 驱动的工具,帮助学生在自己的编码环境中进行实际编码,从而为 Dan 的教学提供进一步补充?

Dan 使用出色的 p5.js JavaScript 库及其可访问的编辑器来教授代码。于是,我们开始着手创建适用于该编辑器的实验性 Chrome 扩展程序,以便将 Dan 的教学风格和他的各种在线资源整合到编码环境中去。

在这篇博文中,我们将分享我们使用 Gemini API 与 Dan 一起制作 ShiffBot 的整个过程。希望我们在此期间吸取的部分经验教训能够激励您,让您创造并构建出属于自己的创意。

如需详细了解 ShiffBot,请访问:shiffbot.withgoogle.com

Link to Youtube Video (visible only when JS is disabled)

当我们开始确定并改进对于这个聊天机器人的构想时,我们发现我们面临着两大关键问题:

  1. ShiffBot 要怎样才能像 Dan 在课堂和视频中那样,激发人们的好奇心并激励他们进行探索和创意表达?
  2. 我们要怎样才能揭示创意编码方法的多样性,并将 Dan 和社区的深厚知识展现出来?

我们通过结合 Google Gemini API 的各项功能来处理上述问题,我们利用提示工程来模仿 Dan 独特的教学方式,并通过嵌入语义检索来提供 Dan 的各种教育内容。下面让我们来看看解决上述问题的具体过程吧。

语气和表述方式:为“ShiffBot”注入“Shiffman 灵魂”

文本提示是一种精心设计的文本序列,用于预先调试大型语言模型 (LLM),以使其通过特定方式生成文本。与许多 AI 应用一样,设计合适的提示是塑造使用体验的重要组成部分。

每当用户向 ShiffBot 提问时,系统都会依据来自多个不同部分的信息实时构建提示;有些提示是静态的,有些则是根据问题动态生成的。

2
ShiffBot 提示基本模块

提示的第一个部分是静态的,并且始终相同。我们与 Dan 密切合作,斟酌该部分的措辞,并测试了许多文本、说明和技术。我们使用 Google AI Studio(基于网络的免费开发者工具)来快速测试多个提示以及用户可能会与 ShiffBot 进行的对话。

首先,ShiffBot 的提示需要设置机器人角色,并定义一些机器人需要遵循的说明和目标。我们希望机器人既能延续 Dan 在他的视频中所展现出的独特精气神,又能秉持 Dan 的学生和粉丝所推崇的教学原则。

我们希望 ShiffBot 能够提供鼓励、指导和获取相关高质量资源的途径。具体来说,ShiffBot 不应简单地提供答案,而是要帮助学生找出适合他们自己的答案(因为答案可能不止一个)。

提示中的说明借鉴了 Dan 的教学风格,包含着“向用户提问”之类的句子,因为 Dan 在课堂上经常会这么做。以下是提示的“角色/说明”部分的一些内容:

你是 ShiffBot,是一款嵌入在 p5.js 网络编辑器中的聊天机器人,能够在用户学习创意编码时为他们提供帮助。你是基于 Daniel Shiffman 的性格以及 The Coding Train YouTube 频道构建的。你友善风趣,以教学为乐,有时还有一点小蠢。你喜欢拿自己开玩笑,而你的任务则是为创意编码过程提供支持,让用户在编码时不那么孤独。你喜欢人类,对他们很着迷,并且想要进一步了解他们。你就是很喜欢帮助人类进行编码工作,这会让你非常高兴……

提示的下一个部分利用了 LLM 的另一项功能,我们称之为少样本学习。这意味着模型只需通过少量示例即可学习特定模式,然后就可以在新输入中使用这些模式。实际上,我们提供了一些输入和预期输出的演示,并将其作为提示的部分内容。

我们与 Dan 合作创建了一小组这样的少样本示例。它们是<用户输入>与<机器人回应>的“配对”,其中的<机器人回应>始终采用我们想要的 ShiffBot 风格。这种“配对”看起来像这样:

用户:怎样画圆?

ShiffBot:哦!🟣 🟢 🔵 这就是“circle()”函数的作用!你可以将函数想象成命令:“我命令你这台计算机给我画一个圆!”你还需要指定画圆的位置以及圆的大小(这就是函数的“参数”!),p5.js 提供的参考资料可以为你提供更多信息,它们都是由美丽的活生生的人编写的!
 
--- 

用户:我的作业是画一幅自画像。ShiffBot:哦!自画像很有趣!你可以画各种形状来呈现自己的样子,但你需要发挥创意,并动用抽象思维!自画像对你来说意味着什么?试着使用“square()”或“circle()”函数开始作画吧,别忘了告诉我情况如何!🎨

我们的提示包含 13 组这样的“配对”。

我们在开发扩展程序的过程中注意到了另一件事,那就是在提示中提供更多背景信息有时会有所帮助。以在 p5.js 中学习创意编码为例,在提示中解释一些 p5.js 原则可指导模型在回答用户的问题时使用这些原则。因此,我们的提示还包含以下这类内容:

使用 let 而不是 var  const

到目前为止,我们讨论的所有内容都是静态的,这意味着这些内容在用户与 ShiffBot 的每一轮对话中都不会改变。现在,我们来探索一些根据对话的发展动态构建而成的部分。

对话与代码上下文

由于 ShiffBot 嵌入在 p5.js 编辑器中,它可以“看到”用户当前正在编写的代码,因而可以生成更加个性化且更具相关性的回应。我们也会抓取此类 HTML DOM 信息并将其附加到提示中。

3
p5.js 编辑器环境

然后,我们会附加完整的对话历史记录,例如:

ShiffBot:☀️ 早上好!现在是早上吗?我不清楚,毕竟我只是一个机器人。你今天要编写什么代码?
用户:怎样画正方形?

ShiffBot:正方形!我喜欢正方形!它们非常稳定可靠。你可以使用“square()”函数来画正方形。这个函数需要四个参数:正方形左上角的 x 和 y 坐标,以及正方形的宽度和高度。例如,square(10, 10, 50, 50) 函数将画出这样一个正方形:其左上角的坐标为 (10, 10),其宽度和高度均为 50 像素。

用户:怎样更改颜色?

ShiffBot:

我们会确保以如下内容结尾:

ShiffBot:

这样一来,模型就会明白它现在需要完成 ShiffBot 的下一段话。

语义检索:以 p5.js 资源和 Dan 的内容为基础塑造体验

多年来,Dan 创作了许多材料,包括 1,000 多个 YouTube 视频、多本书籍及各种代码示例。我们希望让 ShiffBot 在合适的时间向学员展示这些出色的材料。为了实现这一点,我们使用了 Gemini API 中的语义检索功能,您可使用该功能创建文本片段语料库,然后向其发送查询,以便在语料库中获取与您的查询相关性最高的文本。(在后台,该功能会使用一种名为文本嵌入的酷炫技术;您可以在此处阅读更多有关嵌入的信息。)我们根据 Dan 的内容为 ShiffBot 创建了语料库,以便根据需要在提示中添加相关的内容片断,或者在用户与 ShiffBot 的对话中显示这些内容片断。

创建视频语料库

通过在 The Coding Train 频道上发布的视频,Dan 按照由简单到高级的顺序讲解了许多概念,这整个过程中还穿插着各种编码挑战。理想情况下,ShiffBot 可以在合适的时间使用并提供合适的视频。

用户可通过 Gemini API 的语义检索功能创建多个语料库。语料库由文档构成,每个文档包含一个或多个文本块。文档和文本块可能还具有用于过滤或存储更多信息的元数据字段。

在 Dan 的视频语料库中,每个视频都会作为一个文档,且视频网址将与视频标题一起保存为元数据字段。视频会被分为章节(由 Dan 手动划分并上传至 YouTube)。我们使用各个章节作为文本块,各个文本块的文本如下:

<videoTitle>

<videoDescription>

<chapterTitle>

<transcriptText>

我们使用视频标题、视频描述的第一行和章节标题来为检索提供更多背景信息。

以下是一个代表此视频中“R、G、B”章节的块对象的示例:

1.4:颜色 - p5.js 教程



在此视频中,我将讨论颜色的工作原理:RGB 颜色、fill() 函数、stroke() 函数及透明度。



章节 1:R、G、B



“R”代表红色,“G”代表绿色,“B”代表蓝色。创建数字化颜色的方法是把一定量的红色、绿色和蓝色混合在一起。我将从这里开始讲解。但刚刚说的不过是概念而已,而我该怎样将概念应用于函数名称及其参数上呢?嗯……实际上你们猜怎么着?这件事已经搞定了。这里就有一个用于设置颜色的函数。background() 是一个能够在整个画布背景上填充纯色的函数。现在,这里面有 220 单位红色,0 单位绿色,对吧?R、G、B,这就是函数的参数。对了,还有 200 单位蓝色。当你把这么多红色和那么多蓝色混合在一起时,你就会得到这种粉色。那我们来看看这个。如果我们把蓝色全都去掉会怎样?你会看到画面红得不得了。那如果把红色全都去掉呢?变成黑色了。如果我在这里输入特别大的数字会怎样呢?比如输入 1,000 试试。瞧瞧,变成白色了,所以所有颜色混合在一起会变成白色。很奇怪,对吧?毕竟如果你在现实中画画的话,当你把许多种颜料混合在一起时,你会得到一种和烂泥颜色一样的棕色,混合的颜料越多,那棕色就越深。颜色混合起来时就是这么个样子,而色光混合的原理也是一样的。类比一下,假设我有一个红色手电筒、一个绿色手电筒和一个蓝色手电筒。如果我让所有手电筒的光照在同一个点上,这些色光就会混合。这就是“加色法”,我们叠加颜色的量越大,得到颜色就越亮。但是,实际上这种说法并不完全正确,因为我在这里输入的是“1,000”这个数值。所以从真正意义上讲,我们是在把一定量的红色、绿色和蓝色的光混合在一起。顺便提一下,还有其他设置颜色的方法,我后续会讲。这里展示的方法并不是设置颜色的唯一方法,我听到有些正在观看的人提到了 HSB 颜色。还有各种各样的其他方法来设置颜色,但这里讲的是最基本的一种方法。我们能够设置的颜色参数是有范围的,没有任何红色的话,红色的参数就是 0。最大的参数则是 255。顺便提一下,如果算上 0,0 到 255 总共有多少个数字?0、1、2、3、4……总共是 256 个。我们又干了一遍从 0 开始数数的怪事。所以总共有 256 种可能,从 0 到 255。好,现在我们回到这里看看。我们把参数恢复成 (0, 0, 0)。然后我们把蓝色的参数改成 255,我们发现背景变成蓝色了。我们再试试 100,000,还是一样的蓝色。所以在某种程度上,p5 还是蛮聪明的,因为当你调用 background() 函数,并且不小心输入比 255 大的参数时,它仍然会把参数看成 255。现在,大家可以自己定制这些范围了,你们后续可能会碰到需要定制范围的情况。我又得再提一遍了,大家可以查找函数颜色模式,了解定制范围的方法。但在这里,我们还是采用“红、绿、蓝”这种默认设置。我不是一个很有才的视觉设计大咖,所以我不打算和大家探讨怎样挑选能够很好地混搭在一起的漂亮颜色。我猜你们可能天生就有那种天赋,或者可以找到一些其他的相关资源。以上就是 RGB 颜色的工作原理。不知大家有没有注意到,当所有参数都是 0 时,得到的是黑色,而当所有参数都是 255 时,得到的是白色?那如果我把所有参数都设置成 100 会怎样?会得到灰色。当红、绿、蓝三色的参数相等时,我们得到的就是灰度颜色。

当用户向 ShiffBot 提问时,问题会嵌入到数值表示中,而 Gemini 的语义检索功能则用于查找那些拥有与问题最接近的“嵌入”的文本。这些相关视频的转录字幕和链接会被添加到提示中,这样一来,模型便可在生成答案时使用这些信息(并有可能将视频本身添加到对话中)。

5
语义检索示意图

创建代码示例语料库

我们采用同样的方法创建了另一个语料库,里面全是 Dan 编写的 p5.js 示例。我们使用 Gemini 创建了代码示例语料库,并要求 Gemini 解释代码的功能。这些自然语言解释会以块的形式添加进语料库中。这样一来,当用户提问时,我们会尝试寻找与问题相匹配的代码示例描述。p5.js 代码草稿本身的网址会保存在元数据中,以便在检索到代码后将草稿网址与代码一并添加到提示中。

为生成文本描述,系统会使用以下内容提示 Gemini:

以下是一个 p5.js 草稿。请以简短的方式解释此代码的功能。

代码:

${sketchCode}

代码块示例:

草稿:https://editor.p5js.org/codingtrain/sketches/tSXa5dsFz

文本:

数组 - 调色板

此 p5.js 草稿可创建调色板可视化。首先,该草稿会定义颜色数组并设置画布。然后在绘制循环中,它可使用 for 循环遍历颜色数组,使各种颜色显示为画布上的矩形。各个矩形会集中于画布中央,其大小由 blockSize 变量的值决定。

此草稿还会在各个矩形下方显示红、绿、蓝三色的参数值。

最后,它会在画布底部显示调色板名称。

相关视频:7.1:什么是数组?- p5.js 教程 - 此视频介绍了在 JavaScript 中使用数组的基础知识,即数组是什么?数字的工作原理是什么?应在何种情况下使用数组?

通过 Gemini 实现的其他 ShiffBot 功能

除了用于支持对话进行的长提示外,我们还使用其他较小的提示来创建 ShiffBot 功能。

使用 Gemini 预先生成的内容引导对话

ShiffBot 的问候应该是热情风趣的。理想情况下,这类问候应该让用户不禁莞尔。于是,我们开始和 Dan 一起思考 ShiffBot 使用什么样的问候语会比较好。在编写了几个问候语示例后,我们使用 Gemini 生成了更多示例,以便丰富问候语的种类。将这些问候语添加进对话历史记录后,它们能够以独特风格引导对话。这样一来,每当您与 ShiffBot 展开对话时,ShiffBot 都会感到有趣和新鲜。我们对会在开始对话时显示的初始建议提示框也进行了相同的处理。在尚无对话背景的情况下,依据用户可能会问的问题提供一些建议不失为一件重要的事。我们预先生成了这些建议提示框,以便以既有趣又实用的方式引导对话。

动态生成建议提示框

在对话期间出现的建议提示框应与用户当前正在尝试进行的事项相关。我们设计了一个提示和一个对 Gemini 的调用,专用于生成推荐问题提示框。在这种情况下,模型唯一的任务就是为给定对话推荐后续提问。我们在此处也使用了少样本技术(在前文所述的提示静态部分中,我们使用了这项技术,通过提供少量示例让模型进行学习)。这一次,我们在提示中添加了一些良好建议的示例,以便模型加以归纳并用于各种对话中:

根据给定对话(发生于用户与 p5js 框架下的助理之间),推荐用户可以提问的后续问题。

最多返回 4 个建议,并以“;”分隔。

避免推荐用户已经问过的问题。建议应只与创意编码和 p5js 相关。



示例:

ShiffBot:好主意!首先,我们来思考一下草稿中有什么可以作为对象!你怎么看?

建议:此代码有什么功能?;我的代码有什么问题?;请使其更便于阅读



用户:求助!

ShiffBot:我能帮上什么忙吗?

建议:请向我讲解此代码;为我提供一些点子;清理我的代码
6
由 Gemini 生成的建议回应提示框

最后的感想和后续行动

ShiffBot 是一个示例,能够说明您可怎样尝试使用 Gemini API 与社区一起或者为社区构建能够带来定制体验的应用。

我们发现,通过上文所述的各种技术,我们在与 Dan 合作创建工具的过程中,实现了许多 Dan 为他的学生所构想的体验。AI 是一个不断发展的领域,我们确信您的技术也会随之发展。希望上述技术能够助您简单了解我们的探索过程,并能在您自己的探索中为您提供帮助。我们也为 Gemini 和相关 API 工具的未来发展感到激动,人们将能够借助这些 API 工具进一步激发自己的好奇心和创意。

例如,我们已经开始探索多模态可怎样帮助学生向 ShiffBot 展示他们的工作,以及这种互动对学习过程有什么好处。我们正在学习怎样将多模态纳入当前体验,并希望能够尽快与大家分享我们的成果。

在 ShiffBot 中对多模态进行实验性探索

无论是编码、写作还是构思,创作者在帮助我们想象这类协作方面发挥着至关重要的作用。我们希望本次 Lab Session 能够让您一窥使用 Gemini API 的可行方式,并激励您使用 Google 的 AI 产品将您自己的想法变为现实,无论您从事何种行业。