El archivo viaja a la infraestructura del proveedor. Vuelve un objeto con un nombre, no tus bytes.
upload_file(ruta)Solo algunas modalidades. Se sondea el estado hasta que deja de estar procesándose.
get_file(nombre).stateEl objeto se pasa junto al prompt. Se reutiliza tantas veces como quieras: la subida ya está pagada.
generate_content([prompt, archivo])Liberas cuota y dejas de tener material tuyo en un servidor ajeno más tiempo del necesario.
delete_file(nombre)Verlo como un proceso único es lo que convierte cuatro lecciones sueltas en una sola cosa que aprender. Cuando llegue una modalidad nueva, la pregunta ya no es «¿cómo se hace esto?» sino «¿en qué se diferencia de estos cuatro pasos?».
El paso 2 es opcional, y ahí está la trampa: funciona todo perfecto hasta el día que subes un vídeo, porque hasta entonces el archivo siempre estaba listo al volver de la subida.
| Modalidad | ¿Listo al volver? | Qué pasa si no esperas |
|---|---|---|
| Imagen | Sí, prácticamente al instante | — |
| Documento PDF | Sí | — |
| Audio | Normalmente sí; los archivos largos, no | Estado PROCESSING al usarlo |
| Vídeo | No. Requiere procesado en servidor | Error de archivo que no está en estado activo |
El bucle de espera que el material propone es correcto, pero conviene leer lo que le falta:
while archivo.state.name == "PROCESSING":
time.sleep(5)
archivo = genai.get_file(archivo.name)
if archivo.state.name == "FAILED":
raise ValueError("El procesamiento del archivo falló.")
while no tiene techo. Si un archivo se queda atascado en procesamiento, el script
espera para siempre sin decir nada — y en un servicio, eso es un proceso colgado, no un error.
Un límite de intentos y un mensaje al superarlo cuestan dos líneas. La comprobación de
FAILED, en cambio, sí la trae el material, y es la que evita seguir adelante con una
referencia inservible.
Lo más rentable del proceso es el paso 3, y es fácil pasarlo por alto porque el material lo hace sin subrayarlo: sube el PDF una vez y luego le lanza dos prompts distintos —un resumen y una pregunta concreta— sin volver a subir nada.
archivo = genai.upload_file("informe.pdf")
resumen = modelo.generate_content(["Resume en tres párrafos.", archivo])
metodo = modelo.generate_content(["¿Qué metodología usa el autor?", archivo])
riesgos = modelo.generate_content(["Lista los riesgos que menciona.", archivo])
Eso cambia cómo se diseña un script: la subida es el coste fijo y las preguntas son el coste variable, así que agrupar todas las preguntas sobre un mismo documento en una sola ejecución sale mucho mejor que subirlo tres veces desde tres sitios distintos del código.
Pero la referencia es remota, y de ahí salen tres reglas que no aplican a un fichero local:
no sobrevive indefinidamente (guardar el nombre en una base de datos y usarlo la semana que
viene no funciona), no es tuya del todo (mientras exista, ese material está en un servidor
ajeno), y ocupa cuota mientras no la borres. El paso 4 no es limpieza cosmética: es la parte
del proceso que la mayoría se salta y la que aparece como ResourceExhausted semanas
después.
Sube un archivo y quédate con su nombre impreso por pantalla. Sin volver a subirlo, escribe un
segundo script que solo haga get_file(nombre) y muestre el estado. Córrelo al momento,
y otra vez al día siguiente.
Lo que veas la segunda vez es el dato que el material no te da: cuánto dura de verdad tu
referencia. Anótalo en auditoria/ con la fecha, porque es exactamente el tipo de límite
que cambia sin avisar.