| | import ast |
| | import json |
| | from jsonschema import validate |
| | from pydantic import ValidationError |
| | from logger import logger |
| | from utils import extract_json_from_markdown |
| | from schema import FunctionCall, FunctionSignature |
| |
|
| |
|
| | def validate_function_call_schema(call, signatures): |
| | try: |
| | call_data = FunctionCall(**call) |
| | except ValidationError as e: |
| | return False, str(e) |
| |
|
| | for signature in signatures: |
| | try: |
| | signature_data = FunctionSignature(**signature) |
| | if signature_data.function.name == call_data.name: |
| | |
| | for arg_name, arg_schema in signature_data.function.parameters.get( |
| | "properties", {} |
| | ).items(): |
| | if arg_name in call_data.arguments: |
| | call_arg_value = call_data.arguments[arg_name] |
| | if call_arg_value: |
| | try: |
| | validate_argument_type( |
| | arg_name, call_arg_value, arg_schema |
| | ) |
| | except Exception as arg_validation_error: |
| | return False, str(arg_validation_error) |
| |
|
| | |
| | required_arguments = signature_data.function.parameters.get( |
| | "required", [] |
| | ) |
| | result, missing_arguments = check_required_arguments( |
| | call_data.arguments, required_arguments |
| | ) |
| | if not result: |
| | return False, f"Missing required arguments: {missing_arguments}" |
| |
|
| | return True, None |
| | except Exception as e: |
| | |
| | return False, str(e) |
| |
|
| | |
| | return False, f"No matching function signature found for function: {call_data.name}" |
| |
|
| |
|
| | def check_required_arguments(call_arguments, required_arguments): |
| | missing_arguments = [arg for arg in required_arguments if arg not in call_arguments] |
| | return not bool(missing_arguments), missing_arguments |
| |
|
| |
|
| | def validate_enum_value(arg_name, arg_value, enum_values): |
| | if arg_value not in enum_values: |
| | raise Exception( |
| | f"Invalid value '{arg_value}' for parameter {arg_name}. Expected one of {', '.join(map(str, enum_values))}" |
| | ) |
| |
|
| |
|
| | def validate_argument_type(arg_name, arg_value, arg_schema): |
| | arg_type = arg_schema.get("type", None) |
| | if arg_type: |
| | if arg_type == "string" and "enum" in arg_schema: |
| | enum_values = arg_schema["enum"] |
| | if None not in enum_values and enum_values != []: |
| | try: |
| | validate_enum_value(arg_name, arg_value, enum_values) |
| | except Exception as e: |
| | |
| | raise Exception(f"Error validating function call: {e}") |
| |
|
| | python_type = get_python_type(arg_type) |
| | if not isinstance(arg_value, python_type): |
| | raise Exception( |
| | f"Type mismatch for parameter {arg_name}. Expected: {arg_type}, Got: {type(arg_value)}" |
| | ) |
| |
|
| |
|
| | def get_python_type(json_type): |
| | type_mapping = { |
| | "string": str, |
| | "number": (int, float), |
| | "integer": int, |
| | "boolean": bool, |
| | "array": list, |
| | "object": dict, |
| | "null": type(None), |
| | } |
| | return type_mapping[json_type] |
| |
|
| |
|
| | def validate_json_data(json_object, json_schema): |
| | valid = False |
| | error_message = None |
| | result_json = None |
| |
|
| | try: |
| | |
| | try: |
| | result_json = json.loads(json_object) |
| | except json.decoder.JSONDecodeError: |
| | |
| | try: |
| | result_json = ast.literal_eval(json_object) |
| | except (SyntaxError, ValueError) as e: |
| | try: |
| | result_json = extract_json_from_markdown(json_object) |
| | except Exception as e: |
| | error_message = f"JSON decoding error: {e}" |
| | logger.info(f"Validation failed for JSON data: {error_message}") |
| | return valid, result_json, error_message |
| |
|
| | |
| | if result_json is None: |
| | error_message = "Failed to decode JSON data" |
| | logger.info(f"Validation failed for JSON data: {error_message}") |
| | return valid, result_json, error_message |
| |
|
| | |
| | if isinstance(result_json, list): |
| | for index, item in enumerate(result_json): |
| | try: |
| | validate(instance=item, schema=json_schema) |
| | logger.info(f"Item {index+1} is valid against the schema.") |
| | except ValidationError as e: |
| | error_message = f"Validation failed for item {index+1}: {e}" |
| | break |
| | else: |
| | |
| | try: |
| | validate(instance=result_json, schema=json_schema) |
| | except ValidationError as e: |
| | error_message = f"Validation failed: {e}" |
| |
|
| | except Exception as e: |
| | error_message = f"Error occurred: {e}" |
| |
|
| | if error_message is None: |
| | valid = True |
| | logger.info("JSON data is valid against the schema.") |
| | else: |
| | logger.info(f"Validation failed for JSON data: {error_message}") |
| |
|
| | return valid, result_json, error_message |
| |
|