shukdevdatta123's picture
Update app.py
37c6da0 verified
raw
history blame
11.4 kB
import gradio as gr
import os
import re
from openai import OpenAI
import json
import requests
from PIL import Image
import io
import base64
# Constants
DEFAULT_MODEL = "opengvlab/internvl3-14b:free"
# No need for placeholder text as we'll use password type input
DEFAULT_SITE_URL = "https://dynamic-nature-trail-guide.app"
DEFAULT_SITE_NAME = "Dynamic Nature Trail Guide"
# Initialize system prompt for better nature guide responses
SYSTEM_PROMPT = """
You are the Dynamic Nature Trail Guide, an expert in identifying and explaining natural elements
found on nature trails. For any image sent, please:
1. Identify all visible plants, animals, geological features, and ecosystems
2. Provide educational information about identified elements
3. Mention any seasonal characteristics visible in the image
4. Note any ecological significance or conservation considerations
5. Offer suggestions for what to observe or learn about next on the trail
Keep explanations informative yet accessible to people of all ages and backgrounds.
IMPORTANT: Structure your responses with clear sections and headings.
"""
def encode_image_to_base64(image_path):
"""Convert an image file to base64 encoding"""
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')
def format_response_as_html(text):
"""Convert the model's text response to formatted HTML"""
if not text:
return ""
# Check if the response is an error message
if text.startswith("Error analyzing image:"):
return f'<div style="color: red; padding: 10px; border: 1px solid red; border-radius: 5px;">{text}</div>'
# Replace newlines with HTML breaks
text = text.replace('\n\n', '</p><p>').replace('\n', '<br>')
# Handle headings - look for patterns like "1. Identification:" or "Species Identified:"
heading_patterns = [
(r'([A-Za-z\s]+):(?=<br>|</p>)', r'<h3>\1</h3>'), # "Category:" at start of line
(r'(\d+\.\s+[A-Za-z\s]+):(?=<br>|</p>)', r'<h3>\1</h3>'), # "1. Category:" format
]
for pattern, replacement in heading_patterns:
text = re.sub(pattern, replacement, text)
# Enhance species names with bold
text = re.sub(r'\b([A-Z][a-z]+\s+[a-z]+)\b(?!\<\/)', r'<strong>\1</strong>', text)
# Add some color to certain keywords
color_mappings = {
'endangered': 'red',
'rare': '#FF6600',
'native': '#006600',
'invasive': '#CC0000',
'ecosystem': '#006699',
'habitat': '#336699',
}
for keyword, color in color_mappings.items():
text = re.sub(r'\b' + keyword + r'\b', f'<span style="color: {color};">{keyword}</span>', text, flags=re.IGNORECASE)
# Wrap the entire content in a styled div
html = f'''
<div style="padding: 15px; font-family: Arial, sans-serif; line-height: 1.6;">
<p>{text}</p>
</div>
'''
return html
def analyze_image(api_key, image, prompt="What can you identify in this nature trail image? Provide detailed educational information.", site_url=DEFAULT_SITE_URL, site_name=DEFAULT_SITE_NAME, model=DEFAULT_MODEL):
"""Analyze the uploaded image using the InternVL3 model via OpenRouter"""
# Remove the placeholder text check
if not api_key:
return "<div style='color: red; padding: 10px; border: 1px solid red; border-radius: 5px;'>Please provide an OpenRouter API key.</div>"
if image is None:
return "<div style='color: red; padding: 10px; border: 1px solid red; border-radius: 5px;'>Please upload an image to analyze.</div>"
# Save the image temporarily
temp_image_path = "temp_image.jpg"
image.save(temp_image_path)
try:
# Convert image to base64
base64_image = encode_image_to_base64(temp_image_path)
# Initialize OpenAI client
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=api_key,
)
# Create message with image and text
response = client.chat.completions.create(
extra_headers={
"HTTP-Referer": site_url,
"X-Title": site_name,
},
model=model,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{
"role": "user",
"content": [
{
"type": "text",
"text": prompt
},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{base64_image}"
}
}
]
}
]
)
analysis_result = response.choices[0].message.content
return format_response_as_html(analysis_result)
except Exception as e:
error_message = f"Error analyzing image: {str(e)}"
return f'<div style="color: red; padding: 10px; border: 1px solid red; border-radius: 5px;">{error_message}</div>'
finally:
# Clean up the temporary file
if os.path.exists(temp_image_path):
os.remove(temp_image_path)
def build_custom_prompt(identification=True, education=True, seasonal=True, conservation=True, suggestions=True, additional_prompt=""):
"""Build a custom prompt based on user preferences"""
prompt_parts = []
if identification:
prompt_parts.append("Identify all visible plants, animals, geological features, and ecosystems")
if education:
prompt_parts.append("Provide educational information about identified elements")
if seasonal:
prompt_parts.append("Mention any seasonal characteristics visible in the image")
if conservation:
prompt_parts.append("Note any ecological significance or conservation considerations")
if suggestions:
prompt_parts.append("Offer suggestions for what to observe or learn next on the trail")
if additional_prompt:
prompt_parts.append(additional_prompt)
if not prompt_parts:
return "What can you identify in this nature trail image?"
numbered_prompt = "\n".join([f"{i+1}. {part}" for i, part in enumerate(prompt_parts)])
return f"For this nature trail image, please: \n{numbered_prompt}\n\nIMPORTANT: Structure your response with clear sections and headings for better readability."
def create_interface():
"""Create the Gradio interface for the Dynamic Nature Trail Guide"""
with gr.Blocks(title="Dynamic Nature Trail Guide", theme=gr.themes.Soft()) as app:
gr.Markdown("""
# ๐ŸŒฟ Dynamic Nature Trail Guide: Accessible Outdoor Education ๐ŸŒฟ
Upload an image from your nature walk to identify plants, animals, geological features, and learn about the ecosystem.
This application uses the advanced InternVL3 14B multimodal model for nature identification and education.
""")
with gr.Row():
with gr.Column(scale=1):
api_key_input = gr.Textbox(
label="OpenRouter API Key",
placeholder="Enter your OpenRouter API key here...",
type="password"
)
image_input = gr.Image(label="Upload Nature Image", type="pil")
with gr.Accordion("Advanced Settings", open=False):
site_url = gr.Textbox(
label="Site URL (for OpenRouter)",
value=DEFAULT_SITE_URL
)
site_name = gr.Textbox(
label="Site Name (for OpenRouter)",
value=DEFAULT_SITE_NAME
)
model_selection = gr.Dropdown(
label="Model",
choices=[DEFAULT_MODEL],
value=DEFAULT_MODEL
)
with gr.Accordion("Customize Analysis", open=False):
gr.Markdown("Select what information you want to receive about the image:")
identification_checkbox = gr.Checkbox(label="Species & Feature Identification", value=True)
education_checkbox = gr.Checkbox(label="Educational Information", value=True)
seasonal_checkbox = gr.Checkbox(label="Seasonal Characteristics", value=True)
conservation_checkbox = gr.Checkbox(label="Conservation Considerations", value=True)
suggestions_checkbox = gr.Checkbox(label="Trail Suggestions", value=True)
additional_prompt = gr.Textbox(label="Additional Instructions (Optional)")
analyze_button = gr.Button("Analyze Nature Image", variant="primary")
with gr.Column(scale=1):
output_text = gr.HTML(label="Analysis Results")
# Set up the click event for the analyze button
analyze_button.click(
fn=lambda api_key, image, id_check, edu_check, season_check, conserve_check, suggest_check, add_prompt, site_url, site_name, model:
analyze_image(
api_key,
image,
build_custom_prompt(id_check, edu_check, season_check, conserve_check, suggest_check, add_prompt),
site_url,
site_name,
model
),
inputs=[
api_key_input,
image_input,
identification_checkbox,
education_checkbox,
seasonal_checkbox,
conservation_checkbox,
suggestions_checkbox,
additional_prompt,
site_url,
site_name,
model_selection
],
outputs=output_text
)
# Example gallery
with gr.Accordion("Example Images", open=False):
gr.Markdown("Click on an example image to analyze it:")
example_images = gr.Examples(
examples=[
"examples/forest_trail.jpg",
"examples/wetland_boardwalk.jpg",
"examples/mountain_vista.jpg",
"examples/coastal_trail.jpg",
],
inputs=image_input,
label="Nature Trail Examples"
)
gr.Markdown("""
## How to Use This App
1. Enter your OpenRouter API key (sign up at [openrouter.ai](https://openrouter.ai) if needed)
2. Upload an image from your nature walk
3. Customize what kind of information you want (optional)
4. Click "Analyze Nature Image"
5. Explore the detailed educational content about what you're seeing
This application is designed to make nature more accessible and educational for everyone!
""")
return app
# Create and launch the app
if __name__ == "__main__":
app = create_interface()
app.launch()