Dhruv-Ty commited on
Commit
3158c30
·
verified ·
1 Parent(s): 453a4d2

added DB for conversation retention.

Browse files
Files changed (1) hide show
  1. src/database.py +171 -0
src/database.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Database module for handling conversation persistence using Supabase.
3
+ """
4
+
5
+ import os
6
+ import json
7
+ from datetime import datetime
8
+ import requests
9
+ from dotenv import load_dotenv
10
+
11
+ # Load environment variables
12
+ load_dotenv()
13
+
14
+ class SupabaseClient:
15
+ def __init__(self):
16
+ """Initialize Supabase client with credentials from environment variables."""
17
+ self.supabase_url = os.getenv('SUPABASE_URL')
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."""
26
+ url = f"{self.supabase_url}{endpoint}"
27
+ headers = {
28
+ "apikey": self.supabase_key,
29
+ "Authorization": f"Bearer {self.supabase_key}",
30
+ "Content-Type": "application/json",
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,
71
+ "role": message.get("role"),
72
+ "content": message.get("content"),
73
+ "timestamp": datetime.now().isoformat()
74
+ }
75
+
76
+ # Handle additional fields
77
+ if "explanation" in message:
78
+ message_data["explanation"] = message.get("explanation")
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()