Skip to content

Schema as Prompt

语言:English · 中文

Agently 的 .output(...)prompt-native:你写的结构既会被渲染成给模型的文本提示,也会作为返回的 parser/validator。无需另外维护 JSON Schema —— 同一份嵌套 dict 同时驱动两端。

叶子

叶子是元组:

python
(TypeExpr, "description", True)
含义
1. TypeExprPython 类型、typing 表达式、EnumBaseModel,或字符串 token 如 "str""list[str]"
2. description给模型与人的软提示
3. ensureTrue 表示路径/key 必填,会写入 ensure_keys"not_null" 还要求值可用

第三槽是 ensure 标记,不是默认值。旧的「第三槽 = default value」约定已不再支持,YAML 的 $default 也已移除。

简写形式:

python
(str,)                         # 仅类型
(str, "简短描述")              # 类型 + 描述
"仅描述"                       # 等价于 (Any, "仅描述")

Object 与 array 节点

dict 与 list 嵌套组合:

python
{
    "title": (str, "文章标题", True),
    "tags": [(str, "标签", True)],
    "sections": [
        {
            "heading": (str, "标题", True),
            "body": (str, "正文", True),
        }
    ],
}
容器含义
dictobject 节点——字段顺序保留且有语义
list 单个元素同质数组——只写一个 prototype
list 多个元素例子/示意;标准写法只放一个 prototype

字段顺序是契约的一部分

模型按你定义的顺序输出字段。如果你显式暴露 notesanalysis 这类字段,它们会排在 answer 前面并被下游消费。换序就是换行为——不存在「模型自己摸出来」的最佳顺序。不要要求模型输出隐藏推理过程;只暴露业务上确实要保存的字段。

ensure 编译为 ensure_keys

第三槽每个 True"not_null" 都把对应叶子的路径写进解析时的 ensure_keys

python
{
    "title": (str, "标题", True),
    "items": [
        {
            "name": (str, "名称", True),
            "value": (str, "值"),  # 不强制
        }
    ],
}

编译为:

python
ensure_keys = ["title", "items[*].name"]

数组通配 items[*] 是路径语法的一部分。如果解析后 title 缺失或任意 items[i].name 缺失就触发重试(受 max_retries 限制)。value 允许缺失。True 只检查路径存在,所以空字符串、NoneFalse0 或空列表仍可作为合法业务值。若字段遇到 None、空白字符串、空列表或空 wildcard 匹配,以及列表中包含缺失必填值时应重试,使用 "not_null"

python
{
    "ready": (bool, "planner 是否可以继续", True),
    "questions": (list, "需要追问的问题", True),       # [] 合法
    "reply": (str, "ready 时的最终回复", "not_null"), # 空白文本会重试
}

要求「整套 schema 都必须回来」时,agent 上设 ensure_all_keys: True,或 YAML/JSON prompt 顶层 $ensure_all_keys: true —— 它覆盖每叶子的 ensure

YAML / JSON 写法

yaml
output:
  title:
    $type: str
    $desc: 标题
    $ensure: true
  items:
    $type:
      - name:
          $type: str
          $desc: 名称
          $ensure: true
        value:
          $type: str
          $desc: 

约定:

  • $type —— 类型表达(字符串 token 或嵌套结构)
  • $desc —— 描述
  • $ensure: true(或 $ensure: 1)—— 路径/key 存在性 ensure
  • $ensure: "not_null" —— 路径/key 存在性 + 内置值存在性校验
  • 别名 .type / .desc 也被 loader 接受,但推荐 $ 前缀

$default 不再支持 —— default 已不属于 authoring。

YAML 类型 token

常用字符串 token:

Token含义
"str""int""bool""float"标量 Python 类型
"list[str]""dict[str, int]"typing 风格
"Literal[open, closed]"字面量
"Optional[str]"可选类型

Pydantic 与 Enum

TypeExpr 允许 Pydantic 模型与 Enum:

python
from enum import Enum
from pydantic import BaseModel

class Severity(str, Enum):
    P0 = "P0"
    P1 = "P1"
    P2 = "P2"

class Ticket(BaseModel):
    severity: Severity
    rationale: str

agent.output(Ticket)  # 等价于把 BaseModel 展开为嵌套叶子

output() 接收的是 BaseModel 时,response 的 get_data_object() 会返回 Pydantic 实例。

纯文本

需要纯文本而不是结构化输出时,不要output() —— agent.input("...").start() 直接返回字符串,或 result.get_text()。Schema as Prompt 是给结构化输出用的。

不在范围内

Schema as Prompt 是单次模型请求的 authoring 层,不是:

  • JSON Schema 在外部 API 契约场景的替代。
  • TriggerFlow 的契约(TriggerFlow 用自己的 set_contract(...))。
  • UI 表单定义。

早期把 .output()、TriggerFlow 契约和外部 schema 统一为同一 DSL("Agently DSL")的尝试已归档。每个消费者保留自己的入口;本页只覆盖 prompt 侧的 authoring。

另见