PabloRR10Apple commited on
Commit
e5d4b6d
·
unverified ·
1 Parent(s): f66ac51

Updated URL option

Browse files
Files changed (5) hide show
  1. .gitignore +1 -0
  2. Dockerfile +2 -1
  3. Dockerfile.simple +30 -0
  4. Makefile +27 -14
  5. src/streamlit_app.py +42 -36
.gitignore CHANGED
@@ -3,4 +3,5 @@
3
  .vscode/
4
  .cache/
5
  resources/
 
6
 
 
3
  .vscode/
4
  .cache/
5
  resources/
6
+ **/__pycache__/
7
 
Dockerfile CHANGED
@@ -30,7 +30,8 @@ COPY requirements.txt ./
30
  COPY src/ ./src/
31
  COPY data/ ./data/
32
 
33
- RUN pip3 install -r requirements.txt
 
34
 
35
  EXPOSE 8501
36
 
 
30
  COPY src/ ./src/
31
  COPY data/ ./data/
32
 
33
+ RUN pip3 install --user -r requirements.txt
34
+ ENV PATH=$HOME/.local/bin:$PATH
35
 
36
  EXPOSE 8501
37
 
Dockerfile.simple ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ # Create a non-root user and set up home
4
+ RUN useradd -m appuser
5
+ USER appuser
6
+ ENV HOME=/home/appuser
7
+ WORKDIR $HOME
8
+
9
+ # Copy code and requirements
10
+ COPY requirements.txt ./
11
+ COPY src/ ./src/
12
+ COPY data/ ./data/
13
+
14
+ # Install Python dependencies for the user
15
+ RUN pip3 install --user -r requirements.txt
16
+
17
+ # Make sure user-level bin is in PATH
18
+ ENV PATH=$HOME/.local/bin:$PATH
19
+
20
+ # (Optional) Set up cache for torch if needed
21
+ RUN mkdir -p $HOME/.cache/torch
22
+
23
+ # Expose Streamlit's default port
24
+ EXPOSE 8501
25
+
26
+ # Disable XSRF protection for compatibility (optional, but safe for student demos)
27
+ ENV ENABLE_XSRF_PROTECTION=false
28
+
29
+ # Run the Streamlit app
30
+ ENTRYPOINT ["streamlit", "run", "src/streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
Makefile CHANGED
@@ -1,30 +1,43 @@
1
- # Docker image name
2
- IMAGE_NAME = pokemon-similarity-hf-app
3
- CONTAINER_NAME = pokedex-container
 
4
 
5
- # Default port for Streamlit
 
 
6
  PORT = 8501
7
 
8
- .PHONY: build run clean
9
 
10
- # Build the Docker image
11
  build:
12
- docker build -t $(IMAGE_NAME) .
13
 
14
- # Run the Docker container
15
  run:
 
 
 
 
 
 
 
16
  docker run -d \
17
  --name $(CONTAINER_NAME) \
18
  -p $(PORT):8501 \
19
  $(IMAGE_NAME)
20
 
21
- # Stop and remove the container
22
- clean:
23
  docker stop $(CONTAINER_NAME) || true
 
 
 
24
  docker rm $(CONTAINER_NAME) || true
25
 
26
- # Build and run in one command
27
- up: build run
28
 
29
- # Stop and remove container, then rebuild and run
30
- restart: clean up
 
1
+ # Python environment
2
+ PROJECT_ROOT = $(shell pwd)
3
+ VENV = $(PROJECT_ROOT)/.venv
4
+ PYTHON_ENV = $(VENV)/bin/python
5
 
6
+ # Docker image and container names for the student demo
7
+ IMAGE_NAME = streamlit-student-demo
8
+ CONTAINER_NAME = streamlit-student-demo-container
9
  PORT = 8501
10
 
11
+ .PHONY: build run run-detached stop clean up restart
12
 
13
+ # Build the Docker image using Dockerfile.simple
14
  build:
15
+ docker build -f Dockerfile.simple -t $(IMAGE_NAME) .
16
 
17
+ # Run the Docker container interactively (foreground)
18
  run:
19
+ docker run --rm -it \
20
+ --name $(CONTAINER_NAME) \
21
+ -p $(PORT):8501 \
22
+ $(IMAGE_NAME)
23
+
24
+ # Run the Docker container in detached mode (background)
25
+ run-detached:
26
  docker run -d \
27
  --name $(CONTAINER_NAME) \
28
  -p $(PORT):8501 \
29
  $(IMAGE_NAME)
30
 
31
+ # Stop the running container
32
+ stop:
33
  docker stop $(CONTAINER_NAME) || true
34
+
35
+ # Remove the container (if stopped)
36
+ clean:
37
  docker rm $(CONTAINER_NAME) || true
38
 
39
+ # Build and run in one command (detached)
40
+ up: build run-detached
41
 
42
+ # Stop, remove, rebuild, and run
43
+ restart: stop clean up
src/streamlit_app.py CHANGED
@@ -31,45 +31,51 @@ similarity_engine = get_similarity_engine()
31
  # Title and description
32
  st.title("🎮 Pokemon Similarity Finder")
33
  st.markdown("""
34
- Upload an image of a Pokemon and we'll find the closest match in our database!
35
  """)
36
 
37
- # File uploader
38
  uploaded_file = st.file_uploader("Choose a Pokemon image...", type=["jpg", "jpeg", "png"])
 
39
 
 
 
 
40
  if uploaded_file is not None:
41
- logger.info(f"File uploaded: {uploaded_file.name}")
42
- try:
43
- # Display the uploaded image
44
- image = Image.open(uploaded_file)
45
- st.image(image, caption="Uploaded Image", use_column_width=True)
46
- logger.info("Successfully displayed uploaded image")
47
-
48
- # Add a button to trigger the similarity search
49
- if st.button("Find Similar Pokemon"):
50
- logger.info("Find Similar Pokemon button clicked")
51
- with st.spinner("Analyzing image..."):
52
- try:
53
- # Get the image bytes
54
- img_bytes = uploaded_file.getvalue()
55
- logger.info(f"Image size: {len(img_bytes)} bytes")
56
-
57
- # Find the closest Pokemon
58
- logger.info("Finding closest Pokemon match...")
59
- pokemon_name = similarity_engine.find_closest_pokemon(img_bytes)
60
- logger.info(f"Found closest Pokemon: {pokemon_name}")
61
-
62
- # Display the result
63
- st.success(f"🎯 The closest Pokemon is: **{pokemon_name}**")
64
-
65
- # Add some fun styling
66
- st.balloons()
67
- except Exception as e:
68
- logger.error(f"Error during Pokemon matching: {str(e)}")
69
- st.error(f"❌ Error: {str(e)}")
70
- st.info("Please try uploading a different image or try again later.")
71
- except Exception as e:
72
- logger.error(f"Error loading image: {str(e)}")
73
- st.error(f"❌ Error loading image: {str(e)}")
74
- st.info("Please make sure you've uploaded a valid image file.")
 
 
75
 
 
31
  # Title and description
32
  st.title("🎮 Pokemon Similarity Finder")
33
  st.markdown("""
34
+ Upload an image of a Pokemon or provide an image URL and we'll find the closest match in our database!
35
  """)
36
 
37
+ # File uploader and URL input
38
  uploaded_file = st.file_uploader("Choose a Pokemon image...", type=["jpg", "jpeg", "png"])
39
+ image_url = st.text_input("Or enter an image URL:")
40
 
41
+ # Determine which input to use
42
+ image_input = None
43
+ input_type = None
44
  if uploaded_file is not None:
45
+ image_input = uploaded_file.getvalue()
46
+ input_type = 'file'
47
+ elif image_url:
48
+ image_input = image_url
49
+ input_type = 'url'
50
+
51
+ if image_input is not None:
52
+ if input_type == 'file':
53
+ logger.info(f"File uploaded: {uploaded_file.name}")
54
+ try:
55
+ # Display the uploaded image
56
+ image = Image.open(io.BytesIO(image_input))
57
+ st.image(image, caption="Uploaded Image", use_column_width=True)
58
+ logger.info("Successfully displayed uploaded image")
59
+ except Exception as e:
60
+ logger.error(f"Error loading image: {str(e)}")
61
+ st.error(f"❌ Error loading image: {str(e)}")
62
+ st.info("Please make sure you've uploaded a valid image file.")
63
+ elif input_type == 'url':
64
+ logger.info(f"Image URL provided: {image_url}")
65
+ st.image(image_url, caption="Image from URL", use_column_width=True)
66
+
67
+ # Add a button to trigger the similarity search
68
+ if st.button("Find Similar Pokemon"):
69
+ logger.info("Find Similar Pokemon button clicked")
70
+ with st.spinner("Analyzing image..."):
71
+ try:
72
+ logger.info(f"Finding closest Pokemon match using {input_type} input...")
73
+ pokemon_name = similarity_engine.find_closest_pokemon(image_input)
74
+ logger.info(f"Found closest Pokemon: {pokemon_name}")
75
+ st.success(f"🎯 The closest Pokemon is: **{pokemon_name}**")
76
+ st.balloons()
77
+ except Exception as e:
78
+ logger.error(f"Error during Pokemon matching: {str(e)}")
79
+ st.error(f"❌ Error: {str(e)}")
80
+ st.info("Please try uploading a different image, using a different URL, or try again later.")
81