subashdvorak commited on
Commit
956a6ec
·
verified ·
1 Parent(s): 29970fa

Upload 5 files

Browse files
app.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from brain_strom_with_influencer_input import ResponseGeneratorApp
3
+ from recommendations_and_engagement_predict import StoryRecommendationApp
4
+
5
+ # Instantiate the two apps
6
+ brainstorm_app = ResponseGeneratorApp().build_ui()
7
+ print("Brainstorm App:", type(brainstorm_app))
8
+
9
+ recommendation_app = StoryRecommendationApp().launch_interface()
10
+ print("Recommendation App:", type(recommendation_app))
11
+
12
+
13
+ # Combine the two apps into a tabbed interface
14
+ app = gr.TabbedInterface(
15
+ [brainstorm_app, recommendation_app], # List of apps/interfaces
16
+ ["Brainstorm with Influencer Input", "Recommendations with Engagement Predictions"], # Tab names
17
+ )
18
+
19
+ if __name__ == "__main__":
20
+ app.launch(share=True)
brain_strom_with_influencer_input.py ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import gradio as gr
4
+ import torch
5
+ import re
6
+ # from transformers import AutoTokenizer, AutoModelForCausalLM
7
+ from keybert import KeyBERT
8
+ from sentence_transformers import SentenceTransformer
9
+ from datasets import load_dataset,Dataset
10
+ from shared_resources import shared_resources
11
+ from phi.agent import Agent
12
+ from phi.tools.duckduckgo import DuckDuckGo
13
+ from phi.agent import Agent, RunResponse
14
+ from phi.model.huggingface import HuggingFaceChat
15
+
16
+
17
+
18
+ class ResponseGenerator:
19
+ def __init__(self):
20
+
21
+ self.ST = shared_resources.sentence_transformer
22
+ self.data = shared_resources.data
23
+ self.original_query = ""
24
+
25
+ # Define the search function
26
+ def search(self, query: str, usernames=None, k: int = 3):
27
+ """Function to get recommended videos based on user input"""
28
+ self.embedded_query = self.ST.encode(query) # Embed the user input
29
+ self.all_retrievals=[]
30
+ if usernames:
31
+ dataset=self.data.to_pandas()
32
+ for username in usernames:
33
+ username = [username]
34
+ filtered_df = dataset[dataset['username'].isin(username)]
35
+ self.temp_data = Dataset.from_pandas(filtered_df)
36
+ self.temp_data=self.temp_data.add_faiss_index("embeddings")
37
+ self.scores, self.retrieved_examples = self.temp_data.get_nearest_examples("embeddings", self.embedded_query, k=k) # Search for top k results
38
+ self.all_retrievals.append(str(self.retrieved_examples['Caption'][0]))
39
+ self.temp_data=None
40
+ print('All retrievals are:',self.all_retrievals)
41
+ return self.all_retrievals
42
+
43
+ self.scores, self.retrieved_examples = self.data.get_nearest_examples("embeddings", self.embedded_query, k=k) # Search for top k results
44
+ return self.scores, self.retrieved_examples
45
+
46
+
47
+ def generate_response(self, query, username=None, additional_focus=None):
48
+ # print('The usernames are:',username)
49
+ """
50
+ Generates text using the Llama 3.1 model.
51
+ """
52
+ self.original_query = query # Save the original query for future focus
53
+
54
+ # If we are going deeper, add the additional focus to the prompt
55
+ if additional_focus:
56
+ # prompt = f"Explain the Given topic:\n{self.original_query}. Also focus on: {additional_focus}\n1."
57
+ prompt = f"""
58
+ I want to create a detailed storyline for a video primarily focusing on the sentence: **{additional_focus}**, keeping it under 500 words. Please provide the storyline in 6 concise paragraphs that must incorporate the following key features everytime:
59
+
60
+ 1. **Story:** How to introduce the scene and set the tone. What is happening in the scence? Describe key visuals and actions.
61
+ 2. **Narration or Voiceover:** Suggestions for narration or voiceover that complements the visuals.
62
+ 3. **Text in the Video:** Propose important text overlays for key moments.
63
+ 4. **Transitions:** Smooth transitions between scenes to maintain flow.
64
+ 5. **Emotional Tone:** The mood and energy of the scenes (e.g., excitement, calm, tension, joy).
65
+ 6. **Key Visuals & Sounds:** Important props, locations, sound effects, or background music to enhance the video.
66
+
67
+ The storyline should flow naturally, without repeating the same information or listing individual features. Ensure the output is engaging and cohesive.
68
+
69
+ Also, suggest **5 relevant hashtags** for the video that reflect its content and themes commonly used on social media for similar videos.
70
+
71
+
72
+ """
73
+
74
+ else:
75
+ # prompt = f"Explain the Given topic:\n{query}\n1."
76
+ prompt = f"""
77
+ I want to create a detailed storyline for a video in any domain, keeping it under 500 words. Please provide the storyline in 6 concise paragraphs that must incorporate the following key features everytime:
78
+
79
+ 1. **Story:** How to introduce the scene and set the tone. What is happening in the scene? Describe key visuals and actions.
80
+ 2. **Narration or Voiceover:** Suggestions for narration or voiceover that complements the visuals.
81
+ 3. **Text in the Video:** Propose important text overlays for key moments.
82
+ 4. **Transitions:** Smooth transitions between scenes to maintain flow.
83
+ 5. **Emotional Tone:** The mood and energy of the scenes (e.g., excitement, calm, tension, joy).
84
+ 6. **Key Visuals & Sounds:** Important props, locations, sound effects, or background music to enhance the video.
85
+
86
+ The storyline should flow naturally, without repeating the same information or listing individual features. Ensure the output is engaging and cohesive.
87
+
88
+ Also, suggest **5 relevant hashtags** for the video that reflect its content and themes commonly used on social media for similar videos.
89
+
90
+ """
91
+
92
+
93
+ # prefix = f"The question is:{self.original_query}"
94
+ # print('The data is:',self.data)
95
+ if username:
96
+ retrieved_list = self.search(query,username,1)
97
+ retrieved_context = "\n".join(retrieved_list)
98
+ prompt = prompt + f"\n Here is the random video story from the dataset for you. You can use it just for analysing purpose, not for similar generation. This is the story:\n{retrieved_context}"
99
+ prompt = prompt + f"\nNow finally i am providing you a question to create a detailed story line for a video. The question is: **{self.original_query}**"
100
+
101
+ else:
102
+ prompt = prompt + f"\nNow finally i am providing you a question to create a detailed story line for a video. The question is: **{self.original_query}**"
103
+ agent = Agent(
104
+ model=HuggingFaceChat(
105
+ id="meta-llama/Meta-Llama-3-8B-Instruct",
106
+ max_tokens=4096,
107
+ ),
108
+ # tools=[DuckDuckGo()],
109
+ markdown=True
110
+ )
111
+
112
+ # Get the response in a variable
113
+ run: RunResponse = agent.run(prompt)
114
+ return run.content
115
+
116
+
117
+
118
+ def extract_topics(self, story):
119
+ """
120
+ Extracts 5 key sentences from the generated text using KeyBERT.
121
+ """
122
+
123
+ prompt = f'''I want to brainstorm ways to diversify or improve a storyline in exactly 5 sentences. No more than 5 nor less than 5.
124
+ The goal is to generate creative and actionable ideas that are not on the storyline on how the storyline can be expanded or modified for better engagement.
125
+ For example: If the storyline is about creating a promotional video for a restaurant, the new suggestions might include:
126
+ - I want to showcase the chef preparing a signature dish.
127
+ - I want to add a sequence of customers sharing their experiences at the restaurant.
128
+ - I want to highlight the farm-to-table sourcing of ingredients with a short segment showing local farms.
129
+ - I want to include a time-lapse of the restaurant transforming from day to night, capturing its unique ambiance.
130
+ - I want to feature a quick interview with the owner sharing the story behind the restaurant.
131
+
132
+ Now, I will provide you with the storyline. The storyline is:\n{story}
133
+ Please remember, don't give any introduction or explanations. Just generate 5 sentences directly, focusing on creative suggestions for diversifying or modifying the storyline. '''
134
+
135
+
136
+ agent = Agent(
137
+ model=HuggingFaceChat(
138
+ id="meta-llama/Meta-Llama-3-8B-Instruct",
139
+ max_tokens=4096,
140
+ ),
141
+ # tools=[DuckDuckGo()],
142
+ markdown=True
143
+ )
144
+
145
+ # Get the response in a variable
146
+ run: RunResponse = agent.run(prompt)
147
+ generated_text=run.content
148
+ # Split the text into sentences and strip each one
149
+ sentences = [sentence.strip() for sentence in re.split(r'[.?]', generated_text) if sentence.strip()]
150
+ print('The sentences are:',sentences)
151
+
152
+ return sentences[-4:]
153
+
154
+
155
+ def on_select_topic(self, selected_topic, history_stack, current_state):
156
+ """
157
+ Generates new points for the selected topic and updates history.
158
+ """
159
+ # Save current state in history
160
+ history_stack.append(current_state)
161
+
162
+ # Generate new outputs with the selected topic as additional focus
163
+ new_response = self.generate_response(self.original_query, additional_focus=selected_topic)
164
+ new_topics = self.extract_topics(new_response)
165
+
166
+ # Prepare new state
167
+ new_state = {
168
+ "response": new_response,
169
+ "topics": new_topics,
170
+ "key_topics": new_topics
171
+ }
172
+
173
+ return new_state, history_stack, gr.update(value=new_response), gr.update(choices=new_topics)
174
+
175
+ def on_back(self, history_stack):
176
+ """
177
+ Restores the previous state for all outputs.
178
+ """
179
+ if history_stack:
180
+ # Pop the last state from history
181
+ previous_state = history_stack.pop()
182
+
183
+ return history_stack, gr.update(value=previous_state["response"]), \
184
+ gr.update(choices=previous_state["key_topics"])
185
+
186
+ # If no history, clear outputs
187
+ return history_stack, gr.update(value=""), gr.update(choices=[])
188
+
189
+ class ResponseGeneratorApp:
190
+ def __init__(self):
191
+ self.point_generator = ResponseGenerator()
192
+
193
+ def build_ui(self):
194
+ with gr.Blocks() as demo:
195
+ gr.Markdown(
196
+ """
197
+ #Brainstorming App
198
+ Enter a query to generate a detailed response and start brainstroming for further exploration.
199
+ """
200
+ )
201
+
202
+ query_input = gr.Textbox(
203
+ label="Enter your query",
204
+ placeholder="Type a query, e.g., 'I want to create a promotional video of Begnas Lake.'",
205
+ lines=2,
206
+ )
207
+
208
+ usernames = [
209
+ "_travelwithsapana", "givina_9", "rajen.rb", "wh0z.khu5h1", "palam061",
210
+ "prettiest_sky", "explorepokhara", "ggkaam610", "anjana_dhl1"
211
+ ]
212
+
213
+ # username_inputs =gr.Radio(label="Select Username of whose you want similar story::", choices=usernames, type="value")
214
+
215
+ username_inputs = gr.CheckboxGroup(choices=usernames,label="Choose one or more username of whose you want similar story::",type="value")
216
+
217
+
218
+
219
+ generate_btn = gr.Button(value="Generate")
220
+
221
+ # Output box for the generated text
222
+ response_output = gr.Textbox(
223
+ label="Generated Response",
224
+ lines=10,
225
+ interactive=False
226
+ )
227
+
228
+ # Dynamic radio buttons area for the extracted topics
229
+ topics_radio = gr.Radio(
230
+ label="Brain Stroming Areas....",
231
+ choices=[],
232
+ type="value",
233
+ interactive=True
234
+ )
235
+
236
+ back_btn = gr.Button(value="Back")
237
+
238
+ # State for managing current topics and history
239
+ current_state = gr.State({}) # Store response, topics, and key_topics
240
+ history_stack = gr.State([]) # Stack of previous states
241
+
242
+ # Link the generate button to the processing function
243
+ generate_btn.click(
244
+ fn=lambda query,usernames: self.generate_handler(query,usernames),
245
+ inputs=[query_input,username_inputs],
246
+ outputs=[current_state, response_output, topics_radio],
247
+ )
248
+
249
+ # Handle selection of a topic (generate new stage)
250
+ topics_radio.change(
251
+ fn=self.point_generator.on_select_topic,
252
+ inputs=[topics_radio, history_stack, current_state],
253
+ outputs=[current_state, history_stack, response_output, topics_radio]
254
+ )
255
+
256
+ # Handle back button
257
+ back_btn.click(
258
+ fn=self.point_generator.on_back,
259
+ inputs=[history_stack],
260
+ outputs=[history_stack, response_output, topics_radio]
261
+ )
262
+
263
+ return demo
264
+
265
+ def generate_handler(self, query,usernames):
266
+ """
267
+ Handles the generation of the response and topics.
268
+ """
269
+ response = self.point_generator.generate_response(query,usernames)
270
+ topics = self.point_generator.extract_topics(response)
271
+
272
+ # Prepare the current state
273
+ current_state = {
274
+ "response": response,
275
+ "topics": topics,
276
+ "key_topics": topics
277
+ }
278
+
279
+ return current_state, gr.update(value=response), gr.update(choices=topics)
280
+
281
+
recommendations_and_engagement_predict.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+
4
+ import gradio as gr
5
+ # from transformers import AutoTokenizer, AutoModelForCausalLM
6
+ from sentence_transformers import SentenceTransformer
7
+ from datasets import load_dataset
8
+ import numpy as np
9
+ import torch
10
+ from shared_resources import shared_resources
11
+ from phi.agent import Agent
12
+ from phi.tools.duckduckgo import DuckDuckGo
13
+ from phi.agent import Agent, RunResponse
14
+ from phi.model.huggingface import HuggingFaceChat
15
+
16
+
17
+
18
+ class StoryRecommendationApp:
19
+
20
+ def __init__(self):
21
+ # self.tokenizer = shared_resources.tokenizer
22
+ # self.model = shared_resources.model
23
+ self.device = shared_resources.device
24
+ self.sentence_transformer = shared_resources.sentence_transformer
25
+ self.data = shared_resources.data
26
+
27
+ def search(self, query: str, k: int = 3):
28
+ """Search for recommended videos based on user input."""
29
+ embedded_query = self.sentence_transformer.encode(query)
30
+ scores, retrieved_examples = self.data.get_nearest_examples("embeddings", embedded_query, k=k)
31
+
32
+ if isinstance(retrieved_examples, np.ndarray):
33
+ retrieved_examples = np.nan_to_num(retrieved_examples, nan=0)
34
+ elif isinstance(retrieved_examples, list):
35
+ retrieved_examples = [
36
+ [0 if np.isnan(val) else val for val in example] if isinstance(example, list) else example
37
+ for example in retrieved_examples
38
+ ]
39
+ return scores, retrieved_examples
40
+
41
+ def compute_mean_and_predict(self, retrieved_examples):
42
+ """Compute mean for likesCount, commentCount, and shareCount."""
43
+ features = ["LikesCount", "commentCount", "shareCount"]
44
+ predictions = {}
45
+
46
+ for feature in features:
47
+ values = np.array(retrieved_examples[feature])
48
+ values = np.array([np.nan if v is None else v for v in values])
49
+ values = np.nan_to_num(values, nan=0.0)
50
+
51
+ mean_value = int(np.mean(values))
52
+ predictions[f"predicted_{feature}"] = mean_value
53
+
54
+ return predictions
55
+
56
+ def generate_prompt(self, query: str):
57
+ """Generate a prompt for video generation based on the input story."""
58
+ input_text = f'''
59
+ I want to summarize a story in exactly 3 sentences. No more than 3 nor less than 3.
60
+ But the sentences have to be good enough to use as a prompt for video generation, because I have to give those 3 sentences to the video generation model.
61
+ For example: This prompt is about A heartwarming family reunion celebrating love and cherished memories in exactly 3 sentences.
62
+ -A warm, heartfelt reunion in a cozy living room, where family members embrace each other after a long time apart, soft lighting enhances the intimate atmosphere, and laughter fills the air.
63
+ -A close-up shot of a grandmother’s hands carefully arranging a family photo album, as the camera pans over old pictures, evoking cherished memories and a deep sense of love.
64
+ -A final moment around the dinner table, family members sharing a meal together, toasts are made, and the soft glow of candles reflects the joy and connection between generations.
65
+
66
+ So, I will provide you that story now. The story is:\n{query}
67
+
68
+ Please remember, don't give any background descriptions. Just generate 3 sentences likewise the example above. Don't even give the starting text like: "Here are the 3 sentences that summarize the story:" or any other like this. Just give the answers in 3 sentences directly
69
+ '''
70
+ agent = Agent(
71
+ model=HuggingFaceChat(
72
+ id="meta-llama/Meta-Llama-3-8B-Instruct",
73
+ max_tokens=4096,
74
+ ),
75
+ # tools=[DuckDuckGo()],
76
+ markdown=True
77
+ )
78
+
79
+ # Get the response in a variable
80
+ run: RunResponse = agent.run(input_text)
81
+ generated_text=run.content
82
+
83
+ sentences = [sentence.strip() for sentence in generated_text.split('.') if sentence]
84
+ return '. '.join(sentences[-3:]) + ('.' if len(sentences) > 0 else '')
85
+
86
+ def generate_story_and_recommendation(self, generated_response: str):
87
+ """Generate story recommendations and predictions based on the user input."""
88
+ scores, result = self.search(generated_response, 4)
89
+
90
+ recommended_videos_text = ""
91
+ predictions = {}
92
+
93
+ if scores is not None and result is not None:
94
+ recommendations = []
95
+ for idx in range(len(result['url'])):
96
+ recommendations.append(
97
+ f"Video {idx+1}: {result['url'][idx]}\nPlaycount: {int(result['playCount'][idx])}\n"
98
+ )
99
+ recommended_text = "\n\n".join(recommendations)
100
+ recommended_influencer = f"\nYou can use these influencers for this type of video {str(result['username'][:3])}"
101
+
102
+ predictions = self.compute_mean_and_predict(result)
103
+ generated_prompt = self.generate_prompt(generated_response)
104
+
105
+ return recommended_text + recommended_influencer, predictions, generated_prompt
106
+
107
+ def format_predictions(self, predictions):
108
+ """Format predictions for display."""
109
+ if predictions:
110
+ return "\n".join([f"{key}: {value}" for key, value in predictions.items()])
111
+ else:
112
+ return "No predictions available."
113
+
114
+ def launch_interface(self):
115
+ """Launch the Gradio interface."""
116
+ interface=gr.Interface(
117
+ fn=self.generate_story_and_recommendation,
118
+ inputs=gr.Textbox(label="Enter your generated story.", lines=15),
119
+ outputs=[
120
+ gr.Textbox(label="Our Recommendations for you."),
121
+ gr.Textbox(label="Predicted Metrics (Likes, Comments, Shares)", type="text"),
122
+ gr.Textbox(label="Recommended Prompt for video generation:"),
123
+ ],
124
+ title="Video Story Generation and Recommendation",
125
+ description="Enter a request for a video storyline, and get a detailed story along with recommended videos and predicted engagement metrics based on the same input."
126
+ )
127
+ return interface
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio
2
+ transformers
3
+ sentence-transformers
4
+ datasets
5
+ faiss-cpu
6
+ pydub
7
+ torch
8
+ scipy
9
+ phidata
10
+ duckduckgo-search
shared_resources.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # shared_resources.py
2
+ import torch
3
+ # from transformers import AutoTokenizer, AutoModelForCausalLM
4
+ from sentence_transformers import SentenceTransformer
5
+ from datasets import load_dataset
6
+ # from transformers import AutoProcessor, MusicgenForConditionalGeneration
7
+ import re
8
+
9
+ class SharedResources:
10
+ def __init__(self):
11
+ # Set the device
12
+ self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
13
+
14
+
15
+ # Load SentenceTransformer
16
+ self.sentence_transformer = SentenceTransformer("mixedbread-ai/mxbai-embed-large-v1")
17
+
18
+ # Load the dataset
19
+ self.dataset = load_dataset("subashdvorak/tiktok-story-data1", revision="embedded")
20
+ self.data = self.dataset["train"]
21
+ self.data = self.data.add_faiss_index("embeddings")
22
+
23
+ # Create a single instance of SharedResources
24
+ shared_resources = SharedResources()