MAX_API_RETRIES=3 from pydantic import BaseModel import pydantic_core._pydantic_core as pydantic_core from fastapi import FastAPI import json,requests app = FastAPI() def morph(valor,tipo): if isinstance(valor,dict): return tipo(valor) elif isinstance(valor,list): return list(map(lambda v:morph(v,tipo),valor)) else: return valor class ResponseData(BaseModel): error:bool message:str class Diccionario: def __init__(self,diccionario:dict): self.d = diccionario def __str__(self): return json.dumps(self.d) def __repr__(self): return self.__str__() def __getattr__(self,data:str): attr = self.d.get(data,None) return morph(attr,Diccionario) class Mensaje(BaseModel): content:str = "" role:str = "user" class persona(BaseModel): nombres:str apellidos:str edad:int personalidad:str biografia:str pais:str sexo:str hobbies:list[str] class personaje(BaseModel): interpretador:persona nombre:str personalidad:str apariencia:str papel:str edad:int class pelicula(BaseModel): personajes: list[personaje] titulo:str traduccion:dict[str,str] sinopsis:str duracion:int detailed_image_token_prompt_english:list[str] class trabajador(BaseModel): identidad:persona trabajo:str sueldo:int remoto:bool=False historial_sueldo:list[str] class comentario(BaseModel): mensaje:str autor:persona likes:int dislikes:int class publicacion(BaseModel): mensaje:str likes:int dislikes:int visitas:int comentarios:list[comentario] class perfil(BaseModel): data:persona amigos:list[persona] publicaciones:list[publicacion] class steamgame(BaseModel): nombre:str descripcion_corta:str descripcion_larga:str reviews:list[comentario] calificacion:int descargas:int class episodio(BaseModel): personajes_involucrados:list[personaje] dialogos:list[dict[int,dict[str,str]]] descripcion:str class serie(BaseModel): nombre:str personajes:list[personaje] clasificacion:str rating:int episodios:int lista_episodios:list[episodio] def ask(query:str,system_prompt:str)->ResponseData: msgs:list[dict[str,str]] = [ Mensaje(role="system",content=system_prompt).model_dump(), Mensaje(content=query).model_dump() ] response = requests.post("https://text.pollinations.ai/openai",json={ "messages":msgs, "private":True, "jsonMode":True, "model":"openai", "seed":__import__("random").randint(10000,999999) }) data=response.json() error_msg = Diccionario(data).error structured_data = ResponseData(error=True if error_msg else False,message=error_msg or Diccionario(data).choices[0].message.content) return structured_data def generate_model(model:BaseModel,gived_data:BaseModel=None,retries=0)->BaseModel | None: system = f"""Eres un generador de contenido avanzado(evita contenido repetido) capaz de comprender cualquier contexto, debes generar un json valido con estas propiedades, las claves son los valores de title y los valores deben ser del mismo tipo que el valor de type, el title que esta por fuera de propierties debe ser el tipo general, tipo el que contiene todas las propiedades,no realices ningun comentario o acotacion,otorga un json valido,las claves deben estar en minuscula pero los valores no necesariamente""" if gived_data: system+=f"\n Ademas tengo esta informacion: {gived_data.model_dump_json()}" resultado = ask(json.dumps(model.model_json_schema()),system) if resultado.error==True: return {"error":resultado.message} try: data = list(json.loads(resultado.message).values())[0] if retries>MAX_API_RETRIES: return {"error":"Se ha intentado, pero no hubo caso, prueba nuevamente","failed_data":data} if isinstance(data,str): retries+=1 return generate_model(model,gived_data,retries) return model(**(data)) except (pydantic_core.ValidationError, json.JSONDecodeError) as e: retries+=1 return generate_model(model,gived_data,retries) models:BaseModel= [ persona, pelicula, trabajador, publicacion, perfil, steamgame, serie ] def create_handler(model_class: BaseModel): def handler() -> dict: generated=generate_model(model_class) return generated if isinstance(generated,dict) else json.loads(generated.model_dump_json()) handler.__name__=f"Crear {model_class.__name__}" return handler for model in models: app.add_api_route(f"/{model.__name__}",create_handler(model)) @app.post("/generate_movie") def gen_movie(user:persona): return generate_model(pelicula,user)