OpenAI 开发者大会现场直播回顾,涵盖新模型和工具发布,是了解 OpenAI 最新能力的权威源。
我在旧金山参加OpenAI DevDay,尝试一种新的方式:live blog——这个条目会在活动期间不断更新新的笔记。
详见我活动后撰写的笔记《OpenAI DevDay: Let's build developer tools, not digital God》以及《Building an automatically updating live blog in Django》,后者解释了这个live blogging系统的底层工作原理。
主题演讲以回顾o1开始,并展示了一些使用它的应用示例。
他们演示了o1在应用中的一些使用案例,并宣布o1的速率限制翻倍至10000 RPM(从5000 RPM)——现在与GPT-4保持一致。
首个重大公告:realtime API,让开发者能够通过WebSocket实现模型的语音输入和输出。
新的realtime API能做什么?他们演示了升级版本的Wanderlust旅行助手demo。这个demo既用语音作为输入,也用语音作为输出。
还有一个AI助手拨打电话订餐的demo(幸运的是打给舞台上的OpenAI员工,而不是真实商家!)
以及Speak语言学习应用使用新Realtime API的演示。该API今天开始全面推出。
接下来是模型定制。他们现已支持GPT-4o和4o-mini的微调。今天他们宣布支持对视觉模型进行微调。
现在可以使用图像来微调模型了。他们建议这可应用于产品推荐、医学影像分析,甚至是交通标志识别或车道检测等场景(Grab一直在用它做车道检测)。
视觉微调面向所有开发者提供GPT-4支持(他们可能指的是GPT-4o?不太清楚。)
接下来是降价。每个token的成本相比两年前已经便宜99%。
今天他们推出了提示缓存——之前在Claude和Gemini中见过的功能。
他们的提示缓存版本是自动的!对于模型已见过的token,价格下降50%。
模型蒸馏:让较小的模型向较大的模型学习。今天他们推出了模型蒸馏工具——这样你就能基于大型模型的输出来微调4o-mini。
两个新工具:stored completions,让你能在OpenAI平台上永久存储与模型的交互,用于微调和模型蒸馏。这个工具今天向所有开发者推出。
加上新的评估工具,也在今天推出。
Sam Altman会在下午的炉边座谈会上出席,但不会参加之前的主题演讲。
现在休息一下。活动剩余部分的日程已更新——之前显示"将在主题演讲中宣布",现在显示11-11:45是"Structured Outputs for reliable applications",12-12:45是"Powerful small models with distillation"。
然后2-2:45是"Multimodel apps with the realtime API"。
接下来:可靠应用的Structured Outputs。我过去做过很多关于OpenAI工具机制的工作,其中最值得一提的是我的datasette-extract插件,用来把非结构化的文本和图像加载到结构化的SQLite数据库表中。
Atty Eleti和Michelle Pokrass在讲Structured Outputs——这是该机制的最新进化。
Atty从回顾GPT-4应用开始讲起,比如Duolingo、Klarna和Cursor,这些应用"与外部世界交互"——因此需要Structured Outputs,通常采用JSON格式。
过去要求JSON的经典反面教材经常不可靠——得到的响应往往以"这是你要求的JSON..."开头。开发者们最后只能哀求"就给我JSON吧!"。
函数调用在2023年6月推出,有一定帮助。去年11月(上届DevDay时),他们发布了JSON模式,确保了数据有效性——但仍然可能幻觉参数或输出错误的类型。
Structured Outputs于今年8月发布,确保输出完全符合指定的JSON Schema。Michelle会解释这在底层如何工作。挑战在于确保这个方案能高效地进行大规模推理。
函数调用的工作方式保持不变:你提供一个函数类型的工具,然后用JSON Schema描述该函数的参数。将"strict": true添加到该JSON即可为这些函数启用新的Structured Outputs模式。
现在是演示时间,展示了一个函数来描述数据表、它们的列以及可执行的操作。添加"strict": true修复了一个bug,之前模型会使用未在操作符集中定义的运算符。
"response_format": {"type": "json_schema"}可以指定一个完整的JSON Schema,保证会被Structured Outputs模式遵循。
演示展示了AI增强眼镜,使用整洁的{"voice_over": "This is what the glasses say to you", "display": "4 feet tall"}输出格式,用短文本更新显示,同时指定要朗读的较长文本。
下一个演示想象的是一个简历审查应用,用户可以直接将PDF简历拖入网页表单,然后通过Structured Outputs提取简历应用所需的字段。
OpenAI的JavaScript库支持用Zod定义Schema,Python库支持Pydantic。
我推测之前的演示自动把PDF转换成了图像——我不认为OpenAI的任何API直接接受PDF。
下一个演示更有趣:为完整的仪表板界面定义Schema,其中不同的卡片可代表图表、表格或行——这样工具就能输出包含嵌入图表和数据的自定义答案。希望演讲后代码会发布到GitHub。
总体而言,这是一个相当复杂的自定义聊天UI演示,基于函数调用和Structured Outputs构建了各式各样的自定义工具。
Atty强调,在推出Structured Outputs之前,可靠性一直是个大问题——任何一个环节失败都可能导致整个应用崩溃。
接下来Michelle讲解Structured Outputs的底层实现。
"我们采用了结合研究和工程的方法"。它不仅仅是提示工程——他们使用了一种叫"约束解码"的技术。(在我看来有点像Llama.cpp的语法技巧)。
以手写数字识别为例——只有10个可能的输出标签,从0到9。这是典型的机器学习图像识别任务。
LLM生成的不仅是0到9的数字——它们输出token,见我去年的文章《Understanding GPT tokenizers》。
对于Structured Outputs,技巧是限制接下来能生成哪些token。这里用的技术叫"token masking"。LLM仍会为可能的下一个token生成概率,但之后会屏蔽任何不符合目标Schema的token。
这些mask必须在每个推理步骤更新,所以操作要快到闪电般,才能保持推理速度。Token采样发生在GPU的批处理中——这意味着CPU可以在GPU计算概率的同时并行计算下一步的mask。
这些mask必须在10ms内计算完成。"我们想尽可能多地预计算工作"——让mask计算更像查表。他们构建了一个从JSON Schema派生的索引,以尽快获取这些mask。
JSON Schema被转换为语法,然后是解析器,然后他们遍历所有token和解析状态,用这些数据建立索引。
索引是一个trie——一种支持O(1)查询的前缀树数据结构。
生成索引计算成本高,需要遍历所有可能的状态。他们只做一次,然后缓存这个索引——这就是为什么首次查询Structured Outputs可能需要一点时间——有时长达10秒——但后续请求就很快了。
开源社区用过一个技巧,通过把Schema转换为正则表达式来实现mask。但正则表达式无法处理递归或深层嵌套的Schema——所以无法覆盖JSON Schema的全部功能。
生成式UI是一个需要嵌套Schema的好例子——每个组件可以有一个可能包含更多组件的子列表。由于正则表达式对递归嵌套的限制,这种情况无法转换为正则表达式。
11:37 OpenAI 想要递归 JSON schema 支持,所以他们添加了一个栈。他们将其称为 CFG(上下文无关文法)方法,它结合了正则表达式和一个栈。这就是为什么在推理时构建 trie 需要花费一点时间。
11:38 所以这里的权衡是首次遇到 schema 时会有短暂延迟,OpenAI 认为这对于提高可靠性来说是值得的。
11:38 Atty 现在讨论研究方面:我们如何能让模型以最有用的方式遵循 schema?
11:39 如果你强制模型输出符合文法的 JSON,最终可能会得到 {\n\n\n\n\n\n\n\n\n\n\n\n 直到达到令牌的最大值。
11:40 OpenAI 的内部评估显示,使用结构化输出的 gpt-4o-2024-08-06 在准确性上远超仅进行提示的旧模型方法。他们现在在该评估中达到了 100%(不过不清楚这衡量的是什么)。
11:42 一个备受争议的 API 设计决策涉及 additionalProperties: true——这通常是 JSON Schema 中的默认值。OpenAI 在其 API 中默认禁止了额外属性,这与开发者的期望不同。
11:42 OpenAI 认为显式优于隐式,所以开发者必须在他们发送的 JSON Schema 中传递 additionalProperties: false。
11:43 所有属性默认为必需——不支持可选参数(尽管它们可以被设置为可为空)。开发者也需要在他们发送的 JSON Schema 中遵循这个规则。
11:43 字段按照你在 schema 中定义的顺序生成,尽管 JSON 应该忽略键的顺序。这确保你可以通过在 schema 设计中以正确的顺序添加这些键来实现诸如思维链这样的东西。
11:45 看起来新的 Realtime API 的文档现在可用。
11:46 这个会议没有展示任何新功能——它们都已经在文档中了——但对于结构化输出在底层如何工作的深入了解是新的。
12:01 接下来:通过蒸馏实现强大的小模型,由 John Allard 和 Steven Heidel 主讲。
12:02 蒸馏"允许你创建强大的、小型的模型"。他们将讨论为什么这很重要、它如何工作、最佳实践和用例——加上他们今天推出的两个新 API 平台功能的演示。
12:02 一旦你让一个 AI 应用程序运行起来,下一步是弄清楚如何让它在规模上运行。你关心正常运行时间、速率限制、延迟和成本。
12:04 GPT-4o 的成本是 GPT-4o mini 的 15 倍,但它带来了大量额外的"知识"——研究生级物理等。它在最困难的知识基准上表现出色。你的应用程序需要这种类型的智能吗?
12:06 蒸馏:你对小模型的输出进行微调,使其基于大模型的输出。你正在将大模型的一些能力压缩到较小的模型中。
12:07 蒸馏涉及三个步骤。第一个也是最重要的是为你的应用程序构建特定于任务的评估。你不能跳过这一步,因为你无法改进你无法衡量的东西。
12:07 第二步是捕获好的性能是什么样的例子。存储来自像 GPT-4o 这样的大模型的示例完成,并创建一个数据集。
12:08 最后一步是微调。通过向小模型展示许多已捕获的示例,教它如何复制来自大模型的响应。我们试图将大模型的"智能"压缩到小模型中。
12:09 很多人之前在 OpenAI 平台上做过蒸馏,使用现有的微调机制。那样做工作量很大。
12:10 他们今天推出的两个新功能将使蒸馏更容易。第一个是存储的完成:聊天完成 API 的一个新参数,让你可以选择存储模型的完整输入和输出。你也可以应用标签来帮助之后过滤,以为微调创建数据集。{"store:" true}
12:11 第二个功能是 Evals 产品的测试版。这应该允许你在 OpenAI 平台上端到端地进行蒸馏。
12:11 基于 Superhuman 电子邮件应用的真实用例。该应用有一个"快速回复"功能,它根据阅读现有线程来建议回复选项。你将如何将该功能扩展到数亿封电子邮件?
12:13 旁注:这里是 openai/openai-realtime-api-beta,包含使用 JavaScript 与新 Realtime API 对话的示例代码。openai/openai-realtime-console 是一个示例 React 应用。
12:14 使用 Python 客户端库的 client.chat.completions.create(),你可以添加 store=True, metadata={"tag": "test-set"} 来存储提示/响应并将其添加到标签。
12:14 platform.openai.com/chat-completions 上的新 UI 让你可以浏览你存储的完成。
12:15 然后在新的 /evalutions/create 界面中,你可以添加测试条件并使用它来创建新的评估。(我还没有访问该页面的权限。)
12:17 创建了一个评估后,在其他模型上运行它很容易——例如,尝试在 GPT-4o mini 上运行它并与 GPT-4o 进行比较。
12:21 ...现在是微调 UI 的演示,展示在该数据上微调的 GPT-4o mini 模型的性能远优于单独的 4o-mini。
12:23 蒸馏是否适合你的用例?这取决于任务的通用性与所需的精度。蒸馏的理想用例是涵盖相对狭窄领域且精度要求相对较低的任务——非常适合小模型。
12:23 具有高精度需求但范围较小的任务也能很好地工作——这是许多形式的分类。你可能需要更大和更多样化的数据集来使其正常工作。广泛的通用性和低精度的情况相同。
12:24 具有广泛通用性和高精度需求的任务不适合蒸馏——它们需要全功能的大模型。
12:25 需要注意的事项:分布不均匀或有偏见的数据点。你的训练数据应该与你的生产数据的模式相匹配。同样,稀疏的例子可能会导致数据中的盲点。一个很好的例子是欺诈检测——如果它很罕见,你可能会发现 1,000 个样本中完全没有欺诈实例!
12:26 蒸馏的部分价值在于你不一定需要人类生成的数据或响应——但这并不意味着你不需要积极策划你的蒸馏数据集。"我们往往看到蒸馏在数千而不是数百万个例子的量级上效果最好。"
12:27 最后,采取迭代的方法。微调可能在你的第一次尝试中不会奏效——有许多变量需要考虑。重要的是从几百个例子开始,一旦你基于评估知道它有效,就扩大规模。不要直接跳到数百万个数据点。
12:28 在我看来,微调和蒸馏在战略上是将用户锁定在一个平台上的好方法——如果你纯粹基于提示工程构建应用程序,在不同的 LLM 供应商之间切换会容易得多,而不是如果你已经微调了一个模型的话。
12:29 他们预期使用许多不同蒸馏小模型的集合来构建应用程序将变得普遍,加上一些不适合蒸馏的任务的大模型。
12:30 ...现在午餐——会议在下午 2 点恢复。
12:32 我为这个实时博客构建的系统非常简单——只是 fetch() 调用轮询一个端点并使用 innerHTML 更新一个 <div>——但端点本身设置了 10s 缓存,所以无论有多少人在查看该页面,Cloudflare 应该每 10s 只让一次请求通过到底层应用。
13:27 我已经升级了这个实时博客(借助 GPT-4o)——它不再刷新整个更新部分(因为这意味着任何选定的文本都会被取消选择),而是将新更新附加到现有的 HTML。我还添加了一个切换开关来在最近优先或最早优先的显示顺序之间切换。
14:01 使用 Realtime API 的多模态应用——Jordan Sitkin(API 功能)和 Katia Gil Guzman(开发者体验)
14:04 现在构建多模态应用涉及将多个不同的组件连接在一起:Whisper,然后是 GPT-4,然后是用于输出的 TTS 模型。这使得很难构建"感觉逼真的流畅对话体验"。
14:04 新的 Realtime API 意味着 GPT-4o 可以将所有这一切作为单个组件处理——音频输入、处理然后音频输出。
14:06 这个 Realtime API 首个版本的重点是语音、文本和函数调用。
14:08 首先,一个以旧方式构建的应用的演示——使用 Whisper,然后是 GPT-4,然后是 TTS 输出。显然实时性不足以使体验有价值。
14:08 接下来是 Realtime API 的演示,它感觉更敏锐和响应迅速。它本质上提供了与使用 ChatGPT 新语音模式相同的体验。
14:10 Realtime API 暴露了一个新端点,可为应用程序提供 WebSocket 连接。你可以交换 JSON 消息,其中可混合包含文本、音频和函数调用。
14:13 示例代码演示了如何使用 WebSocket 直接连接 API,不过对于大多数应用来说并不推荐这样做,因为这会将 OpenAI API 密钥暴露在源代码中。音频数据使用 base64 编码,并以 JSON 形式发送。
14:16 也可以使用该 API 实现打断功能。
14:17 非常巧妙的是,只使用 Vanilla JavaScript、不添加任何额外依赖,就能连接 API 并实现完整的语音模式(尽管会暴露 API 密钥)——但大多数实现可能不会采用这种方式。
14:19 Katia 使用 o1 协助构建了太阳系的 3D 可视化,然后添加了语音模式,用于回答“太阳系中有多少颗行星”之类的问题(它尝试显示一个柱状图,但失败了;这并非预期行为,而且效果也不太对)。接着,“我对地球很好奇”这句话让可视化画面放大到地球,同时大声介绍这颗行星。
14:20 这是一个非常酷的演示。
14:21 它使用了一个 display_data 工具,在可视化界面上额外渲染图表。
14:22 又一个演示。这一次,“国际空间站现在在哪里”可以让地球旋转并显示国际空间站的位置,其依据是一次函数调用所获取的国际空间站当前真实位置。
14:24 还有一个很巧妙的 show_moons() 小工具,它可以放大到某颗行星并突出显示它的卫星。
14:26 Realtime API 今天开始公开测试,目前正在逐步推出。输入价格将是每 100 万 token 5 美元,而……后面的定价我没看到,他们把幻灯片切过去了。
14:26 S2S = Speech to Speech(语音到语音)。
14:28 定价页面已经更新。文本输入每 100 万 token 5 美元,输出每 100 万 token 20 美元;音频输入每 100 万 token 100 美元,输出每 100 万 token 200 美元。页面上的一条说明写道:“音频输入成本约为每分钟 6 美分;音频输出成本约为每分钟 24 美分。”
14:30 DevDay 的多位参会者都尝试访问 Realtime API,但没有成功(包括我自己)——与 OpenAI 员工交流后,听起来它仍在逐步推出。
14:42 我要换个议程了——我现在来到了 OpenAI Research: Building with o1,由 Jason Wei 和 Hyung Won Chung 主讲(18 分钟后开始)。
14:43 这是我的实时博客界面——我使用 Django admin 添加附加到某篇文章上的新“实时更新”条目,几秒钟后它们就会出现在文章页面上。
15:00 哈,刚刚才注意到,这篇实时博客已经在 Hacker News 上挂了四个小时!
15:01 o1 研究团队的成员将向我们介绍应该如何思考 o1 的使用方式。我一直很难凭直觉判断哪些问题最适合由 o1 处理,因此非常期待这场分享。
15:01 首先,来自 LaunchDarkly 的 Tilde Thurium 正在讨论社会正义与提示词工程。
15:02 Evaluating and Mitigating Discrimination in Language Model Decisions 是 Anthropic 的一篇论文,研究 Claude 2.0 在对人类作出高风险决策时是否表现出偏见。关键教训:不应该使用 LLM 对人类作出高风险决策!
15:04 研究人员尝试了直接加入人口统计数据,也尝试隐藏人口统计数据,但使用能够暗示人口特征的姓名。Claude 对少数群体表现出了积极歧视,但对 65 岁以上的人群表现出了消极歧视。他们确实发现,用提示词提醒 Claude 不要歧视,实际上有一定程度的帮助!
15:05 Anthropic 的那篇论文公开了所使用的提示词和响应。
15:05 第二篇论文:Measuring Implicit Bias in Explicitly Unbiased Large Language Models
15:06 要求模型作出明确的是/否决策,相比让模型执行候选人排序等任务,似乎暴露出的偏见更少。
15:07 “Kelly is a Warm Person, Joseph is a Role Model”: Gender Biases in LLM-Generated Reference Letters。Tilde 认为,我们可以改进那篇论文中使用的提示词。
15:09 LaunchDarkly:Introducing AI Model and AI Prompt Flags——用于运行此类实验的功能。
15:10 现在是:OpenAI Research: Building with o1,由 o1 研究团队的 Jason Wei 和 Hyung Won Chung 主讲。
15:11 o1 是一种“推理模型”——它经过训练,能够使用强化学习进行思考。它学会了“改进自己的思考策略”,并“识别和纠正自己的错误”。
15:13 有了这个新模型,哪些事情发生了变化?现在使用 o1 可以实现什么?未来版本的 o1 又将让什么成为可能?
15:14 未来版本的 o1 应该很容易设想:推理能力会变得更强。如果推理能力提升 50%,你会想构建什么?(我希望他们能定义一下“推理”,因为我始终不太确定人们使用这个术语时具体指什么。)
15:15 他们一直在频繁使用“范式”这个词!
15:17 在一部分数学和代码任务上,GPT-4o 表现不佳,但 o1(以及 o1 preview)处理得要好得多。他们多次引用 Learning to Reason with LLMs 这篇博客文章中的示例。
15:19 对于数学和编程任务,建议使用 o1-mini,而不是 o1 preview。
15:22 理解 o1 的关键在于:它允许我们用额外的时间和处理能力来换取质量更高的答案。
15:25 今天宣布的功能已有更多文档:Introducing vision to the fine-tuning API、Prompt Caching in the API 和 Model Distillation in the API。
15:27 现在等待今天的最后一场活动:下午 4 点 San Altman 与 Kevin Weil 的炉边谈话。
15:42 我刚刚与一位 OpenAI 员工聊了聊 Realtime API。它目前还不支持图像输入,但该功能已在计划中——所以现在只能处理文本和音频。使用它最困难的部分,是搭建一个 WebSocket 代理,以避免向最终用户暴露 API 密钥——我说自己现在最想要的功能,就是让 OpenAI 替我处理这个代理,因为这是将这些功能投入生产时最复杂的部分。
15:44 我还询问了能否一次发送更大的音频块——就我个人而言,我希望在非实时场景中使用这种新机制,将更长的音频直接输入 GPT-4o。目前的预期是,通过 WebSocket multip 发送缓冲的音频。