Faham commited on
Commit
65a44fe
Β·
1 Parent(s): 97db5ba

FIX: response from LLM

Browse files
Files changed (1) hide show
  1. Home.py +63 -235
Home.py CHANGED
@@ -1,12 +1,10 @@
1
  import streamlit as st
2
  import asyncio
3
- import json
4
  import re
5
  import os
6
  import plotly.graph_objects as go
7
  import yfinance as yf
8
  import time
9
- import sys
10
  from datetime import timedelta
11
  import gnews
12
  from bs4 import BeautifulSoup
@@ -20,19 +18,9 @@ from sklearn.linear_model import Ridge
20
  from sklearn.model_selection import GridSearchCV
21
  from dotenv import load_dotenv
22
  from sklearn.preprocessing import StandardScaler
23
-
24
- # Try different import approaches
25
- try:
26
- from langchain_mcp_adapters.client import MultiServerMCPClient
27
- except ImportError:
28
- try:
29
- from langchain_mcp_adapters import MultiServerMCPClient
30
- except ImportError:
31
- # Fallback to basic MCP client
32
- MultiServerMCPClient = None
33
  from langgraph.prebuilt import create_react_agent
34
  from langchain_groq import ChatGroq
35
- from langchain_core.tools import tool
36
 
37
 
38
  # Load environment variables
@@ -914,24 +902,6 @@ async def initialize_mcp_agent(model, tools):
914
  print(f"❌ MCP agent creation traceback: {traceback.format_exc()}")
915
  return None
916
 
917
- # Test the agent with LangGraph
918
- try:
919
- # Use LangGraph ainvoke method for async tools
920
- test_result = await agent.ainvoke(
921
- {
922
- "messages": [
923
- {"role": "user", "content": "What tools do you have available?"}
924
- ]
925
- }
926
- )
927
- print(f"πŸ” Test result: {test_result}")
928
- except Exception as e:
929
- st.warning(f"⚠️ MCP agent test failed: {str(e)}")
930
- print(f"❌ MCP agent test error: {str(e)}")
931
- import traceback
932
-
933
- print(f"❌ MCP agent test traceback: {traceback.format_exc()}")
934
-
935
  return agent
936
 
937
  except Exception as e:
@@ -944,7 +914,7 @@ async def initialize_mcp_agent(model, tools):
944
 
945
 
946
  async def run_agent_with_mcp(user_query: str, selected_ticker: str = None):
947
- """Run the agent using LangGraph React agent"""
948
  try:
949
  # Get tools and model from session state
950
  if "mcp_tools" not in st.session_state or "mcp_model" not in st.session_state:
@@ -989,9 +959,6 @@ Question: {user_query} for {selected_ticker}"""
989
  {"messages": [{"role": "user", "content": full_query}]}
990
  )
991
 
992
- # Debug: Log the result
993
- print(f"πŸ” MCP Agent Result: {result}")
994
-
995
  # Extract the final answer from the result
996
  if isinstance(result, dict) and "output" in result:
997
  final_response = result["output"]
@@ -1000,53 +967,9 @@ Question: {user_query} for {selected_ticker}"""
1000
  else:
1001
  final_response = str(result)
1002
 
1003
- # Debug: Print the result type and structure
1004
- print(f"πŸ” Result type: {type(result)}")
1005
- if isinstance(result, dict):
1006
- print(f"πŸ” Result keys: {list(result.keys())}")
1007
- print(f"πŸ” Final response type: {type(final_response)}")
1008
-
1009
- # If the response contains multiple messages, extract only the final AI response
1010
- if "AIMessage" in final_response:
1011
- # Debug: Print the response structure
1012
- print(f"πŸ” Response structure: {final_response[:500]}...")
1013
-
1014
- # Look for the last AIMessage with content
1015
- ai_messages = re.findall(
1016
- r"AIMessage\(content=\'(.*?)\',", final_response, re.DOTALL
1017
- )
1018
- if ai_messages:
1019
- final_response = ai_messages[-1] # Get the last AI message
1020
- print(f"βœ… Extracted AI message: {final_response[:100]}...")
1021
- else:
1022
- # Try alternative pattern without the comma
1023
- ai_messages = re.findall(
1024
- r"AIMessage\(content=\'(.*?)\'", final_response, re.DOTALL
1025
- )
1026
- if ai_messages:
1027
- final_response = ai_messages[-1]
1028
- print(
1029
- f"βœ… Extracted AI message (alt): {final_response[:100]}..."
1030
- )
1031
- else:
1032
- print("❌ No AI messages found in response")
1033
- # Try to find any content after the last ToolMessage
1034
- if "ToolMessage" in final_response:
1035
- # Split by ToolMessage and take the last part
1036
- parts = final_response.split("ToolMessage")
1037
- if len(parts) > 1:
1038
- last_part = parts[-1]
1039
- # Look for AIMessage in the last part
1040
- ai_match = re.search(
1041
- r"AIMessage\(content=\'(.*?)\'",
1042
- last_part,
1043
- re.DOTALL,
1044
- )
1045
- if ai_match:
1046
- final_response = ai_match.group(1)
1047
- print(
1048
- f"βœ… Extracted from last part: {final_response[:100]}..."
1049
- )
1050
 
