Dhruv-Ty commited on
Commit
abc2d3f
·
verified ·
1 Parent(s): 6732304

Update src/database.py

Browse files
Files changed (1) hide show
  1. src/database.py +84 -174
src/database.py CHANGED
@@ -4,7 +4,6 @@ Database module for handling conversation persistence using Supabase.
4
 
5
  import os
6
  import json
7
- import logging
8
  from datetime import datetime
9
  import requests
10
  from dotenv import load_dotenv
@@ -12,11 +11,6 @@ from dotenv import load_dotenv
12
  # Load environment variables
13
  load_dotenv()
14
 
15
- # Set up logging
16
- logging.basicConfig(level=logging.INFO,
17
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
18
- logger = logging.getLogger('database')
19
-
20
  class SupabaseClient:
21
  def __init__(self):
22
  """Initialize Supabase client with credentials from environment variables."""
@@ -24,11 +18,8 @@ class SupabaseClient:
24
  self.supabase_key = os.getenv('SUPABASE_KEY')
25
 
26
  if not self.supabase_url or not self.supabase_key:
27
- logger.error("Supabase credentials not found in environment variables")
28
  raise ValueError("Supabase credentials not found in environment variables. "
29
  "Please set SUPABASE_URL and SUPABASE_KEY.")
30
-
31
- logger.info(f"Initialized Supabase client with URL: {self.supabase_url[:20]}...")
32
 
33
  def _make_request(self, method, endpoint, data=None, params=None):
34
  """Make a request to Supabase API."""
@@ -40,65 +31,40 @@ class SupabaseClient:
40
  "Prefer": "return=representation"
41
  }
42
 
43
- logger.debug(f"Making {method} request to {endpoint}")
44
-
45
- try:
46
- if method == "GET":
47
- response = requests.get(url, headers=headers, params=params)
48
- elif method == "POST":
49
- logger.debug(f"POST data: {json.dumps(data)[:500]}...")
50
- response = requests.post(url, headers=headers, json=data)
51
- elif method == "PUT":
52
- response = requests.put(url, headers=headers, json=data)
53
- elif method == "DELETE":
54
- response = requests.delete(url, headers=headers, params=params)
55
- else:
56
- raise ValueError(f"Unsupported method: {method}")
57
-
58
- # Check response status and log appropriately
59
- if response.status_code >= 400:
60
- logger.error(f"API error: {method} {endpoint} returned {response.status_code}: {response.text}")
61
- else:
62
- logger.debug(f"API success: {method} {endpoint} returned {response.status_code}")
63
-
64
- return response
65
-
66
- except requests.RequestException as e:
67
- logger.error(f"Request error: {str(e)}")
68
- raise
69
 
70
  def create_conversation(self, consultation_id):
71
  """Create a new conversation record in the database."""
72
- logger.info(f"Creating conversation with ID: {consultation_id}")
73
-
74
  data = {
75
  "consultation_id": consultation_id,
76
  "created_at": datetime.now().isoformat(),
77
  "is_active": True
78
  }
79
 
80
- try:
81
- response = self._make_request(
82
- "POST",
83
- "/rest/v1/conversations",
84
- data=data
85
- )
86
-
87
- if response.status_code not in (200, 201):
88
- logger.error(f"Failed to create conversation: {response.text}")
89
- raise Exception(f"Failed to create conversation: {response.text}")
90
-
91
- logger.info(f"Successfully created conversation: {consultation_id}")
92
- return response.json()
93
-
94
- except Exception as e:
95
- logger.error(f"Error creating conversation: {str(e)}")
96
- raise
97
 
98
  def save_message(self, consultation_id, message):
99
  """Save a single message to the database."""
100
- logger.info(f"Saving message for conversation: {consultation_id}, role: {message.get('role')}")
101
-
102
  # Normalize message format for database storage
