Yoel125 commited on
Commit
2d5a663
Β·
verified Β·
1 Parent(s): a642bc0

Create APP

Browse files
Files changed (1) hide show
  1. APP +204 -0
APP ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import inspect
4
+ import pandas as pd
5
+ import torch
6
+ import re
7
+ from datasets import load_dataset
8
+ from sentence_transformers import SentenceTransformer
9
+ import faiss
10
+ from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
11
+
12
+ # --- 1. LOAD GENERATIVE AI COMPONENT (Stabilized Flan-T5-Base) ---
13
+ device = "cuda" if torch.cuda.is_available() else "cpu"
14
+ print(f"Loading GenAI Component on {device}...")
15
+
16
+ gen_tokenizer = AutoTokenizer.from_pretrained("google/flan-t5-base")
17
+ gen_model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-base").to(device)
18
+
19
+ def generate_sales_pitch(user_query, company_name, sector, theme, description):
20
+ # Safer, simpler prompt to stop hallucinations
21
+ prompt = f"Write one short sentence explaining why {company_name} (a {theme} company) is a good investment for the topic '{user_query}'."
22
+
23
+ try:
24
+ inputs = gen_tokenizer(prompt, return_tensors="pt", max_length=128, truncation=True).to(device)
25
+
26
+ # Stabilized parameters
27
+ outputs = gen_model.generate(
28
+ **inputs,
29
+ max_new_tokens=40,
30
+ do_sample=False,
31
+ num_beams=4,
32
+ no_repeat_ngram_size=2,
33
+ early_stopping=True
34
+ )
35
+ pitch = gen_tokenizer.decode(outputs[0], skip_special_tokens=True)
36
+ return pitch
37
+ except Exception:
38
+ return f"{company_name} is a leading industry player in {theme}, aligning with '{user_query}'."
39
+
40
+
41
+ # --- 2. AUTOMATIC SAFETY AUTO-LOADER (Dataset & Embeddings) ---
42
+ if 'df' not in globals():
43
+ print("Auto-loading dataset 'Yoel125/synthetic-companies-12k' from Hugging Face...")
44
+ df = pd.DataFrame(load_dataset('Yoel125/synthetic-companies-12k', split='train'))
45
+ df['full_text'] = df['sector'] + " - " + df['theme'] + ": " + df['description']
46
+
47
+ if 'embedding_model' not in globals():
48
+ print("Auto-loading embedding model 'paraphrase-MiniLM-L3-v2'...")
49
+ embedding_model = SentenceTransformer('paraphrase-MiniLM-L3-v2')
50
+
51
+ if 'faiss_index' not in globals():
52
+ try:
53
+ print("Loading saved embeddings from company_embeddings.npy...")
54
+ embeddings = np.load('company_embeddings.npy')
55
+ faiss_index = faiss.IndexFlatL2(embeddings.shape[1])
56
+ faiss_index.add(np.array(embeddings).astype('float32'))
57
+ except FileNotFoundError:
58
+ print("Saved embeddings not scratch...")
59
+ embeddings = embedding_model.encode(df['full_text'].tolist(), show_progress_bar=False)
60
+ faiss_index = faiss.IndexFlatL2(embeddings.shape[1])
61
+ faiss_index.add(np.array(embeddings).astype('float32'))
62
+
63
+
64
+ # --- 3. RECOMMENDATION ENGINE LOGIC ---
65
+ all_sectors = ["All Sectors"] + sorted(list(df['sector'].unique()))
66
+
67
+ def recommend_investment(user_query, selected_sector, top_k=3):
68
+ # 1. Check if completely empty
69
+ if (not user_query or not str(user_query).strip()) and selected_sector == "All Sectors":
70
+ yield "Please enter an investment thesis or keyword in the text box above, or select a specific industry sector from the dropdown menu."
71
+ return
72
+
73
+ # 2. English Language Check (Blocks Hebrew, Arabic, etc.)
74
+ if user_query and str(user_query).strip():
75
+ non_english_chars = sum(1 for char in str(user_query) if ord(char) > 127)
76
+ if non_english_chars > 2:
77
+ yield "⚠️ **Language Not Supported:** SectorSync AI is currently optimized exclusively for English data. Please write your investment thesis in English and try again."
78
+ return
79
+
80
+ # 3. Auto-fill sector if text box is empty
81
+ if not user_query or not str(user_query).strip():
82
+ user_query = f"innovative {selected_sector} companies"
83
+
84
+ yield "πŸ” Searching for matching companies and generating AI insights... this can take a few seconds."
85
+
86
+ # 4. Search Execution
87
+ if selected_sector != "All Sectors":
88
+ enriched_query = f"{selected_sector} industry B2B company specializing in: {user_query}"
89
+ else:
90
+ enriched_query = f"B2B investment opportunity specializing in: {user_query}"
91
+
92
+ query_vector = embedding_model.encode([enriched_query])
93
+ search_k = 25 if selected_sector != "All Sectors" else top_k
94
+ distances, indices = faiss_index.search(np.array(query_vector).astype('float32'), k=search_k)
95
+
96
+ matches = []
97
+ for i in range(search_k):
98
+ idx = indices[0][i]
99
+ sim_score = 1 / (1 + distances[0][i])
100
+ company_row = df.iloc[idx]
101
+ if selected_sector != "All Sectors" and company_row['sector'] != selected_sector:
102
+ continue
103
+ matches.append((company_row, sim_score))
104
+ if len(matches) == top_k:
105
+ break
106
+
107
+ if not matches:
108
+ for i in range(min(top_k, len(indices[0]))):
109
+ idx = indices[0][i]
110
+ sim_score = 1 / (1 + distances[0][i])
111
+ matches.append((df.iloc[idx], sim_score))
112
+
113
+ output_markdown = f"### Top {len(matches)} AI-Recommended Matches for: *'{user_query}'*\n\n"
114
+ if selected_sector != "All Sectors":
115
+ output_markdown += f"**Filtered by Sector:** `{selected_sector}`\n\n---\n\n"
116
+ else:
117
+ output_markdown += "---\n\n"
118
+
119
+ match_labels = ["πŸ₯‡ Strongest Match", "πŸ₯ˆ Close Match", "πŸ₯‰ Close Match"]
120
+
121
+ for rank, (row, score) in enumerate(matches, 1):
122
+ c_name = row['company_name']
123
+ ticker = row.get('ticker', 'N/A')
124
+ sector = row['sector']
125
+ theme = row['theme']
126
+ desc = row['description']
127
+
128
+ try:
129
+ pitch = generate_sales_pitch(user_query, c_name, sector, theme, desc)
130
+ except Exception:
131
+ pitch = f"An exceptional strategic match for {user_query} within the {sector} space."
132
+
133
+ tier_label = match_labels[rank - 1] if rank <= len(match_labels) else "Match"
134
+
135
+ # The Fix: No bullet points, reads like a clean, professional report!
136
+ output_markdown += f"#### #{rank}. {c_name} (`{ticker}`) β€” *{sector}*\n\n"
137
+ output_markdown += f"**{tier_label}** (Similarity Score: `{score*100:.1f}%`)\n\n"
138
+ output_markdown += f"**Industry:** {theme}\n\n"
139
+ output_markdown += f"**GenAI Investment Pitch:** *'{pitch}'*\n\n"
140
+ output_markdown += f"**Company Overview:** {desc[:200]}...\n\n---\n\n"
141
+
142
+ # Streams the results instantly!
143
+ yield output_markdown
144
+
145
+
146
+ # --- 4. GRADIO USER INTERFACE ---
147
+ custom_css = """
148
+ body, .gradio-container {
149
+ background-color: #121212 !important;
150
+ color: #f0f4f8 !important;
151
+ }
152
+ .markdown-text, h1, h2, h3, h4, p, li, span, label {
153
+ color: #f0f4f8 !important;
154
+ }
155
+ button.primary {
156
+ background-color: #10b981 !important;
157
+ border-color: #10b981 !important;
158
+ color: #121212 !important;
159
+ font-weight: bold !important;
160
+ }
161
+ button.primary:hover {
162
+ background-color: #059669 !important;
163
+ }
164
+ """
165
+
166
+ with gr.Blocks(theme=gr.themes.Base(), css=custom_css, title="SectorSync AI") as demo:
167
+ gr.Markdown("# SectorSync AI")
168
+ gr.Markdown("Cut Through the Market Noise β€” Find Your Next Winning Stock in Seconds. Discover high-growth companies matching your investment thesis using FAISS Vector Search and Generative AI.")
169
+ gr.Markdown("*Similarity Score reflects how closely a company profile matches your query in AI-embedding space β€” a relative ranking signal, not a calibrated financial confidence rating.*")
170
+
171
+ with gr.Row():
172
+ with gr.Column(scale=2):
173
+ query_input = gr.Textbox(
174
+ label="What is your investment thesis or topic?",
175
+ placeholder="e.g., autonomous robotics, clean battery storage, gene therapy for rare diseases...",
176
+ lines=2
177
+ )
178
+ with gr.Column(scale=1):
179
+ sector_dropdown = gr.Dropdown(
180
+ choices=all_sectors,
181
+ value="All Sectors",
182
+ label="Sector"
183
+ )
184
+
185
+ search_button = gr.Button("Find Investment Matches", variant="primary")
186
+
187
+ gr.Examples(
188
+ examples=[
189
+ ["Artificial Intelligence and Machine Learning in Healthcare", "Healthcare"],
190
+ ["Next-generation Renewable Energy and Solar Battery Storage", "Energy"],
191
+ ["Autonomous Robotics and Supply Chain Logistics Automation", "Industrials"]
192
+ ],
193
+ inputs=[query_input, sector_dropdown],
194
+ label="Quick Starters (1-Click Example Searches)"
195
+ )
196
+
197
+ results_output = gr.Markdown(label="Recommendation Results")
198
+
199
+ search_button.click(fn=recommend_investment, inputs=[query_input, sector_dropdown], outputs=results_output)
200
+ query_input.submit(fn=recommend_investment, inputs=[query_input, sector_dropdown], outputs=results_output)
201
+
202
+ if __name__ == "__main__":
203
+ print("Launching SectorSync AI Recommender App...")
204
+ demo.launch(share=True)