outlines

库

dottxt-ai/outlines

确保大语言模型输出结构化结果。

项目简介

Outlines 是一个 Python 库,确保大语言模型生成符合指定结构(如 JSON、正则或 Pydantic 模型)的输出。支持多种模型后端,与现有工作流无缝集成。

README 预览

\n\n\n\n\n\n 🗒️ *Structured outputs for LLMs* 🗒️\n\nMade with ❤👷️ by the team at [.txt](https://dottxt.co)\nTrusted by NVIDIA, Cohere, HuggingFace, vLLM, etc.\n\n\n[![PyPI Version][pypi-version-badge]][pypi]\n[![Downloads][downloads-badge]][pypistats]\n[![Stars][stars-badge]][stars]\n\n\n[![Discord][discord-badge]][discord]\n[![Blog][dottxt-blog-badge]][dottxt-blog]\n[![Twitter][twitter-badge]][twitter]\n\nThe .txt API is currently in early access. **[Request access here →](https://h1xbpbfsf0w.typeform.com/to/fwQNWmS8?utm_source=github&utm_medium=organic&utm_campaign=outlines)**\n\n\n\n\n## 🚀 Building the future of structured generation\n\nWe're working with select partners to develop new interfaces to structured generation.\n\nNeed XML, FHIR, custom schemas or grammars? Let's talk.\n\nAudit your schema: share one schema, we show you what breaks under generation, the constraints that fix it, and compliance rates before and after. Sign up [here](https://h1xbpbfsf0w.typeform.com/to/rtFUraA2?typeform).\n\n## Table of Contents\n\n- [Why Outlines?](#why-outlines)\n- [Quickstart](#quickstart)\n- [Real-World Examples](#real-world-examples)\n  - [🙋‍♂️ Customer Support Triage](#customer-support-triage)\n  - [📦 E-commerce Product Categorization](#e-commerce-product-categorization)\n  - [📊 Parse Event Details with Incomplete Data](#parse-event-details-with-incomplete-data)\n  - [🗂️ Categorize Documents into Predefined Types](#categorize-documents-into-predefined-types)\n  - [📅 Schedule a Meeting with Function Calling](#schedule-a-meeting-with-function-calling)\n  - [📝 Dynamically Generate Prompts with Re-usable Templates](#dynamically-generate-prompts-with-re-usable-templates)\n- [They Use Outlines](#they-use-outlines)\n- [Model Integrations](#model-integrations)\n- [Core Features](#core-features)\n- [Other Features](#other-features)\n- [About .txt](#about-txt)\n- [Community](#community)\n\n\n\n## Why Outlines?\n\nLLMs are powerful but their outputs are unpredictable

常见问题 (5)

故障排除
在 Outlines 中更改 JsonSchema 的 whitespace_pattern 时,如何修复陈旧的缓存命中或错误的正则表达式输出?

JsonSchema.__eq__ 仅比较解析后的 schema JSON,而忽略了 whitespace_pattern,因此 pattern 不同的 schema 会被视为相同,缓存/去重机制可能会复用错误的 logits processor。请修复相等性判断,使其同时比较 pattern:

def __eq__(self, other):
    if not isinstance(other, JsonSchema):
        return False
    try:
        self_dict = json.loads(self.schema)
        other_dict = json.loads(other.schema)
        return (
            self_dict == other_dict
            and self.whitespace_pattern == other.whitespace_pattern
        )
    except json.JSONDecodeError:
        return (
            self.schema == other.schema
            and self.whitespace_pattern == other.whitespace_pattern
        )

在补丁修复之前,避免仅以 JsonSchema 作为缓存 processor 的键;请使用诸如 (schema.schema, schema.whitespace_pattern) 的缓存键,或在 pattern 发生变化时清除相关缓存。

来源 Issue #1981
故障排除
为什么在使用 MkDocs 将 Python 包迁移到 src 布局后,API Reference 是空的?

更新 scripts/gen_ref_pages.py,使 mkdocs-gen-files 扫描新的包位置。将旧路径 root / "outlines" 替换为 root / "src" / "outlines"。更改完成后,使用 MkDocs 重新构建文档,并验证诸如 site/api_reference/models/index.html 之类的页面已生成。出现此问题的原因是 src-layout 迁移将包从 outlines/ 移动到了 src/outlines/,导致旧的 glob 匹配为空。

来源 Issue #1912
故障排除
为什么 Outlines 的 json_schema_dict_to_dataclass 会为可选字段生成 `age: int = None`,我该如何修复?

在 src/outlines/types/json_schema_utils.py 中,json_schema_dict_to_dataclass 为非必需字段将默认值设为 None,但并未将其类型包装为 Optional。请更新该转换器,使非必需属性使用 Optional[typ]:

from typing import Optional

for property, details in properties.items():
    typ = schema_type_to_python(details, "dataclass")

    if property not in required:
        typ = Optional[typ]
        defaults[property] = None

    annotations[property] = typ

这样,可选的 JSON Schema integer 会生成 age: Optional[int] = None,与 Pydantic 转换器的行为一致,并允许在结构化生成中使用 null。作为临时变通方案,可以手动将非必需的 dataclass 字段声明为 Optional[T] = None,或者在修复应用之前使用 convert_to(schema, "pydantic")。

来源 Issue #1938
故障排除
如何修复 Outlines 中 `Literal[1.5]` 错误匹配 `"1x5"` 这类字符串的问题?

数值在未转义的情况下被转换为正则表达式,因此 1.5 中的 . 会被当作正则表达式通配符。在 src/outlines/types/dsl.py 中,将数值项的构造从 Regex(str(value)) 改为 Regex(re.escape(str(value))),并确保已导入 re:

import re

# 在 python_types_to_terms 处理 int/float 的逻辑中:
term = Regex(re.escape(str(value)))

这样会生成 1\.5,因此 Literal[1.5] 只匹配 "1.5",而拒绝 "1x5"。在该修复发布之前,请使用显式转义的正则表达式(例如 Regex(r"1\.5")),而不要使用浮点数字面量约束。

来源 Issue #1901
故障排除
如何修复 outlines.types.ipv6 接受带前导零的无效 IPv4 映射 IPv6 地址的问题?

ipv6 正则表达式复用了旧的 IPv4 八位字节模式,因此诸如 ::ffff:01.1.1.1 或 ::ffff:00.0.0.0 这样的后缀会被错误地匹配。

请在 src/outlines/types/__init__.py 中修复此问题,将 ipv6 定义中两处旧八位字节模式全部替换:

旧模式:
25[0-5]|2[0-4][0-9]|1?[0-9]{1,2}

新模式:
25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]

必须在两个 IPv4 映射分支中都进行更新:
- ::ffff:a.b.c.d
- x:x:x:x::a.b.c.d

新模式接受规范的八位字节,如 0、1、42 和 192,但拒绝前导零形式,如 00、01 和 007。

在应用补丁之前,作为临时解决方法,可以使用 Python 标准库验证生成的地址:

import ipaddress

def is_valid_ip(value: str) -> bool:
    try:
        ipaddress.ip_address(value)
        return True
    except ValueError:
        return False

应用正则表达式修复后,::ffff:192.168.1.1 和 1:2:3:4::5.6.7.8 仍然匹配,而 ::ffff:01.1.1.1、::ffff:00.0.0.0 和 1:2:3:4::5.6.007.8 会被拒绝。

来源 Issue #1911