103
  message_data = {
104
  "consultation_id": consultation_id,
@@ -113,149 +79,93 @@ class SupabaseClient:
113
 
114
  if "evidence" in message:
115
  # Convert evidence to string for storage
116
- try:
117
- message_data["evidence"] = json.dumps(message.get("evidence"))
118
- except Exception as e:
119
- logger.error(f"Error serializing evidence: {str(e)}")
120
- message_data["evidence"] = "[]"
121
 
122
- try:
123
- # First verify that the consultation_id exists
124
- verify_params = {"consultation_id": f"eq.{consultation_id}"}
125
- verify_response = self._make_request("GET", "/rest/v1/conversations", params=verify_params)
126
-
127
- if verify_response.status_code != 200 or len(verify_response.json()) == 0:
128
- logger.error(f"Conversation {consultation_id} not found, creating it first")
129
- self.create_conversation(consultation_id)
130
-
131
- # Now save the message
132
- response = self._make_request(
133
- "POST",
134
- "/rest/v1/messages",
135
- data=message_data
136
- )
137
-
138
- if response.status_code not in (200, 201):
139
- logger.error(f"Failed to save message: {response.text}")
140
- raise Exception(f"Failed to save message: {response.text}")
141
-
142
- logger.info(f"Successfully saved message for conversation: {consultation_id}")
143
- return response.json()
144
-
145
- except Exception as e:
146
- logger.error(f"Error saving message: {str(e)}")
147
- raise
148
 
149
  def get_conversation_history(self, consultation_id):
150
  """Retrieve full conversation history for a given consultation ID."""
151
- logger.info(f"Retrieving conversation history for: {consultation_id}")
152
-
153
  params = {
154
  "consultation_id": f"eq.{consultation_id}",
155
  "order": "timestamp.asc"
156
  }
157
 
158
- try:
159
- response = self._make_request(
160
- "GET",
161
- "/rest/v1/messages",
162
- params=params
163
- )
164
-
165
- if response.status_code != 200:
166
- logger.error(f"Failed to retrieve conversation history: {response.text}")
167
- raise Exception(f"Failed to retrieve conversation history: {response.text}")
168
-
169
- # Convert database format back to application format
170
- messages = response.json()
171
- history = []
172
-
173
- logger.info(f"Retrieved {len(messages)} messages for conversation: {consultation_id}")
 
 
174
 
175
- for msg in messages:
176
- message_dict = {
177
- "role": msg["role"],
178
- "content": msg["content"]
179
- }
180
-
181
- if msg.get("explanation"):
182
- message_dict["explanation"] = msg["explanation"]
183
-
184
- if msg.get("evidence"):
185
- # Parse evidence JSON string back to object
186
- try:
187
- message_dict["evidence"] = json.loads(msg["evidence"])
188
- except:
189
- message_dict["evidence"] = []
190
-
191
- history.append(message_dict)
192
 
193
- return history
 
 
 
 
 
194
 
195
- except Exception as e:
196
- logger.error(f"Error retrieving conversation history: {str(e)}")
197
- raise
198
 
199
  def delete_conversation(self, consultation_id):
200
  """Delete a completed conversation from the database."""
201
- logger.info(f"Deleting conversation: {consultation_id}")
 
 
202
 
203
- try:
204
- # First delete all messages
205
- msg_params = {"consultation_id": f"eq.{consultation_id}"}
206
- msg_response = self._make_request("DELETE", "/rest/v1/messages", params=msg_params)
207
-
208
- if msg_response.status_code != 200:
209
- logger.warning(f"Failed to delete messages for conversation {consultation_id}: {msg_response.text}")
210
-
211
- # Then delete conversation record
212
- conv_params = {"consultation_id": f"eq.{consultation_id}"}
213
- response = self._make_request("DELETE", "/rest/v1/conversations", params=conv_params)
214
-
215
- if response.status_code != 200:
216
- logger.error(f"Failed to delete conversation: {response.text}")
217
- raise Exception(f"Failed to delete conversation: {response.text}")
218
-
219
- logger.info(f"Successfully deleted conversation: {consultation_id}")
220
- return True
221
-
222
- except Exception as e:
223
- logger.error(f"Error deleting conversation: {str(e)}")
224
- raise
225
 
226
  def get_active_conversations(self):
227
  """Get list of active conversations."""
228
- logger.info("Retrieving active conversations")
229
-
230
  params = {
231
  "is_active": "eq.true",
232
  "order": "created_at.desc"
233
  }
234
 
235
- try:
236
- response = self._make_request(
237
- "GET",
238
- "/rest/v1/conversations",
239
- params=params
240
- )
241
-
242
- if response.status_code != 200:
243
- logger.error(f"Failed to retrieve active conversations: {response.text}")
244
- raise Exception(f"Failed to retrieve active conversations: {response.text}")
245
-
246
- conversations = response.json()
247
- logger.info(f"Retrieved {len(conversations)} active conversations")
248
- return conversations
249
-
250
- except Exception as e:
251
- logger.error(f"Error retrieving active conversations: {str(e)}")
252
- raise
253
 
254
  # Initialize database client
255
  def get_db_client():
256
  """Get database client instance."""
257
- try:
258
- return SupabaseClient()
259
- except Exception as e:
260
- logger.error(f"Error initializing database client: {str(e)}")
261
- raise
 
4
 
5
  import os
6
  import json
 
7
  from datetime import datetime
8
  import requests
9
  from dotenv import load_dotenv
 
11
  # Load environment variables
12
  load_dotenv()
13
 
 
 
 
 
 
14
  class SupabaseClient:
15
  def __init__(self):
16
  """Initialize Supabase client with credentials from environment variables."""
 
18
  self.supabase_key = os.getenv('SUPABASE_KEY')
19
 
20
  if not self.supabase_url or not self.supabase_key:
 
21
  raise ValueError("Supabase credentials not found in environment variables. "
22
  "Please set SUPABASE_URL and SUPABASE_KEY.")
 
 
23
 
24
  def _make_request(self, method, endpoint, data=None, params=None):
25
  """Make a request to Supabase API."""
 
31
  "Prefer": "return=representation"
32
  }
