ChillThrills commited on
Commit
32c5a96
·
1 Parent(s): e39b6a0
Files changed (5) hide show
  1. app.py +0 -0
  2. model/scaler.pkl +3 -0
  3. model/xgboost_model.pkl +3 -0
  4. requirements.txt +12 -0
  5. supabase_logger.py +174 -0
app.py ADDED
The diff for this file is too large to render. See raw diff
 
model/scaler.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7d6c29cf9c373b28886a1d26080dc6b12c80a56b091c99a7914bab4a6aae0927
3
+ size 621
model/xgboost_model.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e39a0f3ea5e70dd9f25bd04f5d397a9348fb7e6ae660c8287ff646ebed923379
3
+ size 69850
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ google-generativeai
2
+ xgboost
3
+ scikit-learn
4
+ pandas
5
+ numpy
6
+ gradio
7
+ python-dotenv
8
+ duckduckgo-search
9
+ tavily-python
10
+ requests
11
+ beautifulsoup4
12
+ supabase
supabase_logger.py ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import json
3
+ import os
4
+ from typing import Optional, Dict, Any
5
+ import datetime
6
+ import re
7
+
8
+ def convert_numpy_floats(obj):
9
+ if isinstance(obj, dict):
10
+ return {k: convert_numpy_floats(v) for k, v in obj.items()}
11
+ elif isinstance(obj, list):
12
+ return [convert_numpy_floats(elem) for elem in obj]
13
+ elif isinstance(obj, float):
14
+ return obj
15
+ return obj
16
+
17
+ SUPABASE_PREDICTION_TABLE_NAME = os.getenv("SUPABASE_PREDICTION_TABLE_NAME")
18
+
19
+ def extract_simplified_contextual_outcome(analysis_response_text: str) -> Optional[str]:
20
+ if not analysis_response_text:
21
+ logging.warning("No analysis response text provided.")
22
+ return None
23
+
24
+ start = analysis_response_text.find("### EXECUTIVE_SUMMARY_START")
25
+ end = analysis_response_text.find("### EXECUTIVE_SUMMARY_END")
26
+ if start != -1 and end != -1 and end > start:
27
+ summary = analysis_response_text[start + len("### EXECUTIVE_SUMMARY_START"):end].strip()
28
+ else:
29
+ logging.info("No standard summary block found, using entire text.")
30
+ summary = analysis_response_text
31
+
32
+ extracted_value_from_source = None
33
+ logging_source_info = ""
34
+
35
+ for line in summary.splitlines():
36
+ if "DUAL RECOMMENDATION" in line:
37
+ m = re.search(r"\bOR\s+([^@|]+?)(?=\s*(?:@|\|))", line, re.IGNORECASE)
38
+ if m:
39
+ extracted_value_from_source = m.group(1).strip()
40
+ logging_source_info = "DUAL RECOMMENDATION"
41
+ break
42
+
43
+ if not extracted_value_from_source:
44
+ for line in summary.splitlines():
45
+ if "Preferred Outcome: Contextual" in line:
46
+ m = re.search(r"Contextual\s*\(([^)]+)\)", line)
47
+ if m:
48
+ raw_fallback_text = m.group(1).strip()
49
+ extracted_value_from_source = raw_fallback_text.split(" due to ")[0].split(" (")[0].strip()
50
+ logging_source_info = "Preferred Outcome: Contextual"
51
+ break
52
+
53
+ if not extracted_value_from_source:
54
+ logging.warning("Could not extract any contextual outcome candidate.")
55
+ return None
56
+
57
+ # Normalize the extracted string for comparison (handles case and internal spaces)
58
+ normalized_for_comparison = ' '.join(extracted_value_from_source.lower().split())
59
+
60
+ if normalized_for_comparison == "home win":
61
+ final_outcome = "Home"
62
+ logging.info(f"Extracted and simplified contextual outcome from {logging_source_info}: '{final_outcome}' (original: '{extracted_value_from_source}')")
63
+ return final_outcome
64
+ elif normalized_for_comparison == "away win":
65
+ final_outcome = "Away"
66
+ logging.info(f"Extracted and simplified contextual outcome from {logging_source_info}: '{final_outcome}' (original: '{extracted_value_from_source}')")
67
+ return final_outcome
68
+ else:
69
+ # No simplification for "Home Win" / "Away Win" applies. Return the extracted value as is.
70
+ logging.info(f"Extracted contextual outcome from {logging_source_info}: '{extracted_value_from_source}' (no 'Win' rule simplification)")
71
+ return extracted_value_from_source
72
+
73
+ def log_new_prediction_session(
74
+ supabase_client,
75
+ user_message_predict: str,
76
+ prediction_context: Dict[str, Any],
77
+ full_bot_response_predict: str
78
+ ) -> Optional[str]:
79
+ logging.info("Attempting to create new prediction session entry in Supabase...")
80
+
81
+ if supabase_client is None:
82
+ logging.warning("Supabase client not provided or initialized. Cannot create prediction session.")
83
+ return None
84
+ if not prediction_context or not prediction_context.get('odds') or not prediction_context.get('prediction') or 'probabilities' not in prediction_context:
85
+ logging.error("Prediction context is incomplete or missing probabilities for saving.")
86
+ return None
87
+
88
+ try:
89
+ odds = prediction_context['odds']
90
+ teams = prediction_context.get('teams')
91
+ pred_code = prediction_context['prediction']
92
+ probabilities_data = prediction_context.get('probabilities', {})
93
+ statistical_pred_str = {"W": "Home", "D": "Draw", "L": "Away"}.get(pred_code, pred_code)
94
+
95
+ data_to_save = {
96
+ "user_message_predict": user_message_predict,
97
+ "match_teams": f"{teams[0]} - {teams[1]}" if teams and isinstance(teams, (list, tuple)) and len(teams) == 2 else None,
98
+ "home_odds": odds.get('W'),
99
+ "draw_odds": odds.get('D'),
100
+ "away_odds": odds.get('L'),
101
+ "statistical_prediction": statistical_pred_str,
102
+ "statistical_probabilities": json.dumps(probabilities_data),
103
+ "full_bot_response_predict": full_bot_response_predict,
104
+ "contextual_prediction": None,
105
+ "user_message_analyze": None,
106
+ "full_bot_response_analyze": None,
107
+ "updated_at": None
108
+ }
109
+
110
+ response = supabase_client.table(SUPABASE_PREDICTION_TABLE_NAME).insert([data_to_save]).execute()
111
+
112
+ if response and hasattr(response, 'data') and response.data:
113
+ new_id = response.data[0].get('id')
114
+ logging.info(f"Successfully created prediction session entry. Record ID: {new_id}")
115
+ return str(new_id)
116
+ elif response and hasattr(response, 'error') and response.error:
117
+ logging.error(f"Supabase insert failed for new session: {response.error.message if hasattr(response.error, 'message') else response.error}")
118
+ return None
119
+ else:
120
+ logging.warning(f"Supabase insert for new session executed, but unexpected response format: {response}")
121
+ return None
122
+
123
+ except Exception as e:
124
+ logging.exception(f"An unexpected error occurred during Supabase new session logging:")
125
+ return None
126
+
127
+ def update_prediction_session_analysis(
128
+ supabase_client,
129
+ session_id: str,
130
+ user_message_analyze: str,
131
+ full_bot_response_analyze: str,
132
+ prediction_context: Dict[str, Any]
133
+ ) -> bool:
134
+ logging.info(f"Attempting to update prediction session entry ID {session_id} with analysis...")
135
+
136
+ if supabase_client is None:
137
+ logging.warning("Supabase client not provided or initialized. Cannot update prediction session.")
138
+ return False
139
+ if not session_id:
140
+ logging.error("No session_id provided for update.")
141
+ return False
142
+
143
+ try:
144
+ contextual_outcome = extract_simplified_contextual_outcome(full_bot_response_analyze)
145
+
146
+ if contextual_outcome is None:
147
+ logging.warning("Could not extract a contextual outcome from the analysis. "
148
+ "Setting contextual_prediction to null in the database.")
149
+
150
+ update_data = {
151
+ "user_message_analyze": user_message_analyze,
152
+ "contextual_prediction": contextual_outcome,
153
+ "full_bot_response_analyze": full_bot_response_analyze,
154
+ "updated_at": datetime.datetime.now(datetime.timezone.utc).isoformat()
155
+ }
156
+
157
+ response = supabase_client.table(SUPABASE_PREDICTION_TABLE_NAME).update(update_data).eq('id', session_id).execute()
158
+
159
+ if response and hasattr(response, 'data') and response.data:
160
+ logging.info(f"Successfully updated prediction session entry ID {session_id} with analysis.")
161
+ return True
162
+ elif response and hasattr(response, 'error') and response.error:
163
+ logging.error(f"Supabase update failed for session ID {session_id}: {response.error.message if hasattr(response.error, 'message') else response.error}")
164
+ return False
165
+ elif response and hasattr(response, 'count') and response.count > 0:
166
+ logging.info(f"Successfully updated prediction session entry ID {session_id} (Count: {response.count}).")
167
+ return True
168
+ else:
169
+ logging.warning(f"Supabase update for session ID {session_id} executed, but unexpected response format or no rows updated: {response}")
170
+ return False
171
+
172
+ except Exception as e:
173
+ logging.exception(f"An unexpected error occurred during Supabase session update for ID {session_id}:")
174
+ return False