from fastapi import FastAPI, UploadFile, File, Form
from fastapi.responses import HTMLResponse
import pandas as pd
import io
import re
import os
from google import genai
from PIL import Image
app = FastAPI()
# 1. THE RAW HTML FRONTEND (Upgraded with JavaScript for dynamic loading)
@app.get("/")
def main_page():
return HTMLResponse("""
PLC Reader
""")
# 2. THE PYTHON BACKEND (Now only returns the formatted tables)
@app.post("/extract")
async def extract_data(api_key_input: str = Form(""), file: UploadFile = File(...)):
try:
api_key = os.environ.get("GEMINI_API_KEY") or api_key_input
if not api_key:
return HTMLResponse("⚠️ Missing API Key. Please enter it above.
")
image_bytes = await file.read()
img = Image.open(io.BytesIO(image_bytes))
client = genai.Client(api_key=api_key)
prompt = "Carefully extract all the data tables from this dashboard image. Format the output strictly as CSV. Enclose the CSV data inside ```csv ``` code blocks. Ensure column headers are included."
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=[prompt, img]
)
csv_blocks = re.findall(r'```csv\n(.*?)\n```', response.text, re.DOTALL)
if not csv_blocks:
return HTMLResponse(f"⚠️ No tables found. The model couldn't detect clear tables.
Raw Output:
{response.text} ")
# Build the HTML snippet for the tables
html_output = f"✅ Extracted {len(csv_blocks)} Table(s)
"
for i, csv_data in enumerate(csv_blocks):
df = pd.read_csv(io.StringIO(csv_data))
html_output += f"Table {i+1}
"
html_output += f"{df.to_html(index=False, border=0)}
"
return HTMLResponse(html_output)
except Exception as e:
return HTMLResponse(f"❌ Error Processing Image:
{str(e)}
")