Source code for belso.translator.providers.openai

from typing import Type

from pydantic import create_model, Field as PydanticField, BaseModel

from belso.schemas import Schema, Field
from belso.utils.logging import get_logger
from belso.utils.schema_helpers import create_fallback_schema

# Replace standard logger with our custom logger
logger = get_logger(__name__)

[docs] def to_openai(schema: Type[Schema]) -> Type: """ Translate a standard schema to OpenAI GPT format (Pydantic model).\n --- ### Args - `schema`: the schema to translate.\n --- ### Returns - `Type`: the translated schema as a Pydantic model. """ try: schema_name = schema.__name__ if hasattr(schema, "__name__") else "unnamed" logger.debug(f"Starting translation of schema '{schema_name}' to OpenAI format...") field_definitions = {} # Build field definitions for Pydantic model for field in schema.fields: field_type = field.type logger.debug(f"Processing field '{field.name}' of type '{field_type.__name__}'...") if not field.required and field.default is not None: logger.debug(f"Field '{field.name}' is optional with default value: {field.default}.") field_definitions[field.name] = (field_type, PydanticField(default=field.default, description=field.description)) else: required_status = "required" if field.required else "optional without default" logger.debug(f"Field '{field.name}' is {required_status}.") field_definitions[field.name] = (field_type, PydanticField(description=field.description)) # Create a Pydantic model dynamically model_name = schema.__name__ if hasattr(schema, "__name__") else "DynamicModel" logger.debug(f"Creating Pydantic model '{model_name}' with {len(field_definitions)} fields...") pydantic_model = create_model(model_name, **field_definitions) logger.debug(f"Successfully created OpenAI schema as Pydantic model '{pydantic_model.__name__}'.") return pydantic_model except Exception as e: logger.error(f"Error translating schema to OpenAI format: {e}") logger.debug("Translation error details", exc_info=True) # Return a simple fallback model if translation fails logger.warning("Returning fallback model due to translation error.") return create_model("FallbackModel", text=(str, ...))
[docs] def from_openai(schema: Type[BaseModel]) -> Type[Schema]: """ Convert an OpenAI schema (Pydantic model) to belso Schema format.\n --- ### Args - `schema`: the schema to convert.\n --- ### Returns - `Type`: the converted schema as a standard Schema subclass. """ try: schema_name = schema.__name__ if hasattr(schema, "__name__") else "unnamed" logger.debug(f"Starting conversion from OpenAI schema '{schema_name}' to belso format...") # Create a new Schema class class ConvertedSchema(Schema): name = schema.__name__ if hasattr(schema, "__name__") else "ConvertedFromOpenAI" fields = [] # Get model fields from Pydantic model model_fields = schema.model_fields if hasattr(schema, "model_fields") else {} # For older Pydantic versions if not model_fields and hasattr(schema, "__fields__"): logger.debug("Using legacy Pydantic v1 field access.") model_fields = schema.__fields__ logger.debug(f"Found {len(model_fields)} fields in Pydantic model.") # Process each field for name, field_info in model_fields.items(): logger.debug(f"Processing field '{name}'.") # Extract field type if hasattr(field_info, "annotation"): field_type = field_info.annotation logger.debug(f"Field '{name}' has type annotation: {field_type}") elif hasattr(field_info, "type_"): field_type = field_info.type_ logger.debug(f"Field '{name}' has type_: {field_type}") else: field_type = str # Default to string logger.debug(f"Field '{name}' has no type information, defaulting to str.") # Extract description description = "" if hasattr(field_info, "description"): description = field_info.description logger.debug(f"Field '{name}' has description: '{description}'.") # Extract required status required = True if hasattr(field_info, "default") and field_info.default is not None: required = False logger.debug(f"Field '{name}' is optional with default value.") # Extract default value default = None if hasattr(field_info, "default") and field_info.default is not None: default = field_info.default logger.debug(f"Field '{name}' has default value: {default}.") ConvertedSchema.fields.append( Field( name=name, type=field_type, description=description, required=required, default=default ) ) logger.debug(f"Successfully converted OpenAI schema to belso schema with {len(ConvertedSchema.fields)} fields.") return ConvertedSchema except Exception as e: logger.error(f"Error converting OpenAI schema to belso format: {e}") logger.debug("Conversion error details", exc_info=True) # Return a minimal schema if conversion fails return create_fallback_schema()