maitrang04 commited on
Commit
1fda108
·
verified ·
1 Parent(s): fd86eaa

Update backend/ai/database.py

Browse files
Files changed (1) hide show
  1. backend/ai/database.py +93 -75
backend/ai/database.py CHANGED
@@ -1,41 +1,39 @@
1
- # database.py
2
  import sqlite3
3
  import datetime
4
  import os
 
5
 
6
  # --- Đường dẫn DB trên Hugging Face Space ---
7
  DB_NAME = os.path.join("/tmp", "vnpt_call_center.db")
 
8
 
9
  # --- 20 DATA MẪU ---
10
  INITIAL_DATA = [
11
  {"customer_id": "CUS_001", "call_id": "CALL_0001", "call_timestamp": "2025-01-20T08:15:00+07:00", "call_duration_seconds": 78, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2350},
12
  {"customer_id": "CUS_002", "call_id": "CALL_0002", "call_timestamp": "2025-01-20T08:35:00+07:00", "call_duration_seconds": 92, "intent": "cancel_package", "sentiment": "neutral", "ai_resolved": True, "upsell_success": True, "csat": 4, "cost_per_call_vnd": 2480},
13
- {"customer_id": "CUS_003", "call_id": "CALL_0003", "call_timestamp": "2025-01-20T09:05:00+07:00", "call_duration_seconds": 110, "intent": "competitor", "sentiment": "negative", "ai_resolved": False, "upsell_success": False, "csat": 3, "cost_per_call_vnd": 2650},
14
- {"customer_id": "CUS_004", "call_id": "CALL_0004", "call_timestamp": "2025-01-20T09:40:00+07:00", "call_duration_seconds": 70, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2300},
15
- {"customer_id": "CUS_005", "call_id": "CALL_0005", "call_timestamp": "2025-01-20T10:10:00+07:00", "call_duration_seconds": 88, "intent": "cancel_package", "sentiment": "neutral", "ai_resolved": True, "upsell_success": True, "csat": 4, "cost_per_call_vnd": 2450},
16
- {"customer_id": "CUS_006", "call_id": "CALL_0006", "call_timestamp": "2025-01-20T10:45:00+07:00", "call_duration_seconds": 80, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2380},
17
- {"customer_id": "CUS_007", "call_id": "CALL_0007", "call_timestamp": "2025-01-18T14:20:00+07:00", "call_duration_seconds": 95, "intent": "cancel_package", "sentiment": "neutral", "ai_resolved": True, "upsell_success": True, "csat": 4, "cost_per_call_vnd": 2500},
18
- {"customer_id": "CUS_008", "call_id": "CALL_0008", "call_timestamp": "2025-01-18T16:05:00+07:00", "call_duration_seconds": 72, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2320},
19
- {"customer_id": "CUS_009", "call_id": "CALL_0009", "call_timestamp": "2025-01-17T10:30:00+07:00", "call_duration_seconds": 105, "intent": "competitor", "sentiment": "negative", "ai_resolved": False, "upsell_success": False, "csat": 3, "cost_per_call_vnd": 2680},
20
- {"customer_id": "CUS_010", "call_id": "CALL_0010", "call_timestamp": "2025-01-17T15:10:00+07:00", "call_duration_seconds": 85, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2400},
21
- {"customer_id": "CUS_011", "call_id": "CALL_0011", "call_timestamp": "2025-01-16T09:45:00+07:00", "call_duration_seconds": 90, "intent": "cancel_package", "sentiment": "neutral", "ai_resolved": True, "upsell_success": True, "csat": 4, "cost_per_call_vnd": 2480},
22
- {"customer_id": "CUS_012", "call_id": "CALL_0012", "call_timestamp": "2025-01-16T11:20:00+07:00", "call_duration_seconds": 76, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2350},
23
- {"customer_id": "CUS_013", "call_id": "CALL_0013", "call_timestamp": "2025-01-15T14:55:00+07:00", "call_duration_seconds": 108, "intent": "competitor", "sentiment": "negative", "ai_resolved": False, "upsell_success": False, "csat": 3, "cost_per_call_vnd": 2620},
24
- {"customer_id": "CUS_014", "call_id": "CALL_0014", "call_timestamp": "2025-01-15T16:40:00+07:00", "call_duration_seconds": 82, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2380},
25
- {"customer_id": "CUS_015", "call_id": "CALL_0015", "call_timestamp": "2025-01-10T10:15:00+07:00", "call_duration_seconds": 88, "intent": "cancel_package", "sentiment": "neutral", "ai_resolved": True, "upsell_success": True, "csat": 4, "cost_per_call_vnd": 2450},
26
- {"customer_id": "CUS_016", "call_id": "CALL_0016", "call_timestamp": "2025-01-08T14:30:00+07:00", "call_duration_seconds": 74, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2350},
27
- {"customer_id": "CUS_017", "call_id": "CALL_0017", "call_timestamp": "2025-01-05T09:50:00+07:00", "call_duration_seconds": 112, "intent": "competitor", "sentiment": "negative", "ai_resolved": False, "upsell_success": False, "csat": 3, "cost_per_call_vnd": 2700},
28
- {"customer_id": "CUS_018", "call_id": "CALL_0018", "call_timestamp": "2025-01-04T15:05:00+07:00", "call_duration_seconds": 80, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2380},
29
- {"customer_id": "CUS_019", "call_id": "CALL_0019", "call_timestamp": "2025-01-03T11:40:00+07:00", "call_duration_seconds": 96, "intent": "cancel_package", "sentiment": "neutral", "ai_resolved": True, "upsell_success": True, "csat": 4, "cost_per_call_vnd": 2500},
30
- {"customer_id": "CUS_020", "call_id": "CALL_0020", "call_timestamp": "2024-12-28T16:10:00+07:00", "call_duration_seconds": 85, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2400}
31
  ]
