Spaces:
Sleeping
Sleeping
Update src/app.py
Browse files- src/app.py +141 -1
src/app.py
CHANGED
@@ -1,2 +1,142 @@
|
|
|
|
|
|
|
|
1 |
|
2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Streamlit web interface for the Logo Downloader
|
3 |
+
"""
|
4 |
|
5 |
+
import os
|
6 |
+
import logging
|
7 |
+
import streamlit as st
|
8 |
+
from pathlib import Path
|
9 |
+
from typing import Optional
|
10 |
+
|
11 |
+
from services.logo_downloader import LogoDownloader
|
12 |
+
from services.appconfig import GEMINI_API_KEY, DEFAULT_LOGOS_PER_ENTITY, MAX_LOGOS_PER_ENTITY
|
13 |
+
|
14 |
+
# Setup logging
|
15 |
+
logging.basicConfig(level=logging.INFO)
|
16 |
+
logger = logging.getLogger(__name__)
|
17 |
+
|
18 |
+
|
19 |
+
def process_text_request(text: str, api_key: Optional[str], num_logos: int = DEFAULT_LOGOS_PER_ENTITY):
|
20 |
+
"""
|
21 |
+
Process text and download logos through Streamlit interface
|
22 |
+
"""
|
23 |
+
try:
|
24 |
+
if not text or not text.strip():
|
25 |
+
return "β Please provide some text to analyze.", None, "No text provided."
|
26 |
+
|
27 |
+
if num_logos < 1 or num_logos > MAX_LOGOS_PER_ENTITY:
|
28 |
+
return f"β Number of logos must be between 1 and {MAX_LOGOS_PER_ENTITY}.", None, f"Invalid number: {num_logos}"
|
29 |
+
|
30 |
+
final_api_key = api_key.strip() if api_key and api_key.strip() else GEMINI_API_KEY
|
31 |
+
|
32 |
+
downloader = LogoDownloader(gemini_api_key=final_api_key)
|
33 |
+
results = downloader.process_text(text, num_logos)
|
34 |
+
|
35 |
+
if results['status'] == 'success' and results['stats']['total_downloads'] > 0:
|
36 |
+
status_msg = f"β
{downloader.get_stats_summary()}"
|
37 |
+
zip_path = results.get('zip_path')
|
38 |
+
detailed_results = _format_detailed_results(results)
|
39 |
+
return status_msg, zip_path, detailed_results
|
40 |
+
|
41 |
+
elif results['status'] == 'warning':
|
42 |
+
return f"β οΈ {results['message']}", None, results.get('message', 'No details available')
|
43 |
+
|
44 |
+
else:
|
45 |
+
return f"β Processing failed: {results['message']}", None, results.get('message', 'Unknown error')
|
46 |
+
|
47 |
+
except Exception as e:
|
48 |
+
logger.error(f"Error in process_text_request: {e}")
|
49 |
+
return f"β An error occurred: {str(e)}", None, f"Error details: {str(e)}"
|
50 |
+
|
51 |
+
|
52 |
+
def _format_detailed_results(results):
|
53 |
+
if not results.get('results'):
|
54 |
+
return "No detailed results available."
|
55 |
+
|
56 |
+
details = []
|
57 |
+
details.append(f"π **Processing Summary:**")
|
58 |
+
details.append(f"- Total entities found: {results['stats']['total_entities']}")
|
59 |
+
details.append(f"- Total logos downloaded: {results['stats']['total_downloads']}")
|
60 |
+
details.append(f"- Successful entities: {results['stats']['successful_entities']}")
|
61 |
+
details.append(f"- Failed entities: {results['stats']['failed_entities']}")
|
62 |
+
details.append("")
|
63 |
+
details.append("π **Entity Details:**")
|
64 |
+
|
65 |
+
for result in results['results']:
|
66 |
+
entity = result['entity']
|
67 |
+
count = result['downloaded_count']
|
68 |
+
if count > 0:
|
69 |
+
details.append(f"β
**{entity}**: {count} logos downloaded")
|
70 |
+
else:
|
71 |
+
error_msg = result.get('error', 'No logos found')
|
72 |
+
details.append(f"β **{entity}**: Failed ({error_msg})")
|
73 |
+
|
74 |
+
return "\n".join(details)
|
75 |
+
|
76 |
+
|
77 |
+
def main():
|
78 |
+
st.set_page_config(page_title="π¨ Logo Downloader", layout="centered")
|
79 |
+
st.title("π¨ Logo Downloader")
|
80 |
+
st.markdown("Extract entities from text and download their logos automatically.")
|
81 |
+
|
82 |
+
with st.form(key="logo_form"):
|
83 |
+
text_input = st.text_area(
|
84 |
+
"π Enter text containing company names, products, or brands:",
|
85 |
+
placeholder="e.g., We use AWS, Docker, React, and Adobe Photoshop for our projects",
|
86 |
+
height=150
|
87 |
+
)
|
88 |
+
|
89 |
+
api_key_input = st.text_input(
|
90 |
+
"π Gemini API Key (optional)",
|
91 |
+
type="password",
|
92 |
+
placeholder="Enter your Gemini API key for enhanced extraction"
|
93 |
+
)
|
94 |
+
|
95 |
+
num_logos_input = st.slider(
|
96 |
+
"πΌοΈ Logos per entity",
|
97 |
+
min_value=1,
|
98 |
+
max_value=MAX_LOGOS_PER_ENTITY,
|
99 |
+
value=DEFAULT_LOGOS_PER_ENTITY,
|
100 |
+
step=1
|
101 |
+
)
|
102 |
+
|
103 |
+
submit_btn = st.form_submit_button("π Download Logos")
|
104 |
+
|
105 |
+
if submit_btn:
|
106 |
+
with st.spinner("Processing logos..."):
|
107 |
+
status_msg, zip_path, detailed_results = process_text_request(
|
108 |
+
text_input,
|
109 |
+
api_key_input,
|
110 |
+
num_logos_input
|
111 |
+
)
|
112 |
+
st.markdown(status_msg)
|
113 |
+
|
114 |
+
if zip_path and Path(zip_path).exists():
|
115 |
+
with open(zip_path, "rb") as f:
|
116 |
+
st.download_button(
|
117 |
+
label="π₯ Download Logos ZIP",
|
118 |
+
data=f,
|
119 |
+
file_name=Path(zip_path).name,
|
120 |
+
mime="application/zip"
|
121 |
+
)
|
122 |
+
|
123 |
+
st.markdown("## π Detailed Results")
|
124 |
+
st.markdown(detailed_results)
|
125 |
+
|
126 |
+
st.markdown("---")
|
127 |
+
st.info("π‘ Tip: Get a free Gemini API key at [Google AI Studio](https://makersuite.google.com/app/apikey) for better extraction accuracy.")
|
128 |
+
|
129 |
+
st.markdown("## π‘ Examples")
|
130 |
+
examples = [
|
131 |
+
"Our tech stack includes React, Node.js, MongoDB, Docker, AWS, and we use Figma for design, along with GitHub for version control.",
|
132 |
+
"The team uses Microsoft Office, Adobe Creative Suite, Slack for communication, Zoom for meetings, and Salesforce for CRM.",
|
133 |
+
"Popular social media platforms like Instagram, TikTok, Twitter, LinkedIn, and YouTube are essential for digital marketing."
|
134 |
+
]
|
135 |
+
|
136 |
+
for ex in examples:
|
137 |
+
if st.button(f"Use example: {ex[:50]}..."):
|
138 |
+
st.session_state["text_input"] = ex
|
139 |
+
|
140 |
+
|
141 |
+
if __name__ == "__main__":
|
142 |
+
main()
|