Yoel125 commited on
Commit
894c97b
·
verified ·
1 Parent(s): 18460d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +19 -32
app.py CHANGED
@@ -17,51 +17,50 @@ print("Loading GenAI Component on CPU safely for ZeroGPU startup...")
17
  gen_tokenizer = AutoTokenizer.from_pretrained("google/flan-t5-small")
18
  gen_model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-small")
19
 
20
- # THE FIX for "the pitch changes every time I search": from_pretrained() does NOT
21
- # put the model in inference mode by default, so its dropout layers stay active and
22
- # randomly perturb every forward pass -- meaning it can produce a different sentence
23
- # for the exact same company and query, even with do_sample=False. Calling .eval()
24
- # turns dropout off. This is a plain CPU/Python flag, safe to call here at module
25
- # load time before any ZeroGPU device placement happens.
26
  gen_model.eval()
27
 
28
-
29
  def generate_sales_pitch(user_query, company_name, sector, theme, description):
30
  # THE PITCH FIX:
31
- # Small models get easily confused by large blocks of text and just copy them.
32
- # By removing the description from the prompt and forcing it to use the 'theme',
33
- # we FORCE the AI to synthesize a brand new, highly persuasive sentence instead of cheating.
34
  prompt = (
35
- f"Write a highly persuasive, single-sentence investment pitch explaining why "
36
- f"{company_name} (a {theme} company) is the perfect strategic investment for someone interested in '{user_query}'."
 
37
  )
38
 
39
  try:
40
- # We securely move the model to the GPU only *inside* the function after startup!
41
  device = "cuda" if torch.cuda.is_available() else "cpu"
42
  gen_model.to(device)
43
  inputs = gen_tokenizer(prompt, return_tensors="pt", max_length=256, truncation=True).to(device)
44
 
45
- # Extra safety net on top of eval(): pin the RNG state right before generation too.
46
  torch.manual_seed(42)
47
 
48
- # do_sample=False and num_beams=4 make the AI mathematically find the single
49
- # "best" response and lock it in every time, instead of rolling dice on each call.
50
  with torch.no_grad():
51
  outputs = gen_model.generate(
52
  **inputs,
53
  max_new_tokens=60,
54
  do_sample=False,
55
  num_beams=4,
56
- repetition_penalty=1.5, # Lowered slightly so the grammar flows naturally
57
  early_stopping=True
58
  )
59
  pitch = gen_tokenizer.decode(outputs[0], skip_special_tokens=True)
60
 
61
- # Clean up any leftover prompt artifacts in case the AI parrots the prompt
62
- pitch = pitch.replace("Write a highly persuasive, single-sentence investment pitch explaining why", "").strip()
 
 
 
 
 
 
 
 
63
 
64
- # Capitalize the first letter for professionalism
 
 
65
  if pitch:
66
  pitch = pitch[0].upper() + pitch[1:]
67
 
@@ -100,25 +99,21 @@ all_sectors = ["All Sectors"] + sorted(list(df['sector'].unique()))
100
 
101
  @spaces.GPU # <--- Hugging Face ZeroGPU Decorator!
102
  def recommend_investment(user_query, selected_sector, top_k=3):
103
- # 1. Check if completely empty
104
  if (not user_query or not str(user_query).strip()) and selected_sector == "All Sectors":
105
  yield "Please enter an investment thesis or keyword in the text box above, or select a specific industry sector from the dropdown menu."
106
  return
107
 
108
- # 2. English Language Check (Blocks Hebrew, Arabic, etc.)
109
  if user_query and str(user_query).strip():
110
  non_english_chars = sum(1 for char in str(user_query) if ord(char) > 127)
111
  if non_english_chars > 2:
112
  yield "⚠️ **Language Not Supported:** SectorSync AI is currently optimized exclusively for English data. Please write your investment thesis in English and try again."
113
  return
114
 
115
- # 3. Auto-fill sector if text box is empty
116
  if not user_query or not str(user_query).strip():
117
  user_query = f"innovative {selected_sector} companies"
118
 
119
  yield "🔍 Searching for matching companies and generating AI insights... this can take a few seconds."
120
 
121
- # 4. Search Execution
122
  if selected_sector != "All Sectors":
123
  enriched_query = f"{selected_sector} industry B2B company specializing in: {user_query}"
124
  else:
@@ -177,7 +172,6 @@ def recommend_investment(user_query, selected_sector, top_k=3):
177
 
178
 
179
  # --- 4. GRADIO USER INTERFACE ---
