ludwig-ai--ludwig
593b94c120
pytest / Unit Tests (push) Has been cancelled
pytest / Integration (integration_tests_a) (push) Has been cancelled
pytest / Integration (integration_tests_b) (push) Has been cancelled
pytest / Integration (integration_tests_c) (push) Has been cancelled
pytest / Integration (integration_tests_d) (push) Has been cancelled
pytest / Integration (integration_tests_e) (push) Has been cancelled
pytest / Integration (integration_tests_f) (push) Has been cancelled
pytest / Integration (integration_tests_g) (push) Has been cancelled
pytest / Integration (integration_tests_h) (push) Has been cancelled
pytest / Integration (integration_tests_i) (push) Has been cancelled
pytest / Integration (integration_tests_j) (push) Has been cancelled
pytest / Distributed (distributed_a) (push) Has been cancelled
pytest / Distributed (distributed_b) (push) Has been cancelled
pytest / Distributed (distributed_c) (push) Has been cancelled
pytest / Distributed (distributed_d) (push) Has been cancelled
pytest / Distributed (distributed_e) (push) Has been cancelled
pytest / Distributed (distributed_f) (push) Has been cancelled
pytest / Minimal Install (push) Has been cancelled
pytest / Event File (push) Has been cancelled
pytest (slow) / py-slow (push) Has been cancelled
Publish JSON Schema / publish-schema (push) Has been cancelled
76 行
3.0 KiB
Python
76 行
3.0 KiB
Python
from functools import lru_cache
|
|
from threading import Lock
|
|
|
|
import jsonschema.exceptions
|
|
from jsonschema import Draft7Validator, validate
|
|
from jsonschema.validators import extend
|
|
|
|
from ludwig.api_annotations import DeveloperAPI
|
|
from ludwig.constants import BASE_MODEL, MODEL_ECD, MODEL_LLM, MODEL_TYPE
|
|
from ludwig.error import ConfigValidationError
|
|
|
|
# TODO(travis): figure out why we need these imports to avoid circular import error
|
|
from ludwig.schema.combiners.utils import get_combiner_jsonschema # noqa
|
|
from ludwig.schema.features.utils import get_input_feature_jsonschema, get_output_feature_jsonschema # noqa
|
|
from ludwig.schema.hyperopt import get_hyperopt_jsonschema # noqa
|
|
from ludwig.schema.trainer import get_model_type_jsonschema, get_trainer_jsonschema # noqa
|
|
from ludwig.schema.utils import unload_jsonschema_from_config_class
|
|
|
|
VALIDATION_LOCK = Lock()
|
|
|
|
|
|
@DeveloperAPI
|
|
@lru_cache(maxsize=3)
|
|
def get_schema(model_type: str = MODEL_ECD):
|
|
# Force populate combiner registry:
|
|
import ludwig.combiners.combiners # noqa: F401
|
|
from ludwig.schema.model_types.base import model_type_schema_registry
|
|
|
|
cls = model_type_schema_registry[model_type]
|
|
props = unload_jsonschema_from_config_class(cls)["properties"]
|
|
|
|
required = ["input_features", "output_features"]
|
|
if model_type == MODEL_LLM:
|
|
required += [BASE_MODEL]
|
|
|
|
return {
|
|
"type": "object",
|
|
"properties": props,
|
|
"title": "model_options",
|
|
"description": "Settings for Ludwig configuration",
|
|
"required": required,
|
|
"additionalProperties": True,
|
|
}
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
def get_validator():
|
|
# Manually add support for tuples (pending upstream changes: https://github.com/Julian/jsonschema/issues/148):
|
|
def custom_is_array(checker, instance):
|
|
return isinstance(instance, list) or isinstance(instance, tuple)
|
|
|
|
# This creates a new class, so cache to prevent a memory leak:
|
|
# https://github.com/python-jsonschema/jsonschema/issues/868
|
|
type_checker = Draft7Validator.TYPE_CHECKER.redefine("array", custom_is_array)
|
|
return extend(Draft7Validator, type_checker=type_checker)
|
|
|
|
|
|
@DeveloperAPI
|
|
def check_schema(updated_config):
|
|
"""Emulates the pure JSONSchema validation that could be used in an environment without marshmallow.
|
|
|
|
The incoming config may not be comprehensive, but is assumed to be up to date with the latest ludwig schema.
|
|
"""
|
|
model_type = updated_config.get(MODEL_TYPE, MODEL_ECD)
|
|
error = None
|
|
with VALIDATION_LOCK:
|
|
try:
|
|
validate(instance=updated_config, schema=get_schema(model_type=model_type), cls=get_validator())
|
|
except jsonschema.exceptions.ValidationError as e:
|
|
# Capture error but don't raise here, otherwise we get the full output from `e`, which contains a dump
|
|
# of the entire schema
|
|
error = e
|
|
|
|
if error is not None:
|
|
raise ConfigValidationError(f"Failed to validate JSON schema for config. Error: {error.message}") from error
|