32
 
33
  class Database:
34
  def __init__(self):
35
- self._init_db()
 
 
 
 
 
 
36
 
37
  def _get_conn(self):
38
- return sqlite3.connect(DB_NAME, check_same_thread=False)
 
 
 
 
 
 
 
39
 
40
  def _init_db(self):
41
  conn = self._get_conn()
@@ -55,69 +53,87 @@ class Database:
55
  cost INTEGER
56
  )
57
  ''')
58
- # Seed nếu DB trống
59
  cursor.execute("SELECT count(*) FROM calls")
60
- if cursor.fetchone()[0] == 0:
61
- print(" [DB] Database trống. Đang nạp 20 bản ghi mẫu...")
 
 
62
  self._seed_data(cursor)
63
  conn.commit()
 
64
  conn.close()
65
 
66
  def _seed_data(self, cursor):
67
  for item in INITIAL_DATA:
68
- cursor.execute('''
69
- INSERT INTO calls (customer_id, call_id, call_timestamp, duration, intent, sentiment, ai_resolved, upsell, csat, cost)
70
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
71
- ''', (
72
- item['customer_id'],
73
- item['call_id'],
74
- item['call_timestamp'],
75
- item['call_duration_seconds'],
76
- item['intent'],
77
- item['sentiment'],
78
- item['ai_resolved'],
79
- item['upsell_success'],
80
- item['csat'],
81
- item['cost_per_call_vnd']
82
- ))
 
 
 
 
83
 
84
  def get_all_calls(self):
85
- conn = self._get_conn()
86
- cursor = conn.cursor()
87
- cursor.execute("SELECT * FROM calls ORDER BY call_timestamp DESC")
88
- rows = cursor.fetchall()
89
- conn.close()
90
- result = []
91
- for r in rows:
92
- result.append({
93
- "id": r[1], # customer_id
94
- "time": r[3], # timestamp
95
- "dur": r[4], # duration
96
- "intent": r[5],
97
- "sent": r[6],
98
- "ai": bool(r[7]),
99
- "upsell": bool(r[8]),
100
- "csat": r[9],
101
- "cost": r[10]
102
- })
103
- return result
 
 
 
 
 
 
104
 
105
  def add_call(self, customer_id, duration, intent, sentiment, ai_resolved, upsell, cost):
106
- conn = self._get_conn()
107
- cursor = conn.cursor()
108
- call_id = f"LIVE_{int(datetime.datetime.now().timestamp())}"
109
- timestamp = datetime.datetime.now().isoformat()
110
- cursor.execute('''
111
- INSERT INTO calls (customer_id, call_id, call_timestamp, duration, intent, sentiment, ai_resolved, upsell, csat, cost)
112
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
113
- ''', (customer_id, call_id, timestamp, duration, intent, sentiment, ai_resolved, upsell, cost['csat'], cost['value']))
114
- conn.commit()
115
- conn.close()
 
 
 
 
 
116
 
117
  def update_call_rating(self, customer_id, stars):
118
- conn = self._get_conn()
119
- cursor = conn.cursor()
120
  try:
 
 
121
  cursor.execute('''
