mirror of
https://github.com/meta-llama/llama-stack.git
synced 2025-12-03 18:00:36 +00:00
even more cleanup, the deltas should be much smaller now
This commit is contained in:
parent
5293b4e5e9
commit
9deb0beb86
14 changed files with 5038 additions and 17435 deletions
File diff suppressed because it is too large
Load diff
2959
docs/static/deprecated-llama-stack-spec.yaml
vendored
2959
docs/static/deprecated-llama-stack-spec.yaml
vendored
File diff suppressed because it is too large
Load diff
7479
docs/static/experimental-llama-stack-spec.yaml
vendored
7479
docs/static/experimental-llama-stack-spec.yaml
vendored
File diff suppressed because it is too large
Load diff
3657
docs/static/llama-stack-spec.yaml
vendored
3657
docs/static/llama-stack-spec.yaml
vendored
File diff suppressed because it is too large
Load diff
3514
docs/static/stainless-llama-stack-spec.yaml
vendored
3514
docs/static/stainless-llama-stack-spec.yaml
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -12,462 +12,492 @@ These lists help the new generator match the previous ordering so that diffs
|
|||
remain readable while we debug schema content regressions. Remove once stable.
|
||||
"""
|
||||
|
||||
LEGACY_PATH_ORDER = ['/v1/batches',
|
||||
'/v1/batches/{batch_id}',
|
||||
'/v1/batches/{batch_id}/cancel',
|
||||
'/v1/chat/completions',
|
||||
'/v1/chat/completions/{completion_id}',
|
||||
'/v1/completions',
|
||||
'/v1/conversations',
|
||||
'/v1/conversations/{conversation_id}',
|
||||
'/v1/conversations/{conversation_id}/items',
|
||||
'/v1/conversations/{conversation_id}/items/{item_id}',
|
||||
'/v1/embeddings',
|
||||
'/v1/files',
|
||||
'/v1/files/{file_id}',
|
||||
'/v1/files/{file_id}/content',
|
||||
'/v1/health',
|
||||
'/v1/inspect/routes',
|
||||
'/v1/models',
|
||||
'/v1/models/{model_id}',
|
||||
'/v1/moderations',
|
||||
'/v1/prompts',
|
||||
'/v1/prompts/{prompt_id}',
|
||||
'/v1/prompts/{prompt_id}/set-default-version',
|
||||
'/v1/prompts/{prompt_id}/versions',
|
||||
'/v1/providers',
|
||||
'/v1/providers/{provider_id}',
|
||||
'/v1/responses',
|
||||
'/v1/responses/{response_id}',
|
||||
'/v1/responses/{response_id}/input_items',
|
||||
'/v1/safety/run-shield',
|
||||
'/v1/scoring-functions',
|
||||
'/v1/scoring-functions/{scoring_fn_id}',
|
||||
'/v1/scoring/score',
|
||||
'/v1/scoring/score-batch',
|
||||
'/v1/shields',
|
||||
'/v1/shields/{identifier}',
|
||||
'/v1/tool-runtime/invoke',
|
||||
'/v1/tool-runtime/list-tools',
|
||||
'/v1/toolgroups',
|
||||
'/v1/toolgroups/{toolgroup_id}',
|
||||
'/v1/tools',
|
||||
'/v1/tools/{tool_name}',
|
||||
'/v1/vector-io/insert',
|
||||
'/v1/vector-io/query',
|
||||
'/v1/vector_stores',
|
||||
'/v1/vector_stores/{vector_store_id}',
|
||||
'/v1/vector_stores/{vector_store_id}/file_batches',
|
||||
'/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}',
|
||||
'/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel',
|
||||
'/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/files',
|
||||
'/v1/vector_stores/{vector_store_id}/files',
|
||||
'/v1/vector_stores/{vector_store_id}/files/{file_id}',
|
||||
'/v1/vector_stores/{vector_store_id}/files/{file_id}/content',
|
||||
'/v1/vector_stores/{vector_store_id}/search',
|
||||
'/v1/version',
|
||||
'/v1beta/datasetio/append-rows/{dataset_id}',
|
||||
'/v1beta/datasetio/iterrows/{dataset_id}',
|
||||
'/v1beta/datasets',
|
||||
'/v1beta/datasets/{dataset_id}',
|
||||
'/v1alpha/eval/benchmarks',
|
||||
'/v1alpha/eval/benchmarks/{benchmark_id}',
|
||||
'/v1alpha/eval/benchmarks/{benchmark_id}/evaluations',
|
||||
'/v1alpha/eval/benchmarks/{benchmark_id}/jobs',
|
||||
'/v1alpha/eval/benchmarks/{benchmark_id}/jobs/{job_id}',
|
||||
'/v1alpha/eval/benchmarks/{benchmark_id}/jobs/{job_id}/result',
|
||||
'/v1alpha/inference/rerank',
|
||||
'/v1alpha/post-training/job/artifacts',
|
||||
'/v1alpha/post-training/job/cancel',
|
||||
'/v1alpha/post-training/job/status',
|
||||
'/v1alpha/post-training/jobs',
|
||||
'/v1alpha/post-training/preference-optimize',
|
||||
'/v1alpha/post-training/supervised-fine-tune']
|
||||
LEGACY_PATH_ORDER = [
|
||||
"/v1/batches",
|
||||
"/v1/batches/{batch_id}",
|
||||
"/v1/batches/{batch_id}/cancel",
|
||||
"/v1/chat/completions",
|
||||
"/v1/chat/completions/{completion_id}",
|
||||
"/v1/completions",
|
||||
"/v1/conversations",
|
||||
"/v1/conversations/{conversation_id}",
|
||||
"/v1/conversations/{conversation_id}/items",
|
||||
"/v1/conversations/{conversation_id}/items/{item_id}",
|
||||
"/v1/embeddings",
|
||||
"/v1/files",
|
||||
"/v1/files/{file_id}",
|
||||
"/v1/files/{file_id}/content",
|
||||
"/v1/health",
|
||||
"/v1/inspect/routes",
|
||||
"/v1/models",
|
||||
"/v1/models/{model_id}",
|
||||
"/v1/moderations",
|
||||
"/v1/prompts",
|
||||
"/v1/prompts/{prompt_id}",
|
||||
"/v1/prompts/{prompt_id}/set-default-version",
|
||||
"/v1/prompts/{prompt_id}/versions",
|
||||
"/v1/providers",
|
||||
"/v1/providers/{provider_id}",
|
||||
"/v1/responses",
|
||||
"/v1/responses/{response_id}",
|
||||
"/v1/responses/{response_id}/input_items",
|
||||
"/v1/safety/run-shield",
|
||||
"/v1/scoring-functions",
|
||||
"/v1/scoring-functions/{scoring_fn_id}",
|
||||
"/v1/scoring/score",
|
||||
"/v1/scoring/score-batch",
|
||||
"/v1/shields",
|
||||
"/v1/shields/{identifier}",
|
||||
"/v1/tool-runtime/invoke",
|
||||
"/v1/tool-runtime/list-tools",
|
||||
"/v1/toolgroups",
|
||||
"/v1/toolgroups/{toolgroup_id}",
|
||||
"/v1/tools",
|
||||
"/v1/tools/{tool_name}",
|
||||
"/v1/vector-io/insert",
|
||||
"/v1/vector-io/query",
|
||||
"/v1/vector_stores",
|
||||
"/v1/vector_stores/{vector_store_id}",
|
||||
"/v1/vector_stores/{vector_store_id}/file_batches",
|
||||
"/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}",
|
||||
"/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/cancel",
|
||||
"/v1/vector_stores/{vector_store_id}/file_batches/{batch_id}/files",
|
||||
"/v1/vector_stores/{vector_store_id}/files",
|
||||
"/v1/vector_stores/{vector_store_id}/files/{file_id}",
|
||||
"/v1/vector_stores/{vector_store_id}/files/{file_id}/content",
|
||||
"/v1/vector_stores/{vector_store_id}/search",
|
||||
"/v1/version",
|
||||
"/v1beta/datasetio/append-rows/{dataset_id}",
|
||||
"/v1beta/datasetio/iterrows/{dataset_id}",
|
||||
"/v1beta/datasets",
|
||||
"/v1beta/datasets/{dataset_id}",
|
||||
"/v1alpha/eval/benchmarks",
|
||||
"/v1alpha/eval/benchmarks/{benchmark_id}",
|
||||
"/v1alpha/eval/benchmarks/{benchmark_id}/evaluations",
|
||||
"/v1alpha/eval/benchmarks/{benchmark_id}/jobs",
|
||||
"/v1alpha/eval/benchmarks/{benchmark_id}/jobs/{job_id}",
|
||||
"/v1alpha/eval/benchmarks/{benchmark_id}/jobs/{job_id}/result",
|
||||
"/v1alpha/inference/rerank",
|
||||
"/v1alpha/post-training/job/artifacts",
|
||||
"/v1alpha/post-training/job/cancel",
|
||||
"/v1alpha/post-training/job/status",
|
||||
"/v1alpha/post-training/jobs",
|
||||
"/v1alpha/post-training/preference-optimize",
|
||||
"/v1alpha/post-training/supervised-fine-tune",
|
||||
]
|
||||
|
||||
LEGACY_SCHEMA_ORDER = ['Error',
|
||||
'ListBatchesResponse',
|
||||
'CreateBatchRequest',
|
||||
'Batch',
|
||||
'Order',
|
||||
'ListOpenAIChatCompletionResponse',
|
||||
'OpenAIAssistantMessageParam',
|
||||
'OpenAIChatCompletionContentPartImageParam',
|
||||
'OpenAIChatCompletionContentPartParam',
|
||||
'OpenAIChatCompletionContentPartTextParam',
|
||||
'OpenAIChatCompletionToolCall',
|
||||
'OpenAIChatCompletionToolCallFunction',
|
||||
'OpenAIChatCompletionUsage',
|
||||
'OpenAIChoice',
|
||||
'OpenAIChoiceLogprobs',
|
||||
'OpenAIDeveloperMessageParam',
|
||||
'OpenAIFile',
|
||||
'OpenAIFileFile',
|
||||
'OpenAIImageURL',
|
||||
'OpenAIMessageParam',
|
||||
'OpenAISystemMessageParam',
|
||||
'OpenAITokenLogProb',
|
||||
'OpenAIToolMessageParam',
|
||||
'OpenAITopLogProb',
|
||||
'OpenAIUserMessageParam',
|
||||
'OpenAIJSONSchema',
|
||||
'OpenAIResponseFormatJSONObject',
|
||||
'OpenAIResponseFormatJSONSchema',
|
||||
'OpenAIResponseFormatParam',
|
||||
'OpenAIResponseFormatText',
|
||||
'OpenAIChatCompletionRequestWithExtraBody',
|
||||
'OpenAIChatCompletion',
|
||||
'OpenAIChatCompletionChunk',
|
||||
'OpenAIChoiceDelta',
|
||||
'OpenAIChunkChoice',
|
||||
'OpenAICompletionWithInputMessages',
|
||||
'OpenAICompletionRequestWithExtraBody',
|
||||
'OpenAICompletion',
|
||||
'OpenAICompletionChoice',
|
||||
'ConversationItem',
|
||||
'OpenAIResponseAnnotationCitation',
|
||||
'OpenAIResponseAnnotationContainerFileCitation',
|
||||
'OpenAIResponseAnnotationFileCitation',
|
||||
'OpenAIResponseAnnotationFilePath',
|
||||
'OpenAIResponseAnnotations',
|
||||
'OpenAIResponseContentPartRefusal',
|
||||
'OpenAIResponseInputFunctionToolCallOutput',
|
||||
'OpenAIResponseInputMessageContent',
|
||||
'OpenAIResponseInputMessageContentFile',
|
||||
'OpenAIResponseInputMessageContentImage',
|
||||
'OpenAIResponseInputMessageContentText',
|
||||
'OpenAIResponseMCPApprovalRequest',
|
||||
'OpenAIResponseMCPApprovalResponse',
|
||||
'OpenAIResponseMessage',
|
||||
'OpenAIResponseOutputMessageContent',
|
||||
'OpenAIResponseOutputMessageContentOutputText',
|
||||
'OpenAIResponseOutputMessageFileSearchToolCall',
|
||||
'OpenAIResponseOutputMessageFunctionToolCall',
|
||||
'OpenAIResponseOutputMessageMCPCall',
|
||||
'OpenAIResponseOutputMessageMCPListTools',
|
||||
'OpenAIResponseOutputMessageWebSearchToolCall',
|
||||
'CreateConversationRequest',
|
||||
'Conversation',
|
||||
'UpdateConversationRequest',
|
||||
'ConversationDeletedResource',
|
||||
'ConversationItemList',
|
||||
'AddItemsRequest',
|
||||
'ConversationItemDeletedResource',
|
||||
'OpenAIEmbeddingsRequestWithExtraBody',
|
||||
'OpenAIEmbeddingData',
|
||||
'OpenAIEmbeddingUsage',
|
||||
'OpenAIEmbeddingsResponse',
|
||||
'OpenAIFilePurpose',
|
||||
'ListOpenAIFileResponse',
|
||||
'OpenAIFileObject',
|
||||
'ExpiresAfter',
|
||||
'OpenAIFileDeleteResponse',
|
||||
'Response',
|
||||
'HealthInfo',
|
||||
'RouteInfo',
|
||||
'ListRoutesResponse',
|
||||
'OpenAIModel',
|
||||
'OpenAIListModelsResponse',
|
||||
'Model',
|
||||
'ModelType',
|
||||
'RunModerationRequest',
|
||||
'ModerationObject',
|
||||
'ModerationObjectResults',
|
||||
'Prompt',
|
||||
'ListPromptsResponse',
|
||||
'CreatePromptRequest',
|
||||
'UpdatePromptRequest',
|
||||
'SetDefaultVersionRequest',
|
||||
'ProviderInfo',
|
||||
'ListProvidersResponse',
|
||||
'ListOpenAIResponseObject',
|
||||
'OpenAIResponseError',
|
||||
'OpenAIResponseInput',
|
||||
'OpenAIResponseInputToolFileSearch',
|
||||
'OpenAIResponseInputToolFunction',
|
||||
'OpenAIResponseInputToolWebSearch',
|
||||
'OpenAIResponseObjectWithInput',
|
||||
'OpenAIResponseOutput',
|
||||
'OpenAIResponsePrompt',
|
||||
'OpenAIResponseText',
|
||||
'OpenAIResponseTool',
|
||||
'OpenAIResponseToolMCP',
|
||||
'OpenAIResponseUsage',
|
||||
'ResponseGuardrailSpec',
|
||||
'OpenAIResponseInputTool',
|
||||
'OpenAIResponseInputToolMCP',
|
||||
'CreateOpenaiResponseRequest',
|
||||
'OpenAIResponseObject',
|
||||
'OpenAIResponseContentPartOutputText',
|
||||
'OpenAIResponseContentPartReasoningSummary',
|
||||
'OpenAIResponseContentPartReasoningText',
|
||||
'OpenAIResponseObjectStream',
|
||||
'OpenAIResponseObjectStreamResponseCompleted',
|
||||
'OpenAIResponseObjectStreamResponseContentPartAdded',
|
||||
'OpenAIResponseObjectStreamResponseContentPartDone',
|
||||
'OpenAIResponseObjectStreamResponseCreated',
|
||||
'OpenAIResponseObjectStreamResponseFailed',
|
||||
'OpenAIResponseObjectStreamResponseFileSearchCallCompleted',
|
||||
'OpenAIResponseObjectStreamResponseFileSearchCallInProgress',
|
||||
'OpenAIResponseObjectStreamResponseFileSearchCallSearching',
|
||||
'OpenAIResponseObjectStreamResponseFunctionCallArgumentsDelta',
|
||||
'OpenAIResponseObjectStreamResponseFunctionCallArgumentsDone',
|
||||
'OpenAIResponseObjectStreamResponseInProgress',
|
||||
'OpenAIResponseObjectStreamResponseIncomplete',
|
||||
'OpenAIResponseObjectStreamResponseMcpCallArgumentsDelta',
|
||||
'OpenAIResponseObjectStreamResponseMcpCallArgumentsDone',
|
||||
'OpenAIResponseObjectStreamResponseMcpCallCompleted',
|
||||
'OpenAIResponseObjectStreamResponseMcpCallFailed',
|
||||
'OpenAIResponseObjectStreamResponseMcpCallInProgress',
|
||||
'OpenAIResponseObjectStreamResponseMcpListToolsCompleted',
|
||||
'OpenAIResponseObjectStreamResponseMcpListToolsFailed',
|
||||
'OpenAIResponseObjectStreamResponseMcpListToolsInProgress',
|
||||
'OpenAIResponseObjectStreamResponseOutputItemAdded',
|
||||
'OpenAIResponseObjectStreamResponseOutputItemDone',
|
||||
'OpenAIResponseObjectStreamResponseOutputTextAnnotationAdded',
|
||||
'OpenAIResponseObjectStreamResponseOutputTextDelta',
|
||||
'OpenAIResponseObjectStreamResponseOutputTextDone',
|
||||
'OpenAIResponseObjectStreamResponseReasoningSummaryPartAdded',
|
||||
'OpenAIResponseObjectStreamResponseReasoningSummaryPartDone',
|
||||
'OpenAIResponseObjectStreamResponseReasoningSummaryTextDelta',
|
||||
'OpenAIResponseObjectStreamResponseReasoningSummaryTextDone',
|
||||
'OpenAIResponseObjectStreamResponseReasoningTextDelta',
|
||||
'OpenAIResponseObjectStreamResponseReasoningTextDone',
|
||||
'OpenAIResponseObjectStreamResponseRefusalDelta',
|
||||
'OpenAIResponseObjectStreamResponseRefusalDone',
|
||||
'OpenAIResponseObjectStreamResponseWebSearchCallCompleted',
|
||||
'OpenAIResponseObjectStreamResponseWebSearchCallInProgress',
|
||||
'OpenAIResponseObjectStreamResponseWebSearchCallSearching',
|
||||
'OpenAIDeleteResponseObject',
|
||||
'ListOpenAIResponseInputItem',
|
||||
'RunShieldRequest',
|
||||
'RunShieldResponse',
|
||||
'SafetyViolation',
|
||||
'ViolationLevel',
|
||||
'AggregationFunctionType',
|
||||
'ArrayType',
|
||||
'BasicScoringFnParams',
|
||||
'BooleanType',
|
||||
'ChatCompletionInputType',
|
||||
'CompletionInputType',
|
||||
'JsonType',
|
||||
'LLMAsJudgeScoringFnParams',
|
||||
'NumberType',
|
||||
'ObjectType',
|
||||
'RegexParserScoringFnParams',
|
||||
'ScoringFn',
|
||||
'ScoringFnParams',
|
||||
'ScoringFnParamsType',
|
||||
'StringType',
|
||||
'UnionType',
|
||||
'ListScoringFunctionsResponse',
|
||||
'ScoreRequest',
|
||||
'ScoreResponse',
|
||||
'ScoringResult',
|
||||
'ScoreBatchRequest',
|
||||
'ScoreBatchResponse',
|
||||
'Shield',
|
||||
'ListShieldsResponse',
|
||||
'InvokeToolRequest',
|
||||
'ImageContentItem',
|
||||
'InterleavedContent',
|
||||
'InterleavedContentItem',
|
||||
'TextContentItem',
|
||||
'ToolInvocationResult',
|
||||
'URL',
|
||||
'ToolDef',
|
||||
'ListToolDefsResponse',
|
||||
'ToolGroup',
|
||||
'ListToolGroupsResponse',
|
||||
'Chunk',
|
||||
'ChunkMetadata',
|
||||
'InsertChunksRequest',
|
||||
'QueryChunksRequest',
|
||||
'QueryChunksResponse',
|
||||
'VectorStoreFileCounts',
|
||||
'VectorStoreListResponse',
|
||||
'VectorStoreObject',
|
||||
'VectorStoreChunkingStrategy',
|
||||
'VectorStoreChunkingStrategyAuto',
|
||||
'VectorStoreChunkingStrategyStatic',
|
||||
'VectorStoreChunkingStrategyStaticConfig',
|
||||
'OpenAICreateVectorStoreRequestWithExtraBody',
|
||||
'OpenaiUpdateVectorStoreRequest',
|
||||
'VectorStoreDeleteResponse',
|
||||
'OpenAICreateVectorStoreFileBatchRequestWithExtraBody',
|
||||
'VectorStoreFileBatchObject',
|
||||
'VectorStoreFileStatus',
|
||||
'VectorStoreFileLastError',
|
||||
'VectorStoreFileObject',
|
||||
'VectorStoreFilesListInBatchResponse',
|
||||
'VectorStoreListFilesResponse',
|
||||
'OpenaiAttachFileToVectorStoreRequest',
|
||||
'OpenaiUpdateVectorStoreFileRequest',
|
||||
'VectorStoreFileDeleteResponse',
|
||||
'bool',
|
||||
'VectorStoreContent',
|
||||
'VectorStoreFileContentResponse',
|
||||
'OpenaiSearchVectorStoreRequest',
|
||||
'VectorStoreSearchResponse',
|
||||
'VectorStoreSearchResponsePage',
|
||||
'VersionInfo',
|
||||
'AppendRowsRequest',
|
||||
'PaginatedResponse',
|
||||
'Dataset',
|
||||
'RowsDataSource',
|
||||
'URIDataSource',
|
||||
'ListDatasetsResponse',
|
||||
'Benchmark',
|
||||
'ListBenchmarksResponse',
|
||||
'BenchmarkConfig',
|
||||
'GreedySamplingStrategy',
|
||||
'ModelCandidate',
|
||||
'SamplingParams',
|
||||
'SystemMessage',
|
||||
'TopKSamplingStrategy',
|
||||
'TopPSamplingStrategy',
|
||||
'EvaluateRowsRequest',
|
||||
'EvaluateResponse',
|
||||
'RunEvalRequest',
|
||||
'Job',
|
||||
'RerankRequest',
|
||||
'RerankData',
|
||||
'RerankResponse',
|
||||
'Checkpoint',
|
||||
'PostTrainingJobArtifactsResponse',
|
||||
'PostTrainingMetric',
|
||||
'CancelTrainingJobRequest',
|
||||
'PostTrainingJobStatusResponse',
|
||||
'ListPostTrainingJobsResponse',
|
||||
'DPOAlignmentConfig',
|
||||
'DPOLossType',
|
||||
'DataConfig',
|
||||
'DatasetFormat',
|
||||
'EfficiencyConfig',
|
||||
'OptimizerConfig',
|
||||
'OptimizerType',
|
||||
'TrainingConfig',
|
||||
'PreferenceOptimizeRequest',
|
||||
'PostTrainingJob',
|
||||
'AlgorithmConfig',
|
||||
'LoraFinetuningConfig',
|
||||
'QATFinetuningConfig',
|
||||
'SupervisedFineTuneRequest',
|
||||
'RegisterModelRequest',
|
||||
'ParamType',
|
||||
'RegisterScoringFunctionRequest',
|
||||
'RegisterShieldRequest',
|
||||
'RegisterToolGroupRequest',
|
||||
'DataSource',
|
||||
'RegisterDatasetRequest',
|
||||
'RegisterBenchmarkRequest']
|
||||
LEGACY_SCHEMA_ORDER = [
|
||||
"Error",
|
||||
"ListBatchesResponse",
|
||||
"CreateBatchRequest",
|
||||
"Batch",
|
||||
"Order",
|
||||
"ListOpenAIChatCompletionResponse",
|
||||
"OpenAIAssistantMessageParam",
|
||||
"OpenAIChatCompletionContentPartImageParam",
|
||||
"OpenAIChatCompletionContentPartParam",
|
||||
"OpenAIChatCompletionContentPartTextParam",
|
||||
"OpenAIChatCompletionToolCall",
|
||||
"OpenAIChatCompletionToolCallFunction",
|
||||
"OpenAIChatCompletionUsage",
|
||||
"OpenAIChoice",
|
||||
"OpenAIChoiceLogprobs",
|
||||
"OpenAIDeveloperMessageParam",
|
||||
"OpenAIFile",
|
||||
"OpenAIFileFile",
|
||||
"OpenAIImageURL",
|
||||
"OpenAIMessageParam",
|
||||
"OpenAISystemMessageParam",
|
||||
"OpenAITokenLogProb",
|
||||
"OpenAIToolMessageParam",
|
||||
"OpenAITopLogProb",
|
||||
"OpenAIUserMessageParam",
|
||||
"OpenAIJSONSchema",
|
||||
"OpenAIResponseFormatJSONObject",
|
||||
"OpenAIResponseFormatJSONSchema",
|
||||
"OpenAIResponseFormatParam",
|
||||
"OpenAIResponseFormatText",
|
||||
"OpenAIChatCompletionRequestWithExtraBody",
|
||||
"OpenAIChatCompletion",
|
||||
"OpenAIChatCompletionChunk",
|
||||
"OpenAIChoiceDelta",
|
||||
"OpenAIChunkChoice",
|
||||
"OpenAICompletionWithInputMessages",
|
||||
"OpenAICompletionRequestWithExtraBody",
|
||||
"OpenAICompletion",
|
||||
"OpenAICompletionChoice",
|
||||
"ConversationItem",
|
||||
"OpenAIResponseAnnotationCitation",
|
||||
"OpenAIResponseAnnotationContainerFileCitation",
|
||||
"OpenAIResponseAnnotationFileCitation",
|
||||
"OpenAIResponseAnnotationFilePath",
|
||||
"OpenAIResponseAnnotations",
|
||||
"OpenAIResponseContentPartRefusal",
|
||||
"OpenAIResponseInputFunctionToolCallOutput",
|
||||
"OpenAIResponseInputMessageContent",
|
||||
"OpenAIResponseInputMessageContentFile",
|
||||
"OpenAIResponseInputMessageContentImage",
|
||||
"OpenAIResponseInputMessageContentText",
|
||||
"OpenAIResponseMCPApprovalRequest",
|
||||
"OpenAIResponseMCPApprovalResponse",
|
||||
"OpenAIResponseMessage",
|
||||
"OpenAIResponseOutputMessageContent",
|
||||
"OpenAIResponseOutputMessageContentOutputText",
|
||||
"OpenAIResponseOutputMessageFileSearchToolCall",
|
||||
"OpenAIResponseOutputMessageFunctionToolCall",
|
||||
"OpenAIResponseOutputMessageMCPCall",
|
||||
"OpenAIResponseOutputMessageMCPListTools",
|
||||
"OpenAIResponseOutputMessageWebSearchToolCall",
|
||||
"CreateConversationRequest",
|
||||
"Conversation",
|
||||
"UpdateConversationRequest",
|
||||
"ConversationDeletedResource",
|
||||
"ConversationItemList",
|
||||
"AddItemsRequest",
|
||||
"ConversationItemDeletedResource",
|
||||
"OpenAIEmbeddingsRequestWithExtraBody",
|
||||
"OpenAIEmbeddingData",
|
||||
"OpenAIEmbeddingUsage",
|
||||
"OpenAIEmbeddingsResponse",
|
||||
"OpenAIFilePurpose",
|
||||
"ListOpenAIFileResponse",
|
||||
"OpenAIFileObject",
|
||||
"ExpiresAfter",
|
||||
"OpenAIFileDeleteResponse",
|
||||
"Response",
|
||||
"HealthInfo",
|
||||
"RouteInfo",
|
||||
"ListRoutesResponse",
|
||||
"OpenAIModel",
|
||||
"OpenAIListModelsResponse",
|
||||
"Model",
|
||||
"ModelType",
|
||||
"RunModerationRequest",
|
||||
"ModerationObject",
|
||||
"ModerationObjectResults",
|
||||
"Prompt",
|
||||
"ListPromptsResponse",
|
||||
"CreatePromptRequest",
|
||||
"UpdatePromptRequest",
|
||||
"SetDefaultVersionRequest",
|
||||
"ProviderInfo",
|
||||
"ListProvidersResponse",
|
||||
"ListOpenAIResponseObject",
|
||||
"OpenAIResponseError",
|
||||
"OpenAIResponseInput",
|
||||
"OpenAIResponseInputToolFileSearch",
|
||||
"OpenAIResponseInputToolFunction",
|
||||
"OpenAIResponseInputToolWebSearch",
|
||||
"OpenAIResponseObjectWithInput",
|
||||
"OpenAIResponseOutput",
|
||||
"OpenAIResponsePrompt",
|
||||
"OpenAIResponseText",
|
||||
"OpenAIResponseTool",
|
||||
"OpenAIResponseToolMCP",
|
||||
"OpenAIResponseUsage",
|
||||
"ResponseGuardrailSpec",
|
||||
"OpenAIResponseInputTool",
|
||||
"OpenAIResponseInputToolMCP",
|
||||
"CreateOpenaiResponseRequest",
|
||||
"OpenAIResponseObject",
|
||||
"OpenAIResponseContentPartOutputText",
|
||||
"OpenAIResponseContentPartReasoningSummary",
|
||||
"OpenAIResponseContentPartReasoningText",
|
||||
"OpenAIResponseObjectStream",
|
||||
"OpenAIResponseObjectStreamResponseCompleted",
|
||||
"OpenAIResponseObjectStreamResponseContentPartAdded",
|
||||
"OpenAIResponseObjectStreamResponseContentPartDone",
|
||||
"OpenAIResponseObjectStreamResponseCreated",
|
||||
"OpenAIResponseObjectStreamResponseFailed",
|
||||
"OpenAIResponseObjectStreamResponseFileSearchCallCompleted",
|
||||
"OpenAIResponseObjectStreamResponseFileSearchCallInProgress",
|
||||
"OpenAIResponseObjectStreamResponseFileSearchCallSearching",
|
||||
"OpenAIResponseObjectStreamResponseFunctionCallArgumentsDelta",
|
||||
"OpenAIResponseObjectStreamResponseFunctionCallArgumentsDone",
|
||||
"OpenAIResponseObjectStreamResponseInProgress",
|
||||
"OpenAIResponseObjectStreamResponseIncomplete",
|
||||
"OpenAIResponseObjectStreamResponseMcpCallArgumentsDelta",
|
||||
"OpenAIResponseObjectStreamResponseMcpCallArgumentsDone",
|
||||
"OpenAIResponseObjectStreamResponseMcpCallCompleted",
|
||||
"OpenAIResponseObjectStreamResponseMcpCallFailed",
|
||||
"OpenAIResponseObjectStreamResponseMcpCallInProgress",
|
||||
"OpenAIResponseObjectStreamResponseMcpListToolsCompleted",
|
||||
"OpenAIResponseObjectStreamResponseMcpListToolsFailed",
|
||||
"OpenAIResponseObjectStreamResponseMcpListToolsInProgress",
|
||||
"OpenAIResponseObjectStreamResponseOutputItemAdded",
|
||||
"OpenAIResponseObjectStreamResponseOutputItemDone",
|
||||
"OpenAIResponseObjectStreamResponseOutputTextAnnotationAdded",
|
||||
"OpenAIResponseObjectStreamResponseOutputTextDelta",
|
||||
"OpenAIResponseObjectStreamResponseOutputTextDone",
|
||||
"OpenAIResponseObjectStreamResponseReasoningSummaryPartAdded",
|
||||
"OpenAIResponseObjectStreamResponseReasoningSummaryPartDone",
|
||||
"OpenAIResponseObjectStreamResponseReasoningSummaryTextDelta",
|
||||
"OpenAIResponseObjectStreamResponseReasoningSummaryTextDone",
|
||||
"OpenAIResponseObjectStreamResponseReasoningTextDelta",
|
||||
"OpenAIResponseObjectStreamResponseReasoningTextDone",
|
||||
"OpenAIResponseObjectStreamResponseRefusalDelta",
|
||||
"OpenAIResponseObjectStreamResponseRefusalDone",
|
||||
"OpenAIResponseObjectStreamResponseWebSearchCallCompleted",
|
||||
"OpenAIResponseObjectStreamResponseWebSearchCallInProgress",
|
||||
"OpenAIResponseObjectStreamResponseWebSearchCallSearching",
|
||||
"OpenAIDeleteResponseObject",
|
||||
"ListOpenAIResponseInputItem",
|
||||
"RunShieldRequest",
|
||||
"RunShieldResponse",
|
||||
"SafetyViolation",
|
||||
"ViolationLevel",
|
||||
"AggregationFunctionType",
|
||||
"ArrayType",
|
||||
"BasicScoringFnParams",
|
||||
"BooleanType",
|
||||
"ChatCompletionInputType",
|
||||
"CompletionInputType",
|
||||
"JsonType",
|
||||
"LLMAsJudgeScoringFnParams",
|
||||
"NumberType",
|
||||
"ObjectType",
|
||||
"RegexParserScoringFnParams",
|
||||
"ScoringFn",
|
||||
"ScoringFnParams",
|
||||
"ScoringFnParamsType",
|
||||
"StringType",
|
||||
"UnionType",
|
||||
"ListScoringFunctionsResponse",
|
||||
"ScoreRequest",
|
||||
"ScoreResponse",
|
||||
"ScoringResult",
|
||||
"ScoreBatchRequest",
|
||||
"ScoreBatchResponse",
|
||||
"Shield",
|
||||
"ListShieldsResponse",
|
||||
"InvokeToolRequest",
|
||||
"ImageContentItem",
|
||||
"InterleavedContent",
|
||||
"InterleavedContentItem",
|
||||
"TextContentItem",
|
||||
"ToolInvocationResult",
|
||||
"URL",
|
||||
"ToolDef",
|
||||
"ListToolDefsResponse",
|
||||
"ToolGroup",
|
||||
"ListToolGroupsResponse",
|
||||
"Chunk",
|
||||
"ChunkMetadata",
|
||||
"InsertChunksRequest",
|
||||
"QueryChunksRequest",
|
||||
"QueryChunksResponse",
|
||||
"VectorStoreFileCounts",
|
||||
"VectorStoreListResponse",
|
||||
"VectorStoreObject",
|
||||
"VectorStoreChunkingStrategy",
|
||||
"VectorStoreChunkingStrategyAuto",
|
||||
"VectorStoreChunkingStrategyStatic",
|
||||
"VectorStoreChunkingStrategyStaticConfig",
|
||||
"OpenAICreateVectorStoreRequestWithExtraBody",
|
||||
"OpenaiUpdateVectorStoreRequest",
|
||||
"VectorStoreDeleteResponse",
|
||||
"OpenAICreateVectorStoreFileBatchRequestWithExtraBody",
|
||||
"VectorStoreFileBatchObject",
|
||||
"VectorStoreFileStatus",
|
||||
"VectorStoreFileLastError",
|
||||
"VectorStoreFileObject",
|
||||
"VectorStoreFilesListInBatchResponse",
|
||||
"VectorStoreListFilesResponse",
|
||||
"OpenaiAttachFileToVectorStoreRequest",
|
||||
"OpenaiUpdateVectorStoreFileRequest",
|
||||
"VectorStoreFileDeleteResponse",
|
||||
"bool",
|
||||
"VectorStoreContent",
|
||||
"VectorStoreFileContentResponse",
|
||||
"OpenaiSearchVectorStoreRequest",
|
||||
"VectorStoreSearchResponse",
|
||||
"VectorStoreSearchResponsePage",
|
||||
"VersionInfo",
|
||||
"AppendRowsRequest",
|
||||
"PaginatedResponse",
|
||||
"Dataset",
|
||||
"RowsDataSource",
|
||||
"URIDataSource",
|
||||
"ListDatasetsResponse",
|
||||
"Benchmark",
|
||||
"ListBenchmarksResponse",
|
||||
"BenchmarkConfig",
|
||||
"GreedySamplingStrategy",
|
||||
"ModelCandidate",
|
||||
"SamplingParams",
|
||||
"SystemMessage",
|
||||
"TopKSamplingStrategy",
|
||||
"TopPSamplingStrategy",
|
||||
"EvaluateRowsRequest",
|
||||
"EvaluateResponse",
|
||||
"RunEvalRequest",
|
||||
"Job",
|
||||
"RerankRequest",
|
||||
"RerankData",
|
||||
"RerankResponse",
|
||||
"Checkpoint",
|
||||
"PostTrainingJobArtifactsResponse",
|
||||
"PostTrainingMetric",
|
||||
"CancelTrainingJobRequest",
|
||||
"PostTrainingJobStatusResponse",
|
||||
"ListPostTrainingJobsResponse",
|
||||
"DPOAlignmentConfig",
|
||||
"DPOLossType",
|
||||
"DataConfig",
|
||||
"DatasetFormat",
|
||||
"EfficiencyConfig",
|
||||
"OptimizerConfig",
|
||||
"OptimizerType",
|
||||
"TrainingConfig",
|
||||
"PreferenceOptimizeRequest",
|
||||
"PostTrainingJob",
|
||||
"AlgorithmConfig",
|
||||
"LoraFinetuningConfig",
|
||||
"QATFinetuningConfig",
|
||||
"SupervisedFineTuneRequest",
|
||||
"RegisterModelRequest",
|
||||
"ParamType",
|
||||
"RegisterScoringFunctionRequest",
|
||||
"RegisterShieldRequest",
|
||||
"RegisterToolGroupRequest",
|
||||
"DataSource",
|
||||
"RegisterDatasetRequest",
|
||||
"RegisterBenchmarkRequest",
|
||||
]
|
||||
|
||||
LEGACY_RESPONSE_ORDER = ['BadRequest400', 'TooManyRequests429', 'InternalServerError500', 'DefaultError']
|
||||
LEGACY_RESPONSE_ORDER = ["BadRequest400", "TooManyRequests429", "InternalServerError500", "DefaultError"]
|
||||
|
||||
LEGACY_TAGS = [{'description': 'APIs for creating and interacting with agentic systems.',
|
||||
'name': 'Agents',
|
||||
'x-displayName': 'Agents'},
|
||||
{'description': 'The API is designed to allow use of openai client libraries for seamless integration.\n'
|
||||
'\n'
|
||||
'This API provides the following extensions:\n'
|
||||
' - idempotent batch creation\n'
|
||||
'\n'
|
||||
'Note: This API is currently under active development and may undergo changes.',
|
||||
'name': 'Batches',
|
||||
'x-displayName': 'The Batches API enables efficient processing of multiple requests in a single operation, '
|
||||
'particularly useful for processing large datasets, batch evaluation workflows, and cost-effective '
|
||||
'inference at scale.'},
|
||||
{'description': '', 'name': 'Benchmarks'},
|
||||
{'description': 'Protocol for conversation management operations.',
|
||||
'name': 'Conversations',
|
||||
'x-displayName': 'Conversations'},
|
||||
{'description': '', 'name': 'DatasetIO'},
|
||||
{'description': '', 'name': 'Datasets'},
|
||||
{'description': 'Llama Stack Evaluation API for running evaluations on model and agent candidates.',
|
||||
'name': 'Eval',
|
||||
'x-displayName': 'Evaluations'},
|
||||
{'description': 'This API is used to upload documents that can be used with other Llama Stack APIs.',
|
||||
'name': 'Files',
|
||||
'x-displayName': 'Files'},
|
||||
{'description': 'Llama Stack Inference API for generating completions, chat completions, and embeddings.\n'
|
||||
'\n'
|
||||
'This API provides the raw interface to the underlying models. Three kinds of models are supported:\n'
|
||||
'- LLM models: these models generate "raw" and "chat" (conversational) completions.\n'
|
||||
'- Embedding models: these models generate embeddings to be used for semantic search.\n'
|
||||
'- Rerank models: these models reorder the documents based on their relevance to a query.',
|
||||
'name': 'Inference',
|
||||
'x-displayName': 'Inference'},
|
||||
{'description': 'APIs for inspecting the Llama Stack service, including health status, available API routes with '
|
||||
'methods and implementing providers.',
|
||||
'name': 'Inspect',
|
||||
'x-displayName': 'Inspect'},
|
||||
{'description': '', 'name': 'Models'},
|
||||
{'description': '', 'name': 'PostTraining (Coming Soon)'},
|
||||
{'description': 'Protocol for prompt management operations.', 'name': 'Prompts', 'x-displayName': 'Prompts'},
|
||||
{'description': 'Providers API for inspecting, listing, and modifying providers and their configurations.',
|
||||
'name': 'Providers',
|
||||
'x-displayName': 'Providers'},
|
||||
{'description': 'OpenAI-compatible Moderations API.', 'name': 'Safety', 'x-displayName': 'Safety'},
|
||||
{'description': '', 'name': 'Scoring'},
|
||||
{'description': '', 'name': 'ScoringFunctions'},
|
||||
{'description': '', 'name': 'Shields'},
|
||||
{'description': '', 'name': 'ToolGroups'},
|
||||
{'description': '', 'name': 'ToolRuntime'},
|
||||
{'description': '', 'name': 'VectorIO'}]
|
||||
LEGACY_TAGS = [
|
||||
{
|
||||
"description": "APIs for creating and interacting with agentic systems.",
|
||||
"name": "Agents",
|
||||
"x-displayName": "Agents",
|
||||
},
|
||||
{
|
||||
"description": "The API is designed to allow use of openai client libraries for seamless integration.\n"
|
||||
"\n"
|
||||
"This API provides the following extensions:\n"
|
||||
" - idempotent batch creation\n"
|
||||
"\n"
|
||||
"Note: This API is currently under active development and may undergo changes.",
|
||||
"name": "Batches",
|
||||
"x-displayName": "The Batches API enables efficient processing of multiple requests in a single operation, "
|
||||
"particularly useful for processing large datasets, batch evaluation workflows, and cost-effective "
|
||||
"inference at scale.",
|
||||
},
|
||||
{"description": "", "name": "Benchmarks"},
|
||||
{
|
||||
"description": "Protocol for conversation management operations.",
|
||||
"name": "Conversations",
|
||||
"x-displayName": "Conversations",
|
||||
},
|
||||
{"description": "", "name": "DatasetIO"},
|
||||
{"description": "", "name": "Datasets"},
|
||||
{
|
||||
"description": "Llama Stack Evaluation API for running evaluations on model and agent candidates.",
|
||||
"name": "Eval",
|
||||
"x-displayName": "Evaluations",
|
||||
},
|
||||
{
|
||||
"description": "This API is used to upload documents that can be used with other Llama Stack APIs.",
|
||||
"name": "Files",
|
||||
"x-displayName": "Files",
|
||||
},
|
||||
{
|
||||
"description": "Llama Stack Inference API for generating completions, chat completions, and embeddings.\n"
|
||||
"\n"
|
||||
"This API provides the raw interface to the underlying models. Three kinds of models are supported:\n"
|
||||
'- LLM models: these models generate "raw" and "chat" (conversational) completions.\n'
|
||||
"- Embedding models: these models generate embeddings to be used for semantic search.\n"
|
||||
"- Rerank models: these models reorder the documents based on their relevance to a query.",
|
||||
"name": "Inference",
|
||||
"x-displayName": "Inference",
|
||||
},
|
||||
{
|
||||
"description": "APIs for inspecting the Llama Stack service, including health status, available API routes with "
|
||||
"methods and implementing providers.",
|
||||
"name": "Inspect",
|
||||
"x-displayName": "Inspect",
|
||||
},
|
||||
{"description": "", "name": "Models"},
|
||||
{"description": "", "name": "PostTraining (Coming Soon)"},
|
||||
{"description": "Protocol for prompt management operations.", "name": "Prompts", "x-displayName": "Prompts"},
|
||||
{
|
||||
"description": "Providers API for inspecting, listing, and modifying providers and their configurations.",
|
||||
"name": "Providers",
|
||||
"x-displayName": "Providers",
|
||||
},
|
||||
{"description": "OpenAI-compatible Moderations API.", "name": "Safety", "x-displayName": "Safety"},
|
||||
{"description": "", "name": "Scoring"},
|
||||
{"description": "", "name": "ScoringFunctions"},
|
||||
{"description": "", "name": "Shields"},
|
||||
{"description": "", "name": "ToolGroups"},
|
||||
{"description": "", "name": "ToolRuntime"},
|
||||
{"description": "", "name": "VectorIO"},
|
||||
]
|
||||
|
||||
LEGACY_TAG_ORDER = ['Agents',
|
||||
'Batches',
|
||||
'Benchmarks',
|
||||
'Conversations',
|
||||
'DatasetIO',
|
||||
'Datasets',
|
||||
'Eval',
|
||||
'Files',
|
||||
'Inference',
|
||||
'Inspect',
|
||||
'Models',
|
||||
'PostTraining (Coming Soon)',
|
||||
'Prompts',
|
||||
'Providers',
|
||||
'Safety',
|
||||
'Scoring',
|
||||
'ScoringFunctions',
|
||||
'Shields',
|
||||
'ToolGroups',
|
||||
'ToolRuntime',
|
||||
'VectorIO']
|
||||
LEGACY_TAG_ORDER = [
|
||||
"Agents",
|
||||
"Batches",
|
||||
"Benchmarks",
|
||||
"Conversations",
|
||||
"DatasetIO",
|
||||
"Datasets",
|
||||
"Eval",
|
||||
"Files",
|
||||
"Inference",
|
||||
"Inspect",
|
||||
"Models",
|
||||
"PostTraining (Coming Soon)",
|
||||
"Prompts",
|
||||
"Providers",
|
||||
"Safety",
|
||||
"Scoring",
|
||||
"ScoringFunctions",
|
||||
"Shields",
|
||||
"ToolGroups",
|
||||
"ToolRuntime",
|
||||
"VectorIO",
|
||||
]
|
||||
|
||||
LEGACY_TAG_GROUPS = [{'name': 'Operations',
|
||||
'tags': ['Agents',
|
||||
'Batches',
|
||||
'Benchmarks',
|
||||
'Conversations',
|
||||
'DatasetIO',
|
||||
'Datasets',
|
||||
'Eval',
|
||||
'Files',
|
||||
'Inference',
|
||||
'Inspect',
|
||||
'Models',
|
||||
'PostTraining (Coming Soon)',
|
||||
'Prompts',
|
||||
'Providers',
|
||||
'Safety',
|
||||
'Scoring',
|
||||
'ScoringFunctions',
|
||||
'Shields',
|
||||
'ToolGroups',
|
||||
'ToolRuntime',
|
||||
'VectorIO']}]
|
||||
LEGACY_TAG_GROUPS = [
|
||||
{
|
||||
"name": "Operations",
|
||||
"tags": [
|
||||
"Agents",
|
||||
"Batches",
|
||||
"Benchmarks",
|
||||
"Conversations",
|
||||
"DatasetIO",
|
||||
"Datasets",
|
||||
"Eval",
|
||||
"Files",
|
||||
"Inference",
|
||||
"Inspect",
|
||||
"Models",
|
||||
"PostTraining (Coming Soon)",
|
||||
"Prompts",
|
||||
"Providers",
|
||||
"Safety",
|
||||
"Scoring",
|
||||
"ScoringFunctions",
|
||||
"Shields",
|
||||
"ToolGroups",
|
||||
"ToolRuntime",
|
||||
"VectorIO",
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
LEGACY_SECURITY = [{'Default': []}]
|
||||
LEGACY_SECURITY = [{"Default": []}]
|
||||
|
||||
LEGACY_OPERATION_KEYS = [
|
||||
'responses',
|
||||
'tags',
|
||||
'summary',
|
||||
'description',
|
||||
'operationId',
|
||||
'parameters',
|
||||
'requestBody',
|
||||
'deprecated',
|
||||
"responses",
|
||||
"tags",
|
||||
"summary",
|
||||
"description",
|
||||
"operationId",
|
||||
"parameters",
|
||||
"requestBody",
|
||||
"deprecated",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from pydantic import Field, create_model
|
|||
|
||||
from llama_stack.log import get_logger
|
||||
from llama_stack_api import Api
|
||||
from llama_stack_api.schema_utils import get_registered_schema_info
|
||||
|
||||
from . import app as app_module
|
||||
from .state import _extra_body_fields, register_dynamic_model
|
||||
|
|
@ -31,23 +32,16 @@ def _to_pascal_case(segment: str) -> str:
|
|||
return "".join(token.capitalize() for token in tokens if token)
|
||||
|
||||
|
||||
def _compose_request_model_name(webmethod, http_method: str, variant: str | None = None) -> str:
|
||||
segments = []
|
||||
level = (webmethod.level or "").lower()
|
||||
if level and level != "v1":
|
||||
segments.append(_to_pascal_case(str(webmethod.level)))
|
||||
for part in filter(None, webmethod.route.split("/")):
|
||||
lower_part = part.lower()
|
||||
if lower_part in {"v1", "v1alpha", "v1beta"}:
|
||||
continue
|
||||
if part.startswith("{"):
|
||||
param = part[1:].split(":", 1)[0]
|
||||
segments.append(f"By{_to_pascal_case(param)}")
|
||||
else:
|
||||
segments.append(_to_pascal_case(part))
|
||||
if not segments:
|
||||
segments.append("Root")
|
||||
base_name = "".join(segments) + http_method.title() + "Request"
|
||||
def _compose_request_model_name(api: Api, method_name: str, variant: str | None = None) -> str:
|
||||
"""Generate a deterministic model name from the protocol method."""
|
||||
|
||||
def _to_pascal_from_snake(value: str) -> str:
|
||||
return "".join(segment.capitalize() for segment in value.split("_") if segment)
|
||||
|
||||
base_name = _to_pascal_from_snake(method_name)
|
||||
if not base_name:
|
||||
base_name = _to_pascal_case(api.value)
|
||||
base_name = f"{base_name}Request"
|
||||
if variant:
|
||||
base_name = f"{base_name}{variant}"
|
||||
return base_name
|
||||
|
|
@ -130,6 +124,7 @@ def _build_field_definitions(query_parameters: list[tuple[str, type, Any]], use_
|
|||
def _create_dynamic_request_model(
|
||||
api: Api,
|
||||
webmethod,
|
||||
method_name: str,
|
||||
http_method: str,
|
||||
query_parameters: list[tuple[str, type, Any]],
|
||||
use_any: bool = False,
|
||||
|
|
@ -140,7 +135,7 @@ def _create_dynamic_request_model(
|
|||
field_definitions = _build_field_definitions(query_parameters, use_any)
|
||||
if not field_definitions:
|
||||
return None
|
||||
model_name = _compose_request_model_name(webmethod, http_method, variant_suffix)
|
||||
model_name = _compose_request_model_name(api, method_name, variant_suffix or None)
|
||||
request_model = create_model(model_name, **field_definitions)
|
||||
return register_dynamic_model(model_name, request_model)
|
||||
except Exception:
|
||||
|
|
@ -261,9 +256,7 @@ def _extract_response_models_from_union(union_type: Any) -> tuple[type | None, t
|
|||
streaming_model = inner_type
|
||||
else:
|
||||
# Might be a registered schema - check if it's registered
|
||||
from llama_stack_api.schema_utils import _registered_schemas
|
||||
|
||||
if inner_type in _registered_schemas:
|
||||
if get_registered_schema_info(inner_type):
|
||||
# We'll need to look this up later, but for now store the type
|
||||
streaming_model = inner_type
|
||||
elif hasattr(arg, "model_json_schema"):
|
||||
|
|
@ -427,17 +420,28 @@ def _find_models_for_endpoint(
|
|||
try:
|
||||
from fastapi import Response as FastAPIResponse
|
||||
except ImportError:
|
||||
FastAPIResponse = None
|
||||
fastapi_response_cls = None
|
||||
else:
|
||||
fastapi_response_cls = FastAPIResponse
|
||||
try:
|
||||
from starlette.responses import Response as StarletteResponse
|
||||
except ImportError:
|
||||
StarletteResponse = None
|
||||
starlette_response_cls = None
|
||||
else:
|
||||
starlette_response_cls = StarletteResponse
|
||||
|
||||
response_types = tuple(t for t in (FastAPIResponse, StarletteResponse) if t is not None)
|
||||
response_types = tuple(t for t in (fastapi_response_cls, starlette_response_cls) if t is not None)
|
||||
if response_types and any(return_annotation is t for t in response_types):
|
||||
response_schema_name = "Response"
|
||||
|
||||
return request_model, response_model, query_parameters, file_form_params, streaming_response_model, response_schema_name
|
||||
return (
|
||||
request_model,
|
||||
response_model,
|
||||
query_parameters,
|
||||
file_form_params,
|
||||
streaming_response_model,
|
||||
response_schema_name,
|
||||
)
|
||||
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
|
|
@ -465,9 +469,7 @@ def _create_fastapi_endpoint(app: FastAPI, route, webmethod, api: Api):
|
|||
file_form_params,
|
||||
streaming_response_model,
|
||||
response_schema_name,
|
||||
) = (
|
||||
_find_models_for_endpoint(webmethod, api, name, is_post_put)
|
||||
)
|
||||
) = _find_models_for_endpoint(webmethod, api, name, is_post_put)
|
||||
operation_description = _extract_operation_description_from_docstring(api, name)
|
||||
response_description = _extract_response_description_from_docstring(webmethod, response_model, api, name)
|
||||
|
||||
|
|
@ -479,6 +481,17 @@ def _create_fastapi_endpoint(app: FastAPI, route, webmethod, api: Api):
|
|||
key = (fastapi_path, method.upper())
|
||||
_extra_body_fields[key] = extra_body_params
|
||||
|
||||
if is_post_put and not request_model and not file_form_params and query_parameters:
|
||||
request_model = _create_dynamic_request_model(
|
||||
api, webmethod, name, primary_method, query_parameters, use_any=False
|
||||
)
|
||||
if not request_model:
|
||||
request_model = _create_dynamic_request_model(
|
||||
api, webmethod, name, primary_method, query_parameters, use_any=True, variant_suffix="Loose"
|
||||
)
|
||||
if request_model:
|
||||
query_parameters = []
|
||||
|
||||
if file_form_params and is_post_put:
|
||||
signature_params = list(file_form_params)
|
||||
param_annotations = {param.name: param.annotation for param in file_form_params}
|
||||
|
|
@ -503,12 +516,16 @@ def _create_fastapi_endpoint(app: FastAPI, route, webmethod, api: Api):
|
|||
endpoint_func = file_form_endpoint
|
||||
elif request_model and response_model:
|
||||
endpoint_func = _create_endpoint_with_request_model(request_model, response_model, operation_description)
|
||||
elif request_model:
|
||||
endpoint_func = _create_endpoint_with_request_model(request_model, None, operation_description)
|
||||
elif response_model and query_parameters:
|
||||
if is_post_put:
|
||||
request_model = _create_dynamic_request_model(api, webmethod, primary_method, query_parameters, use_any=False)
|
||||
request_model = _create_dynamic_request_model(
|
||||
api, webmethod, name, primary_method, query_parameters, use_any=False
|
||||
)
|
||||
if not request_model:
|
||||
request_model = _create_dynamic_request_model(
|
||||
api, webmethod, primary_method, query_parameters, use_any=True, variant_suffix="Loose"
|
||||
api, webmethod, name, primary_method, query_parameters, use_any=True, variant_suffix="Loose"
|
||||
)
|
||||
|
||||
if request_model:
|
||||
|
|
@ -600,10 +617,8 @@ def _create_fastapi_endpoint(app: FastAPI, route, webmethod, api: Api):
|
|||
streaming_schema_name = None
|
||||
# Check if it's a registered schema first (before checking __name__)
|
||||
# because registered schemas might be Annotated types
|
||||
from llama_stack_api.schema_utils import _registered_schemas
|
||||
|
||||
if streaming_response_model in _registered_schemas:
|
||||
streaming_schema_name = _registered_schemas[streaming_response_model]["name"]
|
||||
if schema_info := get_registered_schema_info(streaming_response_model):
|
||||
streaming_schema_name = schema_info.name
|
||||
elif hasattr(streaming_response_model, "__name__"):
|
||||
streaming_schema_name = streaming_response_model.__name__
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,8 @@ Schema discovery and collection for OpenAPI generation.
|
|||
"""
|
||||
|
||||
import importlib
|
||||
import pkgutil
|
||||
from typing import Any
|
||||
|
||||
from .state import _dynamic_models
|
||||
|
||||
|
||||
def _ensure_components_schemas(openapi_schema: dict[str, Any]) -> None:
|
||||
"""Ensure components.schemas exists in the schema."""
|
||||
|
|
@ -23,54 +20,21 @@ def _ensure_components_schemas(openapi_schema: dict[str, Any]) -> None:
|
|||
openapi_schema["components"]["schemas"] = {}
|
||||
|
||||
|
||||
def _import_all_modules_in_package(package_name: str) -> list[Any]:
|
||||
def _load_extra_schema_modules() -> None:
|
||||
"""
|
||||
Dynamically import all modules in a package to trigger register_schema calls.
|
||||
Import modules outside llama_stack_api that use schema_utils to register schemas.
|
||||
|
||||
This walks through all modules in the package and imports them, ensuring
|
||||
that any register_schema() calls at module level are executed.
|
||||
|
||||
Args:
|
||||
package_name: The fully qualified package name (e.g., 'llama_stack_api')
|
||||
|
||||
Returns:
|
||||
List of imported module objects
|
||||
The API package already imports its submodules via __init__, but server-side modules
|
||||
like telemetry need to be imported explicitly so their decorator side effects run.
|
||||
"""
|
||||
modules = []
|
||||
try:
|
||||
package = importlib.import_module(package_name)
|
||||
except ImportError:
|
||||
return modules
|
||||
|
||||
package_path = getattr(package, "__path__", None)
|
||||
if not package_path:
|
||||
return modules
|
||||
|
||||
# Walk packages and modules recursively
|
||||
for _, modname, ispkg in pkgutil.walk_packages(package_path, prefix=f"{package_name}."):
|
||||
if not modname.startswith("_"):
|
||||
try:
|
||||
module = importlib.import_module(modname)
|
||||
modules.append(module)
|
||||
|
||||
# If this is a package, also try to import any .py files directly
|
||||
# (e.g., llama_stack_api.scoring_functions.scoring_functions)
|
||||
if ispkg:
|
||||
try:
|
||||
# Try importing the module file with the same name as the package
|
||||
# This handles cases like scoring_functions/scoring_functions.py
|
||||
module_file_name = f"{modname}.{modname.split('.')[-1]}"
|
||||
module_file = importlib.import_module(module_file_name)
|
||||
if module_file not in modules:
|
||||
modules.append(module_file)
|
||||
except (ImportError, AttributeError, TypeError):
|
||||
# It's okay if this fails - not all packages have a module file with the same name
|
||||
pass
|
||||
except (ImportError, AttributeError, TypeError):
|
||||
# Skip modules that can't be imported (e.g., missing dependencies)
|
||||
continue
|
||||
|
||||
return modules
|
||||
extra_modules = [
|
||||
"llama_stack.core.telemetry.telemetry",
|
||||
]
|
||||
for module_name in extra_modules:
|
||||
try:
|
||||
importlib.import_module(module_name)
|
||||
except ImportError:
|
||||
continue
|
||||
|
||||
|
||||
def _extract_and_fix_defs(schema: dict[str, Any], openapi_schema: dict[str, Any]) -> None:
|
||||
|
|
@ -102,82 +66,66 @@ def _extract_and_fix_defs(schema: dict[str, Any], openapi_schema: dict[str, Any]
|
|||
|
||||
def _ensure_json_schema_types_included(openapi_schema: dict[str, Any]) -> dict[str, Any]:
|
||||
"""
|
||||
Ensure all @json_schema_type decorated models and registered schemas are included in the OpenAPI schema.
|
||||
This finds all models with the _llama_stack_schema_type attribute and schemas registered via register_schema.
|
||||
Ensure all registered schemas (decorated, explicit, and dynamic) are included in the OpenAPI schema.
|
||||
Relies on llama_stack_api's registry instead of recursively importing every module.
|
||||
"""
|
||||
_ensure_components_schemas(openapi_schema)
|
||||
|
||||
# Import TypeAdapter for handling union types and other non-model types
|
||||
from pydantic import TypeAdapter
|
||||
|
||||
# Dynamically import all modules in packages that might register schemas
|
||||
# This ensures register_schema() calls execute and populate _registered_schemas
|
||||
# Also collect the modules for later scanning of @json_schema_type decorated classes
|
||||
apis_modules = _import_all_modules_in_package("llama_stack_api")
|
||||
_import_all_modules_in_package("llama_stack.core.telemetry")
|
||||
from llama_stack_api.schema_utils import (
|
||||
iter_dynamic_schema_types,
|
||||
iter_json_schema_types,
|
||||
iter_registered_schema_types,
|
||||
)
|
||||
|
||||
# First, handle registered schemas (union types, etc.)
|
||||
from llama_stack_api.schema_utils import _registered_schemas
|
||||
# Import extra modules (e.g., telemetry) whose schema registrations live outside llama_stack_api
|
||||
_load_extra_schema_modules()
|
||||
|
||||
for schema_type, registration_info in _registered_schemas.items():
|
||||
schema_name = registration_info["name"]
|
||||
# Handle explicitly registered schemas first (union types, Annotated structs, etc.)
|
||||
for registration_info in iter_registered_schema_types():
|
||||
schema_type = registration_info.type
|
||||
schema_name = registration_info.name
|
||||
if schema_name not in openapi_schema["components"]["schemas"]:
|
||||
try:
|
||||
# Use TypeAdapter for union types and other non-model types
|
||||
# Use ref_template to generate references in the format we need
|
||||
adapter = TypeAdapter(schema_type)
|
||||
schema = adapter.json_schema(ref_template="#/components/schemas/{model}")
|
||||
|
||||
# Extract and fix $defs if present
|
||||
_extract_and_fix_defs(schema, openapi_schema)
|
||||
|
||||
openapi_schema["components"]["schemas"][schema_name] = schema
|
||||
except Exception as e:
|
||||
# Skip if we can't generate the schema
|
||||
print(f"Warning: Failed to generate schema for registered type {schema_name}: {e}")
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
continue
|
||||
|
||||
# Find all classes with the _llama_stack_schema_type attribute
|
||||
# Use the modules we already imported above
|
||||
for module in apis_modules:
|
||||
for attr_name in dir(module):
|
||||
# Add @json_schema_type decorated models
|
||||
for model in iter_json_schema_types():
|
||||
schema_name = getattr(model, "_llama_stack_schema_name", None) or getattr(model, "__name__", None)
|
||||
if not schema_name:
|
||||
continue
|
||||
if schema_name not in openapi_schema["components"]["schemas"]:
|
||||
try:
|
||||
attr = getattr(module, attr_name)
|
||||
if (
|
||||
hasattr(attr, "_llama_stack_schema_type")
|
||||
and hasattr(attr, "model_json_schema")
|
||||
and hasattr(attr, "__name__")
|
||||
):
|
||||
schema_name = attr.__name__
|
||||
if schema_name not in openapi_schema["components"]["schemas"]:
|
||||
try:
|
||||
# Use ref_template to ensure consistent reference format and $defs handling
|
||||
schema = attr.model_json_schema(ref_template="#/components/schemas/{model}")
|
||||
# Extract and fix $defs if present (model_json_schema can also generate $defs)
|
||||
_extract_and_fix_defs(schema, openapi_schema)
|
||||
openapi_schema["components"]["schemas"][schema_name] = schema
|
||||
except Exception as e:
|
||||
# Skip if we can't generate the schema
|
||||
print(f"Warning: Failed to generate schema for {schema_name}: {e}")
|
||||
continue
|
||||
except (AttributeError, TypeError):
|
||||
if hasattr(model, "model_json_schema"):
|
||||
schema = model.model_json_schema(ref_template="#/components/schemas/{model}")
|
||||
else:
|
||||
adapter = TypeAdapter(model)
|
||||
schema = adapter.json_schema(ref_template="#/components/schemas/{model}")
|
||||
_extract_and_fix_defs(schema, openapi_schema)
|
||||
openapi_schema["components"]["schemas"][schema_name] = schema
|
||||
except Exception as e:
|
||||
print(f"Warning: Failed to generate schema for {schema_name}: {e}")
|
||||
continue
|
||||
|
||||
# Also include any dynamic models that were created during endpoint generation
|
||||
# This is a workaround to ensure dynamic models appear in the schema
|
||||
for model in _dynamic_models:
|
||||
# Include any dynamic models generated while building endpoints
|
||||
for model in iter_dynamic_schema_types():
|
||||
try:
|
||||
schema_name = model.__name__
|
||||
if schema_name not in openapi_schema["components"]["schemas"]:
|
||||
schema = model.model_json_schema(ref_template="#/components/schemas/{model}")
|
||||
# Extract and fix $defs if present
|
||||
_extract_and_fix_defs(schema, openapi_schema)
|
||||
openapi_schema["components"]["schemas"][schema_name] = schema
|
||||
except Exception:
|
||||
# Skip if we can't generate the schema
|
||||
continue
|
||||
|
||||
return openapi_schema
|
||||
|
|
|
|||
|
|
@ -16,39 +16,6 @@ from llama_stack_api.version import (
|
|||
LLAMA_STACK_API_V1BETA,
|
||||
)
|
||||
|
||||
from . import schema_collection
|
||||
|
||||
|
||||
def _get_all_json_schema_type_names() -> set[str]:
|
||||
"""
|
||||
Get all schema names from @json_schema_type decorated models.
|
||||
This ensures they are included in filtered schemas even if not directly referenced by paths.
|
||||
"""
|
||||
schema_names = set()
|
||||
apis_modules = schema_collection._import_all_modules_in_package("llama_stack_api")
|
||||
for module in apis_modules:
|
||||
for attr_name in dir(module):
|
||||
try:
|
||||
attr = getattr(module, attr_name)
|
||||
if (
|
||||
hasattr(attr, "_llama_stack_schema_type")
|
||||
and hasattr(attr, "model_json_schema")
|
||||
and hasattr(attr, "__name__")
|
||||
):
|
||||
schema_names.add(attr.__name__)
|
||||
except (AttributeError, TypeError):
|
||||
continue
|
||||
return schema_names
|
||||
|
||||
|
||||
def _get_explicit_schema_names(openapi_schema: dict[str, Any]) -> set[str]:
|
||||
"""Get all registered schema names and @json_schema_type decorated model names."""
|
||||
from llama_stack_api.schema_utils import _registered_schemas
|
||||
|
||||
registered_schema_names = {info["name"] for info in _registered_schemas.values()}
|
||||
json_schema_type_names = _get_all_json_schema_type_names()
|
||||
return registered_schema_names | json_schema_type_names
|
||||
|
||||
|
||||
def _find_schema_refs_in_object(obj: Any) -> set[str]:
|
||||
"""
|
||||
|
|
@ -70,21 +37,12 @@ def _find_schema_refs_in_object(obj: Any) -> set[str]:
|
|||
return refs
|
||||
|
||||
|
||||
def _add_transitive_references(
|
||||
referenced_schemas: set[str], all_schemas: dict[str, Any], initial_schemas: set[str] | None = None
|
||||
) -> set[str]:
|
||||
def _add_transitive_references(referenced_schemas: set[str], all_schemas: dict[str, Any]) -> set[str]:
|
||||
"""Add transitive references for given schemas."""
|
||||
if initial_schemas:
|
||||
referenced_schemas.update(initial_schemas)
|
||||
additional_schemas = set()
|
||||
for schema_name in initial_schemas:
|
||||
if schema_name in all_schemas:
|
||||
additional_schemas.update(_find_schema_refs_in_object(all_schemas[schema_name]))
|
||||
else:
|
||||
additional_schemas = set()
|
||||
for schema_name in referenced_schemas:
|
||||
if schema_name in all_schemas:
|
||||
additional_schemas.update(_find_schema_refs_in_object(all_schemas[schema_name]))
|
||||
additional_schemas = set()
|
||||
for schema_name in referenced_schemas:
|
||||
if schema_name in all_schemas:
|
||||
additional_schemas.update(_find_schema_refs_in_object(all_schemas[schema_name]))
|
||||
|
||||
while additional_schemas:
|
||||
new_schemas = additional_schemas - referenced_schemas
|
||||
|
|
@ -155,8 +113,7 @@ def _filter_schemas_by_references(
|
|||
|
||||
referenced_schemas = _find_schemas_referenced_by_paths(filtered_paths, openapi_schema)
|
||||
all_schemas = openapi_schema.get("components", {}).get("schemas", {})
|
||||
explicit_schema_names = _get_explicit_schema_names(openapi_schema)
|
||||
referenced_schemas = _add_transitive_references(referenced_schemas, all_schemas, explicit_schema_names)
|
||||
referenced_schemas = _add_transitive_references(referenced_schemas, all_schemas)
|
||||
|
||||
filtered_schemas = {
|
||||
name: schema for name, schema in filtered_schema["components"]["schemas"].items() if name in referenced_schemas
|
||||
|
|
|
|||
|
|
@ -19,14 +19,13 @@ from openapi_spec_validator.exceptions import OpenAPISpecValidatorError
|
|||
|
||||
from . import endpoints, schema_collection
|
||||
from ._legacy_order import (
|
||||
LEGACY_OPERATION_KEYS,
|
||||
LEGACY_PATH_ORDER,
|
||||
LEGACY_RESPONSE_ORDER,
|
||||
LEGACY_SCHEMA_ORDER,
|
||||
LEGACY_OPERATION_KEYS,
|
||||
LEGACY_SECURITY,
|
||||
LEGACY_TAGS,
|
||||
LEGACY_TAG_GROUPS,
|
||||
LEGACY_TAG_ORDER,
|
||||
LEGACY_TAGS,
|
||||
)
|
||||
from .state import _extra_body_fields
|
||||
|
||||
|
|
@ -864,7 +863,15 @@ def _apply_legacy_sorting(openapi_schema: dict[str, Any]) -> dict[str, Any]:
|
|||
ordered_path_item[method] = order_mapping(path_item[method], LEGACY_OPERATION_KEYS)
|
||||
for key, value in path_item.items():
|
||||
if key not in ordered_path_item:
|
||||
if isinstance(value, dict) and key.lower() in {"get", "post", "put", "delete", "patch", "head", "options"}:
|
||||
if isinstance(value, dict) and key.lower() in {
|
||||
"get",
|
||||
"post",
|
||||
"put",
|
||||
"delete",
|
||||
"patch",
|
||||
"head",
|
||||
"options",
|
||||
}:
|
||||
ordered_path_item[key] = order_mapping(value, LEGACY_OPERATION_KEYS)
|
||||
else:
|
||||
ordered_path_item[key] = value
|
||||
|
|
|
|||
|
|
@ -11,9 +11,8 @@ Shared state for the OpenAPI generator module.
|
|||
from typing import Any
|
||||
|
||||
from llama_stack_api import Api
|
||||
from llama_stack_api.schema_utils import clear_dynamic_schema_types, register_dynamic_schema_type
|
||||
|
||||
# Global list to store dynamic models created during endpoint generation
|
||||
_dynamic_models: list[Any] = []
|
||||
_dynamic_model_registry: dict[str, type] = {}
|
||||
|
||||
# Cache for protocol methods to avoid repeated lookups
|
||||
|
|
@ -28,14 +27,15 @@ def register_dynamic_model(name: str, model: type) -> type:
|
|||
"""Register and deduplicate dynamically generated request models."""
|
||||
existing = _dynamic_model_registry.get(name)
|
||||
if existing is not None:
|
||||
register_dynamic_schema_type(existing)
|
||||
return existing
|
||||
_dynamic_model_registry[name] = model
|
||||
_dynamic_models.append(model)
|
||||
register_dynamic_schema_type(model)
|
||||
return model
|
||||
|
||||
|
||||
def reset_generator_state() -> None:
|
||||
"""Clear per-run caches so repeated generations stay deterministic."""
|
||||
_dynamic_models.clear()
|
||||
_dynamic_model_registry.clear()
|
||||
_extra_body_fields.clear()
|
||||
clear_dynamic_schema_types()
|
||||
|
|
|
|||
|
|
@ -353,8 +353,15 @@ from .safety import (
|
|||
from .schema_utils import (
|
||||
CallableT,
|
||||
ExtraBodyField,
|
||||
SchemaInfo,
|
||||
WebMethod,
|
||||
clear_dynamic_schema_types,
|
||||
get_registered_schema_info,
|
||||
iter_dynamic_schema_types,
|
||||
iter_json_schema_types,
|
||||
iter_registered_schema_types,
|
||||
json_schema_type,
|
||||
register_dynamic_schema_type,
|
||||
register_schema,
|
||||
webmethod,
|
||||
)
|
||||
|
|
@ -516,6 +523,7 @@ __all__ = [
|
|||
"ExtraBodyField",
|
||||
"Files",
|
||||
"Fp8QuantizationConfig",
|
||||
"clear_dynamic_schema_types",
|
||||
"get_schema_identifier",
|
||||
"get_signature",
|
||||
"GrammarResponseFormat",
|
||||
|
|
@ -536,6 +544,10 @@ __all__ = [
|
|||
"is_type_optional",
|
||||
"is_type_union",
|
||||
"is_unwrapped_body_param",
|
||||
"iter_dynamic_schema_types",
|
||||
"iter_json_schema_types",
|
||||
"iter_registered_schema_types",
|
||||
"get_registered_schema_info",
|
||||
"Job",
|
||||
"JobStatus",
|
||||
"json_dump_string",
|
||||
|
|
@ -738,6 +750,7 @@ __all__ = [
|
|||
"RAGQueryGeneratorConfig",
|
||||
"RAGQueryResult",
|
||||
"RAGSearchMode",
|
||||
"register_dynamic_schema_type",
|
||||
"register_schema",
|
||||
"RLHFAlgorithm",
|
||||
"RRFRanker",
|
||||
|
|
@ -775,6 +788,7 @@ __all__ = [
|
|||
"ScoringResult",
|
||||
"ScoringResultRow",
|
||||
"Schema",
|
||||
"SchemaInfo",
|
||||
"SchemaOptions",
|
||||
"SearchRankingOptions",
|
||||
"Shield",
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
# This source code is licensed under the terms described in the LICENSE file in
|
||||
# the root directory of this source tree.
|
||||
|
||||
from collections.abc import Callable
|
||||
from collections.abc import Callable, Iterable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, TypeVar
|
||||
from typing import Any, Literal, TypeVar
|
||||
|
||||
|
||||
class ExtraBodyField[T]:
|
||||
|
|
@ -46,6 +46,21 @@ class ExtraBodyField[T]:
|
|||
self.description = description
|
||||
|
||||
|
||||
SchemaSource = Literal["json_schema_type", "registered_schema", "dynamic_schema"]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SchemaInfo:
|
||||
"""Metadata describing a schema entry exposed to OpenAPI generation."""
|
||||
|
||||
name: str
|
||||
type: Any
|
||||
source: SchemaSource
|
||||
|
||||
|
||||
_json_schema_types: dict[type, SchemaInfo] = {}
|
||||
|
||||
|
||||
def json_schema_type(cls):
|
||||
"""
|
||||
Decorator to mark a Pydantic model for top-level component registration.
|
||||
|
|
@ -57,11 +72,15 @@ def json_schema_type(cls):
|
|||
for simple one-off types while keeping complex reusable types as components.
|
||||
"""
|
||||
cls._llama_stack_schema_type = True
|
||||
schema_name = getattr(cls, "__name__", f"Anonymous_{id(cls)}")
|
||||
cls._llama_stack_schema_name = schema_name
|
||||
_json_schema_types.setdefault(cls, SchemaInfo(name=schema_name, type=cls, source="json_schema_type"))
|
||||
return cls
|
||||
|
||||
|
||||
# Global registry for registered schemas
|
||||
_registered_schemas = {}
|
||||
# Global registries for schemas discoverable by the generator
|
||||
_registered_schemas: dict[Any, SchemaInfo] = {}
|
||||
_dynamic_schema_types: dict[type, SchemaInfo] = {}
|
||||
|
||||
|
||||
def register_schema(schema_type, name: str | None = None):
|
||||
|
|
@ -82,11 +101,43 @@ def register_schema(schema_type, name: str | None = None):
|
|||
|
||||
# Store the registration information in a global registry
|
||||
# since union types don't allow setting attributes
|
||||
_registered_schemas[schema_type] = {"name": name, "type": schema_type}
|
||||
_registered_schemas[schema_type] = SchemaInfo(name=name, type=schema_type, source="registered_schema")
|
||||
|
||||
return schema_type
|
||||
|
||||
|
||||
def get_registered_schema_info(schema_type: Any) -> SchemaInfo | None:
|
||||
"""Return the registration metadata for a schema type if present."""
|
||||
return _registered_schemas.get(schema_type)
|
||||
|
||||
|
||||
def iter_registered_schema_types() -> Iterable[SchemaInfo]:
|
||||
"""Iterate over all explicitly registered schema entries."""
|
||||
return tuple(_registered_schemas.values())
|
||||
|
||||
|
||||
def iter_json_schema_types() -> Iterable[type]:
|
||||
"""Iterate over all Pydantic models decorated with @json_schema_type."""
|
||||
return tuple(info.type for info in _json_schema_types.values())
|
||||
|
||||
|
||||
def iter_dynamic_schema_types() -> Iterable[type]:
|
||||
"""Iterate over dynamic models registered at generation time."""
|
||||
return tuple(info.type for info in _dynamic_schema_types.values())
|
||||
|
||||
|
||||
def register_dynamic_schema_type(schema_type: type, name: str | None = None) -> type:
|
||||
"""Register a dynamic model generated at runtime for schema inclusion."""
|
||||
schema_name = name if name is not None else getattr(schema_type, "__name__", f"Anonymous_{id(schema_type)}")
|
||||
_dynamic_schema_types[schema_type] = SchemaInfo(name=schema_name, type=schema_type, source="dynamic_schema")
|
||||
return schema_type
|
||||
|
||||
|
||||
def clear_dynamic_schema_types() -> None:
|
||||
"""Clear dynamic schema registrations."""
|
||||
_dynamic_schema_types.clear()
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebMethod:
|
||||
level: str | None = None
|
||||
|
|
|
|||
48
tests/unit/server/test_schema_registry.py
Normal file
48
tests/unit/server/test_schema_registry.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under the terms described in the LICENSE file in
|
||||
# the root directory of this source tree.
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from llama_stack_api import Conversation, SamplingStrategy
|
||||
from llama_stack_api.schema_utils import (
|
||||
clear_dynamic_schema_types,
|
||||
get_registered_schema_info,
|
||||
iter_dynamic_schema_types,
|
||||
iter_json_schema_types,
|
||||
iter_registered_schema_types,
|
||||
register_dynamic_schema_type,
|
||||
)
|
||||
|
||||
|
||||
def test_json_schema_registry_contains_known_model() -> None:
|
||||
assert Conversation in iter_json_schema_types()
|
||||
|
||||
|
||||
def test_registered_schema_registry_contains_sampling_strategy() -> None:
|
||||
registered_names = {info.name for info in iter_registered_schema_types()}
|
||||
assert "SamplingStrategy" in registered_names
|
||||
|
||||
schema_info = get_registered_schema_info(SamplingStrategy)
|
||||
assert schema_info is not None
|
||||
assert schema_info.name == "SamplingStrategy"
|
||||
|
||||
|
||||
def test_dynamic_schema_registration_round_trip() -> None:
|
||||
existing_models = tuple(iter_dynamic_schema_types())
|
||||
clear_dynamic_schema_types()
|
||||
try:
|
||||
|
||||
class TemporaryModel(BaseModel):
|
||||
foo: str
|
||||
|
||||
register_dynamic_schema_type(TemporaryModel)
|
||||
assert TemporaryModel in iter_dynamic_schema_types()
|
||||
|
||||
clear_dynamic_schema_types()
|
||||
assert TemporaryModel not in iter_dynamic_schema_types()
|
||||
finally:
|
||||
for model in existing_models:
|
||||
register_dynamic_schema_type(model)
|
||||
Loading…
Add table
Add a link
Reference in a new issue