发布 Outlines-core 0.1.0:Rust 和 Python 中的结构化生成

发布于 2024 年 10 月 22 日
在 GitHub 上更新

dottxt 和 Hugging Face 很高兴地宣布,我们一直在合作开发 outlines-core,它是 outlines 用于结构化生成的核心算法的 Rust 版本。除了通过 outlines 从 LLM 获得可靠的输出外,这个 Rust 版本还为 outlines 用户提供了以下几个额外的好处:

  • 速度:用户可以期望索引编译速度提高 2 倍。
  • 关注点分离:现在更容易将结构化生成集成到其他库中。outlines-core 非常轻量。
  • 可移植性:将核心算法用 Rust 编写允许绑定其他语言而非仅限于 Python。

这些改进不仅应该提高现有 outlines 用户的性能,而且还应该极大地增加用户将结构化生成集成到其 LLM 工作流中的方式。outlines-core 现已公开,集成到 outlines 中,并且 Python 绑定 0.1.0 版本已发布。您可以在此处找到仓库。

结构化生成快速入门 🧑‍🎓

工作原理

结构化生成意味着您的 LLM 被保证遵循所需的格式。这可以是 JSON、Pydantic 模型、正则表达式或上下文无关语法。关键在于结构化生成禁止生成“错误”的标记。

让我们举一个非常简单的例子。LLM 应该生成一个布尔值,“true”或“false”。仅此而已。为了说明,假设 LLM 生成字符而不是标记。因此,第一个字符是 ",我们可以直接跳过前向传播。对于第二个字符,我们不需要从所有可能的字符中采样。LLM 应该只在 tf 之间选择。


在那之后,无论我们走哪条路径,都只有一个有效的下一个字符。如果 LLM 选择 t 作为第一个字符,那么它必须跟着 rue。类似地,如果它选择 f,它将跟着 alse。并且无论路径如何,都将选择最后一个 " 作为最终字符。当然,这其中还有更多幕后细节,如需更深入的介绍,我们推荐这篇dottxt 博客arxiv 上的相关论文

为什么它很重要

结构化生成可能不会立即显得如此惊艳。许多人首先想到的用例是“太好了,现在我的 LLM 可以返回有效的 JSON,所以我可以将其视为 API 并可靠地序列化/反序列化 JSON”。但这只是冰山一角。仔细想想,结构无处不在,甚至在最意想不到的地方,比如 GSM8K 基准测试

以下是结构化生成所实现功能的几个示例

而且,或许更令人惊讶的是,它降低了评估对所使用的特定提示样本数量的敏感性。除了结构带来的惊人技巧之外,它的性能也更高。dottxt 博客上有很多关于性能基准的优秀文章。

为什么用 Rust 重写?🦀

速度

当您听到“用 Rust 重写”时,您首先想到的可能是性能。是的,outlines-core 也是如此。尽管还有几个关键部分尚未迁移到 Rust,但我们已经看到了编译速度平均提高 2 倍

在 Rust 移植之前,Outlines 使用 Numba 来加速索引的构建。虽然 Numba 很快(运行时性能与 Rust 相当),但 Numba 函数的 JIT 编译在首次运行时增加了延迟源,这让许多用户感到沮丧。使用 Rust 意味着我们可以提前编译索引构建函数,在首次运行时不会增加延迟。虽然这在生产环境中并不重要(因为首次运行可以在部署过程中完成),但在实验阶段却能产生巨大的影响!

安全性和可靠性

用 Rust 重写 Outlines 的主要原因之一是 Rust 带来的安全性和可靠性。Rust 强大的静态类型,结合其所有权模型,消除了整类错误,例如空指针解引用和并发代码中的数据竞争。这使得软件更加健壮和安全。

在 Outlines 的上下文中,安全性至关重要。结构化生成通常涉及复杂的数据结构和操作,尤其是在处理高性能推理引擎时。通过利用 Rust 的安全保证,我们降低了因内存管理不当而导致运行时错误和未定义行为的风险。

此外,Rust 的编译时检查鼓励开发人员编写更清晰、更易于维护的代码。这改进了现有代码库,并使未来的开发更高效。新贡献者可以更快地加入,并且代码更容易审计和验证正确性。

关注点分离

Outlines 的设计不仅仅是为了提供结构化生成的核心算法。除其他功能外,它还包括与 transformers 等其他库的集成,这意味着该库包含许多依赖项。将核心算法与 Outlines 库分离意味着其他希望包含结构化生成的库可以通过导入一个非常轻量级的库来实现。因此,我们可以想象在不久的将来,transformersllama-cpp-python 等库将直接集成结构化生成。这使得 dottxt 团队能够专注于核心算法。

可移植性

大多数 LLM 训练都是用 Python 编写的,但推理略有不同。它发生在许多不同的设备上,在专门的服务器上,并且是用一系列编程语言编写的。这就是为什么可移植性对结构化生成也很重要。通过用 Rust 编写 outlines 的核心功能,我们现在可以创建与其他语言的绑定。

例如,此移植使得与 text-generation-inference 的集成更加顺畅。TGI 的服务器逻辑是用 Rust 编写的,我们希望尽可能避免调用 Python 代码。这也意味着像 mistral.rs 或使用 candle 实现的模型可以受益于 Outlines 的性能和功能。

未来我们计划探索 JS/TS 绑定,允许在 transformers-js 中使用 outlines。或者可能是 Swift 绑定,使 outlines 能够在 Apple 设备上本地使用。但目前,重点将放在 Python 绑定上,并通过扩展对 JSON Schema 规范的支持,继续完善 outlines-core 的功能集。

贡献

您喜欢使用结构化生成、解析器,让 LLM 只输出有效的 JSON 吗?为这个加星,在 Twitter 上分享,加入并贡献!在 Twitter 上,以及与 dottxt 和 Hugging Face 社区分享您的工作。

社区

注册登录以评论