LONGYKING commited on
Commit
a8e2f82
·
1 Parent(s): 75bb6d0

added user profile session management

Browse files
.chainlit/config.toml CHANGED
@@ -82,6 +82,7 @@ custom_css = '/public/stylesheet.css'
82
  # Specify a Javascript file that can be used to customize the user interface.
83
  # The Javascript file can be served from the public directory.
84
  # custom_js = "/public/test.js"
 
85
 
86
  # Specify a custom font url.
87
  # custom_font = "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap"
 
82
  # Specify a Javascript file that can be used to customize the user interface.
83
  # The Javascript file can be served from the public directory.
84
  # custom_js = "/public/test.js"
85
+ custom_js = "/public/script.js"
86
 
87
  # Specify a custom font url.
88
  # custom_font = "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap"
chatxbt-assistant.py CHANGED
@@ -12,6 +12,7 @@ from src.databases.postgres import sqlalchemy_engine
12
  from src.tools.crypto_swap_toolkit import CryptoSwapTools
13
  from src.tools.crypto_data_toolkit import CryptoDataTools
14
  from src.tools.crypto_evm_wallet_toolkit import CryptoEVMWalletTools
 
15
  from phi.storage.assistant.postgres import PgAssistantStorage
16
  from src.knowledge_bases.combined import knowledge_base
17
 
@@ -29,7 +30,28 @@ def oauth_callback(
29
  default_user: cl.User,
30
  ) -> Optional[cl.User]:
31
  # step-todo: will handle auth from v2 api
32
- return default_user
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
 
35
  @cl.set_starters
@@ -66,13 +88,14 @@ async def start():
66
  cxbt_assistant = Assistant(
67
  llm=OpenAIChat(model="gpt-4o"),
68
  tools=[
 
69
  DuckDuckGo(),
70
  CryptoDataTools(),
71
  CryptoSwapTools(),
72
  CryptoEVMWalletTools(),
73
  YFinanceTools(stock_price=True)
74
  ],
75
- show_tool_calls= is_dev_mode,
76
  markdown=True,
77
  knowledge_base=knowledge_base,
78
  storage=storage,
 
12
  from src.tools.crypto_swap_toolkit import CryptoSwapTools
13
  from src.tools.crypto_data_toolkit import CryptoDataTools
14
  from src.tools.crypto_evm_wallet_toolkit import CryptoEVMWalletTools
15
+ from src.tools.user_profile_toolkit import UserProfileToolkit
16
  from phi.storage.assistant.postgres import PgAssistantStorage
17
  from src.knowledge_bases.combined import knowledge_base
18
 
 
30
  default_user: cl.User,
31
  ) -> Optional[cl.User]:
32
  # step-todo: will handle auth from v2 api
33
+ return cl.User(
34
+ identifier=raw_user_data.get('email'),
35
+ email=raw_user_data.get('email'),
36
+ name=raw_user_data.get('name'),
37
+ metadata={**raw_user_data, **({'image':default_user.metadata.get('image')})}
38
+ )
39
+
40
+
41
+ @cl.password_auth_callback
42
+ def auth_callback(username: str, password: str):
43
+ # Fetch the user matching username from your database
44
+ # and compare the hashed password with the value stored in the database
45
+ if (username, password) == ("admin", "admin"):
46
+ user = {
47
+ "identifier": "admin", "email": username, "metadata": {"role": "admin", "provider": "credentials"}
48
+ }
49
+ cl.user_session.set("user_profile", user)
50
+ return cl.User(
51
+ identifier="admin", email=username, metadata={"role": "admin", "provider": "credentials"}
52
+ )
53
+ else:
54
+ return None
55
 
56
 
57
  @cl.set_starters
 