122
  SELECT id FROM calls
123
  WHERE customer_id = ?
@@ -128,11 +144,13 @@ class Database:
128
  if row:
129
  cursor.execute('UPDATE calls SET csat = ? WHERE id = ?', (int(stars), row[0]))
130
  conn.commit()
131
- print(f" [DB] Cập nhật CSAT={stars} cho {customer_id}")
132
- except Exception as e:
133
- print(f" [DB Error] Update Rating: {e}")
134
- finally:
135
  conn.close()
 
 
 
136
 
137
- # Singleton
138
  db = Database()
 
1
+ # database_debug.py
2
  import sqlite3
3
  import datetime
4
  import os
5
+ import traceback
6
 
7
  # --- Đường dẫn DB trên Hugging Face Space ---
8
  DB_NAME = os.path.join("/tmp", "vnpt_call_center.db")
9
+ print(f"[DB DEBUG] Database path: {DB_NAME}")
10
 
11
  # --- 20 DATA MẪU ---
12
  INITIAL_DATA = [
13
  {"customer_id": "CUS_001", "call_id": "CALL_0001", "call_timestamp": "2025-01-20T08:15:00+07:00", "call_duration_seconds": 78, "intent": "network_issue", "sentiment": "positive", "ai_resolved": True, "upsell_success": False, "csat": 5, "cost_per_call_vnd": 2350},
14
  {"customer_id": "CUS_002", "call_id": "CALL_0002", "call_timestamp": "2025-01-20T08:35:00+07:00", "call_duration_seconds": 92, "intent": "cancel_package", "sentiment": "neutral", "ai_resolved": True, "upsell_success": True, "csat": 4, "cost_per_call_vnd": 2480},
15
+ # ... giữ nguyên 20 record mẫu ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  ]
17
 
18
  class Database:
19
  def __init__(self):
20
+ try:
21
+ print("[DB DEBUG] Khởi tạo Database...")
22
+ self._init_db()
23
+ print("[DB DEBUG] Database khởi tạo xong.")
24
+ except Exception as e:
25
+ print(f"[DB ERROR] Init DB failed: {e}")
26
+ traceback.print_exc()
27
 
28
  def _get_conn(self):
29
+ try:
30
+ conn = sqlite3.connect(DB_NAME, check_same_thread=False)
31
+ print("[DB DEBUG] Kết nối SQLite mở thành công.")
32
+ return conn
33
+ except Exception as e:
34
+ print(f"[DB ERROR] Không thể mở kết nối DB: {e}")
35
+ traceback.print_exc()
36
+ raise
37
 
38
  def _init_db(self):
39
  conn = self._get_conn()
 
53
  cost INTEGER
54
  )