1051
  # Clean up the final response to remove escaped characters
1052
  final_response = (
@@ -1055,112 +978,69 @@ Question: {user_query} for {selected_ticker}"""
1055
  .replace('\\"', '"')
1056
  )
1057
 
1058
- # Check if response is incomplete (only shows tool calls)
1059
- if "[TOOL_CALLS" in final_response and (
1060
- "Final Answer:" not in final_response
1061
- and "Based on" not in final_response
1062
- ):
1063
- st.warning("⚠️ Agent response incomplete - only tool calls detected")
1064
- st.info("πŸ”„ Trying to get complete response...")
1065
- # Try a simpler query to get the final analysis
1066
- try:
1067
- simple_query = f"Provide a comprehensive analysis of {selected_ticker} based on the latest news and stock data."
1068
- simple_result = await agent.ainvoke(
1069
- {"messages": [{"role": "user", "content": simple_query}]}
1070
  )
1071
 
1072
- if (
1073
- isinstance(simple_result, dict)
1074
- and "output" in simple_result
1075
- ):
1076
- simple_response = simple_result["output"]
1077
- else:
1078
- simple_response = str(simple_result)
1079
-
1080
- if len(simple_response) > 100:
1081
- return simple_response
1082
- else:
1083
- return f"Tool execution started but final analysis incomplete. Please try again."
1084
- except Exception as e2:
1085
- return f"Tool execution started but final analysis failed: {str(e2)}"
1086
-
1087
- # Look for the final answer section
1088
- if "Final Answer:" in final_response:
1089
- # Extract everything after "Final Answer:"
1090
- final_answer = final_response.split("Final Answer:")[-1].strip()
1091
- return final_answer
1092
- elif "Thought:" in final_response and "Action:" in final_response:
1093
- # If it contains thought process, try to extract the final analysis
1094
- # Look for the last meaningful paragraph
1095
- lines = final_response.split("\n")
1096
- final_lines = []
1097
- for line in reversed(lines):
1098
- if (
1099
- line.strip()
1100
- and not line.startswith("Thought:")
1101
- and not line.startswith("Action:")
1102
- and not line.startswith("Observation:")
1103
- ):
1104
- final_lines.insert(0, line)
1105
- elif line.strip() and (
1106
- "Based on" in line
1107
- or "Recommendation:" in line
1108
- or "Conclusion:" in line
1109
- ):
1110
- final_lines.insert(0, line)
1111
- if final_lines:
1112
- return "\n".join(final_lines)
1113
  else:
1114
- return final_response
1115
- else:
1116
- # Always return a string as a fallback
1117
- return str(final_response)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1118
  except Exception as e:
1119
  st.error(f"❌ Error during agent execution: {str(e)}")
1120
- st.error(f"Error type: {type(e).__name__}")
1121
- import traceback
1122
-
1123
- st.error(f"Full traceback: {traceback.format_exc()}")
1124
- # Log to console
1125
- print(f"❌ MCP Agent Execution Error: {str(e)}")
1126
- print(f"Error type: {type(e).__name__}")
1127
- print(f"Full traceback: {traceback.format_exc()}")
1128
-
1129
- # Check if it's a TaskGroup error
1130
- if "TaskGroup" in str(e):
1131
- st.error(
1132
- "❌ TaskGroup error - this might be due to MCP server connection issues"
1133
- )
1134
- st.info("πŸ”„ Trying to restart MCP agent...")
1135
- # Clear the agent and try to reinitialize
1136
- if "mcp_agent" in st.session_state:
1137
- del st.session_state.mcp_agent
1138
- return "Please try again - MCP agent will be reinitialized"
1139
- else:
1140
- # Try a different approach - use the agent's available methods
1141
- st.info("πŸ”„ Trying alternative execution method...")
1142
- try:
1143
- # Try using the agent's available methods
1144
- if hasattr(agent, "arun"):
1145
- result = await agent.arun(full_query)
1146
- elif hasattr(agent, "run"):
1147
- result = await agent.run(
1148
- full_query
1149
- ) # Always await async methods
1150
- else:
1151
- result = "Agent has no available execution methods"
1152
- return result
1153
- except Exception as e2:
1154
- st.error(f"❌ Alternative execution also failed: {str(e2)}")
1155
- st.error(f"Error type: {type(e2).__name__}")
1156
- import traceback
1157
-
1158
- st.error(f"Full traceback: {traceback.format_exc()}")
1159
- # Log to console
1160
- print(f"❌ MCP Alternative Execution Error: {str(e2)}")
1161
- print(f"Error type: {type(e2).__name__}")
1162
- print(f"Full traceback: {traceback.format_exc()}")
1163
- return f"Error: {str(e2)}"
1164
 
1165
  except Exception as e:
1166
  st.error(f"❌ Error running MCP agent: {e}")
@@ -1261,50 +1141,6 @@ def create_trading_day_future_dataframe(model, periods=30, freq="D"):
1261
  return future_df
1262
 
1263
 
1264
- def test_server_availability():
1265
- """Test if the MCP servers are available and can be executed."""
1266
-
1267
- current_dir = os.path.dirname(os.path.abspath(__file__))
1268
-
1269
- # Test news server
1270
- news_server_path = os.path.join(current_dir, "news_server.py")
1271
- if not os.path.exists(news_server_path):
1272
- print(f"❌ ERROR: news_server.py not found at {news_server_path}")
1273
- return False
1274
-
1275
- # Test stock data server
1276
- stock_server_path = os.path.join(current_dir, "stock_data_server.py")
1277
- if not os.path.exists(stock_server_path):
1278
- print(f"❌ ERROR: stock_data_server.py not found at {stock_server_path}")
1279
- return False
1280
-
1281
- # Test if servers can be executed by checking if they can be imported
1282
-
1283
- try:
1284
- # Test if news_server can be imported
1285
- spec = importlib.util.spec_from_file_location("news_server", news_server_path)
1286
- if spec is None or spec.loader is None:
1287
- print("⚠️ WARNING: Could not load news_server.py")
1288
- else:
1289
- print("βœ… SUCCESS: news_server.py is importable")
1290
- except Exception as e:
1291
- print(f"⚠️ WARNING: Could not import news_server.py: {e}")
1292
-
1293
- try:
1294
- # Test if stock_data_server can be imported
1295
- spec = importlib.util.spec_from_file_location(
1296
- "stock_data_server", stock_server_path
1297
- )
1298
- if spec is None or spec.loader is None:
1299
- print("⚠️ WARNING: Could not load stock_data_server.py")
1300
- else:
1301
- print("βœ… SUCCESS: stock_data_server.py is importable")
1302
- except Exception as e:
1303
- print(f"⚠️ WARNING: Could not import stock_data_server.py: {e}")
1304
-
1305
- return True
1306
-
1307
-
1308
  def main():
1309
  st.set_page_config(page_title="QueryStockAI", page_icon="πŸ“ˆ", layout="wide")
1310
 
@@ -1370,14 +1206,6 @@ def main():
1370
  st.error(f"❌ Failed to initialize MCP client: {str(e)}")
1371
  st.stop()
1372
 
1373
- # Test server availability only once on startup
1374
- if "servers_tested" not in st.session_state:
1375
- st.session_state.servers_tested = False
1376
-
1377
- if not st.session_state.servers_tested:
1378
- test_server_availability()
1379
- st.session_state.servers_tested = True
1380
-
1381
  # Available tickers
1382
  with st.spinner("πŸ”„ Loading available tickers..."):
1383
  available_tickers = get_available_tickers()
 
1
  import streamlit as st
2
  import asyncio
 
3
  import re
4
  import os
5
  import plotly.graph_objects as go
6
  import yfinance as yf
7
  import time
 
8
  from datetime import timedelta
9
  import gnews
10
  from bs4 import BeautifulSoup
 
18
  from sklearn.model_selection import GridSearchCV
19
  from dotenv import load_dotenv
20
  from sklearn.preprocessing import StandardScaler
21
+ from langchain_mcp_adapters.client import MultiServerMCPClient
 
 
 
 
 
 
 
 
 
22
  from langgraph.prebuilt import create_react_agent
23
  from langchain_groq import ChatGroq
 
24
 
25
 
26
  # Load environment variables
 
902
  print(f"❌ MCP agent creation traceback: {traceback.format_exc()}")
903
  return None
904
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
905
  return agent
906
 
907
  except Exception as e:
 
914
 
915
 
916
  async def run_agent_with_mcp(user_query: str, selected_ticker: str = None):
917
+ """Run the agent using LangGraph React agent (non-streaming version)"""
918
  try:
919
  # Get tools and model from session state
920
  if "mcp_tools" not in st.session_state or "mcp_model" not in st.session_state:
 
959
  {"messages": [{"role": "user", "content": full_query}]}
960
  )
961
 
 
 
 
962
  # Extract the final answer from the result
963
  if isinstance(result, dict) and "output" in result:
964
  final_response = result["output"]
 
967
  else:
968
  final_response = str(result)
969
 
970
+ # Debug: Print the raw result to see what we're getting
971
+ print("πŸ” Raw result type:", type(result))
972
+ print("πŸ” Raw result:", result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973
 
974
  # Clean up the final response to remove escaped characters
975
  final_response = (
 
978
  .replace('\\"', '"')
979
  )
980
 
981
+ # Try to extract the final analysis more simply
982
+ # First, try to get the last meaningful content
983
+ if "AIMessage" in final_response:
984
+ # Look for the last AIMessage with content
985
+ ai_messages = re.findall(
986
+ r'AIMessage\(content="([^"]*)"', final_response, re.DOTALL
987
+ )
988
+ if not ai_messages:
989
+ # Try single quotes
990
+ ai_messages = re.findall(
991
+ r"AIMessage\(content='([^']*)'", final_response, re.DOTALL
 
992
  )
993
 
994
+ if ai_messages:
995
+ print(f"πŸ” Found {len(ai_messages)} AIMessages")
996
+ for i, msg in enumerate(ai_messages):
997
+ print(f"πŸ” Message {i+1} length: {len(msg.strip())}")
998
+ print(f"πŸ” Message {i+1} preview: {msg.strip()[:100]}...")
999
+ print(f"πŸ” Message {i+1} starts with: {msg.strip()[:20]}")
1000
+
1001
+ # Always get the last AIMessage which contains the complete analysis
1002
+ # The last AIMessage is the final analysis, not the tool call
1003
+ final_response = ai_messages[-1].strip()
1004
+ print(f"πŸ” Selected message {len(ai_messages)} (the last one)")
1005
+ print(f"πŸ” Selected message starts with: {final_response[:50]}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1006
  else:
1007
+ # If no AIMessage found, try to extract from the raw response
1008
+ final_response = final_response.strip()
1009
+
1010
+ # Remove any remaining tool call artifacts
1011
+ final_response = re.sub(r"<\|.*?\|>", "", final_response)
1012
+ final_response = re.sub(
1013
+ r"functions\.[a-zA-Z_]+:\d+", "", final_response
1014
+ )
1015
+ final_response = re.sub(r'\{[^{}]*"ticker"[^{}]*\}', "", final_response)
1016
+
1017
+ # Remove LangGraph metadata
1018
+ final_response = re.sub(
1019
+ r"\{.*?agent.*?\}", "", final_response, flags=re.DOTALL
1020
+ )
1021
+ final_response = re.sub(
1022
+ r"\{.*?tools.*?\}", "", final_response, flags=re.DOTALL
1023
+ )
1024
+ final_response = re.sub(
1025
+ r"ToolMessage.*?\]", "", final_response, flags=re.DOTALL
1026
+ )
1027
+ final_response = re.sub(
1028
+ r"additional_kwargs.*?usage_metadata.*?\}",
1029
+ "",
1030
+ final_response,
1031
+ flags=re.DOTALL,
1032
+ )
1033
+
1034
+ # Clean up extra whitespace and formatting
1035
+ final_response = re.sub(r"\n\s*\n", "\n\n", final_response)
1036
+ final_response = final_response.strip()
1037
+
1038
+ print("πŸ” Final cleaned response:", final_response)
1039
+ return final_response
1040
+
1041
  except Exception as e:
1042
  st.error(f"❌ Error during agent execution: {str(e)}")
1043
+ return f"Error during execution: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1044
 
1045
  except Exception as e:
1046
  st.error(f"❌ Error running MCP agent: {e}")
 
1141
  return future_df
1142
 
1143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1144
  def main():
1145
  st.set_page_config(page_title="QueryStockAI", page_icon="πŸ“ˆ", layout="wide")
1146
 
 
1206
  st.error(f"❌ Failed to initialize MCP client: {str(e)}")
1207
  st.stop()
1208
 
 
 
 
 
 
 
 
 
1209
  # Available tickers
1210
  with st.spinner("πŸ”„ Loading available tickers..."):
1211
  available_tickers = get_available_tickers()