33
 
34
+ if method == "GET":
35
+ response = requests.get(url, headers=headers, params=params)
36
+ elif method == "POST":
37
+ response = requests.post(url, headers=headers, json=data)
38
+ elif method == "PUT":
39
+ response = requests.put(url, headers=headers, json=data)
40
+ elif method == "DELETE":
41
+ response = requests.delete(url, headers=headers, params=params)
42
+ else:
43
+ raise ValueError(f"Unsupported method: {method}")
44
+
45
+ return response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  def create_conversation(self, consultation_id):
48
  """Create a new conversation record in the database."""
 
 
49
  data = {
50
  "consultation_id": consultation_id,
51
  "created_at": datetime.now().isoformat(),
52
  "is_active": True
53
  }
54
 
55
+ response = self._make_request(
56
+ "POST",
57
+ "/rest/v1/conversations",
58
+ data=data
59
+ )
60
+
61
+ if response.status_code not in (200, 201):
62
+ raise Exception(f"Failed to create conversation: {response.text}")
63
+
64
+ return response.json()
 
 
 
 
 
 
 
65
 
66
  def save_message(self, consultation_id, message):
67
  """Save a single message to the database."""
 
 
68
  # Normalize message format for database storage
69
  message_data = {
70
  "consultation_id": consultation_id,
 
79
 
80
  if "evidence" in message:
81
  # Convert evidence to string for storage
82
+ message_data["evidence"] = json.dumps(message.get("evidence"))
 
 
 
 
83
 
84
+ response = self._make_request(
85
+ "POST",
86
+ "/rest/v1/messages",
87
+ data=message_data
88
+ )
89
+
90
+ if response.status_code not in (200, 201):
91
+ raise Exception(f"Failed to save message: {response.text}")
92
+
93
+ return response.json()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  def get_conversation_history(self, consultation_id):
96
  """Retrieve full conversation history for a given consultation ID."""
 
 
97
  params = {
98
  "consultation_id": f"eq.{consultation_id}",
99
  "order": "timestamp.asc"
100
  }
101
 
102
+ response = self._make_request(
103
+ "GET",
104
+ "/rest/v1/messages",
105
+ params=params
106
+ )
107
+
108
+ if response.status_code != 200:
109
+ raise Exception(f"Failed to retrieve conversation history: {response.text}")
110
+
111
+ # Convert database format back to application format
112
+ messages = response.json()
113
+ history = []
114
+
115
+ for msg in messages:
116
+ message_dict = {
117
+ "role": msg["role"],
118
+ "content": msg["content"]
119
+ }
120
 
121
+ if msg.get("explanation"):
122
+ message_dict["explanation"] = msg["explanation"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
+ if msg.get("evidence"):
125
+ # Parse evidence JSON string back to object
126
+ try:
127
+ message_dict["evidence"] = json.loads(msg["evidence"])
128
+ except:
129
+ message_dict["evidence"] = []
130
 
131
+ history.append(message_dict)
132
+
133
+ return history
134
 
135
  def delete_conversation(self, consultation_id):
136
  """Delete a completed conversation from the database."""
137
+ # First delete all messages
138
+ msg_params = {"consultation_id": f"eq.{consultation_id}"}
139
+ self._make_request("DELETE", "/rest/v1/messages", params=msg_params)
140
 
141
+ # Then delete conversation record
142
+ conv_params = {"consultation_id": f"eq.{consultation_id}"}
143
+ response = self._make_request("DELETE", "/rest/v1/conversations", params=conv_params)
144
+
145
+ if response.status_code != 200:
146
+ raise Exception(f"Failed to delete conversation: {response.text}")
147
+
148
+ return True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
  def get_active_conversations(self):
151
  """Get list of active conversations."""
 
 
152
  params = {
153
  "is_active": "eq.true",
154
  "order": "created_at.desc"
155
  }
156
 
157
+ response = self._make_request(
158
+ "GET",
159
+ "/rest/v1/conversations",
160
+ params=params
161
+ )
162
+
163
+ if response.status_code != 200:
164
+ raise Exception(f"Failed to retrieve active conversations: {response.text}")
165
+
166
+ return response.json()
 
 
 
 
 
 
 
 
167
 
168
  # Initialize database client
169
  def get_db_client():
170
  """Get database client instance."""
171
+ return SupabaseClient()