55
  ''')
56
+ conn.commit()
57
  cursor.execute("SELECT count(*) FROM calls")
58
+ count = cursor.fetchone()[0]
59
+ print(f"[DB DEBUG] Số bản ghi hiện tại: {count}")
60
+ if count == 0:
61
+ print(" [DB DEBUG] Database trống. Đang nạp 20 bản ghi mẫu...")
62
  self._seed_data(cursor)
63
  conn.commit()
64
+ print(" [DB DEBUG] Seed dữ liệu xong.")
65
  conn.close()
66
 
67
  def _seed_data(self, cursor):
68
  for item in INITIAL_DATA:
69
+ try:
70
+ cursor.execute('''
71
+ INSERT INTO calls (customer_id, call_id, call_timestamp, duration, intent, sentiment, ai_resolved, upsell, csat, cost)
72
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
73
+ ''', (
74
+ item['customer_id'],
75
+ item['call_id'],
76
+ item['call_timestamp'],
77
+ item['call_duration_seconds'],
78
+ item['intent'],
79
+ item['sentiment'],
80
+ item['ai_resolved'],
81
+ item['upsell_success'],
82
+ item['csat'],
83
+ item['cost_per_call_vnd']
84
+ ))
85
+ except Exception as e:
86
+ print(f"[DB ERROR] Seed record {item['call_id']} thất bại: {e}")
87
+ traceback.print_exc()
88
 
89
  def get_all_calls(self):
90
+ try:
91
+ conn = self._get_conn()
92
+ cursor = conn.cursor()
93
+ cursor.execute("SELECT * FROM calls ORDER BY call_timestamp DESC")
94
+ rows = cursor.fetchall()
95
+ conn.close()
96
+ result = []
97
+ for r in rows:
98
+ result.append({
99
+ "id": r[1], # customer_id
100
+ "time": r[3], # timestamp
101
+ "dur": r[4], # duration
102
+ "intent": r[5],
103
+ "sent": r[6],
104
+ "ai": bool(r[7]),
105
+ "upsell": bool(r[8]),
106
+ "csat": r[9],
107
+ "cost": r[10]
108
+ })
109
+ print(f"[DB DEBUG] Lấy {len(result)} bản ghi thành công.")
110
+ return result
111
+ except Exception as e:
112
+ print(f"[DB ERROR] Lấy tất cả calls thất bại: {e}")
113
+ traceback.print_exc()
114
+ return []
115
 
116
  def add_call(self, customer_id, duration, intent, sentiment, ai_resolved, upsell, cost):
117
+ try:
118
+ conn = self._get_conn()
119
+ cursor = conn.cursor()
120
+ call_id = f"LIVE_{int(datetime.datetime.now().timestamp())}"
121
+ timestamp = datetime.datetime.now().isoformat()
122
+ cursor.execute('''
123
+ INSERT INTO calls (customer_id, call_id, call_timestamp, duration, intent, sentiment, ai_resolved, upsell, csat, cost)
124
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
125
+ ''', (customer_id, call_id, timestamp, duration, intent, sentiment, ai_resolved, upsell, cost['csat'], cost['value']))
126
+ conn.commit()
127
+ conn.close()
128
+ print(f"[DB DEBUG] Thêm call {call_id} cho customer {customer_id} thành công.")
129
+ except Exception as e:
130
+ print(f"[DB ERROR] Thêm call thất bại: {e}")
131
+ traceback.print_exc()
132
 
133
  def update_call_rating(self, customer_id, stars):
 
 
134
  try:
135
+ conn = self._get_conn()
136
+ cursor = conn.cursor()
137
  cursor.execute('''
138
  SELECT id FROM calls
139
  WHERE customer_id = ?
 
144
  if row:
145
  cursor.execute('UPDATE calls SET csat = ? WHERE id = ?', (int(stars), row[0]))
146
  conn.commit()
147
+ print(f"[DB DEBUG] Cập nhật CSAT={stars} cho {customer_id}")
148
+ else:
149
+ print(f"[DB DEBUG] Không tìm thấy call nào để cập nhật CSAT cho {customer_id}")
 
150
  conn.close()
151
+ except Exception as e:
152
+ print(f"[DB ERROR] Update Rating: {e}")
153
+ traceback.print_exc()
154
 
155
+ # Singleton debug
156
  db = Database()