from typing import Any, Type
from google.ai.generativelanguage_v1beta.types import content
from belso.schemas import Schema, Field
from belso.utils.logging import get_logger
from belso.utils.schema_helpers import create_fallback_schema
logger = get_logger(__name__)
[docs]
def to_google(schema: Type[Schema]) -> content.Schema:
"""
Translate a standard schema to Google Gemini format.\n
---
### Args
- `schema` (`Type[Schema]`) : the belso schema to translate.\n
---
### Returns
- `content.Schema`: a Google Gemini schema in dict format for use in the API.
"""
try:
logger.debug(f"Starting translation of schema '{schema.__name__ if hasattr(schema, '__name__') else 'unnamed'}' to Google format...")
# Type mapping for Gemini
type_mapping = {
list: content.Type.ARRAY,
bool: content.Type.BOOLEAN,
str: content.Type.STRING,
float: content.Type.NUMBER,
int: content.Type.INTEGER,
dict: content.Type.OBJECT,
Any: content.Type.TYPE_UNSPECIFIED,
}
properties = {}
required_fields = schema.get_required_fields()
logger.debug(f"Found {len(schema.fields)} fields, {len(required_fields)} required.")
# Build properties for each field
for field in schema.fields:
field_type = type_mapping.get(field.type, content.Type.TYPE_UNSPECIFIED)
logger.debug(f"Mapping field '{field.name}' of type '{field.type.__name__}' to Google type '{field_type}'...")
properties[field.name] = content.Schema(
type=field_type,
description=field.description
)
# Create the schema
gemini_schema = content.Schema(
type=content.Type.OBJECT,
properties=properties,
required=required_fields
)
logger.debug("Successfully created Google schema.")
return gemini_schema
except Exception as e:
logger.error(f"Error translating schema to Gemini format: {e}")
logger.debug("Translation error details", exc_info=True)
return {}
[docs]
def from_google(schema: content.Schema) -> Type[Schema]:
"""
Convert a Google Gemini schema to belso Schema format.\n
---
### Args
- `schema` (`content.Schema`) : the Google Gemini schema to convert.\n
---
### Returns
- `Type[Schema]`: a standard schema.
"""
try:
logger.debug("Starting conversion from Google schema to belso format...")
# Create a new Schema class
class ConvertedSchema(Schema):
name = "ConvertedFromGoogle"
fields = []
# Type mapping from Google to Python
reverse_type_mapping = {
content.Type.ARRAY: list,
content.Type.BOOLEAN: bool,
content.Type.STRING: str,
content.Type.NUMBER: float,
content.Type.INTEGER: int,
content.Type.OBJECT: dict,
content.Type.TYPE_UNSPECIFIED: Any,
}
# Extract properties
properties = schema.properties if hasattr(schema, "properties") else {}
required_fields = schema.required if hasattr(schema, "required") else []
logger.debug(f"Found {len(properties)} properties, {len(required_fields)} required fields.")
# Convert each property
for name, prop in properties.items():
field_type = reverse_type_mapping.get(prop.type, str)
description = prop.description if hasattr(prop, "description") else ""
required = name in required_fields
logger.debug(f"Converting property '{name}' of Google type '{prop.type}' to Python type '{field_type.__name__}'...")
ConvertedSchema.fields.append(
Field(
name=name,
type=field_type,
description=description,
required=required
)
)
logger.debug(f"Successfully converted Google schema to belso schema with {len(ConvertedSchema.fields)} fields.")
return ConvertedSchema
except Exception as e:
logger.error(f"Error converting Google schema to belso format: {e}")
logger.debug("Conversion error details", exc_info=True)
# Return a minimal schema if conversion fails
return create_fallback_schema()