feat(files): fix expires_after API shape (#3604)

This was just quite incorrect. See source here:
https://platform.openai.com/docs/api-reference/files/create
This commit is contained in:
Ashwin Bharambe 2025-09-29 21:29:15 -07:00 committed by GitHub
parent 5e7fed8bbb
commit 3a09f00cdb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 705 additions and 448 deletions

View file

@ -5,6 +5,7 @@
# the root directory of this source tree.
import hashlib
import inspect
import ipaddress
import types
import typing
@ -12,6 +13,7 @@ from dataclasses import make_dataclass
from typing import Annotated, Any, Dict, get_args, get_origin, Set, Union
from fastapi import UploadFile
from pydantic import BaseModel
from llama_stack.apis.datatypes import Error
from llama_stack.strong_typing.core import JsonType
@ -632,14 +634,22 @@ class Generator:
base_type = get_args(param_type)[0]
else:
base_type = param_type
# Check if the type is optional
is_optional = is_type_optional(base_type)
if is_optional:
base_type = unwrap_optional_type(base_type)
if base_type is UploadFile:
# File upload
properties[name] = {"type": "string", "format": "binary"}
else:
# Form field
# All other types - generate schema reference
# This includes enums, BaseModels, and simple types
properties[name] = self.schema_builder.classdef_to_ref(base_type)
required_fields.append(name)
if not is_optional:
required_fields.append(name)
multipart_schema = {
"type": "object",

View file

@ -6070,7 +6070,7 @@
"Files"
],
"summary": "Upload a file that can be used across various endpoints.",
"description": "Upload a file that can be used across various endpoints.\nThe file upload should be a multipart form request with:\n- file: The File object (not file name) to be uploaded.\n- purpose: The intended purpose of the uploaded file.\n- expires_after: Optional form values describing expiration for the file. Expected expires_after[anchor] = \"created_at\", expires_after[seconds] = {integer}. Seconds must be between 3600 and 2592000 (1 hour to 30 days).",
"description": "Upload a file that can be used across various endpoints.\nThe file upload should be a multipart form request with:\n- file: The File object (not file name) to be uploaded.\n- purpose: The intended purpose of the uploaded file.\n- expires_after: Optional form values describing expiration for the file.",
"parameters": [],
"requestBody": {
"content": {
@ -6085,32 +6085,13 @@
"purpose": {
"$ref": "#/components/schemas/OpenAIFilePurpose"
},
"expires_after_anchor": {
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"expires_after_seconds": {
"oneOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
"expires_after": {
"$ref": "#/components/schemas/ExpiresAfter"
}
},
"required": [
"file",
"purpose",
"expires_after_anchor",
"expires_after_seconds"
"purpose"
]
}
}
@ -6218,7 +6199,7 @@
"Files"
],
"summary": "Upload a file that can be used across various endpoints.",
"description": "Upload a file that can be used across various endpoints.\nThe file upload should be a multipart form request with:\n- file: The File object (not file name) to be uploaded.\n- purpose: The intended purpose of the uploaded file.\n- expires_after: Optional form values describing expiration for the file. Expected expires_after[anchor] = \"created_at\", expires_after[seconds] = {integer}. Seconds must be between 3600 and 2592000 (1 hour to 30 days).",
"description": "Upload a file that can be used across various endpoints.\nThe file upload should be a multipart form request with:\n- file: The File object (not file name) to be uploaded.\n- purpose: The intended purpose of the uploaded file.\n- expires_after: Optional form values describing expiration for the file.",
"parameters": [],
"requestBody": {
"content": {
@ -6233,32 +6214,13 @@
"purpose": {
"$ref": "#/components/schemas/OpenAIFilePurpose"
},
"expires_after_anchor": {
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"expires_after_seconds": {
"oneOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
"expires_after": {
"$ref": "#/components/schemas/ExpiresAfter"
}
},
"required": [
"file",
"purpose",
"expires_after_anchor",
"expires_after_seconds"
"purpose"
]
}
}
@ -7978,7 +7940,25 @@
"type": "object",
"properties": {
"strategy": {
"$ref": "#/components/schemas/SamplingStrategy",
"oneOf": [
{
"$ref": "#/components/schemas/GreedySamplingStrategy"
},
{
"$ref": "#/components/schemas/TopPSamplingStrategy"
},
{
"$ref": "#/components/schemas/TopKSamplingStrategy"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"greedy": "#/components/schemas/GreedySamplingStrategy",
"top_p": "#/components/schemas/TopPSamplingStrategy",
"top_k": "#/components/schemas/TopKSamplingStrategy"
}
},
"description": "The sampling strategy."
},
"max_tokens": {
@ -8006,27 +7986,6 @@
"title": "SamplingParams",
"description": "Sampling parameters."
},
"SamplingStrategy": {
"oneOf": [
{
"$ref": "#/components/schemas/GreedySamplingStrategy"
},
{
"$ref": "#/components/schemas/TopPSamplingStrategy"
},
{
"$ref": "#/components/schemas/TopKSamplingStrategy"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"greedy": "#/components/schemas/GreedySamplingStrategy",
"top_p": "#/components/schemas/TopPSamplingStrategy",
"top_k": "#/components/schemas/TopKSamplingStrategy"
}
}
},
"SystemMessage": {
"type": "object",
"properties": {
@ -8609,7 +8568,25 @@
"description": "Type of the event"
},
"delta": {
"$ref": "#/components/schemas/ContentDelta",
"oneOf": [
{
"$ref": "#/components/schemas/TextDelta"
},
{
"$ref": "#/components/schemas/ImageDelta"
},
{
"$ref": "#/components/schemas/ToolCallDelta"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"text": "#/components/schemas/TextDelta",
"image": "#/components/schemas/ImageDelta",
"tool_call": "#/components/schemas/ToolCallDelta"
}
},
"description": "Content generated since last event. This can be one or more tokens, or a tool call."
},
"logprobs": {
@ -8659,27 +8636,6 @@
"title": "ChatCompletionResponseStreamChunk",
"description": "A chunk of a streamed chat completion response."
},
"ContentDelta": {
"oneOf": [
{
"$ref": "#/components/schemas/TextDelta"
},
{
"$ref": "#/components/schemas/ImageDelta"
},
{
"$ref": "#/components/schemas/ToolCallDelta"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"text": "#/components/schemas/TextDelta",
"image": "#/components/schemas/ImageDelta",
"tool_call": "#/components/schemas/ToolCallDelta"
}
}
},
"ImageDelta": {
"type": "object",
"properties": {
@ -9608,7 +9564,37 @@
"type": "object",
"properties": {
"payload": {
"$ref": "#/components/schemas/AgentTurnResponseEventPayload",
"oneOf": [
{
"$ref": "#/components/schemas/AgentTurnResponseStepStartPayload"
},
{
"$ref": "#/components/schemas/AgentTurnResponseStepProgressPayload"
},
{
"$ref": "#/components/schemas/AgentTurnResponseStepCompletePayload"
},
{
"$ref": "#/components/schemas/AgentTurnResponseTurnStartPayload"
},
{
"$ref": "#/components/schemas/AgentTurnResponseTurnCompletePayload"
},
{
"$ref": "#/components/schemas/AgentTurnResponseTurnAwaitingInputPayload"
}
],
"discriminator": {
"propertyName": "event_type",
"mapping": {
"step_start": "#/components/schemas/AgentTurnResponseStepStartPayload",
"step_progress": "#/components/schemas/AgentTurnResponseStepProgressPayload",
"step_complete": "#/components/schemas/AgentTurnResponseStepCompletePayload",
"turn_start": "#/components/schemas/AgentTurnResponseTurnStartPayload",
"turn_complete": "#/components/schemas/AgentTurnResponseTurnCompletePayload",
"turn_awaiting_input": "#/components/schemas/AgentTurnResponseTurnAwaitingInputPayload"
}
},
"description": "Event-specific payload containing event data"
}
},
@ -9619,39 +9605,6 @@
"title": "AgentTurnResponseEvent",
"description": "An event in an agent turn response stream."
},
"AgentTurnResponseEventPayload": {
"oneOf": [
{
"$ref": "#/components/schemas/AgentTurnResponseStepStartPayload"
},
{
"$ref": "#/components/schemas/AgentTurnResponseStepProgressPayload"
},
{
"$ref": "#/components/schemas/AgentTurnResponseStepCompletePayload"
},
{
"$ref": "#/components/schemas/AgentTurnResponseTurnStartPayload"
},
{
"$ref": "#/components/schemas/AgentTurnResponseTurnCompletePayload"
},
{
"$ref": "#/components/schemas/AgentTurnResponseTurnAwaitingInputPayload"
}
],
"discriminator": {
"propertyName": "event_type",
"mapping": {
"step_start": "#/components/schemas/AgentTurnResponseStepStartPayload",
"step_progress": "#/components/schemas/AgentTurnResponseStepProgressPayload",
"step_complete": "#/components/schemas/AgentTurnResponseStepCompletePayload",
"turn_start": "#/components/schemas/AgentTurnResponseTurnStartPayload",
"turn_complete": "#/components/schemas/AgentTurnResponseTurnCompletePayload",
"turn_awaiting_input": "#/components/schemas/AgentTurnResponseTurnAwaitingInputPayload"
}
}
},
"AgentTurnResponseStepCompletePayload": {
"type": "object",
"properties": {
@ -9752,7 +9705,25 @@
"description": "Unique identifier for the step within a turn"
},
"delta": {
"$ref": "#/components/schemas/ContentDelta",
"oneOf": [
{
"$ref": "#/components/schemas/TextDelta"
},
{
"$ref": "#/components/schemas/ImageDelta"
},
{
"$ref": "#/components/schemas/ToolCallDelta"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"text": "#/components/schemas/TextDelta",
"image": "#/components/schemas/ImageDelta",
"tool_call": "#/components/schemas/ToolCallDelta"
}
},
"description": "Incremental content changes during step execution"
}
},
@ -11162,23 +11133,6 @@
"title": "OpenAIResponseOutputMessageMCPListTools",
"description": "MCP list tools output message containing available tools from an MCP server."
},
"OpenAIResponseContentPart": {
"oneOf": [
{
"$ref": "#/components/schemas/OpenAIResponseContentPartOutputText"
},
{
"$ref": "#/components/schemas/OpenAIResponseContentPartRefusal"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"output_text": "#/components/schemas/OpenAIResponseContentPartOutputText",
"refusal": "#/components/schemas/OpenAIResponseContentPartRefusal"
}
}
},
"OpenAIResponseContentPartOutputText": {
"type": "object",
"properties": {
@ -11344,7 +11298,21 @@
"description": "Unique identifier of the output item containing this content part"
},
"part": {
"$ref": "#/components/schemas/OpenAIResponseContentPart",
"oneOf": [
{
"$ref": "#/components/schemas/OpenAIResponseContentPartOutputText"
},
{
"$ref": "#/components/schemas/OpenAIResponseContentPartRefusal"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"output_text": "#/components/schemas/OpenAIResponseContentPartOutputText",
"refusal": "#/components/schemas/OpenAIResponseContentPartRefusal"
}
},
"description": "The content part that was added"
},
"sequence_number": {
@ -11381,7 +11349,21 @@
"description": "Unique identifier of the output item containing this content part"
},
"part": {
"$ref": "#/components/schemas/OpenAIResponseContentPart",
"oneOf": [
{
"$ref": "#/components/schemas/OpenAIResponseContentPartOutputText"
},
{
"$ref": "#/components/schemas/OpenAIResponseContentPartRefusal"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"output_text": "#/components/schemas/OpenAIResponseContentPartOutputText",
"refusal": "#/components/schemas/OpenAIResponseContentPartRefusal"
}
},
"description": "The completed content part"
},
"sequence_number": {
@ -11705,7 +11687,37 @@
"description": "Unique identifier of the response containing this output"
},
"item": {
"$ref": "#/components/schemas/OpenAIResponseOutput",
"oneOf": [
{
"$ref": "#/components/schemas/OpenAIResponseMessage"
},
{
"$ref": "#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall"
},
{
"$ref": "#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall"
},
{
"$ref": "#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall"
},
{
"$ref": "#/components/schemas/OpenAIResponseOutputMessageMCPCall"
},
{
"$ref": "#/components/schemas/OpenAIResponseOutputMessageMCPListTools"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"message": "#/components/schemas/OpenAIResponseMessage",
"web_search_call": "#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall",
"file_search_call": "#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall",
"function_call": "#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall",
"mcp_call": "#/components/schemas/OpenAIResponseOutputMessageMCPCall",
"mcp_list_tools": "#/components/schemas/OpenAIResponseOutputMessageMCPListTools"
}
},
"description": "The output item that was added (message, tool call, etc.)"
},
"output_index": {
@ -11742,7 +11754,37 @@
"description": "Unique identifier of the response containing this output"
},
"item": {
"$ref": "#/components/schemas/OpenAIResponseOutput",
"oneOf": [
{
"$ref": "#/components/schemas/OpenAIResponseMessage"
},
{
"$ref": "#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall"
},
{
"$ref": "#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall"
},
{
"$ref": "#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall"
},
{
"$ref": "#/components/schemas/OpenAIResponseOutputMessageMCPCall"
},
{
"$ref": "#/components/schemas/OpenAIResponseOutputMessageMCPListTools"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"message": "#/components/schemas/OpenAIResponseMessage",
"web_search_call": "#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall",
"file_search_call": "#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall",
"function_call": "#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall",
"mcp_call": "#/components/schemas/OpenAIResponseOutputMessageMCPCall",
"mcp_list_tools": "#/components/schemas/OpenAIResponseOutputMessageMCPListTools"
}
},
"description": "The completed output item (message, tool call, etc.)"
},
"output_index": {
@ -12095,7 +12137,21 @@
"type": "object",
"properties": {
"eval_candidate": {
"$ref": "#/components/schemas/EvalCandidate",
"oneOf": [
{
"$ref": "#/components/schemas/ModelCandidate"
},
{
"$ref": "#/components/schemas/AgentCandidate"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"model": "#/components/schemas/ModelCandidate",
"agent": "#/components/schemas/AgentCandidate"
}
},
"description": "The candidate to evaluate."
},
"scoring_params": {
@ -12118,23 +12174,6 @@
"title": "BenchmarkConfig",
"description": "A benchmark configuration for evaluation."
},
"EvalCandidate": {
"oneOf": [
{
"$ref": "#/components/schemas/ModelCandidate"
},
{
"$ref": "#/components/schemas/AgentCandidate"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"model": "#/components/schemas/ModelCandidate",
"agent": "#/components/schemas/AgentCandidate"
}
}
},
"LLMAsJudgeScoringFnParams": {
"type": "object",
"properties": {
@ -12770,7 +12809,33 @@
"type": "object",
"properties": {
"message": {
"$ref": "#/components/schemas/OpenAIMessageParam",
"oneOf": [
{
"$ref": "#/components/schemas/OpenAIUserMessageParam"
},
{
"$ref": "#/components/schemas/OpenAISystemMessageParam"
},
{
"$ref": "#/components/schemas/OpenAIAssistantMessageParam"
},
{
"$ref": "#/components/schemas/OpenAIToolMessageParam"
},
{
"$ref": "#/components/schemas/OpenAIDeveloperMessageParam"
}
],
"discriminator": {
"propertyName": "role",
"mapping": {
"user": "#/components/schemas/OpenAIUserMessageParam",
"system": "#/components/schemas/OpenAISystemMessageParam",
"assistant": "#/components/schemas/OpenAIAssistantMessageParam",
"tool": "#/components/schemas/OpenAIToolMessageParam",
"developer": "#/components/schemas/OpenAIDeveloperMessageParam"
}
},
"description": "The message from the model"
},
"finish_reason": {
@ -13146,23 +13211,6 @@
],
"title": "OpenAICompletionWithInputMessages"
},
"DataSource": {
"oneOf": [
{
"$ref": "#/components/schemas/URIDataSource"
},
{
"$ref": "#/components/schemas/RowsDataSource"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"uri": "#/components/schemas/URIDataSource",
"rows": "#/components/schemas/RowsDataSource"
}
}
},
"Dataset": {
"type": "object",
"properties": {
@ -13202,7 +13250,21 @@
"description": "Purpose of the dataset indicating its intended use"
},
"source": {
"$ref": "#/components/schemas/DataSource",
"oneOf": [
{
"$ref": "#/components/schemas/URIDataSource"
},
{
"$ref": "#/components/schemas/RowsDataSource"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"uri": "#/components/schemas/URIDataSource",
"rows": "#/components/schemas/RowsDataSource"
}
},
"description": "Data source configuration for the dataset"
},
"metadata": {
@ -13531,55 +13593,6 @@
"title": "ObjectType",
"description": "Parameter type for object values."
},
"ParamType": {
"oneOf": [
{
"$ref": "#/components/schemas/StringType"
},
{
"$ref": "#/components/schemas/NumberType"
},
{
"$ref": "#/components/schemas/BooleanType"
},
{
"$ref": "#/components/schemas/ArrayType"
},
{
"$ref": "#/components/schemas/ObjectType"
},
{
"$ref": "#/components/schemas/JsonType"
},
{
"$ref": "#/components/schemas/UnionType"
},
{
"$ref": "#/components/schemas/ChatCompletionInputType"
},
{
"$ref": "#/components/schemas/CompletionInputType"
},
{
"$ref": "#/components/schemas/AgentTurnInputType"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"string": "#/components/schemas/StringType",
"number": "#/components/schemas/NumberType",
"boolean": "#/components/schemas/BooleanType",
"array": "#/components/schemas/ArrayType",
"object": "#/components/schemas/ObjectType",
"json": "#/components/schemas/JsonType",
"union": "#/components/schemas/UnionType",
"chat_completion_input": "#/components/schemas/ChatCompletionInputType",
"completion_input": "#/components/schemas/CompletionInputType",
"agent_turn_input": "#/components/schemas/AgentTurnInputType"
}
}
},
"ScoringFn": {
"type": "object",
"properties": {
@ -13638,7 +13651,53 @@
}
},
"return_type": {
"$ref": "#/components/schemas/ParamType"
"oneOf": [
{
"$ref": "#/components/schemas/StringType"
},
{
"$ref": "#/components/schemas/NumberType"
},
{
"$ref": "#/components/schemas/BooleanType"
},
{
"$ref": "#/components/schemas/ArrayType"
},
{
"$ref": "#/components/schemas/ObjectType"
},
{
"$ref": "#/components/schemas/JsonType"
},
{
"$ref": "#/components/schemas/UnionType"
},
{
"$ref": "#/components/schemas/ChatCompletionInputType"
},
{
"$ref": "#/components/schemas/CompletionInputType"
},
{
"$ref": "#/components/schemas/AgentTurnInputType"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"string": "#/components/schemas/StringType",
"number": "#/components/schemas/NumberType",
"boolean": "#/components/schemas/BooleanType",
"array": "#/components/schemas/ArrayType",
"object": "#/components/schemas/ObjectType",
"json": "#/components/schemas/JsonType",
"union": "#/components/schemas/UnionType",
"chat_completion_input": "#/components/schemas/ChatCompletionInputType",
"completion_input": "#/components/schemas/CompletionInputType",
"agent_turn_input": "#/components/schemas/AgentTurnInputType"
}
}
},
"params": {
"$ref": "#/components/schemas/ScoringFnParams"
@ -15548,7 +15607,21 @@
"description": "Event type identifier set to STRUCTURED_LOG"
},
"payload": {
"$ref": "#/components/schemas/StructuredLogPayload",
"oneOf": [
{
"$ref": "#/components/schemas/SpanStartPayload"
},
{
"$ref": "#/components/schemas/SpanEndPayload"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"span_start": "#/components/schemas/SpanStartPayload",
"span_end": "#/components/schemas/SpanEndPayload"
}
},
"description": "The structured payload data for the log event"
}
},
@ -15563,23 +15636,6 @@
"title": "StructuredLogEvent",
"description": "A structured log event containing typed payload data."
},
"StructuredLogPayload": {
"oneOf": [
{
"$ref": "#/components/schemas/SpanStartPayload"
},
{
"$ref": "#/components/schemas/SpanEndPayload"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"span_start": "#/components/schemas/SpanStartPayload",
"span_end": "#/components/schemas/SpanEndPayload"
}
}
},
"StructuredLogType": {
"type": "string",
"enum": [
@ -15864,7 +15920,21 @@
"description": "Key-value attributes associated with the file"
},
"chunking_strategy": {
"$ref": "#/components/schemas/VectorStoreChunkingStrategy",
"oneOf": [
{
"$ref": "#/components/schemas/VectorStoreChunkingStrategyAuto"
},
{
"$ref": "#/components/schemas/VectorStoreChunkingStrategyStatic"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"auto": "#/components/schemas/VectorStoreChunkingStrategyAuto",
"static": "#/components/schemas/VectorStoreChunkingStrategyStatic"
}
},
"description": "Strategy used for splitting the file into chunks"
},
"created_at": {
@ -17677,6 +17747,25 @@
],
"title": "OpenaiUpdateVectorStoreFileRequest"
},
"ExpiresAfter": {
"type": "object",
"properties": {
"anchor": {
"type": "string",
"const": "created_at"
},
"seconds": {
"type": "integer"
}
},
"additionalProperties": false,
"required": [
"anchor",
"seconds"
],
"title": "ExpiresAfter",
"description": "Control expiration of uploaded files.\nParams:\n - anchor, must be \"created_at\"\n - seconds, must be int between 3600 and 2592000 (1 hour to 30 days)"
},
"DPOAlignmentConfig": {
"type": "object",
"properties": {
@ -18028,7 +18117,21 @@
"type": "object",
"properties": {
"query_generator_config": {
"$ref": "#/components/schemas/RAGQueryGeneratorConfig",
"oneOf": [
{
"$ref": "#/components/schemas/DefaultRAGQueryGeneratorConfig"
},
{
"$ref": "#/components/schemas/LLMRAGQueryGeneratorConfig"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"default": "#/components/schemas/DefaultRAGQueryGeneratorConfig",
"llm": "#/components/schemas/LLMRAGQueryGeneratorConfig"
}
},
"description": "Configuration for the query generator."
},
"max_tokens_in_context": {
@ -18066,23 +18169,6 @@
"title": "RAGQueryConfig",
"description": "Configuration for the RAG query generation."
},
"RAGQueryGeneratorConfig": {
"oneOf": [
{
"$ref": "#/components/schemas/DefaultRAGQueryGeneratorConfig"
},
{
"$ref": "#/components/schemas/LLMRAGQueryGeneratorConfig"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"default": "#/components/schemas/DefaultRAGQueryGeneratorConfig",
"llm": "#/components/schemas/LLMRAGQueryGeneratorConfig"
}
}
},
"RAGSearchMode": {
"type": "string",
"enum": [
@ -18664,6 +18750,23 @@
],
"title": "RegisterBenchmarkRequest"
},
"DataSource": {
"oneOf": [
{
"$ref": "#/components/schemas/URIDataSource"
},
{
"$ref": "#/components/schemas/RowsDataSource"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"uri": "#/components/schemas/URIDataSource",
"rows": "#/components/schemas/RowsDataSource"
}
}
},
"RegisterDatasetRequest": {
"type": "object",
"properties": {
@ -18770,6 +18873,55 @@
],
"title": "RegisterModelRequest"
},
"ParamType": {
"oneOf": [
{
"$ref": "#/components/schemas/StringType"
},
{
"$ref": "#/components/schemas/NumberType"
},
{
"$ref": "#/components/schemas/BooleanType"
},
{
"$ref": "#/components/schemas/ArrayType"
},
{
"$ref": "#/components/schemas/ObjectType"
},
{
"$ref": "#/components/schemas/JsonType"
},
{
"$ref": "#/components/schemas/UnionType"
},
{
"$ref": "#/components/schemas/ChatCompletionInputType"
},
{
"$ref": "#/components/schemas/CompletionInputType"
},
{
"$ref": "#/components/schemas/AgentTurnInputType"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"string": "#/components/schemas/StringType",
"number": "#/components/schemas/NumberType",
"boolean": "#/components/schemas/BooleanType",
"array": "#/components/schemas/ArrayType",
"object": "#/components/schemas/ObjectType",
"json": "#/components/schemas/JsonType",
"union": "#/components/schemas/UnionType",
"chat_completion_input": "#/components/schemas/ChatCompletionInputType",
"completion_input": "#/components/schemas/CompletionInputType",
"agent_turn_input": "#/components/schemas/AgentTurnInputType"
}
}
},
"RegisterScoringFunctionRequest": {
"type": "object",
"properties": {

View file

@ -4383,8 +4383,6 @@ paths:
- purpose: The intended purpose of the uploaded file.
- expires_after: Optional form values describing expiration for the file.
Expected expires_after[anchor] = "created_at", expires_after[seconds] = {integer}.
Seconds must be between 3600 and 2592000 (1 hour to 30 days).
parameters: []
requestBody:
content:
@ -4397,19 +4395,11 @@ paths:
format: binary
purpose:
$ref: '#/components/schemas/OpenAIFilePurpose'
expires_after_anchor:
oneOf:
- type: string
- type: 'null'
expires_after_seconds:
oneOf:
- type: integer
- type: 'null'
expires_after:
$ref: '#/components/schemas/ExpiresAfter'
required:
- file
- purpose
- expires_after_anchor
- expires_after_seconds
required: true
/v1/openai/v1/files:
get:
@ -4504,8 +4494,6 @@ paths:
- purpose: The intended purpose of the uploaded file.
- expires_after: Optional form values describing expiration for the file.
Expected expires_after[anchor] = "created_at", expires_after[seconds] = {integer}.
Seconds must be between 3600 and 2592000 (1 hour to 30 days).
parameters: []
requestBody:
content:
@ -4518,19 +4506,11 @@ paths:
format: binary
purpose:
$ref: '#/components/schemas/OpenAIFilePurpose'
expires_after_anchor:
oneOf:
- type: string
- type: 'null'
expires_after_seconds:
oneOf:
- type: integer
- type: 'null'
expires_after:
$ref: '#/components/schemas/ExpiresAfter'
required:
- file
- purpose
- expires_after_anchor
- expires_after_seconds
required: true
/v1/openai/v1/models:
get:
@ -5763,7 +5743,16 @@ components:
type: object
properties:
strategy:
$ref: '#/components/schemas/SamplingStrategy'
oneOf:
- $ref: '#/components/schemas/GreedySamplingStrategy'
- $ref: '#/components/schemas/TopPSamplingStrategy'
- $ref: '#/components/schemas/TopKSamplingStrategy'
discriminator:
propertyName: type
mapping:
greedy: '#/components/schemas/GreedySamplingStrategy'
top_p: '#/components/schemas/TopPSamplingStrategy'
top_k: '#/components/schemas/TopKSamplingStrategy'
description: The sampling strategy.
max_tokens:
type: integer
@ -5791,17 +5780,6 @@ components:
- strategy
title: SamplingParams
description: Sampling parameters.
SamplingStrategy:
oneOf:
- $ref: '#/components/schemas/GreedySamplingStrategy'
- $ref: '#/components/schemas/TopPSamplingStrategy'
- $ref: '#/components/schemas/TopKSamplingStrategy'
discriminator:
propertyName: type
mapping:
greedy: '#/components/schemas/GreedySamplingStrategy'
top_p: '#/components/schemas/TopPSamplingStrategy'
top_k: '#/components/schemas/TopKSamplingStrategy'
SystemMessage:
type: object
properties:
@ -6248,7 +6226,16 @@ components:
- progress
description: Type of the event
delta:
$ref: '#/components/schemas/ContentDelta'
oneOf:
- $ref: '#/components/schemas/TextDelta'
- $ref: '#/components/schemas/ImageDelta'
- $ref: '#/components/schemas/ToolCallDelta'
discriminator:
propertyName: type
mapping:
text: '#/components/schemas/TextDelta'
image: '#/components/schemas/ImageDelta'
tool_call: '#/components/schemas/ToolCallDelta'
description: >-
Content generated since last event. This can be one or more tokens, or
a tool call.
@ -6291,17 +6278,6 @@ components:
title: ChatCompletionResponseStreamChunk
description: >-
A chunk of a streamed chat completion response.
ContentDelta:
oneOf:
- $ref: '#/components/schemas/TextDelta'
- $ref: '#/components/schemas/ImageDelta'
- $ref: '#/components/schemas/ToolCallDelta'
discriminator:
propertyName: type
mapping:
text: '#/components/schemas/TextDelta'
image: '#/components/schemas/ImageDelta'
tool_call: '#/components/schemas/ToolCallDelta'
ImageDelta:
type: object
properties:
@ -6983,7 +6959,22 @@ components:
type: object
properties:
payload:
$ref: '#/components/schemas/AgentTurnResponseEventPayload'
oneOf:
- $ref: '#/components/schemas/AgentTurnResponseStepStartPayload'
- $ref: '#/components/schemas/AgentTurnResponseStepProgressPayload'
- $ref: '#/components/schemas/AgentTurnResponseStepCompletePayload'
- $ref: '#/components/schemas/AgentTurnResponseTurnStartPayload'
- $ref: '#/components/schemas/AgentTurnResponseTurnCompletePayload'
- $ref: '#/components/schemas/AgentTurnResponseTurnAwaitingInputPayload'
discriminator:
propertyName: event_type
mapping:
step_start: '#/components/schemas/AgentTurnResponseStepStartPayload'
step_progress: '#/components/schemas/AgentTurnResponseStepProgressPayload'
step_complete: '#/components/schemas/AgentTurnResponseStepCompletePayload'
turn_start: '#/components/schemas/AgentTurnResponseTurnStartPayload'
turn_complete: '#/components/schemas/AgentTurnResponseTurnCompletePayload'
turn_awaiting_input: '#/components/schemas/AgentTurnResponseTurnAwaitingInputPayload'
description: >-
Event-specific payload containing event data
additionalProperties: false
@ -6992,23 +6983,6 @@ components:
title: AgentTurnResponseEvent
description: >-
An event in an agent turn response stream.
AgentTurnResponseEventPayload:
oneOf:
- $ref: '#/components/schemas/AgentTurnResponseStepStartPayload'
- $ref: '#/components/schemas/AgentTurnResponseStepProgressPayload'
- $ref: '#/components/schemas/AgentTurnResponseStepCompletePayload'
- $ref: '#/components/schemas/AgentTurnResponseTurnStartPayload'
- $ref: '#/components/schemas/AgentTurnResponseTurnCompletePayload'
- $ref: '#/components/schemas/AgentTurnResponseTurnAwaitingInputPayload'
discriminator:
propertyName: event_type
mapping:
step_start: '#/components/schemas/AgentTurnResponseStepStartPayload'
step_progress: '#/components/schemas/AgentTurnResponseStepProgressPayload'
step_complete: '#/components/schemas/AgentTurnResponseStepCompletePayload'
turn_start: '#/components/schemas/AgentTurnResponseTurnStartPayload'
turn_complete: '#/components/schemas/AgentTurnResponseTurnCompletePayload'
turn_awaiting_input: '#/components/schemas/AgentTurnResponseTurnAwaitingInputPayload'
AgentTurnResponseStepCompletePayload:
type: object
properties:
@ -7087,7 +7061,16 @@ components:
description: >-
Unique identifier for the step within a turn
delta:
$ref: '#/components/schemas/ContentDelta'
oneOf:
- $ref: '#/components/schemas/TextDelta'
- $ref: '#/components/schemas/ImageDelta'
- $ref: '#/components/schemas/ToolCallDelta'
discriminator:
propertyName: type
mapping:
text: '#/components/schemas/TextDelta'
image: '#/components/schemas/ImageDelta'
tool_call: '#/components/schemas/ToolCallDelta'
description: >-
Incremental content changes during step execution
additionalProperties: false
@ -8156,15 +8139,6 @@ components:
title: OpenAIResponseOutputMessageMCPListTools
description: >-
MCP list tools output message containing available tools from an MCP server.
OpenAIResponseContentPart:
oneOf:
- $ref: '#/components/schemas/OpenAIResponseContentPartOutputText'
- $ref: '#/components/schemas/OpenAIResponseContentPartRefusal'
discriminator:
propertyName: type
mapping:
output_text: '#/components/schemas/OpenAIResponseContentPartOutputText'
refusal: '#/components/schemas/OpenAIResponseContentPartRefusal'
OpenAIResponseContentPartOutputText:
type: object
properties:
@ -8272,7 +8246,14 @@ components:
description: >-
Unique identifier of the output item containing this content part
part:
$ref: '#/components/schemas/OpenAIResponseContentPart'
oneOf:
- $ref: '#/components/schemas/OpenAIResponseContentPartOutputText'
- $ref: '#/components/schemas/OpenAIResponseContentPartRefusal'
discriminator:
propertyName: type
mapping:
output_text: '#/components/schemas/OpenAIResponseContentPartOutputText'
refusal: '#/components/schemas/OpenAIResponseContentPartRefusal'
description: The content part that was added
sequence_number:
type: integer
@ -8307,7 +8288,14 @@ components:
description: >-
Unique identifier of the output item containing this content part
part:
$ref: '#/components/schemas/OpenAIResponseContentPart'
oneOf:
- $ref: '#/components/schemas/OpenAIResponseContentPartOutputText'
- $ref: '#/components/schemas/OpenAIResponseContentPartRefusal'
discriminator:
propertyName: type
mapping:
output_text: '#/components/schemas/OpenAIResponseContentPartOutputText'
refusal: '#/components/schemas/OpenAIResponseContentPartRefusal'
description: The completed content part
sequence_number:
type: integer
@ -8593,7 +8581,22 @@ components:
description: >-
Unique identifier of the response containing this output
item:
$ref: '#/components/schemas/OpenAIResponseOutput'
oneOf:
- $ref: '#/components/schemas/OpenAIResponseMessage'
- $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall'
- $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall'
- $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall'
- $ref: '#/components/schemas/OpenAIResponseOutputMessageMCPCall'
- $ref: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools'
discriminator:
propertyName: type
mapping:
message: '#/components/schemas/OpenAIResponseMessage'
web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall'
file_search_call: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall'
function_call: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall'
mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall'
mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools'
description: >-
The output item that was added (message, tool call, etc.)
output_index:
@ -8629,7 +8632,22 @@ components:
description: >-
Unique identifier of the response containing this output
item:
$ref: '#/components/schemas/OpenAIResponseOutput'
oneOf:
- $ref: '#/components/schemas/OpenAIResponseMessage'
- $ref: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall'
- $ref: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall'
- $ref: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall'
- $ref: '#/components/schemas/OpenAIResponseOutputMessageMCPCall'
- $ref: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools'
discriminator:
propertyName: type
mapping:
message: '#/components/schemas/OpenAIResponseMessage'
web_search_call: '#/components/schemas/OpenAIResponseOutputMessageWebSearchToolCall'
file_search_call: '#/components/schemas/OpenAIResponseOutputMessageFileSearchToolCall'
function_call: '#/components/schemas/OpenAIResponseOutputMessageFunctionToolCall'
mcp_call: '#/components/schemas/OpenAIResponseOutputMessageMCPCall'
mcp_list_tools: '#/components/schemas/OpenAIResponseOutputMessageMCPListTools'
description: >-
The completed output item (message, tool call, etc.)
output_index:
@ -8952,7 +8970,14 @@ components:
type: object
properties:
eval_candidate:
$ref: '#/components/schemas/EvalCandidate'
oneOf:
- $ref: '#/components/schemas/ModelCandidate'
- $ref: '#/components/schemas/AgentCandidate'
discriminator:
propertyName: type
mapping:
model: '#/components/schemas/ModelCandidate'
agent: '#/components/schemas/AgentCandidate'
description: The candidate to evaluate.
scoring_params:
type: object
@ -8973,15 +8998,6 @@ components:
title: BenchmarkConfig
description: >-
A benchmark configuration for evaluation.
EvalCandidate:
oneOf:
- $ref: '#/components/schemas/ModelCandidate'
- $ref: '#/components/schemas/AgentCandidate'
discriminator:
propertyName: type
mapping:
model: '#/components/schemas/ModelCandidate'
agent: '#/components/schemas/AgentCandidate'
LLMAsJudgeScoringFnParams:
type: object
properties:
@ -9445,7 +9461,20 @@ components:
type: object
properties:
message:
$ref: '#/components/schemas/OpenAIMessageParam'
oneOf:
- $ref: '#/components/schemas/OpenAIUserMessageParam'
- $ref: '#/components/schemas/OpenAISystemMessageParam'
- $ref: '#/components/schemas/OpenAIAssistantMessageParam'
- $ref: '#/components/schemas/OpenAIToolMessageParam'
- $ref: '#/components/schemas/OpenAIDeveloperMessageParam'
discriminator:
propertyName: role
mapping:
user: '#/components/schemas/OpenAIUserMessageParam'
system: '#/components/schemas/OpenAISystemMessageParam'
assistant: '#/components/schemas/OpenAIAssistantMessageParam'
tool: '#/components/schemas/OpenAIToolMessageParam'
developer: '#/components/schemas/OpenAIDeveloperMessageParam'
description: The message from the model
finish_reason:
type: string
@ -9738,15 +9767,6 @@ components:
- model
- input_messages
title: OpenAICompletionWithInputMessages
DataSource:
oneOf:
- $ref: '#/components/schemas/URIDataSource'
- $ref: '#/components/schemas/RowsDataSource'
discriminator:
propertyName: type
mapping:
uri: '#/components/schemas/URIDataSource'
rows: '#/components/schemas/RowsDataSource'
Dataset:
type: object
properties:
@ -9781,7 +9801,14 @@ components:
description: >-
Purpose of the dataset indicating its intended use
source:
$ref: '#/components/schemas/DataSource'
oneOf:
- $ref: '#/components/schemas/URIDataSource'
- $ref: '#/components/schemas/RowsDataSource'
discriminator:
propertyName: type
mapping:
uri: '#/components/schemas/URIDataSource'
rows: '#/components/schemas/RowsDataSource'
description: >-
Data source configuration for the dataset
metadata:
@ -10027,31 +10054,6 @@ components:
- type
title: ObjectType
description: Parameter type for object values.
ParamType:
oneOf:
- $ref: '#/components/schemas/StringType'
- $ref: '#/components/schemas/NumberType'
- $ref: '#/components/schemas/BooleanType'
- $ref: '#/components/schemas/ArrayType'
- $ref: '#/components/schemas/ObjectType'
- $ref: '#/components/schemas/JsonType'
- $ref: '#/components/schemas/UnionType'
- $ref: '#/components/schemas/ChatCompletionInputType'
- $ref: '#/components/schemas/CompletionInputType'
- $ref: '#/components/schemas/AgentTurnInputType'
discriminator:
propertyName: type
mapping:
string: '#/components/schemas/StringType'
number: '#/components/schemas/NumberType'
boolean: '#/components/schemas/BooleanType'
array: '#/components/schemas/ArrayType'
object: '#/components/schemas/ObjectType'
json: '#/components/schemas/JsonType'
union: '#/components/schemas/UnionType'
chat_completion_input: '#/components/schemas/ChatCompletionInputType'
completion_input: '#/components/schemas/CompletionInputType'
agent_turn_input: '#/components/schemas/AgentTurnInputType'
ScoringFn:
type: object
properties:
@ -10090,7 +10092,30 @@ components:
- type: array
- type: object
return_type:
$ref: '#/components/schemas/ParamType'
oneOf:
- $ref: '#/components/schemas/StringType'
- $ref: '#/components/schemas/NumberType'
- $ref: '#/components/schemas/BooleanType'
- $ref: '#/components/schemas/ArrayType'
- $ref: '#/components/schemas/ObjectType'
- $ref: '#/components/schemas/JsonType'
- $ref: '#/components/schemas/UnionType'
- $ref: '#/components/schemas/ChatCompletionInputType'
- $ref: '#/components/schemas/CompletionInputType'
- $ref: '#/components/schemas/AgentTurnInputType'
discriminator:
propertyName: type
mapping:
string: '#/components/schemas/StringType'
number: '#/components/schemas/NumberType'
boolean: '#/components/schemas/BooleanType'
array: '#/components/schemas/ArrayType'
object: '#/components/schemas/ObjectType'
json: '#/components/schemas/JsonType'
union: '#/components/schemas/UnionType'
chat_completion_input: '#/components/schemas/ChatCompletionInputType'
completion_input: '#/components/schemas/CompletionInputType'
agent_turn_input: '#/components/schemas/AgentTurnInputType'
params:
$ref: '#/components/schemas/ScoringFnParams'
additionalProperties: false
@ -11542,7 +11567,14 @@ components:
description: >-
Event type identifier set to STRUCTURED_LOG
payload:
$ref: '#/components/schemas/StructuredLogPayload'
oneOf:
- $ref: '#/components/schemas/SpanStartPayload'
- $ref: '#/components/schemas/SpanEndPayload'
discriminator:
propertyName: type
mapping:
span_start: '#/components/schemas/SpanStartPayload'
span_end: '#/components/schemas/SpanEndPayload'
description: >-
The structured payload data for the log event
additionalProperties: false
@ -11555,15 +11587,6 @@ components:
title: StructuredLogEvent
description: >-
A structured log event containing typed payload data.
StructuredLogPayload:
oneOf:
- $ref: '#/components/schemas/SpanStartPayload'
- $ref: '#/components/schemas/SpanEndPayload'
discriminator:
propertyName: type
mapping:
span_start: '#/components/schemas/SpanStartPayload'
span_end: '#/components/schemas/SpanEndPayload'
StructuredLogType:
type: string
enum:
@ -11772,7 +11795,14 @@ components:
description: >-
Key-value attributes associated with the file
chunking_strategy:
$ref: '#/components/schemas/VectorStoreChunkingStrategy'
oneOf:
- $ref: '#/components/schemas/VectorStoreChunkingStrategyAuto'
- $ref: '#/components/schemas/VectorStoreChunkingStrategyStatic'
discriminator:
propertyName: type
mapping:
auto: '#/components/schemas/VectorStoreChunkingStrategyAuto'
static: '#/components/schemas/VectorStoreChunkingStrategyStatic'
description: >-
Strategy used for splitting the file into chunks
created_at:
@ -13084,6 +13114,25 @@ components:
required:
- attributes
title: OpenaiUpdateVectorStoreFileRequest
ExpiresAfter:
type: object
properties:
anchor:
type: string
const: created_at
seconds:
type: integer
additionalProperties: false
required:
- anchor
- seconds
title: ExpiresAfter
description: >-
Control expiration of uploaded files.
Params:
- anchor, must be "created_at"
- seconds, must be int between 3600 and 2592000 (1 hour to 30 days)
DPOAlignmentConfig:
type: object
properties:
@ -13369,7 +13418,14 @@ components:
type: object
properties:
query_generator_config:
$ref: '#/components/schemas/RAGQueryGeneratorConfig'
oneOf:
- $ref: '#/components/schemas/DefaultRAGQueryGeneratorConfig'
- $ref: '#/components/schemas/LLMRAGQueryGeneratorConfig'
discriminator:
propertyName: type
mapping:
default: '#/components/schemas/DefaultRAGQueryGeneratorConfig'
llm: '#/components/schemas/LLMRAGQueryGeneratorConfig'
description: Configuration for the query generator.
max_tokens_in_context:
type: integer
@ -13412,15 +13468,6 @@ components:
title: RAGQueryConfig
description: >-
Configuration for the RAG query generation.
RAGQueryGeneratorConfig:
oneOf:
- $ref: '#/components/schemas/DefaultRAGQueryGeneratorConfig'
- $ref: '#/components/schemas/LLMRAGQueryGeneratorConfig'
discriminator:
propertyName: type
mapping:
default: '#/components/schemas/DefaultRAGQueryGeneratorConfig'
llm: '#/components/schemas/LLMRAGQueryGeneratorConfig'
RAGSearchMode:
type: string
enum:
@ -13856,6 +13903,15 @@ components:
- dataset_id
- scoring_functions
title: RegisterBenchmarkRequest
DataSource:
oneOf:
- $ref: '#/components/schemas/URIDataSource'
- $ref: '#/components/schemas/RowsDataSource'
discriminator:
propertyName: type
mapping:
uri: '#/components/schemas/URIDataSource'
rows: '#/components/schemas/RowsDataSource'
RegisterDatasetRequest:
type: object
properties:
@ -13940,6 +13996,31 @@ components:
required:
- model_id
title: RegisterModelRequest
ParamType:
oneOf:
- $ref: '#/components/schemas/StringType'
- $ref: '#/components/schemas/NumberType'
- $ref: '#/components/schemas/BooleanType'
- $ref: '#/components/schemas/ArrayType'
- $ref: '#/components/schemas/ObjectType'
- $ref: '#/components/schemas/JsonType'
- $ref: '#/components/schemas/UnionType'
- $ref: '#/components/schemas/ChatCompletionInputType'
- $ref: '#/components/schemas/CompletionInputType'
- $ref: '#/components/schemas/AgentTurnInputType'
discriminator:
propertyName: type
mapping:
string: '#/components/schemas/StringType'
number: '#/components/schemas/NumberType'
boolean: '#/components/schemas/BooleanType'
array: '#/components/schemas/ArrayType'
object: '#/components/schemas/ObjectType'
json: '#/components/schemas/JsonType'
union: '#/components/schemas/UnionType'
chat_completion_input: '#/components/schemas/ChatCompletionInputType'
completion_input: '#/components/schemas/CompletionInputType'
agent_turn_input: '#/components/schemas/AgentTurnInputType'
RegisterScoringFunctionRequest:
type: object
properties:

View file

@ -111,9 +111,7 @@ class Files(Protocol):
self,
file: Annotated[UploadFile, File()],
purpose: Annotated[OpenAIFilePurpose, Form()],
expires_after_anchor: Annotated[str | None, Form(alias="expires_after[anchor]")] = None,
expires_after_seconds: Annotated[int | None, Form(alias="expires_after[seconds]")] = None,
# TODO: expires_after is producing strange openapi spec, params are showing up as a required w/ oneOf being null
expires_after: Annotated[ExpiresAfter | None, Form()] = None,
) -> OpenAIFileObject:
"""
Upload a file that can be used across various endpoints.
@ -121,10 +119,11 @@ class Files(Protocol):
The file upload should be a multipart form request with:
- file: The File object (not file name) to be uploaded.
- purpose: The intended purpose of the uploaded file.
- expires_after: Optional form values describing expiration for the file. Expected expires_after[anchor] = "created_at", expires_after[seconds] = {integer}. Seconds must be between 3600 and 2592000 (1 hour to 30 days).
- expires_after: Optional form values describing expiration for the file.
:param file: The uploaded file object containing content and metadata (filename, content_type, etc.).
:param purpose: The intended purpose of the uploaded file (e.g., "assistants", "fine-tune").
:param expires_after: Optional form values describing expiration for the file.
:returns: An OpenAIFileObject representing the uploaded file.
"""
...

View file

@ -14,6 +14,7 @@ from fastapi import File, Form, Response, UploadFile
from llama_stack.apis.common.errors import ResourceNotFoundError
from llama_stack.apis.common.responses import Order
from llama_stack.apis.files import (
ExpiresAfter,
Files,
ListOpenAIFileResponse,
OpenAIFileDeleteResponse,
@ -86,14 +87,13 @@ class LocalfsFilesImpl(Files):
self,
file: Annotated[UploadFile, File()],
purpose: Annotated[OpenAIFilePurpose, Form()],
expires_after_anchor: Annotated[str | None, Form(alias="expires_after[anchor]")] = None,
expires_after_seconds: Annotated[int | None, Form(alias="expires_after[seconds]")] = None,
expires_after: Annotated[ExpiresAfter | None, Form()] = None,
) -> OpenAIFileObject:
"""Upload a file that can be used across various endpoints."""
if not self.sql_store:
raise RuntimeError("Files provider not initialized")
if expires_after_anchor is not None or expires_after_seconds is not None:
if expires_after is not None:
raise NotImplementedError("File expiration is not supported by this provider")
file_id = self._generate_file_id()

View file

@ -195,8 +195,7 @@ class S3FilesImpl(Files):
self,
file: Annotated[UploadFile, File()],
purpose: Annotated[OpenAIFilePurpose, Form()],
expires_after_anchor: Annotated[str | None, Form(alias="expires_after[anchor]")] = None,
expires_after_seconds: Annotated[int | None, Form(alias="expires_after[seconds]")] = None,
expires_after: Annotated[ExpiresAfter | None, Form()] = None,
) -> OpenAIFileObject:
file_id = f"file-{uuid.uuid4().hex}"
@ -204,14 +203,6 @@ class S3FilesImpl(Files):
created_at = self._now()
expires_after = None
if expires_after_anchor is not None or expires_after_seconds is not None:
# we use ExpiresAfter to validate input
expires_after = ExpiresAfter(
anchor=expires_after_anchor, # type: ignore[arg-type]
seconds=expires_after_seconds, # type: ignore[arg-type]
)
# the default is no expiration.
# to implement no expiration we set an expiration beyond the max.
# we'll hide this fact from users when returning the file object.

View file

@ -567,6 +567,22 @@ def get_class_properties(typ: type) -> Iterable[Tuple[str, type | str]]:
if is_dataclass_type(typ):
return ((field.name, field.type) for field in dataclasses.fields(typ))
elif hasattr(typ, "model_fields"):
# Pydantic BaseModel - use model_fields to exclude ClassVar and other non-field attributes
# Reconstruct Annotated type if discriminator exists to preserve metadata
from typing import Annotated, Any, cast
from pydantic.fields import FieldInfo
def get_field_type(name: str, field: Any) -> type | str:
# If field has discriminator, wrap in Annotated to preserve it for schema generation
if field.discriminator:
field_info = FieldInfo(annotation=None, discriminator=field.discriminator)
# Annotated returns _AnnotatedAlias which isn't a type but is valid here
return Annotated[field.annotation, field_info] # type: ignore[return-value]
# field.annotation can be Union types, Annotated, etc. which aren't type but are valid
return field.annotation # type: ignore[return-value,no-any-return]
return ((name, get_field_type(name, field)) for name, field in typ.model_fields.items())
else:
resolved_hints = get_resolved_hints(typ)
return resolved_hints.items()

View file

@ -92,7 +92,12 @@ def get_class_property_docstrings(
:returns: A dictionary mapping property names to descriptions.
"""
result = {}
result: Dict[str, str] = {}
# Only try to get MRO if data_type is actually a class
# Special types like Literal, Union, etc. don't have MRO
if not inspect.isclass(data_type):
return result
for base in inspect.getmro(data_type):
docstr = docstring.parse_type(base)
for param in docstr.params.values():

View file

@ -228,12 +228,13 @@ class TestS3FilesImpl:
mock_now.return_value = 0
from llama_stack.apis.files import ExpiresAfter
sample_text_file.filename = "test_expired_file"
uploaded = await s3_provider.openai_upload_file(
file=sample_text_file,
purpose=OpenAIFilePurpose.ASSISTANTS,
expires_after_anchor="created_at",
expires_after_seconds=two_hours,
expires_after=ExpiresAfter(anchor="created_at", seconds=two_hours),
)
mock_now.return_value = two_hours * 2 # fast forward 4 hours
@ -259,42 +260,44 @@ class TestS3FilesImpl:
async def test_unsupported_expires_after_anchor(self, s3_provider, sample_text_file):
"""Unsupported anchor value should raise ValueError."""
from llama_stack.apis.files import ExpiresAfter
sample_text_file.filename = "test_unsupported_expires_after_anchor"
with pytest.raises(ValueError, match="Input should be 'created_at'"):
await s3_provider.openai_upload_file(
file=sample_text_file,
purpose=OpenAIFilePurpose.ASSISTANTS,
expires_after_anchor="now",
expires_after_seconds=3600,
expires_after=ExpiresAfter(anchor="now", seconds=3600), # type: ignore
)
async def test_nonint_expires_after_seconds(self, s3_provider, sample_text_file):
"""Non-integer seconds in expires_after should raise ValueError."""
from llama_stack.apis.files import ExpiresAfter
sample_text_file.filename = "test_nonint_expires_after_seconds"
with pytest.raises(ValueError, match="should be a valid integer"):
await s3_provider.openai_upload_file(
file=sample_text_file,
purpose=OpenAIFilePurpose.ASSISTANTS,
expires_after_anchor="created_at",
expires_after_seconds="many",
expires_after=ExpiresAfter(anchor="created_at", seconds="many"), # type: ignore
)
async def test_expires_after_seconds_out_of_bounds(self, s3_provider, sample_text_file):
"""Seconds outside allowed range should raise ValueError."""
from llama_stack.apis.files import ExpiresAfter
with pytest.raises(ValueError, match="greater than or equal to 3600"):
await s3_provider.openai_upload_file(
file=sample_text_file,
purpose=OpenAIFilePurpose.ASSISTANTS,
expires_after_anchor="created_at",
expires_after_seconds=3599,
expires_after=ExpiresAfter(anchor="created_at", seconds=3599),
)
with pytest.raises(ValueError, match="less than or equal to 2592000"):
await s3_provider.openai_upload_file(
file=sample_text_file,
purpose=OpenAIFilePurpose.ASSISTANTS,
expires_after_anchor="created_at",
expires_after_seconds=2592001,
expires_after=ExpiresAfter(anchor="created_at", seconds=2592001),
)