pinge commited on
Commit
aa99ac2
·
1 Parent(s): eeb7ca8

Deploy my app

Browse files
Files changed (3) hide show
  1. .env +1 -0
  2. app.py +198 -0
  3. requirements.txt +10 -0
.env ADDED
@@ -0,0 +1 @@
 
 
1
+ GROQ_API_KEY=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
app.py ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import faiss
2
+ import numpy as np
3
+ import yfinance as yf
4
+ import os
5
+ import streamlit as st
6
+ from dotenv import load_dotenv
7
+ from sentence_transformers import SentenceTransformer
8
+ from groq import Groq
9
+
10
+ # Load environment variables
11
+ load_dotenv()
12
+ groq_api_key = os.getenv("GROQ_API_KEY")
13
+ if not groq_api_key:
14
+ st.error("GROQ_API_KEY is missing. Set it in Railway's environment variables.")
15
+ st.stop()
16
+
17
+ client = Groq(api_key=groq_api_key)
18
+
19
+ # Initialize session state for dark mode (default: True)
20
+ if "dark_mode" not in st.session_state:
21
+ st.session_state.dark_mode = True
22
+
23
+ # Icon switch
24
+ icon = "🔆" if st.session_state.dark_mode else "🌙"
25
+
26
+ # Custom CSS to remove container and position icon in the top-right corner
27
+ st.markdown(
28
+ """
29
+ <style>
30
+ .stButton > button {
31
+ background: none !important;
32
+ border: none !important;
33
+ box-shadow: none !important;
34
+ font-size: 24px !important;
35
+ position: absolute !important;
36
+ top: 10px !important;
37
+ right: 10px !important;
38
+ cursor: pointer !important;
39
+ }
40
+ </style>
41
+ """,
42
+ unsafe_allow_html=True,
43
+ )
44
+
45
+ # Toggle button (tap to switch modes)
46
+ if st.button(icon, key="dark_mode_toggle"):
47
+ st.session_state.dark_mode = not st.session_state.dark_mode
48
+ st.rerun()
49
+
50
+ # Apply styles for dark & light modes
51
+ if st.session_state.dark_mode:
52
+ st.markdown(
53
+ """
54
+ <style>
55
+ body, .stApp { background-color: #0A192F; color: #E0E5EC; font-family: 'Segoe UI', sans-serif; }
56
+ h1, h2, h3, p, label { color: white !important; }
57
+ .stTextInput > div > div > input {
58
+ background-color: #112240;
59
+ color: #E0E5EC;
60
+ border-radius: 8px;
61
+ padding: 10px;
62
+ border: 2px solid transparent;
63
+ box-shadow: 0px 0px 10px rgba(255, 255, 255, 0.2);
64
+ }
65
+ </style>
66
+ """,
67
+ unsafe_allow_html=True,
68
+ )
69
+ else:
70
+ st.markdown(
71
+ """
72
+ <style>
73
+ body, .stApp { background-color: #ffffff; color: #333; }
74
+ h1, h2, h3, p, label { color: #333 !important; }
75
+ .stTextInput > div > div > input {
76
+ background-color: #f8f9fa;
77
+ color: #333;
78
+ border-radius: 8px;
79
+ padding: 10px;
80
+ border: 1px solid #ccc;
81
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
82
+ }
83
+ </style>
84
+ """,
85
+ unsafe_allow_html=True,
86
+ )
87
+
88
+ # Hide Streamlit UI elements
89
+ st.markdown(
90
+ """
91
+ <style>
92
+ #MainMenu {visibility: hidden;}
93
+ footer {visibility: hidden;}
94
+ header {visibility: hidden;}
95
+ </style>
96
+ """,
97
+ unsafe_allow_html=True
98
+ )
99
+
100
+ # Load Sentence-Transformer Model (22MB)
101
+ embedding_model = SentenceTransformer("sentence-transformers/paraphrase-MiniLM-L3-v2")
102
+
103
+ def get_embeddings(text):
104
+ """Fetch embeddings using the local MiniLM model."""
105
+ return np.array(embedding_model.encode(text))
106
+
107
+ def get_stock_info(symbol: str) -> dict:
108
+ """Retrieve stock information and description from Yahoo Finance."""
109
+ try:
110
+ data = yf.Ticker(symbol)
111
+ stock_info = data.info
112
+ description = stock_info.get("longBusinessSummary", "No description available.")
113
+ return {"symbol": symbol, "description": description}
114
+ except Exception as e:
115
+ return {"symbol": symbol, "description": f"Error retrieving stock info: {str(e)}"}
116
+
117
+ # Determine embedding size dynamically
118
+ test_embedding = get_embeddings("Test")
119
+ d = test_embedding.shape[0]
120
+
121
+ # Initialize FAISS index
122
+ index = faiss.IndexFlatL2(d)
123
+ stock_metadata = {}
124
+
125
+ def store_stock_embeddings(stock_list):
126
+ """Store stock embeddings in FAISS index."""
127
+ global stock_metadata
128
+ vectors = []
129
+ metadata = []
130
+
131
+ for stock in stock_list:
132
+ description = stock["description"]
133
+ symbol = stock["symbol"]
134
+ embedding = get_embeddings(description)
135
+
136
+ if np.any(embedding):
137
+ vectors.append(embedding)
138
+ metadata.append({"symbol": symbol, "description": description})
139
+
140
+ if vectors:
141
+ index.add(np.array(vectors))
142
+ for i, meta in enumerate(metadata):
143
+ stock_metadata[len(stock_metadata)] = meta
144
+
145
+ def find_similar_stocks(query):
146
+ """Find similar stocks based on query embedding."""
147
+ if index.ntotal == 0:
148
+ return []
149
+
150
+ query_embedding = get_embeddings(query).reshape(1, -1)
151
+ D, I = index.search(query_embedding, k=10)
152
+ return [stock_metadata[idx] for idx in I[0] if idx in stock_metadata]
153
+
154
+ def analyze_stocks(query, stocks):
155
+ """Generate stock analysis using Groq's Llama model."""
156
+ if not stocks:
157
+ return "No relevant stocks found."
158
+
159
+ context = "\n".join([f"Symbol: {s['symbol']}, Description: {s['description']}" for s in stocks])
160
+ prompt = f"""
161
+ You are a financial assistant. Analyze the following stocks based on the given query: {query}.
162
+
163
+ Stock data:
164
+ {context}
165
+
166
+ Provide insights based on performance, trends, and any notable aspects.
167
+ """
168
+
169
+ try:
170
+ response = client.chat.completions.create(
171
+ model="llama-3.2-11b-vision-preview",
172
+ messages=[{"role": "user", "content": prompt}]
173
+ )
174
+ return response.choices[0].message.content
175
+ except Exception as e:
176
+ return f"Error generating analysis: {str(e)}"
177
+
178
+ # Load stock data at startup
179
+ default_stocks = ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA"]
180
+ stock_data = [get_stock_info(symbol) for symbol in default_stocks]
181
+ store_stock_embeddings(stock_data)
182
+
183
+ # Streamlit UI
184
+ st.title('Stock Analysis Dashboard')
185
+
186
+ with st.container():
187
+ query = st.text_input('Ask About Stocks:', '')
188
+
189
+ if st.button('Get Stock Info'):
190
+ stocks = find_similar_stocks(query)
191
+ analysis = analyze_stocks(query, stocks)
192
+
193
+ st.markdown("### Stock Insights:")
194
+ st.markdown(f"<div class='stMarkdown'>{analysis}</div>", unsafe_allow_html=True)
195
+
196
+ st.markdown("---")
197
+ if not stocks:
198
+ st.error("No relevant stocks found.")
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ yfinance
2
+ faiss-cpu
3
+ groq
4
+ python-dotenv
5
+ numpy
6
+ requests
7
+ scikit-learn
8
+ streamlit
9
+ sentence-transformers
10
+ asyncio