180
- # We build a native Gradio Dark Theme to fix the white boxes!
181
  custom_theme = gr.themes.Base(
182
  primary_hue="emerald",
183
  neutral_hue="slate"
@@ -202,11 +196,6 @@ custom_theme = gr.themes.Base(
202
  button_primary_background_fill_dark="#10b981",
203
  button_primary_text_color="#121212",
204
  button_primary_text_color_dark="#121212",
205
- # THE TABLE FIX: Hard-locking the table colors to dark mode grays for everyone.
206
- # NOTE: "table_row_focus_fill" is not a real Gradio theme token -- that's what
207
- # crashed the app (Base.set() rejects unknown keyword arguments outright, so
208
- # the whole Space fails to even start). Removed it; these three are the real,
209
- # documented table tokens and are enough to fix the white background.
210
  table_even_background_fill="#1e1e1e",
211
  table_even_background_fill_dark="#1e1e1e",
212
  table_odd_background_fill="#121212",
@@ -215,8 +204,6 @@ custom_theme = gr.themes.Base(
215
  table_border_color_dark="#333333"
216
  )
217
 
218
- # Belt-and-suspenders CSS in case this Gradio version's Examples table doesn't
219
- # fully respect the table_* theme tokens above.
220
  table_css = """
221
  table, table.dataset, tbody, thead, tr, td, th {
222
  background-color: #1e1e1e !important;
 
17
  gen_tokenizer = AutoTokenizer.from_pretrained("google/flan-t5-small")
18
  gen_model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-small")
19
 
 
 
 
 
 
 
20
  gen_model.eval()
21
 
 
22
  def generate_sales_pitch(user_query, company_name, sector, theme, description):
23
  # THE PITCH FIX:
24
+ # To stop the AI from generating generic corporate boilerplate that accidentally
25
+ # matches the synthetic dataset descriptions, we force it to answer a specific Question.
 
26
  prompt = (
27
+ f"Context: {company_name} is a leading {theme} company.\n"
28
+ f"Question: Why is {company_name} a brilliant and highly profitable investment for someone searching for '{user_query}'?\n"
29
+ f"Answer:"
30
  )
31
 
32
  try:
 
33
  device = "cuda" if torch.cuda.is_available() else "cpu"
34
  gen_model.to(device)
35
  inputs = gen_tokenizer(prompt, return_tensors="pt", max_length=256, truncation=True).to(device)
36
 
 
37
  torch.manual_seed(42)
38
 
 
 
39
  with torch.no_grad():
40
  outputs = gen_model.generate(
41
  **inputs,
42
  max_new_tokens=60,
43
  do_sample=False,
44
  num_beams=4,
45
+ repetition_penalty=1.5,
46
  early_stopping=True
47
  )
48
  pitch = gen_tokenizer.decode(outputs[0], skip_special_tokens=True)
49
 
50
+ pitch = pitch.replace("Answer:", "").strip()
51
+
52
+ # =========================================================================
53
+ # THE ULTIMATE ANTI-COPYING SAFETY NET
54
+ # If the small AI model generates a sentence that starts the exact same way
55
+ # as the company overview, we intercept it and replace it with a beautiful,
56
+ # highly customized dynamic pitch so they NEVER match!
57
+ # =========================================================================
58
+ desc_words = description.lower().split()
59
+ pitch_words = pitch.lower().split()
60
 
61
+ if len(pitch_words) < 5 or pitch_words[:4] == desc_words[:4] or pitch.lower() in description.lower():
62
+ pitch = f"Investing in {company_name} is a brilliant strategic move for '{user_query}', as their cutting-edge focus on {theme} perfectly captures the massive growth potential in this sector."
63
+
64
  if pitch:
65
  pitch = pitch[0].upper() + pitch[1:]
66
 
 
99
 
100
  @spaces.GPU # <--- Hugging Face ZeroGPU Decorator!
101
  def recommend_investment(user_query, selected_sector, top_k=3):
 
102
  if (not user_query or not str(user_query).strip()) and selected_sector == "All Sectors":
103
  yield "Please enter an investment thesis or keyword in the text box above, or select a specific industry sector from the dropdown menu."
104
  return
105
 
 
106
  if user_query and str(user_query).strip():
107
  non_english_chars = sum(1 for char in str(user_query) if ord(char) > 127)
108
  if non_english_chars > 2:
109
  yield "⚠️ **Language Not Supported:** SectorSync AI is currently optimized exclusively for English data. Please write your investment thesis in English and try again."
110
  return
111
 
 
112
  if not user_query or not str(user_query).strip():
113
  user_query = f"innovative {selected_sector} companies"
114
 
115
  yield "🔍 Searching for matching companies and generating AI insights... this can take a few seconds."
116
 
 
117
  if selected_sector != "All Sectors":
118
  enriched_query = f"{selected_sector} industry B2B company specializing in: {user_query}"
119
  else:
 
172
 
173
 
174
  # --- 4. GRADIO USER INTERFACE ---
 
175
  custom_theme = gr.themes.Base(
176
  primary_hue="emerald",
177
  neutral_hue="slate"
 
196
  button_primary_background_fill_dark="#10b981",
197
  button_primary_text_color="#121212",
198
  button_primary_text_color_dark="#121212",
 
 
 
 
 
199
  table_even_background_fill="#1e1e1e",
200
  table_even_background_fill_dark="#1e1e1e",
201
  table_odd_background_fill="#121212",
 
204
  table_border_color_dark="#333333"
205
  )
206
 
 
 
207
  table_css = """
208
  table, table.dataset, tbody, thead, tr, td, th {
209
  background-color: #1e1e1e !important;