GabrielSalem commited on
Commit
08a0ac5
·
verified ·
1 Parent(s): 1fd965e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -49
app.py CHANGED
@@ -3,24 +3,17 @@ from bs4 import BeautifulSoup
3
  import pandas as pd
4
  from io import StringIO
5
  from datetime import datetime, timedelta
6
-
7
  from langchain.tools import tool
8
- from langchain.agents import initialize_agent, Tool
9
  from langchain_openai import ChatOpenAI
 
10
 
11
  # === Configuration ===
12
- OPENROUTER_API_KEY = "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"
13
-
14
  HEADERS = {
15
- 'User-Agent': (
16
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
17
- 'AppleWebKit/537.36 (KHTML, like Gecko) '
18
- 'Chrome/124.0.0.0 Safari/537.36'
19
- ),
20
- 'Accept': (
21
- 'text/html,application/xhtml+xml,application/xml;'
22
- 'q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8'
23
- ),
24
  'Accept-Language': 'en-US,en;q=0.9',
25
  'Referer': 'https://www.google.com/',
26
  'Connection': 'keep-alive',
@@ -28,9 +21,10 @@ HEADERS = {
28
  'Upgrade-Insecure-Requests': '1'
29
  }
30
 
 
31
  @tool("GetCurrentPrice")
32
  def get_current_price(symbol: str) -> str:
33
- """Get the current price for a stock symbol (e.g., 'AAPL')."""
34
  url = f'https://www.marketwatch.com/investing/stock/{symbol}'
35
  response = requests.get(url, headers=HEADERS)
36
  if response.status_code == 200:
@@ -38,7 +32,7 @@ def get_current_price(symbol: str) -> str:
38
  price_tag = soup.find('bg-quote', class_='value')
39
  if price_tag:
40
  price = price_tag.get_text(strip=True)
41
- return f"{symbol.upper()} current price: ${price} (from MarketWatch)"
42
  else:
43
  return "Stock price not found."
44
  else:
@@ -46,7 +40,7 @@ def get_current_price(symbol: str) -> str:
46
 
47
  @tool("GetHistoricalData")
48
  def get_historical_data(symbol: str, days: int = 5000) -> str:
49
- """Get the last N days of historical OHLCV data for a stock symbol as CSV."""
50
  end_date = datetime.now()
51
  start_date = end_date - timedelta(days=days)
52
  start_date_str = start_date.strftime('%m/%d/%Y 00:00:00')
@@ -61,7 +55,7 @@ def get_historical_data(symbol: str, days: int = 5000) -> str:
61
  if response.status_code == 200:
62
  try:
63
  df = pd.read_csv(StringIO(response.text))
64
- return f"Historical data for {symbol.upper()} (from MarketWatch):\n" + df.head(10).to_csv(index=False)
65
  except Exception as e:
66
  return f"Failed to parse CSV data: {e}"
67
  else:
@@ -79,6 +73,7 @@ Technical Analysis: Core Concepts & Formulas
79
 
80
  Key Technical Indicators and Their Formulas:
81
  -------------------------------------------
 
82
  1. Simple Moving Average (SMA): SMA(time_period) = Sum(Price_t ... Price_{t-n}) / n
83
  2. Exponential Moving Average (EMA): EMA_t = (Price_t * α) + EMA_{t-1} * (1 - α), where α = 2/(n+1)
84
  3. Relative Strength Index (RSI): RSI = 100 - [100 / (1 + Avg Gain / Avg Loss)]
@@ -144,45 +139,69 @@ Key Technical Indicators and Their Formulas:
144
  - Hammer, Shooting Star, Engulfing, Doji, Morning/Evening Star, etc.
145
  """
146
 
 
147
  tools = [
148
- Tool.from_function(
149
- get_current_price,
150
- name="GetCurrentPrice",
151
- description="Get the current price for a stock symbol (e.g., AAPL)"
152
- ),
153
- Tool.from_function(
154
- get_historical_data,
155
- name="GetHistoricalData",
156
- description="Get the last N days of historical OHLCV data for a stock symbol as CSV"
157
- ),
158
- Tool.from_function(
159
- get_technical_analysis_docs,
160
- name="GetTechnicalAnalysisDocs",
161
- description="Provide documentation for technical analysis indicators"
162
- )
163
  ]
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  llm = ChatOpenAI(
166
  openai_api_key=OPENROUTER_API_KEY,
167
  openai_api_base="https://openrouter.ai/api/v1",
168
  model_name="google/gemma-3n-e4b-it:free"
169
  )
170
 
171
- agent = initialize_agent(
172
- tools,
173
- llm,
174
- agent="zero-shot-react-description",
175
- verbose=True # This will show all reasoning and tool usage!
176
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
 
178
- if __name__ == "__main__":
179
- print("Welcome to the Stock Analysis Agent!")
180
- print("Ask anything about stocks, technical analysis, or predictions.")
181
- print("Type 'exit' to quit.")
182
- while True:
183
- user_input = input("\nYour question: ")
184
- if user_input.lower() in ["exit", "quit"]:
185
- print("Goodbye!")
186
- break
187
- result = agent.run(user_input)
188
- print("\nAgent's answer:\n", result)
 
3
  import pandas as pd
4
  from io import StringIO
5
  from datetime import datetime, timedelta
6
+ import gradio as gr
7
  from langchain.tools import tool
8
+ from langchain.agents import initialize_agent, Tool, AgentExecutor
9
  from langchain_openai import ChatOpenAI
10
+ from langchain.callbacks.base import BaseCallbackHandler
11
 
12
  # === Configuration ===
13
+ OPENROUTER_API_KEY = "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"
 
14
  HEADERS = {
15
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
16
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
 
 
 
 
 
 
 
17
  'Accept-Language': 'en-US,en;q=0.9',
18
  'Referer': 'https://www.google.com/',
19
  'Connection': 'keep-alive',
 
21
  'Upgrade-Insecure-Requests': '1'
22
  }
23
 
24
+ # === Tools ===
25
  @tool("GetCurrentPrice")
26
  def get_current_price(symbol: str) -> str:
27
+ """here is the doc string"""
28
  url = f'https://www.marketwatch.com/investing/stock/{symbol}'
29
  response = requests.get(url, headers=HEADERS)
30
  if response.status_code == 200:
 
32
  price_tag = soup.find('bg-quote', class_='value')
33
  if price_tag:
34
  price = price_tag.get_text(strip=True)
35
+ return f"{symbol.upper()} current price: ${price}"
36
  else:
37
  return "Stock price not found."
38
  else:
 
40
 
41
  @tool("GetHistoricalData")
42
  def get_historical_data(symbol: str, days: int = 5000) -> str:
43
+ """here is it"""
44
  end_date = datetime.now()
45
  start_date = end_date - timedelta(days=days)
46
  start_date_str = start_date.strftime('%m/%d/%Y 00:00:00')
 
55
  if response.status_code == 200:
56
  try:
57
  df = pd.read_csv(StringIO(response.text))
58
+ return df.head(10).to_csv(index=False)
59
  except Exception as e:
60
  return f"Failed to parse CSV data: {e}"
61
  else:
 
73
 
74
  Key Technical Indicators and Their Formulas:
75
  -------------------------------------------
76
+
77
  1. Simple Moving Average (SMA): SMA(time_period) = Sum(Price_t ... Price_{t-n}) / n
78
  2. Exponential Moving Average (EMA): EMA_t = (Price_t * α) + EMA_{t-1} * (1 - α), where α = 2/(n+1)
79
  3. Relative Strength Index (RSI): RSI = 100 - [100 / (1 + Avg Gain / Avg Loss)]
 
139
  - Hammer, Shooting Star, Engulfing, Doji, Morning/Evening Star, etc.
140
  """
141
 
142
+ # === Register Tools ===
143
  tools = [
144
+ Tool.from_function(get_current_price, name="GetCurrentPrice", description="Get current stock price."),
145
+ Tool.from_function(get_historical_data, name="GetHistoricalData", description="Get stock historical data as CSV."),
146
+ Tool.from_function(get_technical_analysis_docs, name="GetTechnicalAnalysisDocs", description="Technical indicator docs.")
 
 
 
 
 
 
 
 
 
 
 
 
147
  ]
148
 
149
+ # === Callback handler to stream reasoning to chat ===
150
+ class ReasoningCallbackHandler(BaseCallbackHandler):
151
+ def __init__(self, chat_callback):
152
+ self.chat_callback = chat_callback
153
+
154
+ def on_tool_start(self, serialized, input_str, **kwargs):
155
+ self.chat_callback(f"🛠️ Using Tool: {serialized['name']} with input: {input_str}")
156
+
157
+ def on_tool_end(self, output, **kwargs):
158
+ self.chat_callback(f"✅ Tool output: {output}")
159
+
160
+ def on_llm_new_token(self, token, **kwargs):
161
+ if token.strip():
162
+ self.chat_callback(token)
163
+
164
+ # === OpenAI-compatible LLM via OpenRouter ===
165
  llm = ChatOpenAI(
166
  openai_api_key=OPENROUTER_API_KEY,
167
  openai_api_base="https://openrouter.ai/api/v1",
168
  model_name="google/gemma-3n-e4b-it:free"
169
  )
170
 
171
+ # === Agent Execution with live reasoning ===
172
+ def run_agent(question, chat_callback):
173
+ callback_handler = ReasoningCallbackHandler(chat_callback)
174
+ agent_executor = initialize_agent(
175
+ tools, llm,
176
+ agent="zero-shot-react-description",
177
+ verbose=True,
178
+ callbacks=[callback_handler]
179
+ )
180
+ try:
181
+ result = agent_executor.run(question)
182
+ except Exception as e:
183
+ result = f"❌ Error: {str(e)}"
184
+
185
+ chat_callback(f"✅ Final Answer: {result}")
186
+
187
+ # === Gradio UI ===
188
+ with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
189
+ gr.Markdown("## 📈 Stock Market Analysis Agent")
190
+ chatbot = gr.Chatbot(label="Stock Agent Chat")
191
+ with gr.Row():
192
+ user_input = gr.Textbox(label="Type your question here...", scale=4)
193
+ submit_btn = gr.Button("Submit", scale=1)
194
+
195
+ def respond(msg, chat_history):
196
+ chat_history.append((msg, ""))
197
+ def chat_callback(new_msg):
198
+ chat_history.append(("", new_msg))
199
+ chatbot.value = chat_history
200
+ run_agent(msg, chat_callback)
201
+ return chat_history
202
+
203
+
204
+
205
+ submit_btn.click(respond, [user_input, chatbot], [chatbot])
206
 
207
+ demo.launch()