witcheverly commited on
Commit
3b27d22
·
1 Parent(s): e442f69

first commit

Browse files
CaptionGenerator.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ This script contains the CaptionGenerator class,
3
+ which is used to generate Instagram captions for images
4
+ using BLIP and Gemini models.
5
+ '''
6
+ import google.generativeai as genai
7
+ import streamlit as st
8
+ import app_utils as utils
9
+ from transformers import AutoProcessor, Blip2ForConditionalGeneration
10
+
11
+ genai.configure(api_key=utils.get_gemini_api_key())
12
+
13
+ class CaptionGenerator:
14
+ """
15
+ Class for generating Instagram captions for images using BLIP and Gemini models.
16
+ The model from Hugging Face is used to generate the initial caption for the image,
17
+ which is then used as a prompt for the Gemini model to generate five distinct and
18
+ engaging captions for the image.
19
+
20
+ Attributes:
21
+ - google_api_key (str): Google API key for accessing the Generative AI API.
22
+ - gemini_model (GenerativeModel): Gemini model for generating Instagram captions.
23
+ - blip_processor (AutoProcessor): BLIP model processor for image captioning.
24
+ - blip_model (BlipForConditionalGeneration): BLIP model for image captioning.
25
+
26
+ Methods:
27
+ - process_image(image_data): Resize and prepare the image for caption generation.
28
+ - predict(image_data): Generate five Instagram captions for the provided image.
29
+ """
30
+ def __init__(self):
31
+ self.gemini = genai.GenerativeModel('gemini-pro')
32
+ self.processor = None
33
+ self.model = None
34
+
35
+ def image_2_text(self, image_data):
36
+ """
37
+ Generate a caption for the provided image using the BLIP-2 model.
38
+ :param image_data: PIL.Image - The image for which the caption is to be generated.
39
+ :return: description - The description generated for the image.
40
+ """
41
+ try:
42
+ self.processor, self.model, _ = utils.init_model(init_model_required=True)
43
+ inputs = self.processor(images=image_data, return_tensors="pt")
44
+ generated_ids = self.model.generate(**inputs, max_length=100)
45
+ description = self.processor.batch_decode(generated_ids, skip_special_tokens=True)[0].strip()
46
+ return description
47
+
48
+ except Exception as e:
49
+ st.error(f"Error occurred during image captioning: {e}")
50
+
51
+
52
+ def text_2_caption(self, image_description):
53
+ """
54
+ Generate five Instagram captions for the provided image.
55
+ The image is first processed before generating captions.
56
+
57
+ :param image_description: str - The description of the image for which captions are to be generated.
58
+ :return: str - Five Instagram captions formatted as specified.
59
+ """
60
+ prompt = (
61
+ f"This caption was generated with a deep learning model."
62
+ f"Your task is to enhance the caption to make it more engaging:"
63
+ f"Given this provided photo description, generate five distinct "
64
+ f"fun and engaging Instagram captions. Each caption must include "
65
+ f"at least one emoji and one hashtag. The captions should be "
66
+ f"formatted with a preceding 'Caption #', followed by the "
67
+ f"caption text. Ensure each caption is separated by a blank "
68
+ f"line for readability."
69
+ f"Original Caption: {image_description}"
70
+ f"Please format your response as follows: \n"
71
+ f"**Caption 1**: [caption text]\n"
72
+ f"**Caption 2**: [caption text]\n"
73
+ f"**Caption 3**: [caption text]\n"
74
+ f"**Caption 4**: [caption text]\n"
75
+ f"**Caption 5**: [caption text]\n"
76
+ )
77
+
78
+ try:
79
+ response = self.gemini.generate_content(prompt)
80
+ caption = response.parts[0].text
81
+ caption_list = response.parts[0].text.split("\n")
82
+ return caption, caption_list, image_description
83
+
84
+ except Exception as e:
85
+ st.error(f"Unable to connect to Gemini API: {e}")
86
+
87
+
88
+ # try:
89
+ # response = gemini_model.generate_content(prompt)
90
+ # caption = response.parts[0].text
91
+ # caption_list = response.parts[0].text.split("\n")
92
+ # return caption, caption_list, image_description
93
+ #
94
+ # except Exception as e:
95
+ # st.error(f"Unable to generate captions from description: {e}")
96
+
97
+ def caption_2_hashtag(self, caption):
98
+ """
99
+ Generate additional hashtags based on the content of the caption.
100
+
101
+ :param caption: str - The caption for which hashtags are to be generated.
102
+ :return: str - Additional hashtags based on the content of the caption.
103
+ """
104
+ # Generate hashtags based on the content of the caption
105
+ prompt = (f"Given the provided caption, generate relevant hashtags to increase engagement,"
106
+ f"and are related to the caption content. Original Image Description: {caption},"
107
+ f"Please format your response as follows:\n"
108
+ f'[hashtags separated by commas]'
109
+ f" \n")
110
+
111
+ try:
112
+ response = self.gemini.generate_content(prompt)
113
+ hashtags = response.parts[0].text
114
+ return hashtags
115
+
116
+ except Exception as e:
117
+ st.error(f"Error occurred with Gemini API: {e}")
118
+
119
+
120
+ @st.cache_resource()
121
+ def load_model():
122
+ """
123
+ Loads the BLIP-2 model for image captioning. This function is cached to avoid
124
+ re-loading the model on every call.
125
+ :param CaptionGenerator: The class for generating captions for images.
126
+ :return: Instance of the CaptionGenerator class.
127
+ """
128
+ return CaptionGenerator()
129
+
130
+
131
+ # Example usage of the CaptionGenerator class
132
+ # caption_generator = load_model()
133
+ # image = Image.open("example.jpg")
134
+ # desc = caption_generator.image_2_text(image)
135
+ # captions, caption_list, img_description = caption_generator.text_2_caption(desc)
136
+ # hashtags = caption_generator.caption_2_hashtag(img_description)
137
+ # print(captions)
138
+ # print(hashtags)
app_utils.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Utility functions for the Instagram Caption Generator app.
3
+ """
4
+ import streamlit as st
5
+ from dotenv import load_dotenv
6
+ from transformers import AutoProcessor, Blip2ForConditionalGeneration
7
+ import os
8
+ from pathlib import Path
9
+ import pandas as pd
10
+
11
+
12
+ def get_gemini_api_key():
13
+ """
14
+ Retrieves the Google API key for accessing the Generative AI API.
15
+ :return: str - The Google API key.
16
+ """
17
+ load_dotenv()
18
+ google_api_key = os.getenv("GOOGLE_API_KEY")
19
+ return google_api_key
20
+
21
+
22
+ @st.cache_resource()
23
+ def init_model(init_model_required):
24
+ """
25
+ Initializes the BLIP-2 model and processor for image captioning.
26
+ This helper function allows for lazy loading of the model and processor.
27
+ The streamlit app can call this function to load the model and processor
28
+ only when needed.
29
+ :param init_model_required: bo
30
+ ol - Flag to indicate if the model needs to be initialized.
31
+ :returns: AutoProcessor, Blip2ForConditionalGeneration, bool - Model processor, BLIP-2 model, and flag.
32
+ """
33
+ if init_model_required:
34
+ try:
35
+ processor = AutoProcessor.from_pretrained('./data/pretrained/blip2-opt-2.7b')
36
+ blip2_model = Blip2ForConditionalGeneration.from_pretrained('./data/pretrained/blip2-opt-2.7b')
37
+ init_model_required = False
38
+ return processor, blip2_model, init_model_required
39
+ except Exception as e:
40
+ st.error(f"Error occurred during model initialization: {e}")
41
+
42
+
43
+ # Function to store the user data to a CSV file
44
+ def save_user_data(first_name, last_name, email, phone):
45
+ """
46
+ Function to store the user data to a CSV file
47
+
48
+ :param first_name: str - First name of the user
49
+ :param last_name: str - Last name of the user
50
+ :param email: str - Email of the user
51
+ :param phone: str - Phone number of the user
52
+ :return: None
53
+ """
54
+ csv_file = Path("./user_data/user_data.csv")
55
+ # Check if the file exists and create a DataFrame accordingly
56
+ if csv_file.exists():
57
+ df = pd.read_csv(csv_file)
58
+ else:
59
+ df = pd.DataFrame(columns=["First Name", "Last Name", "Email", "Phone Number"])
60
+
61
+ # Add and save new user data (not for production).
62
+ new_data = pd.DataFrame({"First Name": [first_name],
63
+ "Last Name": [last_name],
64
+ "Email": [email],
65
+ "Phone Number": [phone]})
66
+ df = pd.concat([df, new_data], ignore_index=True)
67
+ df.to_csv(csv_file, index=False)
68
+ return None
69
+
70
+
71
+ def get_gif(path):
72
+ """Function to get the GIF image"""
73
+ with open(path, "rb") as file:
74
+ gif = file.read()
75
+ return gif
76
+
77
+
78
+ # Blip-2 does most of the standard image processing needed for image captioning.
79
+ def process_image(image_data, processor):
80
+ pass
images/.DS_Store ADDED
Binary file (6.15 kB). View file
 
images/insta.png ADDED
images/insta_post.png ADDED
pages/📸_InstaMuse.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import streamlit as st
3
+ from PIL import Image
4
+ import pyperclip
5
+ import app_utils as utils
6
+ from CaptionGenerator import CaptionGenerator, load_model
7
+
8
+ # Define Streamlit configurations
9
+ st.set_page_config(
10
+ page_title="Instamuse",
11
+ page_icon=":camera:",
12
+ layout='wide',
13
+ menu_items={
14
+ 'Get Help': 'https://www.streamlit.io',
15
+ 'Report a bug': "https://github.com/aditya-67/Instagram_Caption_Generator/issues",
16
+ 'About': "# This is a Streamlit app that uses AI to generate captions for images."
17
+ }
18
+ )
19
+
20
+ # Initialize the caption generator
21
+ caption_generator = load_model()
22
+
23
+ # Define aesthetic enhancements, including CSS for the spinner
24
+ st.markdown(
25
+ """
26
+ <style>
27
+ .big-font {
28
+ font-size:30px !important;
29
+ font-weight: bold;
30
+ }
31
+ .image-shadow {
32
+ box-shadow: 8px 8px 20px grey;
33
+ }
34
+ /* Centering the spinner */
35
+ .st-bq {
36
+ position: fixed;
37
+ top: 50%;
38
+ left: 50%;
39
+ transform: translate(-50%, -50%);
40
+ font-size: 20px; /* Make text larger */
41
+ }
42
+ </style>
43
+ """,
44
+ unsafe_allow_html=True
45
+ )
46
+
47
+ # Sidebar configuration
48
+ with st.sidebar:
49
+ st.image(os.path.join('images', 'insta.png'), width=300)
50
+ st.title("Welcome to InstaMuse!")
51
+ st.subheader("Turn your snapshots into social media sensations.")
52
+ st.write("Start turning heads with your posts. Use InstaMuse now and watch your likes soar!")
53
+
54
+ # Main page content
55
+ st.markdown('<p class="big-font">InstaMuse Photo Caption Generator</p>', unsafe_allow_html=True)
56
+ st.write("### Upload your photo below and spark some caption magic! ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊")
57
+
58
+ # Upload image file and process image
59
+ file = st.file_uploader(
60
+ "Upload your image here:",
61
+ type=["jpg", "png"],
62
+ help="Only jpg and png images are supported"
63
+ )
64
+
65
+ if file:
66
+ image = Image.open(file)
67
+ image.thumbnail((600, 600), Image.Resampling.LANCZOS)
68
+
69
+ try:
70
+ desc = caption_generator.image_2_text(image)
71
+ captions, caption_list, img_description = caption_generator.text_2_caption(desc)
72
+ st.session_state['captions'] = captions
73
+ st.session_state['caption_list'] = caption_list
74
+ st.session_state['img_description'] = img_description
75
+ except Exception as e:
76
+ st.error(f"Error generating captions: {e}")
77
+ captions = None
78
+
79
+ with st.spinner(r'#### :sparkles: :sparkles: Generating... please wait :hourglass_flowing_sand:'):
80
+ st.session_state['file'] = file
81
+
82
+ with st.container():
83
+ col1, col2 = st.columns(2)
84
+
85
+ with col1:
86
+ st.markdown("## 📸 Your Image:")
87
+ st.image(image, caption='Uploaded Image', use_column_width=True)
88
+
89
+ with col2:
90
+ if captions:
91
+ st.markdown("## 📝 Generated Captions:")
92
+ for caption in caption_list:
93
+ if caption.strip():
94
+ st.info(f"##### {caption}")
95
+
96
+ # Action buttons with functionality
97
+ if 'captions' in st.session_state and st.session_state['captions']:
98
+ col1, col2, col3, col4 = st.columns(4)
99
+ if col1.button("📋 Copy"):
100
+ pyperclip.copy(st.session_state['captions'])
101
+ st.success("Caption copied to clipboard!")
102
+
103
+ if col2.button("🔄 Regenerate"):
104
+ with st.spinner('Regenerating captions...'):
105
+ st.rerun()
106
+
107
+ if col3.button("✨ More Hashtags"):
108
+ with st.spinner('Generating hashtags...'):
109
+ try:
110
+ hashtags = caption_generator.caption_2_hashtag(st.session_state['img_description'])
111
+ except Exception as e:
112
+ st.error(f"Error generating hashtags: {e}")
113
+ hashtags = None
114
+ st.write("### Generated Hashtags:")
115
+ st.write(f"**{hashtags}**")
116
+
117
+ if col4.button(":window: Clear Screen"):
118
+ st.rerun()
119
+
120
+ with st.expander("Need help?"):
121
+ st.write("Please contact us at [email](mailto:jess@llmjessica.com)")
122
+
123
+ # Footer
124
+ st.markdown("---")
125
+ st.caption("Thank you for using InstaMuse! Feel free to contact us for any suggestions or issues.")
test_app.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import unittest
2
+ from PIL import Image
3
+ from app import import_and_predict
4
+
5
+
6
+ class TestApp(unittest.TestCase):
7
+
8
+ def test_import_and_predict(self):
9
+ image_data = Image.new('RGB', (100, 100)) # Mock image data
10
+ caption = import_and_predict(image_data) # Call the function
11
+ self.assertIsInstance(caption, str) # Check if caption is a string
12
+ self.assertTrue(len(caption) > 0) # Check if caption is not empty
13
+
14
+
15
+ if __name__ == '__main__':
16
+ unittest.main()
user_data/user_data.csv ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ First Name,Last Name,Email,Phone Number
2
+ Jane,Doe,jd@gmail.com,99999999
3
+ j`,as,22,22
4
+ z,asds,4,3
5
+ test,test,test,test
✨_Home.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import streamlit as st
3
+ from app_utils import get_gif, save_user_data
4
+
5
+
6
+ def main():
7
+ # Define Streamlit configurations
8
+ st.set_page_config(page_title="Instamuse", page_icon=":camera:", initial_sidebar_state='auto')
9
+
10
+ # Sidebar configuration
11
+ with st.sidebar:
12
+ st.image(os.path.abspath('images/insta.png'))
13
+ st.title("InstaMuse")
14
+ st.subheader(
15
+ "Welcome to InstaMuse, the ultimate tool for turning your snapshots "
16
+ "into social media sensations!"
17
+ )
18
+ st.write("Start turning heads with your posts. Use InstaMuse now and watch your likes soar!")
19
+
20
+ # Title and Style
21
+ st.markdown("""
22
+ <style>
23
+ .title-font {
24
+ font-size: 50px;
25
+ font-weight: bold;
26
+ font-family: 'Helvetica', sans-serif;
27
+ color: #FF573D;
28
+ }
29
+ </style>
30
+ """, unsafe_allow_html=True)
31
+ st.markdown('<h1 class="title-font">The Worlds Best Instagram Caption Generator</h1>', unsafe_allow_html=True)
32
+
33
+ # Subheader
34
+ st.write(
35
+ "### Transform your online presence—join InstaMuse to create "
36
+ "innovative captions that increase likes and enhance your visibility."
37
+ )
38
+
39
+ # Gif display
40
+ st.image(get_gif(os.path.abspath('images/insta.png')))
41
+
42
+ # Why us?
43
+ st.subheader('Why InstaMuse?')
44
+ st.write("""
45
+ - 🎨 **Creativity at your fingertips:** Generate unique captions that stand out.
46
+ - ⏳ **Save time:** Stop spending hours trying to write the perfect caption.
47
+ - 🚀 **Boost engagement:** Captions crafted to keep your audience engaged.
48
+ - 💸 **Free to use:** Get access to our technology preview at no cost.
49
+ """)
50
+
51
+ # Success Stories
52
+ st.subheader('Success Stories')
53
+ cols = st.columns(2)
54
+ with cols[0]:
55
+ st.image(os.path.abspath('images/insta_post.png'))
56
+ with cols[1]:
57
+ st.write("")
58
+ st.write('"InstaMuse helped us reach a wider audience. Our engagement rates have never been higher!" - CR')
59
+ st.write('"Thanks to InstaMuse, our posts now resonate better with our audience, bringing more likes and comments than ever before." - LJ')
60
+ st.write('"The creative captions we developed with InstaMuse have not only increased likes but also built lasting connections with our followers." - MK')
61
+
62
+ # Sign up section
63
+ st.subheader('Sign up here for priority access')
64
+ st.write('Enter your details below to get early access to our innovative caption generator.')
65
+
66
+ # Form to collect user details
67
+ with st.form(key='user_details_form', clear_on_submit=True):
68
+ cols = st.columns(2)
69
+ with cols[0]:
70
+ first_name = st.text_input("First Name")
71
+ email = st.text_input("Email", help="We'll never share your email with anyone else.")
72
+ with cols[1]:
73
+ last_name = st.text_input("Last Name")
74
+ phone = st.text_input("Phone Number", help="We'll never share your number with anyone else.")
75
+ submit_button = st.form_submit_button("Start Using InstaMuse")
76
+
77
+ if submit_button:
78
+ if first_name and last_name and email and phone:
79
+ save_user_data(first_name, last_name, email, phone)
80
+ st.success("Thank you for signing up! We will be in touch soon.")
81
+ else:
82
+ st.error("Please fill in all the fields.")
83
+
84
+
85
+ if __name__ == "__main__":
86
+ main()