Spaces:
Running
Running
| import streamlit as st | |
| import requests | |
| import os | |
| import base64 | |
| from PIL import Image | |
| from io import BytesIO # Correctly import BytesIO from the io module | |
| import pyperclip # For copying text to clipboard | |
| # Set page title and layout | |
| st.set_page_config(page_title="Image Caption Generator", layout="centered") | |
| # API key from environment variable | |
| API_KEY = os.environ.get("NEBIUS_API_KEY") | |
| if not API_KEY: | |
| st.error("API key not found. Please set the `NEBIUS_API_KEY` environment variable.") | |
| # Function to call Nebius API | |
| def generate_caption(image_base64, api_key): | |
| api_url = "https://api.studio.nebius.ai/v1/chat/completions" | |
| headers = {"Authorization": f"Bearer {api_key}"} | |
| payload = { | |
| "model": "Qwen/Qwen2-VL-72B-Instruct", | |
| "messages": [ | |
| { | |
| "role": "system", | |
| "content": """You are an image to prompt converter. Your work is to observe each and every detail of the image and craft a detailed prompt under 75 words in this format: [image content/subject, description of action, state, and mood], [art form, style], [artist/photographer reference if needed], [additional settings such as camera and lens settings, lighting, colors, effects, texture, background, rendering].""", | |
| }, | |
| { | |
| "role": "user", | |
| "content": [ | |
| {"type": "text", "text": "Write a caption for this image"}, | |
| {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_base64}"}}, | |
| ], | |
| }, | |
| ], | |
| "temperature": 0, | |
| } | |
| try: | |
| response = requests.post(api_url, json=payload, headers=headers) | |
| if response.status_code == 200: | |
| return response.json() | |
| else: | |
| st.error(f"API Error: {response.status_code}, {response.text}") | |
| return {"error": response.text} | |
| except Exception as e: | |
| st.error(f"An exception occurred: {e}") | |
| return {"error": str(e)} | |
| # File uploader for image | |
| uploaded_image = st.file_uploader("Upload an image", type=["png", "jpg", "jpeg"]) | |
| if uploaded_image and API_KEY: | |
| # Convert the image to base64 | |
| image = Image.open(uploaded_image) | |
| buffered = BytesIO() # Use BytesIO from the io module | |
| image.save(buffered, format="PNG") | |
| image_base64 = base64.b64encode(buffered.getvalue()).decode() | |
| # Show the uploaded image | |
| st.image(image, caption="Uploaded Image", use_container_width=True) | |
| # Add a button to trigger caption generation | |
| if st.button("Generate Caption", use_container_width=True): | |
| st.write("Generating caption...") | |
| result = generate_caption(image_base64, API_KEY) | |
| # Extract and display the generated caption | |
| if "error" in result: | |
| st.error(f"Error: {result['error']}") | |
| else: | |
| try: | |
| # Extract the caption from the response | |
| caption = ( | |
| result.get("choices", [{}])[0] | |
| .get("message", {}) | |
| .get("content", "No caption generated.") | |
| ) | |
| st.subheader("Generated Caption") | |
| # Use a text area for the caption so it can be copied easily | |
| caption_area = st.text_area("", caption, height=100, key="caption_area", disabled=True) | |
| # Add a copy button to copy the caption to clipboard | |
| copy_button = st.button("Copy Caption", use_container_width=True) | |
| if copy_button: | |
| pyperclip.copy(caption_area) # Copy caption to clipboard | |
| st.success("Caption copied to clipboard!") | |
| except Exception as e: | |
| st.error(f"Error processing the response: {e}") | |
| else: | |
| if not API_KEY: | |
| st.warning("Please set the `NEBIUS_API_KEY` environment variable.") | |
| else: | |
| st.info("Please upload an image.") | |
| # Remove the sidebar and center the content | |
| st.markdown( | |
| """ | |
| <style> | |
| .css-1d391kg {text-align: center;} | |
| .css-1v3fvcr {justify-content: center; display: flex;} | |
| .css-1y4ccs5 {margin: 0 auto;} | |
| .css-1aumxhk {display: flex; justify-content: center;} | |
| .css-1k6kn8p {justify-content: center; align-items: center; display: flex;} | |
| .css-ffhzg6 {text-align: center;} | |
| </style> | |
| """, unsafe_allow_html=True | |
| ) | |