diff --git a/docs/source/specs/openapi.json b/docs/source/specs/openapi.json index d952a79c9..df8a0652a 100644 --- a/docs/source/specs/openapi.json +++ b/docs/source/specs/openapi.json @@ -1 +1 @@ -{"openapi": "3.1.0", "info": {"title": "Lumigator Backend", "description": "Backend server", "version": "0.0.1"}, "paths": {"/api/v1/health/": {"get": {"tags": ["health"], "summary": "Get Health", "operationId": "get_health_api_v1_health__get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HealthResponse"}}}}}}}, "/api/v1/datasets/": {"post": {"tags": ["datasets"], "summary": "Upload Dataset", "description": "Uploads the dataset for use in Lumigator.\n\nAn uploaded dataset is parsed into HuggingFace format files and stored alongside a\nrecreated version of the input dataset.\n\nNOTE: The recreated version of the CSV file may not have identical delimiters as it will follow\nthe format that HuggingFace uses when it generates the CSV.", "operationId": "upload_dataset_api_v1_datasets__post", "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"$ref": "#/components/schemas/Body_upload_dataset_api_v1_datasets__post"}}}}, "responses": {"201": {"description": "Dataset successfully uploaded", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DatasetResponse"}}}}, "413": {"description": "Max dataset size (50MB)"}, "422": {"description": "Invalid CSV file"}}}, "get": {"tags": ["datasets"], "summary": "List Datasets", "operationId": "list_datasets_api_v1_datasets__get", "parameters": [{"name": "skip", "in": "query", "required": false, "schema": {"type": "integer", "default": 0, "title": "Skip"}}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer", "default": 100, "title": "Limit"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListingResponse_DatasetResponse_"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/datasets/{dataset_id}": {"get": {"tags": ["datasets"], "summary": "Get Dataset", "operationId": "get_dataset_api_v1_datasets__dataset_id__get", "parameters": [{"name": "dataset_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Dataset Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DatasetResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["datasets"], "summary": "Delete Dataset", "operationId": "delete_dataset_api_v1_datasets__dataset_id__delete", "parameters": [{"name": "dataset_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Dataset Id"}}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/datasets/{dataset_id}/download": {"get": {"tags": ["datasets"], "summary": "Get Dataset Download", "description": "Returns a collection of pre-signed URLs which can be used to download the dataset.", "operationId": "get_dataset_download_api_v1_datasets__dataset_id__download_get", "parameters": [{"name": "dataset_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Dataset Id"}}, {"name": "extension", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "When specified, will be used to return only URLs for files which have a matching file extension. Wildcards are not accepted. By default all files are returned. e.g. csv", "title": "Extension"}, "description": "When specified, will be used to return only URLs for files which have a matching file extension. Wildcards are not accepted. By default all files are returned. e.g. csv"}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DatasetDownloadResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/inference/": {"post": {"tags": ["jobs"], "summary": "Create Inference Job", "operationId": "create_inference_job_api_v1_jobs_inference__post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobInferenceCreate"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/annotate/": {"post": {"tags": ["jobs"], "summary": "Create Annotation Job", "description": "This uses a hardcoded model, that is, Lumigator's opinion on what\nreference model should be used to generate annotations.\nSee more: https://blog.mozilla.ai/lets-build-an-app-for-evaluating-llms/", "operationId": "create_annotation_job_api_v1_jobs_annotate__post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobAnnotateCreate"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/evaluator/": {"post": {"tags": ["jobs"], "summary": "Create Evaluation Job", "operationId": "create_evaluation_job_api_v1_jobs_evaluator__post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobEvalCreate"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/": {"get": {"tags": ["jobs"], "summary": "List Jobs", "description": "Retrieves job data from the Lumigator repository where Ray\nmetadata is also available.\n\nResults are a merged representation which form an augmented view of a 'job'.\n\nNOTE: Lumigator repository data takes precedence over Ray metadata.", "operationId": "list_jobs_api_v1_jobs__get", "parameters": [{"name": "skip", "in": "query", "required": false, "schema": {"type": "integer", "default": 0, "title": "Skip"}}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer", "default": 100, "title": "Limit"}}, {"name": "job_types", "in": "query", "required": false, "schema": {"type": "array", "items": {"type": "string"}, "default": [], "title": "Job Types"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListingResponse_Job_"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/{job_id}": {"get": {"tags": ["jobs"], "summary": "Get Job", "description": "Retrieves merged job data from the Lumigator repository and Ray\nfor a valid UUID.\n\nThe result is a merged representation which forms an augmented view of a 'job'.\n\nNOTE: Lumigator repository data takes precedence over Ray metadata.", "operationId": "get_job_api_v1_jobs__job_id__get", "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Job Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Job"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/{job_id}/logs": {"get": {"tags": ["jobs"], "summary": "Get Job Logs", "operationId": "get_job_logs_api_v1_jobs__job_id__logs_get", "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Job Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobLogsResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/{job_id}/result": {"get": {"tags": ["jobs"], "summary": "Get Job Result", "description": "Return job results metadata if available in the DB.", "operationId": "get_job_result_api_v1_jobs__job_id__result_get", "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Job Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobResultResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/{job_id}/dataset": {"get": {"tags": ["jobs"], "summary": "Get Job Dataset", "description": "Return the job-associated dataset if available in the DB.", "operationId": "get_job_dataset_api_v1_jobs__job_id__dataset_get", "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Job Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"anyOf": [{"$ref": "#/components/schemas/DatasetResponse"}, {"type": "null"}], "title": "Response Get Job Dataset Api V1 Jobs Job Id Dataset Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/{job_id}/result/download": {"get": {"tags": ["jobs"], "summary": "Get Job Result Download", "description": "Return job results file URL for downloading.", "operationId": "get_job_result_download_api_v1_jobs__job_id__result_download_get", "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Job Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobResultDownloadResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/experiments/": {"post": {"tags": ["experiments"], "summary": "Create Experiment Id", "description": "Create an experiment ID.", "operationId": "create_experiment_id_api_v1_experiments__post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ExperimentCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GetExperimentResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["experiments"], "summary": "List Experiments", "description": "List all experiments.", "operationId": "list_experiments_api_v1_experiments__get", "parameters": [{"name": "skip", "in": "query", "required": false, "schema": {"type": "integer", "default": 0, "title": "Skip"}}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer", "default": 100, "title": "Limit"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListingResponse_GetExperimentResponse_"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/experiments/{experiment_id}": {"get": {"tags": ["experiments"], "summary": "Get Experiment", "description": "Get an experiment by ID.", "operationId": "get_experiment_api_v1_experiments__experiment_id__get", "parameters": [{"name": "experiment_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Experiment Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GetExperimentResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["experiments"], "summary": "Delete Experiment", "description": "Delete an experiment by ID.", "operationId": "delete_experiment_api_v1_experiments__experiment_id__delete", "parameters": [{"name": "experiment_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Experiment Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/models/": {"get": {"tags": ["models"], "summary": "Get Suggested Models", "description": "Get a list of suggested models for the given tasks.\n\nUsage: GET api/v1/models/?tasks=summarization&tasks=translation\n\nArgs:\n tasks (List[str], optional): The task names to filter by.\n\nReturns:\n ListingResponse[ModelsResponse]: A list of suggested models.", "operationId": "get_suggested_models_api_v1_models__get", "parameters": [{"name": "tasks", "in": "query", "required": false, "schema": {"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Filter models by task types", "title": "Tasks"}, "description": "Filter models by task types"}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListingResponse_ModelsResponse_"}}}}, "400": {"description": "Bad Request"}, "500": {"description": "Internal Server Error"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/workflows/": {"post": {"tags": ["workflows"], "summary": "Create Workflow", "description": "A workflow is a single execution for an experiment.\nA workflow is a collection of 1 or more jobs.\nIt must be associated with an experiment id,\nwhich means you must already have created an experiment and have that ID in the request.", "operationId": "create_workflow_api_v1_workflows__post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkflowCreateRequest"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkflowResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/workflows/{workflow_id}": {"get": {"tags": ["workflows"], "summary": "Get Workflow", "description": "Get a workflow by ID.", "operationId": "get_workflow_api_v1_workflows__workflow_id__get", "parameters": [{"name": "workflow_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Workflow Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkflowDetailsResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["workflows"], "summary": "Delete Workflow", "description": "Delete a workflow by ID.\n\nArgs:\n service: Workflow service dependency\n workflow_id: ID of the workflow to delete\n force: If True, force deletion even if the workflow is active or has dependencies", "operationId": "delete_workflow_api_v1_workflows__workflow_id__delete", "parameters": [{"name": "workflow_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Workflow Id"}}, {"name": "force", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Force"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkflowDetailsResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/workflows/{workflow_id}/logs": {"get": {"tags": ["workflows"], "summary": "Get Workflow Logs", "description": "Get the logs for a workflow.", "operationId": "get_workflow_logs_api_v1_workflows__workflow_id__logs_get", "parameters": [{"name": "workflow_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Workflow Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobLogsResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/workflows/{workflow_id}/result/download": {"get": {"tags": ["workflows"], "summary": "Get Workflow Result Download", "description": "Return workflow results file URL for downloading.\n\nArgs:\n service: Workflow service dependency\n workflow_id: ID of the workflow whose results will be returned", "operationId": "get_workflow_result_download_api_v1_workflows__workflow_id__result_download_get", "parameters": [{"name": "workflow_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Workflow Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "string", "title": "Response Get Workflow Result Download Api V1 Workflows Workflow Id Result Download Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/settings/secrets/": {"get": {"tags": ["settings"], "summary": "List Secrets", "description": "Lists all API configured secret names (and descriptions) stored in Lumigator.", "operationId": "list_secrets_api_v1_settings_secrets__get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/SecretGetRequest"}, "type": "array", "title": "Response List Secrets Api V1 Settings Secrets Get"}}}}}}}, "/api/v1/settings/secrets/{secret_name}": {"delete": {"tags": ["settings"], "summary": "Delete Secret", "description": "Deletes a secret identified by its name.", "operationId": "delete_secret_api_v1_settings_secrets__secret_name__delete", "parameters": [{"name": "secret_name", "in": "path", "required": true, "schema": {"type": "string", "title": "Secret Name"}}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "put": {"tags": ["settings"], "summary": "Upload Secret", "description": "Uploads a secret for use in Lumigator.\n\nLumigator uses different secrets for purposes such as external API calls.\nThe user can upload new values for these secrets, but they cannot retrieve\nthose values.", "operationId": "upload_secret_api_v1_settings_secrets__secret_name__put", "parameters": [{"name": "secret_name", "in": "path", "required": true, "schema": {"type": "string", "title": "Secret Name"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SecretUploadRequest"}}}}, "responses": {"201": {"description": "Secret successfully created", "content": {"application/json": {"schema": {}}}}, "204": {"description": "Secret successfully updated"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/": {"get": {"summary": "Get Root", "operationId": "get_root__get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}}}}}, "components": {"schemas": {"Body_upload_dataset_api_v1_datasets__post": {"properties": {"dataset": {"type": "string", "format": "binary", "title": "Dataset"}, "format": {"$ref": "#/components/schemas/DatasetFormat"}}, "type": "object", "required": ["dataset", "format"], "title": "Body_upload_dataset_api_v1_datasets__post"}, "DatasetDownloadResponse": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "download_urls": {"items": {"type": "string"}, "type": "array", "title": "Download Urls"}}, "type": "object", "required": ["id", "download_urls"], "title": "DatasetDownloadResponse"}, "DatasetFormat": {"type": "string", "enum": ["job"], "title": "DatasetFormat"}, "DatasetResponse": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "filename": {"type": "string", "title": "Filename"}, "format": {"$ref": "#/components/schemas/DatasetFormat"}, "size": {"type": "integer", "title": "Size"}, "ground_truth": {"type": "boolean", "title": "Ground Truth"}, "run_id": {"anyOf": [{"type": "string", "format": "uuid"}, {"type": "null"}], "title": "Run Id"}, "generated": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Generated"}, "generated_by": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Generated By"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}}, "type": "object", "required": ["id", "filename", "format", "size", "ground_truth", "run_id", "generated", "generated_by", "created_at"], "title": "DatasetResponse"}, "DeepEvalLocalModelConfig": {"properties": {"model_name": {"type": "string", "title": "Model Name"}, "model_base_url": {"type": "string", "title": "Model Base Url"}, "model_api_key": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Model Api Key", "default": "ollama"}}, "type": "object", "required": ["model_name", "model_base_url"], "title": "DeepEvalLocalModelConfig"}, "DeploymentType": {"type": "string", "enum": ["local", "development", "staging", "production"], "title": "DeploymentType"}, "ExperimentCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description", "default": ""}, "dataset": {"type": "string", "format": "uuid", "title": "Dataset"}, "max_samples": {"type": "integer", "title": "Max Samples", "default": -1}, "task_definition": {"oneOf": [{"$ref": "#/components/schemas/SummarizationTaskDefinition"}, {"$ref": "#/components/schemas/TranslationTaskDefinition"}, {"$ref": "#/components/schemas/TextGenerationTaskDefinition"}], "title": "Task Definition", "discriminator": {"propertyName": "task", "mapping": {"summarization": "#/components/schemas/SummarizationTaskDefinition", "text-generation": "#/components/schemas/TextGenerationTaskDefinition", "translation": "#/components/schemas/TranslationTaskDefinition"}}}}, "type": "object", "required": ["name", "dataset"], "title": "ExperimentCreate"}, "GenerationConfig": {"properties": {"max_new_tokens": {"type": "integer", "title": "Max New Tokens", "default": 1024}, "frequency_penalty": {"type": "number", "title": "Frequency Penalty", "default": 0.0}, "temperature": {"type": "number", "title": "Temperature", "default": 0.5}, "top_p": {"type": "number", "title": "Top P", "default": 0.5}}, "additionalProperties": false, "type": "object", "title": "GenerationConfig", "description": "Custom and limited configuration for generation.\nSort of a subset of HF GenerationConfig\nhttps://huggingface.co/docs/transformers/en/main_classes/text_generation#transformers.GenerationConfig"}, "GetExperimentResponse": {"properties": {"id": {"type": "string", "title": "Id"}, "name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "max_samples": {"type": "integer", "title": "Max Samples", "default": -1}, "task_definition": {"oneOf": [{"$ref": "#/components/schemas/SummarizationTaskDefinition"}, {"$ref": "#/components/schemas/TranslationTaskDefinition"}, {"$ref": "#/components/schemas/TextGenerationTaskDefinition"}], "title": "Task Definition", "discriminator": {"propertyName": "task", "mapping": {"summarization": "#/components/schemas/SummarizationTaskDefinition", "text-generation": "#/components/schemas/TextGenerationTaskDefinition", "translation": "#/components/schemas/TranslationTaskDefinition"}}}, "dataset": {"type": "string", "format": "uuid", "title": "Dataset"}, "updated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Updated At"}, "workflows": {"anyOf": [{"items": {"$ref": "#/components/schemas/WorkflowDetailsResponse"}, "type": "array"}, {"type": "null"}], "title": "Workflows"}}, "type": "object", "required": ["id", "name", "description", "created_at", "task_definition", "dataset"], "title": "GetExperimentResponse"}, "HTTPValidationError": {"properties": {"detail": {"items": {"$ref": "#/components/schemas/ValidationError"}, "type": "array", "title": "Detail"}}, "type": "object", "title": "HTTPValidationError"}, "HealthResponse": {"properties": {"status": {"type": "string", "title": "Status"}, "deployment_type": {"$ref": "#/components/schemas/DeploymentType"}}, "type": "object", "required": ["status", "deployment_type"], "title": "HealthResponse"}, "Job": {"properties": {"type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Type"}, "submission_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Submission Id"}, "driver_info": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Driver Info"}, "status": {"$ref": "#/components/schemas/JobStatus"}, "config": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Config"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Message"}, "error_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Error Type"}, "start_time": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Start Time"}, "end_time": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "End Time"}, "metadata": {"type": "object", "title": "Metadata"}, "runtime_env": {"type": "object", "title": "Runtime Env"}, "driver_agent_http_address": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Driver Agent Http Address"}, "driver_node_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Driver Node Id"}, "driver_exit_code": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Driver Exit Code"}, "id": {"type": "string", "format": "uuid", "title": "Id"}, "name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description"}, "job_type": {"$ref": "#/components/schemas/JobType"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "experiment_id": {"anyOf": [{"type": "string", "format": "uuid"}, {"type": "null"}], "title": "Experiment Id"}, "updated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Updated At"}}, "type": "object", "required": ["status", "id", "name", "description", "job_type", "created_at"], "title": "Job", "description": "Job represents the composition of JobResponse and JobSubmissionResponse.\n\nJobSubmissionResponse was formerly returned from some /health/jobs related\nendpoints, while JobResponse was used by /jobs related endpoints.\n\nThe only conflicting field in the two schemas is 'status' which is consistent\nin what it intends to represent, but uses different types (JobStatus/str).\n\nThe Job type has both id and submission_id which will contain the same data.\n\nNOTE: Job is intended to reduce breaking changes experienced by the UI and other\nconsumers. Tt was not conceived as a type that will be around for long, as\nthe API needs to be refactored to better support experiments."}, "JobAnnotateConfig": {"properties": {"secret_key_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Secret Key Name", "description": "An optional secret key name. When creating a job, the secret key name identifies an existing secret stored in Lumigator that should be used to access the provider."}, "model": {"type": "string", "title": "Model", "default": "facebook/bart-large-cnn"}, "provider": {"type": "string", "title": "Provider", "default": "hf"}, "task_definition": {"oneOf": [{"$ref": "#/components/schemas/SummarizationTaskDefinition"}, {"$ref": "#/components/schemas/TranslationTaskDefinition"}, {"$ref": "#/components/schemas/TextGenerationTaskDefinition"}], "title": "Task Definition", "discriminator": {"propertyName": "task", "mapping": {"summarization": "#/components/schemas/SummarizationTaskDefinition", "text-generation": "#/components/schemas/TextGenerationTaskDefinition", "translation": "#/components/schemas/TranslationTaskDefinition"}}}, "accelerator": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Accelerator", "default": "auto"}, "revision": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Revision", "default": "main"}, "use_fast": {"type": "boolean", "title": "Use Fast", "default": true}, "trust_remote_code": {"type": "boolean", "title": "Trust Remote Code", "default": false}, "torch_dtype": {"type": "string", "title": "Torch Dtype", "default": "auto"}, "base_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Base Url"}, "generation_config": {"$ref": "#/components/schemas/GenerationConfig"}, "store_to_dataset": {"type": "boolean", "title": "Store To Dataset", "default": true}, "system_prompt": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "System Prompt", "description": "System prompt to use for the model inference.If not provided, a task-specific default prompt will be used.", "examples": ["You are an advanced AI trained to summarize documents accurately and concisely. Your goal is to extract key information while maintaining clarity and coherence."]}}, "type": "object", "title": "JobAnnotateConfig", "description": "Job configuration for the annotation job type\n\nAn annotation job is a special type of inference job that is used to\nannotate a dataset with predictions from a model. The predictions are\nstored in the dataset as a new field called `ground_truth`.\n\nJobAnnotateConfig inherits from JobInferenceConfig but fixes the following\nfields, using the `SkipJsonSchema` type to prevent them from being included\nin the JSON schema:\n- job_type: Literal[JobType.ANNOTATION]\n- output_field: \"ground_truth\"\n\nIt also sets sensible defaults for the following fields:\n- store_to_dataset: True\n- model: \"facebook/bart-large-cnn\"\n- provider: \"hf\"\n\nUsers can change the model and provider fields but cannot change the\njob_type or output_field fields.\n\nNote that, currently, ground truth generation is limited to summarization\ntasks from the UI. Users can run any ground truth generation task from the\nAPI."}, "JobAnnotateCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description", "default": ""}, "dataset": {"type": "string", "format": "uuid", "title": "Dataset"}, "max_samples": {"type": "integer", "title": "Max Samples", "default": -1}, "batch_size": {"type": "integer", "exclusiveMinimum": 0.0, "title": "Batch Size", "default": 1}, "job_config": {"$ref": "#/components/schemas/JobAnnotateConfig"}}, "type": "object", "required": ["name", "dataset", "job_config"], "title": "JobAnnotateCreate"}, "JobEvalConfig": {"properties": {"secret_key_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Secret Key Name", "description": "An optional secret key name. When creating a job, the secret key name identifies an existing secret stored in Lumigator that should be used to access the provider."}, "job_type": {"type": "string", "const": "evaluator", "title": "Job Type", "default": "evaluator"}, "metrics": {"items": {"type": "string"}, "type": "array", "title": "Metrics", "default": ["rouge", "meteor", "bertscore", "bleu"]}, "llm_as_judge": {"anyOf": [{"$ref": "#/components/schemas/DeepEvalLocalModelConfig"}, {"type": "null"}]}}, "type": "object", "title": "JobEvalConfig"}, "JobEvalCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description", "default": ""}, "dataset": {"type": "string", "format": "uuid", "title": "Dataset"}, "max_samples": {"type": "integer", "title": "Max Samples", "default": -1}, "batch_size": {"type": "integer", "exclusiveMinimum": 0.0, "title": "Batch Size", "default": 1}, "job_config": {"$ref": "#/components/schemas/JobEvalConfig"}}, "type": "object", "required": ["name", "dataset", "job_config"], "title": "JobEvalCreate"}, "JobInferenceConfig": {"properties": {"secret_key_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Secret Key Name", "description": "An optional secret key name. When creating a job, the secret key name identifies an existing secret stored in Lumigator that should be used to access the provider."}, "job_type": {"type": "string", "const": "inference", "title": "Job Type", "default": "inference"}, "model": {"type": "string", "title": "Model"}, "provider": {"type": "string", "title": "Provider"}, "task_definition": {"oneOf": [{"$ref": "#/components/schemas/SummarizationTaskDefinition"}, {"$ref": "#/components/schemas/TranslationTaskDefinition"}, {"$ref": "#/components/schemas/TextGenerationTaskDefinition"}], "title": "Task Definition", "discriminator": {"propertyName": "task", "mapping": {"summarization": "#/components/schemas/SummarizationTaskDefinition", "text-generation": "#/components/schemas/TextGenerationTaskDefinition", "translation": "#/components/schemas/TranslationTaskDefinition"}}}, "accelerator": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Accelerator", "default": "auto"}, "revision": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Revision", "default": "main"}, "use_fast": {"type": "boolean", "title": "Use Fast", "default": true}, "trust_remote_code": {"type": "boolean", "title": "Trust Remote Code", "default": false}, "torch_dtype": {"type": "string", "title": "Torch Dtype", "default": "auto"}, "base_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Base Url"}, "output_field": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Output Field", "default": "predictions"}, "generation_config": {"$ref": "#/components/schemas/GenerationConfig"}, "store_to_dataset": {"type": "boolean", "title": "Store To Dataset", "default": false}, "system_prompt": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "System Prompt", "description": "System prompt to use for the model inference.If not provided, a task-specific default prompt will be used.", "examples": ["You are an advanced AI trained to summarize documents accurately and concisely. Your goal is to extract key information while maintaining clarity and coherence."]}}, "type": "object", "required": ["model", "provider"], "title": "JobInferenceConfig"}, "JobInferenceCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description", "default": ""}, "dataset": {"type": "string", "format": "uuid", "title": "Dataset"}, "max_samples": {"type": "integer", "title": "Max Samples", "default": -1}, "batch_size": {"type": "integer", "exclusiveMinimum": 0.0, "title": "Batch Size", "default": 1}, "job_config": {"$ref": "#/components/schemas/JobInferenceConfig"}}, "type": "object", "required": ["name", "dataset", "job_config"], "title": "JobInferenceCreate"}, "JobLogsResponse": {"properties": {"logs": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Logs"}}, "type": "object", "title": "JobLogsResponse"}, "JobResponse": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description"}, "status": {"$ref": "#/components/schemas/JobStatus"}, "job_type": {"$ref": "#/components/schemas/JobType"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "experiment_id": {"anyOf": [{"type": "string", "format": "uuid"}, {"type": "null"}], "title": "Experiment Id"}, "updated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Updated At"}}, "type": "object", "required": ["id", "name", "description", "status", "job_type", "created_at"], "title": "JobResponse"}, "JobResultDownloadResponse": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "download_url": {"type": "string", "title": "Download Url"}}, "type": "object", "required": ["id", "download_url"], "title": "JobResultDownloadResponse"}, "JobResultResponse": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "job_id": {"type": "string", "format": "uuid", "title": "Job Id"}}, "type": "object", "required": ["id", "job_id"], "title": "JobResultResponse"}, "JobResults": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "metrics": {"anyOf": [{"items": {"type": "object"}, "type": "array"}, {"type": "null"}], "title": "Metrics"}, "parameters": {"anyOf": [{"items": {"type": "object"}, "type": "array"}, {"type": "null"}], "title": "Parameters"}, "metric_url": {"type": "string", "title": "Metric Url"}, "artifact_url": {"type": "string", "title": "Artifact Url"}}, "type": "object", "required": ["id", "metric_url", "artifact_url"], "title": "JobResults"}, "JobStatus": {"type": "string", "enum": ["created", "pending", "running", "failed", "succeeded", "stopped"], "title": "JobStatus"}, "JobType": {"type": "string", "enum": ["inference", "evaluator", "annotate"], "title": "JobType"}, "ListingResponse_DatasetResponse_": {"properties": {"total": {"type": "integer", "title": "Total"}, "items": {"items": {"$ref": "#/components/schemas/DatasetResponse"}, "type": "array", "title": "Items"}}, "type": "object", "required": ["total", "items"], "title": "ListingResponse[DatasetResponse]"}, "ListingResponse_GetExperimentResponse_": {"properties": {"total": {"type": "integer", "title": "Total"}, "items": {"items": {"$ref": "#/components/schemas/GetExperimentResponse"}, "type": "array", "title": "Items"}}, "type": "object", "required": ["total", "items"], "title": "ListingResponse[GetExperimentResponse]"}, "ListingResponse_Job_": {"properties": {"total": {"type": "integer", "title": "Total"}, "items": {"items": {"$ref": "#/components/schemas/Job"}, "type": "array", "title": "Items"}}, "type": "object", "required": ["total", "items"], "title": "ListingResponse[Job]"}, "ListingResponse_ModelsResponse_": {"properties": {"total": {"type": "integer", "title": "Total"}, "items": {"items": {"$ref": "#/components/schemas/ModelsResponse"}, "type": "array", "title": "Items"}}, "type": "object", "required": ["total", "items"], "title": "ListingResponse[ModelsResponse]"}, "ModelInfo": {"properties": {"parameter_count": {"type": "string", "title": "Parameter Count"}, "tensor_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Tensor Type"}, "model_size": {"type": "string", "title": "Model Size"}}, "type": "object", "required": ["parameter_count", "model_size"], "title": "ModelInfo"}, "ModelRequirement": {"type": "string", "enum": ["api_key", "llamafile"], "title": "ModelRequirement", "description": "Represents a type of requirement for a model"}, "ModelsResponse": {"properties": {"display_name": {"type": "string", "title": "Model name", "description": "Name of the model used in the task. It's just a display name"}, "model": {"type": "string", "title": "Model ID", "description": "Model ID used in the task"}, "provider": {"type": "string", "title": "Model Provider", "description": "LiteLLM key for where the model is hosted (e.g. `openai`, `deepseek`, `gpt3`, etc). If using a HF model that is hosted in the inference job, use `hf`"}, "base_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Base URL", "description": "Base URL for the model API (if applicable, e.g. for Llamafile, vLLM, etc)"}, "website_url": {"type": "string", "title": "Information page URL", "description": "URI containing detailed information about the model"}, "description": {"type": "string", "title": "Model description", "description": "Detailed model description"}, "requirements": {"items": {"$ref": "#/components/schemas/ModelRequirement"}, "type": "array", "title": "Model requirements", "description": "Additional requirements that need to be fulfilled before using the model (e.g. `{ModelRequirement.LLAMAFILE}` to indicate that a llamafile needs to be running or `{ModelRequirement.API_KEY}` to indicate that an API key is necessary)"}, "info": {"anyOf": [{"$ref": "#/components/schemas/ModelInfo"}, {"type": "null"}], "title": "Model info", "description": "Detailed model capabilities"}, "tasks": {"items": {"additionalProperties": {"type": "object"}, "type": "object"}, "type": "array", "title": "Applicable tasks", "description": "List of tasks to which the model can be applied"}}, "type": "object", "required": ["display_name", "model", "provider", "website_url", "description", "tasks"], "title": "ModelsResponse", "description": "Contains detailed model information"}, "SecretGetRequest": {"properties": {"name": {"type": "string", "maxLength": 255, "minLength": 1, "title": "Name"}, "description": {"type": "string", "title": "Description"}}, "type": "object", "required": ["name", "description"], "title": "SecretGetRequest", "description": "Represents the result of a get secret request.\n\nNOTE: The secret value should never be exposed to the end user."}, "SecretUploadRequest": {"properties": {"value": {"type": "string", "maxLength": 1024, "minLength": 1, "title": "Value"}, "description": {"type": "string", "title": "Description"}}, "type": "object", "required": ["value", "description"], "title": "SecretUploadRequest", "description": "Represents a secret upload request."}, "SummarizationTaskDefinition": {"properties": {"task": {"type": "string", "const": "summarization", "title": "Task", "default": "summarization"}}, "additionalProperties": false, "type": "object", "title": "SummarizationTaskDefinition"}, "TextGenerationTaskDefinition": {"properties": {"task": {"type": "string", "const": "text-generation", "title": "Task", "default": "text-generation"}}, "additionalProperties": false, "type": "object", "title": "TextGenerationTaskDefinition"}, "TranslationTaskDefinition": {"properties": {"task": {"type": "string", "const": "translation", "title": "Task", "default": "translation"}, "source_language": {"type": "string", "title": "Source Language", "examples": ["en", "English"]}, "target_language": {"type": "string", "title": "Target Language", "examples": ["de", "German"]}}, "additionalProperties": false, "type": "object", "required": ["source_language", "target_language"], "title": "TranslationTaskDefinition"}, "ValidationError": {"properties": {"loc": {"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "type": "array", "title": "Location"}, "msg": {"type": "string", "title": "Message"}, "type": {"type": "string", "title": "Error Type"}}, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError"}, "WorkflowCreateRequest": {"properties": {"name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description", "default": ""}, "experiment_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Experiment Id"}, "model": {"type": "string", "title": "Model"}, "provider": {"type": "string", "title": "Provider"}, "secret_key_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Secret Key Name", "description": "An optional secret key name. Identifies an existing secret stored in Lumigator that should be used to access the provider."}, "batch_size": {"type": "integer", "exclusiveMinimum": 0.0, "title": "Batch Size", "default": 1}, "base_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Base Url"}, "system_prompt": {"type": "string", "title": "System Prompt", "default": ""}, "inference_output_field": {"type": "string", "title": "Inference Output Field", "default": "predictions"}, "config_template": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Config Template"}, "generation_config": {"$ref": "#/components/schemas/GenerationConfig"}, "job_timeout_sec": {"type": "integer", "exclusiveMinimum": 0.0, "title": "Job Timeout Sec", "default": 3600}, "metrics": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Metrics"}}, "type": "object", "required": ["name", "model", "provider"], "title": "WorkflowCreateRequest"}, "WorkflowDetailsResponse": {"properties": {"id": {"type": "string", "title": "Id"}, "experiment_id": {"type": "string", "title": "Experiment Id"}, "model": {"type": "string", "title": "Model"}, "name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description"}, "system_prompt": {"type": "string", "title": "System Prompt"}, "status": {"$ref": "#/components/schemas/WorkflowStatus"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "updated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Updated At"}, "jobs": {"anyOf": [{"items": {"$ref": "#/components/schemas/JobResults"}, "type": "array"}, {"type": "null"}], "title": "Jobs"}, "metrics": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Metrics"}, "parameters": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Parameters"}, "artifacts_download_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Artifacts Download Url"}}, "type": "object", "required": ["id", "experiment_id", "model", "name", "description", "system_prompt", "status", "created_at"], "title": "WorkflowDetailsResponse"}, "WorkflowResponse": {"properties": {"id": {"type": "string", "title": "Id"}, "experiment_id": {"type": "string", "title": "Experiment Id"}, "model": {"type": "string", "title": "Model"}, "name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description"}, "system_prompt": {"type": "string", "title": "System Prompt"}, "status": {"$ref": "#/components/schemas/WorkflowStatus"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "updated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Updated At"}}, "type": "object", "required": ["id", "experiment_id", "model", "name", "description", "system_prompt", "status", "created_at"], "title": "WorkflowResponse"}, "WorkflowStatus": {"type": "string", "enum": ["created", "running", "failed", "succeeded"], "title": "WorkflowStatus"}}}} \ No newline at end of file +{"openapi": "3.1.0", "info": {"title": "Lumigator Backend", "description": "Backend server", "version": "0.0.1"}, "paths": {"/api/v1/health/": {"get": {"tags": ["health"], "summary": "Get Health", "operationId": "get_health_api_v1_health__get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HealthResponse"}}}}}}}, "/api/v1/datasets/": {"post": {"tags": ["datasets"], "summary": "Upload Dataset", "description": "Uploads the dataset for use in Lumigator.\n\nAn uploaded dataset is parsed into HuggingFace format files and stored alongside a\nrecreated version of the input dataset.\n\nNOTE: The recreated version of the CSV file may not have identical delimiters as it will follow\nthe format that HuggingFace uses when it generates the CSV.", "operationId": "upload_dataset_api_v1_datasets__post", "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"$ref": "#/components/schemas/Body_upload_dataset_api_v1_datasets__post"}}}}, "responses": {"201": {"description": "Dataset successfully uploaded", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DatasetResponse"}}}}, "413": {"description": "Max dataset size (50MB)"}, "422": {"description": "Invalid CSV file"}}}, "get": {"tags": ["datasets"], "summary": "List Datasets", "operationId": "list_datasets_api_v1_datasets__get", "parameters": [{"name": "skip", "in": "query", "required": false, "schema": {"type": "integer", "default": 0, "title": "Skip"}}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer", "default": 100, "title": "Limit"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListingResponse_DatasetResponse_"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/datasets/{dataset_id}": {"get": {"tags": ["datasets"], "summary": "Get Dataset", "operationId": "get_dataset_api_v1_datasets__dataset_id__get", "parameters": [{"name": "dataset_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Dataset Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DatasetResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["datasets"], "summary": "Delete Dataset", "operationId": "delete_dataset_api_v1_datasets__dataset_id__delete", "parameters": [{"name": "dataset_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Dataset Id"}}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/datasets/{dataset_id}/download": {"get": {"tags": ["datasets"], "summary": "Get Dataset Download", "description": "Returns a collection of pre-signed URLs which can be used to download the dataset.", "operationId": "get_dataset_download_api_v1_datasets__dataset_id__download_get", "parameters": [{"name": "dataset_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Dataset Id"}}, {"name": "extension", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "When specified, will be used to return only URLs for files which have a matching file extension. Wildcards are not accepted. By default all files are returned. e.g. csv", "title": "Extension"}, "description": "When specified, will be used to return only URLs for files which have a matching file extension. Wildcards are not accepted. By default all files are returned. e.g. csv"}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DatasetDownloadResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/inference/": {"post": {"tags": ["jobs"], "summary": "Create Inference Job", "operationId": "create_inference_job_api_v1_jobs_inference__post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobInferenceCreate"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/annotate/": {"post": {"tags": ["jobs"], "summary": "Create Annotation Job", "description": "This uses a hardcoded model, that is, Lumigator's opinion on what\nreference model should be used to generate annotations.\nSee more: https://blog.mozilla.ai/lets-build-an-app-for-evaluating-llms/", "operationId": "create_annotation_job_api_v1_jobs_annotate__post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobAnnotateCreate"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/evaluator/": {"post": {"tags": ["jobs"], "summary": "Create Evaluation Job", "operationId": "create_evaluation_job_api_v1_jobs_evaluator__post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobEvalCreate"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/": {"get": {"tags": ["jobs"], "summary": "List Jobs", "description": "Retrieves job data from the Lumigator repository where Ray\nmetadata is also available.\n\nResults are a merged representation which form an augmented view of a 'job'.\n\nNOTE: Lumigator repository data takes precedence over Ray metadata.", "operationId": "list_jobs_api_v1_jobs__get", "parameters": [{"name": "skip", "in": "query", "required": false, "schema": {"type": "integer", "default": 0, "title": "Skip"}}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer", "default": 100, "title": "Limit"}}, {"name": "job_types", "in": "query", "required": false, "schema": {"type": "array", "items": {"type": "string"}, "default": [], "title": "Job Types"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListingResponse_Job_"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/{job_id}": {"get": {"tags": ["jobs"], "summary": "Get Job", "description": "Retrieves merged job data from the Lumigator repository and Ray\nfor a valid UUID.\n\nThe result is a merged representation which forms an augmented view of a 'job'.\n\nNOTE: Lumigator repository data takes precedence over Ray metadata.", "operationId": "get_job_api_v1_jobs__job_id__get", "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Job Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Job"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/{job_id}/logs": {"get": {"tags": ["jobs"], "summary": "Get Job Logs", "operationId": "get_job_logs_api_v1_jobs__job_id__logs_get", "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Job Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobLogsResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/{job_id}/result": {"get": {"tags": ["jobs"], "summary": "Get Job Result", "description": "Return job results metadata if available in the DB.", "operationId": "get_job_result_api_v1_jobs__job_id__result_get", "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Job Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobResultResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/{job_id}/dataset": {"get": {"tags": ["jobs"], "summary": "Get Job Dataset", "description": "Return the job-associated dataset if available in the DB.", "operationId": "get_job_dataset_api_v1_jobs__job_id__dataset_get", "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Job Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"anyOf": [{"$ref": "#/components/schemas/DatasetResponse"}, {"type": "null"}], "title": "Response Get Job Dataset Api V1 Jobs Job Id Dataset Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/jobs/{job_id}/result/download": {"get": {"tags": ["jobs"], "summary": "Get Job Result Download", "description": "Return job results file URL for downloading.", "operationId": "get_job_result_download_api_v1_jobs__job_id__result_download_get", "parameters": [{"name": "job_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Job Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobResultDownloadResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/experiments/": {"post": {"tags": ["experiments"], "summary": "Create Experiment Id", "description": "Create an experiment ID.", "operationId": "create_experiment_id_api_v1_experiments__post", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ExperimentCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GetExperimentResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["experiments"], "summary": "List Experiments", "description": "List all experiments.", "operationId": "list_experiments_api_v1_experiments__get", "parameters": [{"name": "skip", "in": "query", "required": false, "schema": {"type": "integer", "default": 0, "title": "Skip"}}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer", "default": 100, "title": "Limit"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListingResponse_GetExperimentResponse_"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/experiments/{experiment_id}": {"get": {"tags": ["experiments"], "summary": "Get Experiment", "description": "Get an experiment by ID.", "operationId": "get_experiment_api_v1_experiments__experiment_id__get", "parameters": [{"name": "experiment_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Experiment Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GetExperimentResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["experiments"], "summary": "Delete Experiment", "description": "Delete an experiment by ID.", "operationId": "delete_experiment_api_v1_experiments__experiment_id__delete", "parameters": [{"name": "experiment_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Experiment Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/models/": {"get": {"tags": ["models"], "summary": "Get Suggested Models", "description": "Get a list of suggested models for the given tasks.\n\nUsage: GET api/v1/models/?tasks=summarization&tasks=translation\n\nArgs:\n tasks (List[str], optional): The task names to filter by.\n\nReturns:\n ListingResponse[ModelsResponse]: A list of suggested models.", "operationId": "get_suggested_models_api_v1_models__get", "parameters": [{"name": "tasks", "in": "query", "required": false, "schema": {"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "description": "Filter models by task types", "title": "Tasks"}, "description": "Filter models by task types"}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListingResponse_ModelsResponse_"}}}}, "400": {"description": "Bad Request"}, "500": {"description": "Internal Server Error"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/workflows/": {"post": {"tags": ["workflows"], "summary": "Create Workflow", "description": "A workflow is a single execution for an experiment.\nA workflow is a collection of 1 or more jobs.\nIt must be associated with an experiment id,\nwhich means you must already have created an experiment and have that ID in the request.", "operationId": "create_workflow_api_v1_workflows__post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkflowCreateRequest"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkflowResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/workflows/{workflow_id}": {"get": {"tags": ["workflows"], "summary": "Get Workflow", "description": "Get a workflow by ID.", "operationId": "get_workflow_api_v1_workflows__workflow_id__get", "parameters": [{"name": "workflow_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Workflow Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkflowDetailsResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["workflows"], "summary": "Delete Workflow", "description": "Delete a workflow by ID.\n\nArgs:\n service: Workflow service dependency\n workflow_id: ID of the workflow to delete\n force: If True, force deletion even if the workflow is active or has dependencies", "operationId": "delete_workflow_api_v1_workflows__workflow_id__delete", "parameters": [{"name": "workflow_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Workflow Id"}}, {"name": "force", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Force"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WorkflowDetailsResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/workflows/{workflow_id}/logs": {"get": {"tags": ["workflows"], "summary": "Get Workflow Logs", "description": "Get the logs for a workflow.", "operationId": "get_workflow_logs_api_v1_workflows__workflow_id__logs_get", "parameters": [{"name": "workflow_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Workflow Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JobLogsResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/workflows/{workflow_id}/result/download": {"get": {"tags": ["workflows"], "summary": "Get Workflow Result Download", "description": "Return workflow results file URL for downloading.\n\nArgs:\n service: Workflow service dependency\n workflow_id: ID of the workflow whose results will be returned", "operationId": "get_workflow_result_download_api_v1_workflows__workflow_id__result_download_get", "parameters": [{"name": "workflow_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Workflow Id"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "string", "title": "Response Get Workflow Result Download Api V1 Workflows Workflow Id Result Download Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/settings/secrets/": {"get": {"tags": ["settings"], "summary": "List Secrets", "description": "Lists all API configured secret names (and descriptions) stored in Lumigator.", "operationId": "list_secrets_api_v1_settings_secrets__get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/SecretGetRequest"}, "type": "array", "title": "Response List Secrets Api V1 Settings Secrets Get"}}}}}}}, "/api/v1/settings/secrets/{secret_name}": {"delete": {"tags": ["settings"], "summary": "Delete Secret", "description": "Deletes a secret identified by its name.", "operationId": "delete_secret_api_v1_settings_secrets__secret_name__delete", "parameters": [{"name": "secret_name", "in": "path", "required": true, "schema": {"type": "string", "title": "Secret Name"}}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "put": {"tags": ["settings"], "summary": "Upload Secret", "description": "Uploads a secret for use in Lumigator.\n\nLumigator uses different secrets for purposes such as external API calls.\nThe user can upload new values for these secrets, but they cannot retrieve\nthose values.", "operationId": "upload_secret_api_v1_settings_secrets__secret_name__put", "parameters": [{"name": "secret_name", "in": "path", "required": true, "schema": {"type": "string", "title": "Secret Name"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SecretUploadRequest"}}}}, "responses": {"201": {"description": "Secret successfully created", "content": {"application/json": {"schema": {}}}}, "204": {"description": "Secret successfully updated"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/": {"get": {"summary": "Get Root", "operationId": "get_root__get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}}}}}, "components": {"schemas": {"Body_upload_dataset_api_v1_datasets__post": {"properties": {"dataset": {"type": "string", "format": "binary", "title": "Dataset"}, "format": {"$ref": "#/components/schemas/DatasetFormat"}}, "type": "object", "required": ["dataset", "format"], "title": "Body_upload_dataset_api_v1_datasets__post"}, "DatasetDownloadResponse": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "download_urls": {"items": {"type": "string"}, "type": "array", "title": "Download Urls"}}, "type": "object", "required": ["id", "download_urls"], "title": "DatasetDownloadResponse"}, "DatasetFormat": {"type": "string", "enum": ["job"], "title": "DatasetFormat"}, "DatasetResponse": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "filename": {"type": "string", "title": "Filename"}, "format": {"$ref": "#/components/schemas/DatasetFormat"}, "size": {"type": "integer", "title": "Size"}, "ground_truth": {"type": "boolean", "title": "Ground Truth"}, "run_id": {"anyOf": [{"type": "string", "format": "uuid"}, {"type": "null"}], "title": "Run Id"}, "generated": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Generated"}, "generated_by": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Generated By"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}}, "type": "object", "required": ["id", "filename", "format", "size", "ground_truth", "run_id", "generated", "generated_by", "created_at"], "title": "DatasetResponse"}, "DeepEvalLocalModelConfig": {"properties": {"model_name": {"type": "string", "title": "Model Name"}, "model_base_url": {"type": "string", "title": "Model Base Url"}, "model_api_key": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Model Api Key", "default": "ollama"}}, "type": "object", "required": ["model_name", "model_base_url"], "title": "DeepEvalLocalModelConfig"}, "DeploymentType": {"type": "string", "enum": ["local", "development", "staging", "production"], "title": "DeploymentType"}, "ExperimentCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description", "default": ""}, "dataset": {"type": "string", "format": "uuid", "title": "Dataset"}, "max_samples": {"type": "integer", "title": "Max Samples", "default": -1}, "task_definition": {"oneOf": [{"$ref": "#/components/schemas/SummarizationTaskDefinition"}, {"$ref": "#/components/schemas/TranslationTaskDefinition"}, {"$ref": "#/components/schemas/TextGenerationTaskDefinition"}], "title": "Task Definition", "discriminator": {"propertyName": "task", "mapping": {"summarization": "#/components/schemas/SummarizationTaskDefinition", "text-generation": "#/components/schemas/TextGenerationTaskDefinition", "translation": "#/components/schemas/TranslationTaskDefinition"}}}}, "type": "object", "required": ["name", "dataset"], "title": "ExperimentCreate"}, "GenerationConfig": {"properties": {"max_new_tokens": {"type": "integer", "title": "Max New Tokens", "default": 1024}, "frequency_penalty": {"type": "number", "title": "Frequency Penalty", "default": 0.0}, "temperature": {"type": "number", "title": "Temperature", "default": 0.5}, "top_p": {"type": "number", "title": "Top P", "default": 0.5}}, "additionalProperties": false, "type": "object", "title": "GenerationConfig", "description": "Custom and limited configuration for generation.\nSort of a subset of HF GenerationConfig\nhttps://huggingface.co/docs/transformers/en/main_classes/text_generation#transformers.GenerationConfig"}, "GetExperimentResponse": {"properties": {"id": {"type": "string", "title": "Id"}, "name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "max_samples": {"type": "integer", "title": "Max Samples", "default": -1}, "task_definition": {"oneOf": [{"$ref": "#/components/schemas/SummarizationTaskDefinition"}, {"$ref": "#/components/schemas/TranslationTaskDefinition"}, {"$ref": "#/components/schemas/TextGenerationTaskDefinition"}], "title": "Task Definition", "discriminator": {"propertyName": "task", "mapping": {"summarization": "#/components/schemas/SummarizationTaskDefinition", "text-generation": "#/components/schemas/TextGenerationTaskDefinition", "translation": "#/components/schemas/TranslationTaskDefinition"}}}, "dataset": {"type": "string", "format": "uuid", "title": "Dataset"}, "updated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Updated At"}, "workflows": {"anyOf": [{"items": {"$ref": "#/components/schemas/WorkflowDetailsResponse"}, "type": "array"}, {"type": "null"}], "title": "Workflows"}}, "type": "object", "required": ["id", "name", "description", "created_at", "task_definition", "dataset"], "title": "GetExperimentResponse"}, "HTTPValidationError": {"properties": {"detail": {"items": {"$ref": "#/components/schemas/ValidationError"}, "type": "array", "title": "Detail"}}, "type": "object", "title": "HTTPValidationError"}, "HealthResponse": {"properties": {"status": {"type": "string", "title": "Status"}, "deployment_type": {"$ref": "#/components/schemas/DeploymentType"}}, "type": "object", "required": ["status", "deployment_type"], "title": "HealthResponse"}, "Job": {"properties": {"type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Type"}, "submission_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Submission Id"}, "driver_info": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Driver Info"}, "status": {"$ref": "#/components/schemas/JobStatus"}, "config": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Config"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Message"}, "error_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Error Type"}, "start_time": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Start Time"}, "end_time": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "End Time"}, "metadata": {"type": "object", "title": "Metadata"}, "runtime_env": {"type": "object", "title": "Runtime Env"}, "driver_agent_http_address": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Driver Agent Http Address"}, "driver_node_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Driver Node Id"}, "driver_exit_code": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Driver Exit Code"}, "id": {"type": "string", "format": "uuid", "title": "Id"}, "name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description"}, "job_type": {"$ref": "#/components/schemas/JobType"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "experiment_id": {"anyOf": [{"type": "string", "format": "uuid"}, {"type": "null"}], "title": "Experiment Id"}, "updated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Updated At"}}, "type": "object", "required": ["status", "id", "name", "description", "job_type", "created_at"], "title": "Job", "description": "Job represents the composition of JobResponse and JobSubmissionResponse.\n\nJobSubmissionResponse was formerly returned from some /health/jobs related\nendpoints, while JobResponse was used by /jobs related endpoints.\n\nThe only conflicting field in the two schemas is 'status' which is consistent\nin what it intends to represent, but uses different types (JobStatus/str).\n\nThe Job type has both id and submission_id which will contain the same data.\n\nNOTE: Job is intended to reduce breaking changes experienced by the UI and other\nconsumers. Tt was not conceived as a type that will be around for long, as\nthe API needs to be refactored to better support experiments."}, "JobAnnotateConfig": {"properties": {"secret_key_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Secret Key Name", "description": "An optional secret key name. When creating a job, the secret key name identifies an existing secret stored in Lumigator that should be used to access the provider."}, "model": {"type": "string", "title": "Model", "default": "facebook/bart-large-cnn"}, "provider": {"type": "string", "title": "Provider", "default": "hf"}, "task_definition": {"oneOf": [{"$ref": "#/components/schemas/SummarizationTaskDefinition"}, {"$ref": "#/components/schemas/TranslationTaskDefinition"}, {"$ref": "#/components/schemas/TextGenerationTaskDefinition"}], "title": "Task Definition", "discriminator": {"propertyName": "task", "mapping": {"summarization": "#/components/schemas/SummarizationTaskDefinition", "text-generation": "#/components/schemas/TextGenerationTaskDefinition", "translation": "#/components/schemas/TranslationTaskDefinition"}}}, "accelerator": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Accelerator", "default": "auto"}, "revision": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Revision", "default": "main"}, "use_fast": {"type": "boolean", "title": "Use Fast", "default": true}, "trust_remote_code": {"type": "boolean", "title": "Trust Remote Code", "default": false}, "torch_dtype": {"type": "string", "title": "Torch Dtype", "default": "auto"}, "base_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Base Url"}, "generation_config": {"$ref": "#/components/schemas/GenerationConfig"}, "store_to_dataset": {"type": "boolean", "title": "Store To Dataset", "default": true}, "system_prompt": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "System Prompt", "description": "System prompt to use for the model inference.If not provided, a task-specific default prompt will be used.", "examples": ["You are an advanced AI trained to summarize documents accurately and concisely. Your goal is to extract key information while maintaining clarity and coherence."]}}, "type": "object", "title": "JobAnnotateConfig", "description": "Job configuration for the annotation job type\n\nAn annotation job is a special type of inference job that is used to\nannotate a dataset with predictions from a model. The predictions are\nstored in the dataset as a new field called `ground_truth`.\n\nJobAnnotateConfig inherits from JobInferenceConfig but fixes the following\nfields, using the `SkipJsonSchema` type to prevent them from being included\nin the JSON schema:\n- job_type: Literal[JobType.ANNOTATION]\n- output_field: \"ground_truth\"\n\nIt also sets sensible defaults for the following fields:\n- store_to_dataset: True\n- model: \"facebook/bart-large-cnn\"\n- provider: \"hf\"\n\nUsers can change the model and provider fields but cannot change the\njob_type or output_field fields.\n\nNote that, currently, ground truth generation is limited to summarization\ntasks from the UI. Users can run any ground truth generation task from the\nAPI."}, "JobAnnotateCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description", "default": ""}, "dataset": {"type": "string", "format": "uuid", "title": "Dataset"}, "max_samples": {"type": "integer", "title": "Max Samples", "default": -1}, "batch_size": {"type": "integer", "exclusiveMinimum": 0.0, "title": "Batch Size", "default": 1}, "job_config": {"$ref": "#/components/schemas/JobAnnotateConfig"}}, "type": "object", "required": ["name", "dataset", "job_config"], "title": "JobAnnotateCreate"}, "JobEvalConfig": {"properties": {"secret_key_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Secret Key Name", "description": "An optional secret key name. When creating a job, the secret key name identifies an existing secret stored in Lumigator that should be used to access the provider."}, "job_type": {"type": "string", "const": "evaluator", "title": "Job Type", "default": "evaluator"}, "metrics": {"items": {"type": "string"}, "type": "array", "title": "Metrics", "default": ["rouge", "meteor", "bertscore", "bleu"]}, "llm_as_judge": {"anyOf": [{"$ref": "#/components/schemas/DeepEvalLocalModelConfig"}, {"type": "null"}]}}, "type": "object", "title": "JobEvalConfig"}, "JobEvalCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description", "default": ""}, "dataset": {"type": "string", "format": "uuid", "title": "Dataset"}, "max_samples": {"type": "integer", "title": "Max Samples", "default": -1}, "batch_size": {"type": "integer", "exclusiveMinimum": 0.0, "title": "Batch Size", "default": 1}, "job_config": {"$ref": "#/components/schemas/JobEvalConfig"}}, "type": "object", "required": ["name", "dataset", "job_config"], "title": "JobEvalCreate"}, "JobInferenceConfig": {"properties": {"secret_key_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Secret Key Name", "description": "An optional secret key name. When creating a job, the secret key name identifies an existing secret stored in Lumigator that should be used to access the provider."}, "job_type": {"type": "string", "const": "inference", "title": "Job Type", "default": "inference"}, "model": {"type": "string", "title": "Model"}, "provider": {"type": "string", "title": "Provider"}, "task_definition": {"oneOf": [{"$ref": "#/components/schemas/SummarizationTaskDefinition"}, {"$ref": "#/components/schemas/TranslationTaskDefinition"}, {"$ref": "#/components/schemas/TextGenerationTaskDefinition"}], "title": "Task Definition", "discriminator": {"propertyName": "task", "mapping": {"summarization": "#/components/schemas/SummarizationTaskDefinition", "text-generation": "#/components/schemas/TextGenerationTaskDefinition", "translation": "#/components/schemas/TranslationTaskDefinition"}}}, "accelerator": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Accelerator", "default": "auto"}, "revision": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Revision", "default": "main"}, "use_fast": {"type": "boolean", "title": "Use Fast", "default": true}, "trust_remote_code": {"type": "boolean", "title": "Trust Remote Code", "default": false}, "torch_dtype": {"type": "string", "title": "Torch Dtype", "default": "auto"}, "base_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Base Url"}, "output_field": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Output Field", "default": "predictions"}, "generation_config": {"$ref": "#/components/schemas/GenerationConfig"}, "store_to_dataset": {"type": "boolean", "title": "Store To Dataset", "default": false}, "system_prompt": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "System Prompt", "description": "System prompt to use for the model inference.If not provided, a task-specific default prompt will be used.", "examples": ["You are an advanced AI trained to summarize documents accurately and concisely. Your goal is to extract key information while maintaining clarity and coherence."]}}, "type": "object", "required": ["model", "provider"], "title": "JobInferenceConfig"}, "JobInferenceCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description", "default": ""}, "dataset": {"type": "string", "format": "uuid", "title": "Dataset"}, "max_samples": {"type": "integer", "title": "Max Samples", "default": -1}, "batch_size": {"type": "integer", "exclusiveMinimum": 0.0, "title": "Batch Size", "default": 1}, "job_config": {"$ref": "#/components/schemas/JobInferenceConfig"}}, "type": "object", "required": ["name", "dataset", "job_config"], "title": "JobInferenceCreate"}, "JobLogsResponse": {"properties": {"logs": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Logs"}}, "type": "object", "title": "JobLogsResponse"}, "JobResponse": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description"}, "status": {"$ref": "#/components/schemas/JobStatus"}, "job_type": {"$ref": "#/components/schemas/JobType"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "experiment_id": {"anyOf": [{"type": "string", "format": "uuid"}, {"type": "null"}], "title": "Experiment Id"}, "updated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Updated At"}}, "type": "object", "required": ["id", "name", "description", "status", "job_type", "created_at"], "title": "JobResponse"}, "JobResultDownloadResponse": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "download_url": {"type": "string", "title": "Download Url"}}, "type": "object", "required": ["id", "download_url"], "title": "JobResultDownloadResponse"}, "JobResultResponse": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "job_id": {"type": "string", "format": "uuid", "title": "Job Id"}}, "type": "object", "required": ["id", "job_id"], "title": "JobResultResponse"}, "JobResults": {"properties": {"id": {"type": "string", "format": "uuid", "title": "Id"}, "metrics": {"anyOf": [{"items": {"type": "object"}, "type": "array"}, {"type": "null"}], "title": "Metrics"}, "parameters": {"anyOf": [{"items": {"type": "object"}, "type": "array"}, {"type": "null"}], "title": "Parameters"}, "metric_url": {"type": "string", "title": "Metric Url"}, "artifact_url": {"type": "string", "title": "Artifact Url"}}, "type": "object", "required": ["id", "metric_url", "artifact_url"], "title": "JobResults"}, "JobStatus": {"type": "string", "enum": ["created", "pending", "running", "failed", "succeeded", "stopped"], "title": "JobStatus"}, "JobType": {"type": "string", "enum": ["inference", "evaluator", "annotate"], "title": "JobType"}, "ListingResponse_DatasetResponse_": {"properties": {"total": {"type": "integer", "title": "Total"}, "items": {"items": {"$ref": "#/components/schemas/DatasetResponse"}, "type": "array", "title": "Items"}}, "type": "object", "required": ["total", "items"], "title": "ListingResponse[DatasetResponse]"}, "ListingResponse_GetExperimentResponse_": {"properties": {"total": {"type": "integer", "title": "Total"}, "items": {"items": {"$ref": "#/components/schemas/GetExperimentResponse"}, "type": "array", "title": "Items"}}, "type": "object", "required": ["total", "items"], "title": "ListingResponse[GetExperimentResponse]"}, "ListingResponse_Job_": {"properties": {"total": {"type": "integer", "title": "Total"}, "items": {"items": {"$ref": "#/components/schemas/Job"}, "type": "array", "title": "Items"}}, "type": "object", "required": ["total", "items"], "title": "ListingResponse[Job]"}, "ListingResponse_ModelsResponse_": {"properties": {"total": {"type": "integer", "title": "Total"}, "items": {"items": {"$ref": "#/components/schemas/ModelsResponse"}, "type": "array", "title": "Items"}}, "type": "object", "required": ["total", "items"], "title": "ListingResponse[ModelsResponse]"}, "ModelInfo": {"properties": {"parameter_count": {"type": "string", "title": "Parameter Count"}, "tensor_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Tensor Type"}, "model_size": {"type": "string", "title": "Model Size"}}, "type": "object", "required": ["parameter_count", "model_size"], "title": "ModelInfo"}, "ModelRequirement": {"type": "string", "enum": ["api_key", "llamafile"], "title": "ModelRequirement", "description": "Represents a type of requirement for a model"}, "ModelsResponse": {"properties": {"display_name": {"type": "string", "title": "Model name", "description": "Name of the model used in the task. It's just a display name"}, "model": {"type": "string", "title": "Model ID", "description": "Model ID used in the task"}, "provider": {"type": "string", "title": "Model Provider", "description": "LiteLLM key for where the model is hosted (e.g. `openai`, `deepseek`, `gpt3`, etc). If using a HF model that is hosted in the inference job, use `hf`"}, "base_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Base URL", "description": "Base URL for the model API (if applicable, e.g. for Llamafile, vLLM, etc)"}, "website_url": {"type": "string", "title": "Information page URL", "description": "URI containing detailed information about the model"}, "description": {"type": "string", "title": "Model description", "description": "Detailed model description"}, "requirements": {"items": {"$ref": "#/components/schemas/ModelRequirement"}, "type": "array", "title": "Model requirements", "description": "Additional requirements that need to be fulfilled before using the model (e.g. `{ModelRequirement.LLAMAFILE}` to indicate that a llamafile needs to be running or `{ModelRequirement.API_KEY}` to indicate that an API key is necessary)"}, "info": {"anyOf": [{"$ref": "#/components/schemas/ModelInfo"}, {"type": "null"}], "title": "Model info", "description": "Detailed model capabilities"}, "tasks": {"items": {"additionalProperties": {"type": "object"}, "type": "object"}, "type": "array", "title": "Applicable tasks", "description": "List of tasks to which the model can be applied"}}, "type": "object", "required": ["display_name", "model", "provider", "website_url", "description", "tasks"], "title": "ModelsResponse", "description": "Contains detailed model information"}, "SecretGetRequest": {"properties": {"name": {"type": "string", "maxLength": 255, "minLength": 1, "title": "Name"}, "description": {"type": "string", "title": "Description"}}, "type": "object", "required": ["name", "description"], "title": "SecretGetRequest", "description": "Represents the result of a get secret request.\n\nNOTE: The secret value should never be exposed to the end user."}, "SecretUploadRequest": {"properties": {"value": {"type": "string", "maxLength": 1024, "minLength": 1, "title": "Value"}, "description": {"type": "string", "title": "Description"}}, "type": "object", "required": ["value", "description"], "title": "SecretUploadRequest", "description": "Represents a secret upload request."}, "SummarizationTaskDefinition": {"properties": {"task": {"type": "string", "const": "summarization", "title": "Task", "default": "summarization"}}, "additionalProperties": false, "type": "object", "title": "SummarizationTaskDefinition"}, "TextGenerationTaskDefinition": {"properties": {"task": {"type": "string", "const": "text-generation", "title": "Task", "default": "text-generation"}}, "additionalProperties": false, "type": "object", "title": "TextGenerationTaskDefinition"}, "TranslationTaskDefinition": {"properties": {"task": {"type": "string", "const": "translation", "title": "Task", "default": "translation"}, "source_language": {"type": "string", "title": "Source Language", "examples": ["en", "English"]}, "target_language": {"type": "string", "title": "Target Language", "examples": ["de", "German"]}}, "additionalProperties": false, "type": "object", "required": ["source_language", "target_language"], "title": "TranslationTaskDefinition"}, "ValidationError": {"properties": {"loc": {"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "type": "array", "title": "Location"}, "msg": {"type": "string", "title": "Message"}, "type": {"type": "string", "title": "Error Type"}}, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError"}, "WorkflowCreateRequest": {"properties": {"name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description", "default": ""}, "experiment_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Experiment Id"}, "model": {"type": "string", "title": "Model"}, "provider": {"type": "string", "title": "Provider"}, "secret_key_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Secret Key Name", "description": "An optional secret key name. Identifies an existing secret stored in Lumigator that should be used to access the provider."}, "batch_size": {"type": "integer", "exclusiveMinimum": 0.0, "title": "Batch Size", "default": 1}, "base_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Base Url"}, "system_prompt": {"type": "string", "title": "System Prompt", "default": ""}, "inference_output_field": {"type": "string", "title": "Inference Output Field", "default": "predictions"}, "config_template": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Config Template"}, "generation_config": {"$ref": "#/components/schemas/GenerationConfig"}, "job_timeout_sec": {"type": "integer", "exclusiveMinimum": 0.0, "title": "Job Timeout Sec", "default": 300}, "metrics": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Metrics"}}, "type": "object", "required": ["name", "model", "provider"], "title": "WorkflowCreateRequest"}, "WorkflowDetailsResponse": {"properties": {"id": {"type": "string", "title": "Id"}, "experiment_id": {"type": "string", "title": "Experiment Id"}, "model": {"type": "string", "title": "Model"}, "name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description"}, "system_prompt": {"type": "string", "title": "System Prompt"}, "status": {"$ref": "#/components/schemas/WorkflowStatus"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "updated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Updated At"}, "jobs": {"anyOf": [{"items": {"$ref": "#/components/schemas/JobResults"}, "type": "array"}, {"type": "null"}], "title": "Jobs"}, "metrics": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Metrics"}, "parameters": {"anyOf": [{"type": "object"}, {"type": "null"}], "title": "Parameters"}, "artifacts_download_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Artifacts Download Url"}}, "type": "object", "required": ["id", "experiment_id", "model", "name", "description", "system_prompt", "status", "created_at"], "title": "WorkflowDetailsResponse"}, "WorkflowResponse": {"properties": {"id": {"type": "string", "title": "Id"}, "experiment_id": {"type": "string", "title": "Experiment Id"}, "model": {"type": "string", "title": "Model"}, "name": {"type": "string", "title": "Name"}, "description": {"type": "string", "title": "Description"}, "system_prompt": {"type": "string", "title": "System Prompt"}, "status": {"$ref": "#/components/schemas/WorkflowStatus"}, "created_at": {"type": "string", "format": "date-time", "title": "Created At"}, "updated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Updated At"}}, "type": "object", "required": ["id", "experiment_id", "model", "name", "description", "system_prompt", "status", "created_at"], "title": "WorkflowResponse"}, "WorkflowStatus": {"type": "string", "enum": ["created", "running", "failed", "succeeded"], "title": "WorkflowStatus"}}}} \ No newline at end of file diff --git a/lumigator/backend/backend/services/jobs.py b/lumigator/backend/backend/services/jobs.py index 64f5e4ed5..1523bb5e9 100644 --- a/lumigator/backend/backend/services/jobs.py +++ b/lumigator/backend/backend/services/jobs.py @@ -2,6 +2,7 @@ import csv import json import re +import time from http import HTTPStatus from io import BytesIO, StringIO from pathlib import Path @@ -71,7 +72,7 @@ DEFAULT_SKIP = 0 DEFAULT_LIMIT = 100 -DEFAULT_POST_INFER_JOB_TIMEOUT_SEC = 10 * 60 +DEFAULT_POST_INFER_JOB_TIMEOUT_SEC = 5 * 60 JobSpecificRestrictedConfig = type[JobEvalConfig | JobInferenceConfig] @@ -150,8 +151,8 @@ async def stop_job(self, job_id: UUID) -> bool: return True try: - status = await self.wait_for_job_complete(job_id, max_wait_time_sec=10) - except JobUpstreamError as e: + status = await self.wait_for_job_complete(job_id, timeout_seconds=10) + except TimeoutError as e: loguru.logger.error("Failed to stop job {}: {}", job_id, e) return False @@ -369,34 +370,50 @@ def _retrieve_job_logs(self, job_id: UUID) -> JobLogsResponse: except json.JSONDecodeError as e: raise JobUpstreamError("ray", f"JSON decode error from {resp.text or ''}") from e - async def wait_for_job_complete(self, job_id, max_wait_time_sec): + async def wait_for_job_complete( + self, + job_id: UUID, + timeout_seconds: int = 300, + initial_poll_interval_seconds: float = 1.0, + max_poll_interval_seconds: float = 10.0, + backoff_factor: float = 1.5, + ): """Waits for a job to complete, or until a maximum wait time is reached. :param job_id: The ID of the job to wait for. - :param max_wait_time_sec: The maximum time in seconds to wait for the job to complete. - :return: The status of the job when it completes. - :rtype: str - :raises JobUpstreamError: If there is an error with the upstream service returning the - job status + :param timeout_seconds: The maximum time in seconds to wait for the job to complete. + :param initial_poll_interval_seconds: The initial time in seconds to wait between polling the job status. + :param max_poll_interval_seconds: The maximum time in seconds to wait between polling the job status. + :param backoff_factor: The factor by which the poll interval will increase after each poll. + :return str: The status of the job when it completes. + :raises TimeoutError: If the job does not complete within the timeout period. """ - loguru.logger.info(f"Waiting for job {job_id} to complete...") - # Get the initial job status - job_status = self.get_upstream_job_status(job_id) + start_time = time.time() + poll_interval = initial_poll_interval_seconds + previous_status = "" + loguru.logger.info(f"Waiting for job {job_id} to complete (timeout {timeout_seconds} seconds)...") - # Wait for the job to complete - elapsed_time = 0 - while job_status not in self.TERMINAL_STATUS: - if elapsed_time >= max_wait_time_sec: - loguru.logger.info(f"Job {job_id} did not complete within the maximum wait time.") - break - await asyncio.sleep(5) - elapsed_time += 5 - job_status = self.get_upstream_job_status(job_id) + while time.time() - start_time < timeout_seconds: + try: + job_status = self.get_upstream_job_status(job_id) + + if job_status in self.TERMINAL_STATUS: + # Once the job is finished, retrieve the log and store it in the internal DB + self.get_job_logs(job_id) + loguru.logger.info(f"Job {job_id}, terminal status: {job_status}") + return job_status + + if job_status != previous_status: + loguru.logger.info(f"Job {job_id}, current status: {job_status}") + previous_status = job_status - # Once the job is finished, retrieve the log and store it in the internal db - self.get_job_logs(job_id) + except JobUpstreamError as e: + loguru.logger.error("Error waiting for job {}. Cannot get upstream status: {}", job_id, e) - return job_status + await asyncio.sleep(poll_interval) + poll_interval = min(poll_interval * backoff_factor, max_poll_interval_seconds) + + raise TimeoutError(f"Job {job_id} did not complete within {timeout_seconds} seconds.") async def handle_annotation_job(self, job_id: UUID, request: JobCreate, max_wait_time_sec: int): """Long term we maybe want to move logic about how to handle a specific job @@ -409,8 +426,13 @@ async def handle_annotation_job(self, job_id: UUID, request: JobCreate, max_wait dataset_filename = self._dataset_service.get_dataset(dataset_id=request.dataset).filename dataset_filename = Path(dataset_filename).stem dataset_filename = f"{dataset_filename}-annotated.csv" + job_status = "" + + try: + job_status = await self.wait_for_job_complete(job_id, max_wait_time_sec) + except TimeoutError as e: + loguru.logger.error(f"Job {job_id} timed out after {max_wait_time_sec} seconds: {e}") - job_status = await self.wait_for_job_complete(job_id, max_wait_time_sec) if job_status == JobStatus.SUCCEEDED.value: self._add_dataset_to_db( job_id=job_id, diff --git a/lumigator/backend/backend/services/workflows.py b/lumigator/backend/backend/services/workflows.py index f5200db8a..ddeb8cbec 100644 --- a/lumigator/backend/backend/services/workflows.py +++ b/lumigator/backend/backend/services/workflows.py @@ -171,21 +171,23 @@ async def _run_inference_eval_pipeline( try: # Wait for the inference job to 'complete'. status = await self._job_service.wait_for_job_complete( - inference_job.id, max_wait_time_sec=request.job_timeout_sec + job_id=inference_job.id, timeout_seconds=request.job_timeout_sec ) if status != JobStatus.SUCCEEDED: # Trigger the failure handling logic - raise JobUpstreamError(f"Inference job {inference_job.id} failed with status '{status}'") from None + raise JobUpstreamError(f"Inference job {inference_job.id} failed with status {status}") from None # Mark the job as successful in the tracking client. await self._tracking_client.update_workflow_status(inference_run_id, WorkflowStatus.SUCCEEDED) - except JobUpstreamError as e: + except TimeoutError as timeout_exc: loguru.logger.error( - "Workflow pipeline error: Workflow {}. Inference job: {} failed: {}", workflow.id, inference_job.id, e + f"Workflow pipeline error: " + f"Workflow {workflow.id}. " + f"Inference job: {inference_job.id} failed: " + f"{timeout_exc}" ) - await self._handle_workflow_failure(workflow.id) - return + return await self._handle_workflow_failure(workflow.id) try: # Figure out the dataset filename @@ -292,7 +294,7 @@ async def _run_inference_eval_pipeline( try: # wait for the evaluation job to complete status = await self._job_service.wait_for_job_complete( - evaluation_job.id, max_wait_time_sec=request.job_timeout_sec + evaluation_job.id, timeout_seconds=request.job_timeout_sec ) if status != JobStatus.SUCCEEDED: @@ -304,7 +306,7 @@ async def _run_inference_eval_pipeline( # Mark the job as successful in the tracking client. await self._tracking_client.update_workflow_status(eval_run_id, WorkflowStatus.SUCCEEDED) - except (JobUpstreamError, ValidationError) as e: + except (TimeoutError, ValidationError) as e: loguru.logger.error( "Workflow pipeline error: Workflow {}. Evaluation job: {} failed: {}", workflow.id, evaluation_job.id, e ) diff --git a/lumigator/backend/backend/tests/integration/api/routes/test_api_workflows.py b/lumigator/backend/backend/tests/integration/api/routes/test_api_workflows.py index adf99fcb8..a30df42af 100644 --- a/lumigator/backend/backend/tests/integration/api/routes/test_api_workflows.py +++ b/lumigator/backend/backend/tests/integration/api/routes/test_api_workflows.py @@ -264,7 +264,7 @@ def run_workflow( "model": model, "provider": "hf", "experiment_id": experiment_id, - "job_timeout_sec": 1000, + "job_timeout_sec": 60 * 3, } # The timeout cannot be 0 if job_timeout_sec: @@ -503,7 +503,7 @@ def wait_for_workflow_complete(local_client: TestClient, workflow_id: UUID) -> W f"Workflow: {workflow_id}," f"request: ({attempt}/{max_attempts}), " f"status: {workflow.status}, " - f"succeeded and processed)" + f"succeeded and processed" ) return workflow diff --git a/lumigator/schemas/lumigator_schemas/workflows.py b/lumigator/schemas/lumigator_schemas/workflows.py index 2618f0c38..31f2d6ce4 100644 --- a/lumigator/schemas/lumigator_schemas/workflows.py +++ b/lumigator/schemas/lumigator_schemas/workflows.py @@ -34,7 +34,7 @@ class WorkflowCreateRequest(BaseModel): inference_output_field: str = "predictions" config_template: str | None = None generation_config: GenerationConfig = Field(default_factory=GenerationConfig) - job_timeout_sec: PositiveInt = 60 * 60 + job_timeout_sec: PositiveInt = 60 * 5 # Eventually metrics should be managed by the experiment level https://github.com/mozilla-ai/lumigator/issues/1105 metrics: list[str] | None = None