| 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 |
|
|