Thomas Richardson commited on
Commit
cdf2b67
·
unverified ·
2 Parent(s): f0c6c684b10639

Merge pull request #148 from ttt246/feature/update_watch_ui_134

Browse files

feature(#134): build APIs for implement search contact functionality on Apple Watch

.gitignore CHANGED
@@ -1,3 +1,4 @@
1
  /Brain/firebase_cred.json
2
  /.idea
3
  Brain/firebase_cred.json
 
 
1
  /Brain/firebase_cred.json
2
  /.idea
3
  Brain/firebase_cred.json
4
+ Brain/logs
Brain/logs/activity.log DELETED
@@ -1,82 +0,0 @@
1
- 2023-06-11 01:39:05,597 ERROR sendNotification
2
- 2023-06-11 03:49:04,950 DEBUG Chat with AI on model : gpt-3.5-turbo
3
- 2023-06-11 03:49:04,950 DEBUG ------------ CONTEXT SENT TO AI ---------------
4
- 2023-06-11 03:49:04,950 DEBUG System: You are a helpful assistant.
5
- 2023-06-11 03:49:04,950 DEBUG
6
- 2023-06-11 03:49:04,950 DEBUG User: Who won the world series in 2020?
7
- 2023-06-11 03:49:04,950 DEBUG
8
- 2023-06-11 03:49:04,950 DEBUG Assistant: The Los Angeles Dodgers won the World Series in 2020.
9
- 2023-06-11 03:49:04,950 DEBUG
10
- 2023-06-11 03:49:04,950 DEBUG User: Where was it played?
11
- 2023-06-11 03:49:04,951 DEBUG
12
- 2023-06-11 03:49:04,951 DEBUG ----------- END OF CONTEXT ----------------
13
- 2023-06-11 03:49:14,350 WARNING API Rate Limit Reached. Waiting 10 seconds... Error:
14
- 2023-06-11 03:49:34,004 DEBUG Chat with AI on model : gpt-3.5-turbo
15
- 2023-06-11 03:49:34,004 DEBUG ------------ CONTEXT SENT TO AI ---------------
16
- 2023-06-11 03:49:34,004 DEBUG System: You are a helpful assistant.
17
- 2023-06-11 03:49:34,004 DEBUG
18
- 2023-06-11 03:49:34,004 DEBUG User: Who won the world series in 2020?
19
- 2023-06-11 03:49:34,004 DEBUG
20
- 2023-06-11 03:49:34,004 DEBUG Assistant: The Los Angeles Dodgers won the World Series in 2020.
21
- 2023-06-11 03:49:34,004 DEBUG
22
- 2023-06-11 03:49:34,004 DEBUG User: Where was it played?
23
- 2023-06-11 03:49:34,004 DEBUG
24
- 2023-06-11 03:49:34,004 DEBUG ----------- END OF CONTEXT ----------------
25
- 2023-06-11 03:50:02,195 DEBUG Chat with AI on model : gpt-3.5-turbo
26
- 2023-06-11 03:50:02,196 DEBUG ------------ CONTEXT SENT TO AI ---------------
27
- 2023-06-11 03:50:02,196 DEBUG System: You are a helpful assistant.
28
- 2023-06-11 03:50:02,196 DEBUG
29
- 2023-06-11 03:50:02,196 DEBUG User: Who won the world series in 2020?
30
- 2023-06-11 03:50:02,197 DEBUG
31
- 2023-06-11 03:50:02,197 DEBUG Assistant: The Los Angeles Dodgers won the World Series in 2020.
32
- 2023-06-11 03:50:02,197 DEBUG
33
- 2023-06-11 03:50:02,197 DEBUG User: Where was it played?
34
- 2023-06-11 03:50:02,197 DEBUG
35
- 2023-06-11 03:50:02,197 DEBUG ----------- END OF CONTEXT ----------------
36
- 2023-06-11 03:52:01,682 WARNING API Rate Limit Reached. Waiting 10 seconds... Error:
37
- 2023-06-11 03:52:04,881 DEBUG Chat with AI on model : gpt-3.5-turbo
38
- 2023-06-11 03:52:04,882 DEBUG ------------ CONTEXT SENT TO AI ---------------
39
- 2023-06-11 03:52:04,882 DEBUG System: You are a helpful assistant.
40
- 2023-06-11 03:52:04,882 DEBUG
41
- 2023-06-11 03:52:04,882 DEBUG User: Who won the world series in 2020?
42
- 2023-06-11 03:52:04,883 DEBUG
43
- 2023-06-11 03:52:04,883 DEBUG Assistant: The Los Angeles Dodgers won the World Series in 2020.
44
- 2023-06-11 03:52:04,883 DEBUG
45
- 2023-06-11 03:52:04,884 DEBUG User: Where was it played?
46
- 2023-06-11 03:52:04,884 DEBUG
47
- 2023-06-11 03:52:04,884 DEBUG ----------- END OF CONTEXT ----------------
48
- 2023-06-11 03:59:41,875 DEBUG Chat with AI on model : gpt-3.5-turbo
49
- 2023-06-11 03:59:41,876 DEBUG ------------ CONTEXT SENT TO AI ---------------
50
- 2023-06-11 03:59:41,876 DEBUG System: You are a helpful assistant.
51
- 2023-06-11 03:59:41,876 DEBUG
52
- 2023-06-11 03:59:41,876 DEBUG User: Who won the world series in 2020?
53
- 2023-06-11 03:59:41,876 DEBUG
54
- 2023-06-11 03:59:41,876 DEBUG Assistant: The Los Angeles Dodgers won the World Series in 2020.
55
- 2023-06-11 03:59:41,876 DEBUG
56
- 2023-06-11 03:59:41,876 DEBUG User: Where was it played?
57
- 2023-06-11 03:59:41,876 DEBUG
58
- 2023-06-11 03:59:41,876 DEBUG ----------- END OF CONTEXT ----------------
59
- 2023-06-12 17:08:50,779 DEBUG Chat with AI on model : gpt-3.5-turbo
60
- 2023-06-12 17:08:50,780 DEBUG ------------ CONTEXT SENT TO AI ---------------
61
- 2023-06-12 17:08:50,780 DEBUG System: You are a helpful assistant.
62
- 2023-06-12 17:08:50,780 DEBUG
63
- 2023-06-12 17:08:50,780 DEBUG User: Who won the world series in 2020?
64
- 2023-06-12 17:08:50,780 DEBUG
65
- 2023-06-12 17:08:50,780 DEBUG Assistant: The Los Angeles Dodgers won the World Series in 2020.
66
- 2023-06-12 17:08:50,780 DEBUG
67
- 2023-06-12 17:08:50,780 DEBUG User: Where was it played?
68
- 2023-06-12 17:08:50,780 DEBUG
69
- 2023-06-12 17:08:50,780 DEBUG ----------- END OF CONTEXT ----------------
70
- 2023-06-16 14:22:55,555 ERROR sendNotification json parsing or get completion error
71
- 2023-06-16 14:23:59,508 ERROR sendNotification json parsing or get completion error
72
- 2023-06-16 15:58:51,640 DEBUG Chat with AI on model : gpt-3.5-turbo
73
- 2023-06-16 15:58:51,641 DEBUG ------------ CONTEXT SENT TO AI ---------------
74
- 2023-06-16 15:58:51,641 DEBUG System: You are a helpful assistant.
75
- 2023-06-16 15:58:51,642 DEBUG
76
- 2023-06-16 15:58:51,642 DEBUG User: Who won the world series in 2020?
77
- 2023-06-16 15:58:51,642 DEBUG
78
- 2023-06-16 15:58:51,642 DEBUG Assistant: The Los Angeles Dodgers won the World Series in 2020.
79
- 2023-06-16 15:58:51,642 DEBUG
80
- 2023-06-16 15:58:51,642 DEBUG User: Where was it played?
81
- 2023-06-16 15:58:51,642 DEBUG
82
- 2023-06-16 15:58:51,642 DEBUG ----------- END OF CONTEXT ----------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Brain/src/common/assembler.py CHANGED
@@ -69,3 +69,18 @@ class Assembler:
69
 
70
  def to_req_model(self, basic_req: BasicReq.Confs) -> ReqModel:
71
  return ReqModel(basic_req.to_json())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
  def to_req_model(self, basic_req: BasicReq.Confs) -> ReqModel:
71
  return ReqModel(basic_req.to_json())
72
+
73
+ """mapping data from a ContactModel into json
74
+ {
75
+ "contactId": int,
76
+ "displayName": string,
77
+ "phoneNumbers": [string]
78
+ }
79
+ """
80
+
81
+ def to_contact_result_format(self, contact: ContactModel) -> Any:
82
+ return {
83
+ "contactId": contact.contact_id,
84
+ "displayName": contact.display_name,
85
+ "phoneNumbers": contact.phone_numbers,
86
+ }
Brain/src/model/requests/request_model.py CHANGED
@@ -215,3 +215,10 @@ class AutoTaskDelete(BasicReq):
215
  reference_link: str
216
 
217
  data: Body
 
 
 
 
 
 
 
 
215
  reference_link: str
216
 
217
  data: Body
218
+
219
+
220
+ """endpoint : /contact/get_by_ids"""
221
+
222
+
223
+ class GetContactsByIds(BasicReq):
224
+ contactIds: list[str]
Brain/src/router/api.py CHANGED
@@ -19,6 +19,7 @@ from Brain.src.model.requests.request_model import (
19
  ClientInfo,
20
  get_client_info,
21
  AutoTaskDelete,
 
22
  )
23
  from Brain.src.rising_plugin.risingplugin import (
24
  getCompletion,
@@ -90,7 +91,9 @@ def construct_blueprint_api() -> APIRouter:
90
 
91
  # check contact querying
92
  try:
93
- contacts_service = ContactsService(setting=setting)
 
 
94
  if result["program"] == ProgramType.AUTO_TASK:
95
  auto_task_service = AutoTaskService()
96
  result["content"] = auto_task_service.ask_task_with_autogpt(
@@ -413,7 +416,9 @@ def construct_blueprint_api() -> APIRouter:
413
  for contact in data.contacts:
414
  contacts.append(assembler.to_contact_model(contact))
415
  # train contact
416
- contacts_service = ContactsService(setting=setting)
 
 
417
  contacts_service.train(uuid, contacts)
418
  except Exception as e:
419
  if isinstance(e, BrainException):
@@ -444,7 +449,9 @@ def construct_blueprint_api() -> APIRouter:
444
 
445
  # parsing contacts
446
  # train contact
447
- contacts_service = ContactsService(setting=setting)
 
 
448
  contacts_service.delete_all(uuid)
449
  except Exception as e:
450
  if isinstance(e, BrainException):
@@ -492,4 +499,36 @@ def construct_blueprint_api() -> APIRouter:
492
  200, "Deleted data from real-time database of firebase", ""
493
  )
494
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
495
  return router
 
19
  ClientInfo,
20
  get_client_info,
21
  AutoTaskDelete,
22
+ GetContactsByIds,
23
  )
24
  from Brain.src.rising_plugin.risingplugin import (
25
  getCompletion,
 
91
 
92
  # check contact querying
93
  try:
94
+ contacts_service = ContactsService(
95
+ firebase_app=firebase_app, setting=setting
96
+ )
97
  if result["program"] == ProgramType.AUTO_TASK:
98
  auto_task_service = AutoTaskService()
99
  result["content"] = auto_task_service.ask_task_with_autogpt(
 
416
  for contact in data.contacts:
417
  contacts.append(assembler.to_contact_model(contact))
418
  # train contact
419
+ contacts_service = ContactsService(
420
+ firebase_app=firebase_app, setting=setting
421
+ )
422
  contacts_service.train(uuid, contacts)
423
  except Exception as e:
424
  if isinstance(e, BrainException):
 
449
 
450
  # parsing contacts
451
  # train contact
452
+ contacts_service = ContactsService(
453
+ firebase_app=firebase_app, setting=setting
454
+ )
455
  contacts_service.delete_all(uuid)
456
  except Exception as e:
457
  if isinstance(e, BrainException):
 
499
  200, "Deleted data from real-time database of firebase", ""
500
  )
501
 
502
+ """@generator.request_body(
503
+ {
504
+ "token": "String",
505
+ "uuid": "String",
506
+ "contactIds": [
507
+ String
508
+ ]
509
+ }
510
+ )
511
+
512
+ @generator.response(
513
+ status_code=200, schema={"message": "message", "result": "test_result"}
514
+ )
515
+
516
+ """
517
+
518
+ @router.post("/contacts/get_by_ids")
519
+ def get_contacts_by_ids(data: GetContactsByIds):
520
+ try:
521
+ setting, firebase_app = firebase_admin_with_setting(data)
522
+ except BrainException as ex:
523
+ return ex.get_response_exp()
524
+
525
+ token: str = setting.token
526
+ uuid: str = setting.uuid
527
+
528
+ result = ContactsService(
529
+ firebase_app=firebase_app, setting=setting
530
+ ).get_contacts_by_ids(uuid=uuid, contactIds=data.contactIds)
531
+
532
+ return assembler.to_response(200, "Success to get contacts by uuid", result)
533
+
534
  return router
Brain/src/service/contact_service.py CHANGED
@@ -1,6 +1,8 @@
1
  """service to manage contacts"""
2
  from typing import List, Any
3
 
 
 
4
  from Brain.src.model.req_model import ReqModel
5
  from Brain.src.rising_plugin.csv_embed import get_embed
6
  from Brain.src.rising_plugin.pinecone_engine import (
@@ -15,10 +17,18 @@ from Brain.src.rising_plugin.pinecone_engine import (
15
  from Brain.src.common.utils import PINECONE_INDEX_NAME
16
  from Brain.src.model.contact_model import ContactModel, ContactStatus
17
 
 
 
 
18
 
19
  class ContactsService:
20
- def __init__(self, setting: ReqModel):
 
 
 
 
21
  self.setting = setting
 
22
 
23
  """train contacts (getting embedding) and update pinecone with embeddings by contact_id
24
  train datatype:
@@ -28,7 +38,9 @@ class ContactsService:
28
  def train(self, uuid: str, contacts: List[ContactModel]) -> None:
29
  # getting index namespaceof pinecone
30
  pinecone_namespace = self.get_pinecone_index_namespace(uuid)
 
31
  for contact in contacts:
 
32
  # generate key and values for pinecone data
33
  key = contact.contact_id
34
  value = f"{contact.display_name}, {contact.get_str_phones()}"
@@ -42,12 +54,14 @@ class ContactsService:
42
  value=vectoring_values,
43
  setting=self.setting,
44
  )
 
45
  elif contact.status == ContactStatus.DELETED:
46
  delete_pinecone(
47
  namespace=pinecone_namespace,
48
  key=key,
49
  setting=self.setting,
50
  )
 
51
  elif contact.status == ContactStatus.UPDATED:
52
  update_pinecone(
53
  namespace=pinecone_namespace,
@@ -55,6 +69,7 @@ class ContactsService:
55
  value=vectoring_values,
56
  setting=self.setting,
57
  )
 
58
 
59
  """"query contact with search text
60
  response: list of contactId as index key of pinecone"""
@@ -85,3 +100,54 @@ class ContactsService:
85
 
86
  def get_pinecone_index_namespace(self, uuid: str) -> str:
87
  return get_pinecone_index_namespace(f"{uuid}-contacts")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  """service to manage contacts"""
2
  from typing import List, Any
3
 
4
+
5
+ from Brain.src.common.assembler import Assembler
6
  from Brain.src.model.req_model import ReqModel
7
  from Brain.src.rising_plugin.csv_embed import get_embed
8
  from Brain.src.rising_plugin.pinecone_engine import (
 
17
  from Brain.src.common.utils import PINECONE_INDEX_NAME
18
  from Brain.src.model.contact_model import ContactModel, ContactStatus
19
 
20
+ import firebase_admin
21
+ from firebase_admin import firestore
22
+
23
 
24
  class ContactsService:
25
+ db: Any
26
+ phones_ref: Any
27
+
28
+ def __init__(self, firebase_app: firebase_admin.App, setting: ReqModel):
29
+ self.firebase_app = firebase_app
30
  self.setting = setting
31
+ self.init_firestore()
32
 
33
  """train contacts (getting embedding) and update pinecone with embeddings by contact_id
34
  train datatype:
 
38
  def train(self, uuid: str, contacts: List[ContactModel]) -> None:
39
  # getting index namespaceof pinecone
40
  pinecone_namespace = self.get_pinecone_index_namespace(uuid)
41
+
42
  for contact in contacts:
43
+ # Save the data
44
  # generate key and values for pinecone data
45
  key = contact.contact_id
46
  value = f"{contact.display_name}, {contact.get_str_phones()}"
 
54
  value=vectoring_values,
55
  setting=self.setting,
56
  )
57
+ self.create_one_contact(uuid=uuid, contact=contact)
58
  elif contact.status == ContactStatus.DELETED:
59
  delete_pinecone(
60
  namespace=pinecone_namespace,
61
  key=key,
62
  setting=self.setting,
63
  )
64
+ self.delete_one_contact(uuid=uuid, contact=contact)
65
  elif contact.status == ContactStatus.UPDATED:
66
  update_pinecone(
67
  namespace=pinecone_namespace,
 
69
  value=vectoring_values,
70
  setting=self.setting,
71
  )
72
+ self.update_one_contact(uuid=uuid, contact=contact)
73
 
74
  """"query contact with search text
75
  response: list of contactId as index key of pinecone"""
 
100
 
101
  def get_pinecone_index_namespace(self, uuid: str) -> str:
102
  return get_pinecone_index_namespace(f"{uuid}-contacts")
103
+
104
+ """init firestore to save user's contacts"""
105
+
106
+ def init_firestore(self):
107
+ self.db = firestore.client(app=self.firebase_app)
108
+ self.phones_ref = self.db.collection("phones")
109
+
110
+ """create a contact into document which name is uuid in phone collections in firestore"""
111
+
112
+ def create_one_contact(self, uuid: str, contact: ContactModel):
113
+ assembler = Assembler()
114
+ data = assembler.to_contact_result_format(contact)
115
+ phones_doc_ref = self.phones_ref.document(uuid)
116
+ contacts_doc_ref = phones_doc_ref.collection("contacts").document(
117
+ contact.contact_id
118
+ )
119
+ contacts_doc_ref.set(data)
120
+
121
+ """update a contact into document which name is uuid in phone collections in firestore"""
122
+
123
+ def update_one_contact(self, uuid: str, contact: ContactModel):
124
+ assembler = Assembler()
125
+ data = assembler.to_contact_result_format(contact)
126
+ phones_doc_ref = self.phones_ref.document(uuid)
127
+ contacts_doc_ref = phones_doc_ref.collection("contacts").document(
128
+ contact.contact_id
129
+ )
130
+ contacts_doc_ref.update(data)
131
+
132
+ """delete a contact into document which name is uuid in phone collections in firestore"""
133
+
134
+ def delete_one_contact(self, uuid: str, contact: ContactModel):
135
+ phones_doc_ref = self.phones_ref.document(uuid)
136
+ contacts_doc_ref = phones_doc_ref.collection("contacts").document(
137
+ contact.contact_id
138
+ )
139
+ contacts_doc_ref.delete()
140
+
141
+ def get_contacts_by_ids(self, uuid: str, contactIds: list[str]) -> []:
142
+ phones_doc_ref = self.phones_ref.document(uuid)
143
+ contacts_ref = phones_doc_ref.collection("contacts")
144
+
145
+ # Retrieve all documents in the 'contacts' sub-collection
146
+ contacts = contacts_ref.where("contactId", "in", contactIds).stream()
147
+
148
+ result = []
149
+ # Iterate through the documents and print out their data
150
+ for contact in contacts:
151
+ result.append(contact.to_dict())
152
+
153
+ return result