File size: 3,163 Bytes
efd5c52
 
 
 
 
 
 
 
 
 
 
 
0e84b87
efd5c52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import os
os.environ["XDG_CONFIG_HOME"] = os.path.join(os.getcwd(), ".config")

import streamlit as st
import pandas as pd
import openai
import time

# --- CONFIG ---
st.set_page_config(page_title="πŸ–ΌοΈ Alt Text Generator", layout="wide")
VALID_IMAGE_EXTENSIONS = [".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp"]

st.title("πŸ–ΌοΈ Alt Text Generator")
st.markdown("Generate SEO-friendly alt text for image URLs using GPT-4o Vision.\nMade by [Florian Potier](https://twitter.com/FloPots)")

# --- INPUT API KEY ---
api_key = st.text_input("πŸ”‘ Enter your OpenAI API key", type="password")
if not api_key:
    st.stop()
client = openai.OpenAI(api_key=api_key)

# --- INPUT FILE ---
uploaded_file = st.file_uploader("πŸ“ Upload a CSV with image URLs", type=["csv"])
if uploaded_file:
    df = pd.read_csv(uploaded_file)
    st.success("βœ… File uploaded successfully")
    st.dataframe(df.head())

    # --- COLUMN SELECT ---
    image_col = st.selectbox("🧭 Select the column with image URLs", df.columns)

    # --- PROMPT INPUT ---
    prompt_instruction = st.text_area("πŸ“ Enter the prompt to generate alt text",
        value="Write a concise, SEO-friendly alt text for the image below. Do not use brand names unless visible.")

    def is_valid_image_url(url: str):
        return any(url.lower().endswith(ext) for ext in VALID_IMAGE_EXTENSIONS)

    df["Valid Image"] = df[image_col].astype(str).apply(is_valid_image_url)
    valid_df = df[df["Valid Image"] == True]

    if valid_df.empty:
        st.error("❌ No valid image URLs found. Make sure URLs end with .jpg, .png, .webp, etc.")
        st.stop()

    st.info(f"πŸ” {len(valid_df)} valid image URLs found. Invalid ones will be skipped.")

    # --- PROCESS ---
    if st.button("πŸš€ Start Processing"):
        progress = st.progress(0)
        results = []
        urls = valid_df[image_col].tolist()

        for idx, url in enumerate(urls):
            try:
                response = client.chat.completions.create(
                    model="gpt-4o",
                    messages=[
                        {
                            "role": "user",
                            "content": [
                                {"type": "text", "text": prompt_instruction},
                                {"type": "image_url", "image_url": {"url": url}}
                            ]
                        }
                    ]
                )
                alt_text = response.choices[0].message.content.strip()
            except Exception as e:
                alt_text = f"ERROR: {e}"

            results.append(alt_text)
            progress.progress((idx + 1) / len(urls))
            time.sleep(1)

        valid_df["Generated Alt Text"] = results
        output_df = df.copy()
        output_df.loc[valid_df.index, "Generated Alt Text"] = valid_df["Generated Alt Text"]

        st.success("βœ… Done! Preview of the results:")
        st.dataframe(output_df[[image_col, "Generated Alt Text"]].head())

        csv = output_df.to_csv(index=False).encode("utf-8")
        st.download_button("πŸ“₯ Download CSV with Alt Text", csv, "alt_text_output.csv", "text/csv")