import os import tempfile import time import mimetypes from markitdown import MarkItDown from google import genai client = genai.Client(api_key=os.getenv("GOOGLE_API_KEY")) md = MarkItDown() EXTRACTION_PROMPT = """ You are a data extraction tool feeding a text-only AI agent. Do NOT summarize. - For images: Extract all visible text (OCR) and describe the scene/charts in exhaustive detail. - For audio/video: Provide a full transcript of what is spoken. Describe key visual events or slide text if visible. Leave nothing out. """ async def process_files(files): if not files: return "", [] full_context = "" uploaded_metadata = [] for file in files: mime_type = mimetypes.guess_type(file.filename)[0] or "application/octet-stream" file_bytes = await file.read() extracted_text = "" if mime_type == "application/pdf" or "text" in mime_type or "csv" in mime_type: fd, tmp_path = tempfile.mkstemp(suffix=f"_{file.filename}") os.close(fd) with open(tmp_path, "wb") as f: f.write(file_bytes) try: result = md.convert(tmp_path) extracted_text = result.text_content except Exception as e: print(f"MarkItDown failed for {file.filename}: {e}") extracted_text = "[Failed to extract document text]" finally: os.remove(tmp_path) elif mime_type.startswith(("image/", "video/", "audio/")): ext = os.path.splitext(file.filename)[1] fd, tmp_path = tempfile.mkstemp(suffix=ext) os.close(fd) with open(tmp_path, "wb") as f: f.write(file_bytes) try: gemini_file = client.files.upload(file=tmp_path) while gemini_file.state.name == "PROCESSING": print(".", end="", flush=True) time.sleep(2) gemini_file = client.files.get(name=gemini_file.name) if gemini_file.state.name == "FAILED": raise Exception("Gemini video processing failed.") response = client.models.generate_content( model="gemini-3-flash-preview", contents=[gemini_file, EXTRACTION_PROMPT] ) extracted_text = response.text client.files.delete(name=gemini_file.name) except Exception as e: print(f"Gemini Media Extraction failed for {file.filename}: {e}") extracted_text = "[Failed to process media]" finally: os.remove(tmp_path) full_context += f"\n\n--- START OF FILE: {file.filename} ---\n{extracted_text}\n--- END OF FILE {file.filename} ---\n" uploaded_metadata.append({ "name": file.filename, "type": file.content_type, "size": file.size, }) return full_context, uploaded_metadata