schemas.py — verl/tools/schemas.py¶
文件路径¶
verl/tools/schemas.py
文件概述¶
这个文件定义了 verl 工具系统中所有的数据模式(Schema),使用 Pydantic 的 BaseModel 来做数据验证和序列化。这些 Schema 遵循 OpenAI 的 Function Calling 格式,是工具系统的"数据契约"——所有工具的输入输出都必须符合这些格式。
为什么需要这个文件? 在强化学习中,模型(LLM)需要调用外部工具(如搜索、代码执行等)。OpenAI 定义了一套标准的 tool calling 格式,verl 按照这个格式来描述工具的名称、参数、返回值等信息,这样 LLM 就知道有哪些工具可用、每个工具接受什么参数。
关键代码讲解¶
1. 工具参数的属性定义¶
class OpenAIFunctionPropertySchema(BaseModel):
"""The schema of a parameter in OpenAI format."""
type: str
description: str | None = None
enum: list[str] | None = None
描述工具函数某一个参数的类型信息。例如一个搜索工具的 query 参数可以表示为:
2. 工具参数集合定义¶
class OpenAIFunctionParametersSchema(BaseModel):
"""The schema of parameters in OpenAI format."""
type: str
properties: dict[str, OpenAIFunctionPropertySchema]
required: list[str]
将多个参数组合在一起。properties 是参数名到参数定义的映射,required 列出必填参数。
3. 函数定义¶
class OpenAIFunctionSchema(BaseModel):
"""The schema of a function in OpenAI format."""
name: str
description: str
parameters: OpenAIFunctionParametersSchema = Field(
default_factory=lambda: OpenAIFunctionParametersSchema(
type="object", properties={}, required=[]
)
)
strict: bool = False
描述一个完整的函数:名称、描述、参数列表。strict=False 表示不强制要求参数严格匹配。
4. 完整的工具 Schema¶
class OpenAIFunctionToolSchema(BaseModel):
"""The schema of a tool in OpenAI format."""
type: str
function: OpenAIFunctionSchema
这是最外层的工具描述,type 通常为 "function",function 字段包含函数的详细定义。一个完整的工具 schema 长这样:
{
"type": "function",
"function": {
"name": "search",
"description": "搜索相关信息",
"parameters": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"]
}
}
}
5. 函数调用解析¶
class OpenAIFunctionCallSchema(BaseModel):
"""The parsed schema of a tool in OpenAI format."""
name: str
arguments: dict[str, Any]
@staticmethod
def from_openai_function_parsed_schema(
parsed_schema: OpenAIFunctionParsedSchema,
) -> tuple["OpenAIFunctionCallSchema", bool]:
has_decode_error = False
try:
arguments = json.loads(parsed_schema.arguments)
except json.JSONDecodeError:
arguments = {}
has_decode_error = True
if not isinstance(arguments, dict):
arguments = {}
has_decode_error = True
return OpenAIFunctionCallSchema(name=parsed_schema.name, arguments=arguments), has_decode_error
LLM 生成的函数调用中,arguments 是一个 JSON 字符串。这个方法负责将其解析为 Python 字典,并处理 JSON 解析失败的情况(返回空字典并标记错误)。
6. 工具响应¶
class ToolResponse(BaseModel):
"""The response from a tool execution."""
text: str | None = None
image: list[Any] | None = None
video: list[Any] | None = None
@model_validator(mode="before")
@classmethod
def initialize_request(cls, values):
if "image" in values and not isinstance(values["image"], list):
raise ValueError(...)
if "video" in values and not isinstance(values["video"], list):
raise ValueError(...)
return values
def is_empty(self) -> bool:
return not self.text and not self.image and not self.video
def is_text_only(self) -> bool:
return self.text and not self.image and not self.video
工具执行后返回的结果,支持三种类型:文本、图片列表、视频列表。验证器确保 image 和 video 字段必须是列表类型。
核心类/函数列表¶
| 类名 | 作用 |
|---|---|
OpenAIFunctionPropertySchema |
描述单个参数的类型/描述 |
OpenAIFunctionParametersSchema |
描述参数集合 |
OpenAIFunctionSchema |
描述一个函数(名称+描述+参数) |
OpenAIFunctionToolSchema |
最外层工具描述 |
OpenAIFunctionParsedSchema |
LLM 输出的原始函数调用(arguments 为字符串) |
OpenAIFunctionCallSchema |
解析后的函数调用(arguments 为字典) |
OpenAIFunctionToolCall |
完整的工具调用(含 id 和 type) |
ToolResponse |
工具执行的返回结果 |
与其他模块的关系¶
- 被所有工具类使用:
BaseTool、SandboxFusionTool、SearchTool等都依赖这些 Schema。 - 被
tool_registry.py使用:从配置文件加载工具时,会将配置转换为OpenAIFunctionToolSchema。 - 与 LLM 推理对接:rollout 过程中,LLM 的输出会被解析为
OpenAIFunctionCallSchema,然后传递给工具执行。
小结¶
schemas.py 是工具系统的数据层,定义了工具描述、函数调用、工具响应等所有数据格式。它遵循 OpenAI 的 Function Calling 规范,使得 verl 的工具系统与 OpenAI 兼容的 LLM 可以无缝对接。