Flopot2 commited on
Commit
bc65c4d
Β·
verified Β·
1 Parent(s): f94e7a2

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +93 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,95 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
1
  import streamlit as st
2
+ import pandas as pd
3
+ import openai
4
+ import re
5
+ import asyncio
6
+ import httpx
7
+ import time
8
+ from io import StringIO
9
+ from typing import List
10
+
11
+ # --- CONFIG ---
12
+ st.set_page_config(page_title="πŸ–ΌοΈ Alt Text Generator", layout="wide")
13
+ VALID_IMAGE_EXTENSIONS = [".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp"]
14
+
15
+ st.title("πŸ–ΌοΈ AI Alt Text Generator")
16
+ st.markdown("Generate SEO-friendly alt text for image URLs using GPT-4o Vision.\nMade by [Florian Potier](https://twitter.com/FloPots)")
17
+
18
+ # --- INPUT API KEY ---
19
+ api_key = st.text_input("πŸ”‘ Enter your OpenAI API key", type="password")
20
+ if not api_key:
21
+ st.stop()
22
+ openai_client = openai.AsyncOpenAI(api_key=api_key)
23
+
24
+ # --- INPUT FILE ---
25
+ uploaded_file = st.file_uploader("πŸ“ Upload a CSV with image URLs", type=["csv"])
26
+ if not uploaded_file:
27
+ st.stop()
28
+
29
+ df = pd.read_csv(uploaded_file)
30
+ st.success("βœ… File uploaded successfully")
31
+ st.dataframe(df.head())
32
+
33
+ # --- COLUMN SELECT ---
34
+ image_col = st.selectbox("🧭 Select the column with image URLs", df.columns)
35
+
36
+ # --- PROMPT INPUT ---
37
+ prompt_instruction = st.text_area("πŸ“ Enter the prompt to generate alt text",
38
+ value="Write a concise, SEO-friendly alt text for the image below. Do not use brand names unless visible.")
39
+
40
+ # --- FILTER IMAGES ---
41
+ def is_valid_image_url(url: str):
42
+ return any(url.lower().endswith(ext) for ext in VALID_IMAGE_EXTENSIONS)
43
+
44
+ df["Valid Image"] = df[image_col].astype(str).apply(is_valid_image_url)
45
+ valid_df = df[df["Valid Image"] == True]
46
+
47
+ if valid_df.empty:
48
+ st.error("❌ No valid image URLs found. Make sure URLs end with .jpg, .png, .webp, etc.")
49
+ st.stop()
50
+
51
+ st.info(f"πŸ” {len(valid_df)} valid image URLs found. Invalid ones will be skipped.")
52
+
53
+ # --- GENERATE ALT TEXT ---
54
+ async def generate_alt_text(url: str, prompt: str):
55
+ try:
56
+ response = await openai_client.chat.completions.create(
57
+ model="gpt-4o",
58
+ messages=[
59
+ {
60
+ "role": "user",
61
+ "content": [
62
+ {"type": "text", "text": prompt},
63
+ {"type": "image_url", "image_url": {"url": url}}
64
+ ]
65
+ }
66
+ ]
67
+ )
68
+ return response.choices[0].message.content.strip()
69
+ except Exception as e:
70
+ return f"ERROR: {e}"
71
+
72
+ st.markdown("### πŸš€ Run Alt Text Generation")
73
+ if st.button("Start Processing"):
74
+ progress = st.progress(0)
75
+ results = []
76
+ urls = valid_df[image_col].tolist()
77
+
78
+ async def run_all():
79
+ for idx, url in enumerate(urls):
80
+ alt_text = await generate_alt_text(url, prompt_instruction)
81
+ results.append(alt_text)
82
+ progress.progress((idx + 1) / len(urls))
83
+ await asyncio.sleep(1) # polite delay
84
+
85
+ asyncio.run(run_all())
86
+
87
+ valid_df["Generated Alt Text"] = results
88
+ output_df = df.copy()
89
+ output_df.loc[valid_df.index, "Generated Alt Text"] = valid_df["Generated Alt Text"]
90
+
91
+ st.success("βœ… Done! Preview of the results:")
92
+ st.dataframe(output_df[[image_col, "Generated Alt Text"]].head())
93
 
94
+ csv = output_df.to_csv(index=False).encode("utf-8")
95
+ st.download_button("πŸ“₯ Download CSV with Alt Text", csv, "alt_text_output.csv", "text/csv")