88
  cxbt_assistant = Assistant(
89
  llm=OpenAIChat(model="gpt-4o"),
90
  tools=[
91
+ UserProfileToolkit(),
92
  DuckDuckGo(),
93
  CryptoDataTools(),
94
  CryptoSwapTools(),
95
  CryptoEVMWalletTools(),
96
  YFinanceTools(stock_price=True)
97
  ],
98
+ show_tool_calls=is_dev_mode,
99
  markdown=True,
100
  knowledge_base=knowledge_base,
101
  storage=storage,
node_modules/.yarn-integrity ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "systemParams": "darwin-x64-115",
3
+ "modulesFolders": [],
4
+ "flags": [],
5
+ "linkedModules": [],
6
+ "topLevelPatterns": [],
7
+ "lockfileEntries": {},
8
+ "files": [],
9
+ "artifacts": {}
10
+ }
public/script.js ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ const items = { ...localStorage };
3
+ const isAuthed = items?.token;
4
+
5
+ const wdgt = {
6
+ idBox: 'wdgt',
7
+ url_widget: 'https://next-starter.thirdweb-example.com/',
8
+ url_style: 'http://localhost:8080/css/widget.css',
9
+
10
+ init: function (identifier, byClass = false) {
11
+ console.log("Begin Widget initialization");
12
+
13
+ const observer = new MutationObserver((mutations, observer) => {
14
+ let elements = [];
15
+ if (byClass) {
16
+ elements = document.querySelectorAll(`.${identifier}`);
17
+ console.log(`Looking for elements by class: .${identifier}`);
18
+ } else {
19
+ const element = document.getElementById(identifier || this.idBox);
20
+ if (element) {
21
+ elements.push(element);
22
+ }
23
+ console.log(`Looking for element by ID: #${identifier || this.idBox}`);
24
+ }
25
+
26
+ console.log(`Found elements:`, elements);
27
+
28
+ if (elements.length > 0 && elements[0] != null) {
29
+ observer.disconnect(); // Stop observing once elements are found
30
+ try {
31
+ const XHR = ("onload" in new XMLHttpRequest()) ? XMLHttpRequest : XDomainRequest;
32
+ const xhr = new XHR();
33
+ xhr.open('GET', this.url_widget, true);
34
+
35
+ xhr.onload = function () {
36
+ if (this.status >= 200 && this.status < 300) {
37
+ elements.forEach(element => {
38
+ element.innerHTML = this.responseText;
39
+ });
40
+ } else {
41
+ console.error('Failed to load widget content. Status:', this.status);
42
+ }
43
+ };
44
+
45
+ xhr.onerror = function () {
46
+ console.error('onerror', this.status);
47
+ };
48
+
49
+ xhr.send();
50
+ } catch (error) {
51
+ console.error('Error loading widget:', error);
52
+ }
53
+ }
54
+ });
55
+
56
+ // Start observing the document body for changes
57
+ observer.observe(document.body, { childList: true, subtree: true });
58
+
59
+ // Initial check in case the elements are already present
60
+ let elements = [];
61
+ if (byClass) {
62
+ elements = document.querySelectorAll(`.${identifier}`);
63
+ } else {
64
+ const element = document.getElementById(identifier || this.idBox);
65
+ if (element) {
66
+ elements.push(element);
67
+ }
68
+ }
69
+
70
+ if (elements.length > 0 && elements[0] != null) {
71
+ observer.disconnect(); // Stop observing if elements are found initially
72
+ try {
73
+ const XHR = ("onload" in new XMLHttpRequest()) ? XMLHttpRequest : XDomainRequest;
74
+ const xhr = new XHR();
75
+ xhr.open('GET', this.url_widget, true);
76
+
77
+ xhr.onload = function () {
78
+ if (this.status >= 200 && this.status < 300) {
79
+ elements.forEach(element => {
80
+ element.innerHTML = this.responseText;
81
+ });
82
+ } else {
83
+ console.error('Failed to load widget content. Status:', this.status);
84
+ }
85
+ };
86
+
87
+ xhr.onerror = function () {
88
+ console.error('onerror', this.status);
89
+ };
90
+
91
+ xhr.send();
92
+ } catch (error) {
93
+ console.error('Error loading widget:', error);
94
+ }
95
+ }
96
+ },
97
+
98
+ addStyle: function () {
99
+ const style = document.createElement('link');
100
+ style.rel = 'stylesheet';
101
+ style.type = 'text/css';
102
+ style.href = this.url_style;
103
+ document.head.appendChild(style);
104
+ }
105
+ };
106
+
107
+ if (isAuthed) {
108
+ // alert('You are authed');
109
+ } else {
110
+ // alert('You are not authed');
111
+ // wdgt.init('root', false); // Change 'true' to 'false' if you want to use an ID instead of class
112
+ }
113
+ });
src/tools/user_profile_toolkit.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import chainlit as cl
2
+ from phi.tools import Toolkit
3
+ from phi.utils.log import logger
4
+
5
+
6
+ class UserProfileToolkit(Toolkit):
7
+ def __init__(self):
8
+ super().__init__(name="user_profile_toolkit")
9
+
10
+ # Registering methods to make them accessible via the toolkit
11
+ self.register(self.get_user_name)
12
+ self.register(self.get_user_email)
13
+ self.register(self.get_user_picture)
14
+ self.register(self.get_all_user_info)
15
+ self.register(self.update_user_info)
16
+ self.register(self.update_user_name)
17
+ self.register(self.update_user_email)
18
+ self.register(self.update_user_picture)
19
+
20
+ @cl.on_chat_start
21
+ def get_user_info(self, info_type: str) -> str:
22
+ """
23
+ Fetches user information from the Chainlit user session.
24
+
25
+ Args:
26
+ info_type (str): The type of information to fetch ('name', 'email', 'picture').
27
+
28
+ Returns:
29
+ str: The requested user information.
30
+
31
+ Example:
32
+ >>> get_user_info('name')
33
+ """
34
+ logger.info(f"Fetching user info: {info_type}")
35
+ try:
36
+ # Fetch user session data
37
+ user_session = cl.user_session.get("user").metadata
38
+ if not user_session:
39
+ raise ValueError("User session not found")
40
+
41
+ response = user_session[info_type]
42
+ return f"{response}"
43
+ except Exception as e:
44
+ logger.warning(f"Failed to get user info: {e}")
45
+ return f"Error: {e}"
46
+
47
+ def get_all_user_info(self) -> str:
48
+ """
49
+ Fetches all user information from the Chainlit user session.
50
+
51
+ Returns:
52
+ dict: A dictionary containing all user information.
53
+
54
+ Example:
55
+ >>> get_all_user_info()
56
+ """
57
+ logger.info("Fetching all user info")
58
+ try:
59
+ # Fetch user session data
60
+ user_session = cl.user_session.get("user").metadata
61
+ if not user_session:
62
+ raise ValueError("User session not found")
63
+
64
+ response = user_session
65
+ return f"{response}"
66
+ except Exception as e:
67
+ logger.warning(f"Failed to get all user info: {e}")
68
+ # return {"error": str(e)}
69
+ return f"Error: {e}"
70
+
71
+ def update_user_info(self, info_type: str, value: str) -> str:
72
+ """
73
+ Updates user information in the Chainlit user session.
74
+
75
+ Args:
76
+ info_type (str): The type of information to update ('name', 'email', 'picture').
77
+ value (str): The new value to set.
78
+
79
+ Returns:
80
+ str: Confirmation message.
81
+
82
+ Example:
83
+ >>> update_user_info('name', 'Jane Doe')
84
+ """
85
+ logger.info(f"Updating user info: {info_type} to {value}")
86
+ try:
87
+ # Fetch user session data
88
+ user_session = cl.user_session.get("user").metadata
89
+ if not user_session:
90
+ raise ValueError("User session not found")
91
+
92
+ # Update the user session data
93
+ user_session[info_type] = value
94
+ cl.user_session.set("user", user_session)
95
+ return f"{info_type} updated to {value}"
96
+ except Exception as e:
97
+ logger.warning(f"Failed to update user info: {e}")
98
+ return f"Error: {e}"
99
+
100
+ def get_user_name(self) -> str:
101
+ """
102
+ Fetches the user's name from the Chainlit user session.
103
+
104
+ Returns:
105
+ str: The user's name.
106
+
107
+ Example:
108
+ >>> get_user_name()
109
+ """
110
+ response = self.get_user_info('name')
111
+ return f"{response}"
112
+
113
+ def get_user_email(self) -> str:
114
+ """
115
+ Fetches the user's email from the Chainlit user session.
116
+
117
+ Returns:
118
+ str: The user's email.
119
+
120
+ Example:
121
+ >>> get_user_email()
122
+ """
123
+ response = self.get_user_info('email')
124
+ return f"{response}"
125
+
126
+ def get_user_picture(self) -> str:
127
+ """
128
+ Fetches the user's picture URL from the Chainlit user session.
129
+
130
+ Returns:
131
+ str: The user's picture URL.
132
+
133
+ Example:
134
+ >>> get_user_picture()
135
+ """
136
+ response = self.get_user_info('picture')
137
+ return f"{response}"
138
+
139
+ def update_user_name(self, name: str) -> str:
140
+ """
141
+ Updates the user's name in the Chainlit user session.
142
+
143
+ Args:
144
+ name (str): The new name to set.
145
+
146
+ Returns:
147
+ str: Confirmation message.
148
+
149
+ Example:
150
+ >>> update_user_name('Jane Doe')
151
+ """
152
+ response = self.update_user_info('name', name)
153
+ return f"{response}"
154
+
155
+ def update_user_email(self, email: str) -> str:
156
+ """
157
+ Updates the user's email in the Chainlit user session.
158
+
159
+ Args:
160
+ email (str): The new email to set.
161
+
162
+ Returns:
163
+ str: Confirmation message.
164
+
165
+ Example:
166
+ >>> update_user_email('jane.doe@example.com')
167
+ """
168
+ response = self.update_user_info('email', email)
169
+ return f"{response}"
170
+
171
+ def update_user_picture(self, picture: str) -> str:
172
+ """
173
+ Updates the user's picture URL in the Chainlit user session.
174
+
175
+ Args:
176
+ picture (str): The new picture URL to set.
177
+
178
+ Returns:
179
+ str: Confirmation message.
180
+
181
+ Example:
182
+ >>> update_user_picture('https://example.com/new_picture.jpg')
183
+ """
184
+ response = self.update_user_info('picture', picture)
185
+ return f"{response}"
yarn.lock ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2
+ # yarn lockfile v1
3
+
4
+