chatgraph 0.1.2__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of chatgraph might be problematic. Click here for more details.
- {chatgraph-0.1.2 → chatgraph-0.1.4}/PKG-INFO +4 -4
- {chatgraph-0.1.2 → chatgraph-0.1.4}/README.md +3 -3
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/bot/chatbot_model.py +19 -13
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/bot/chatbot_router.py +9 -9
- chatgraph-0.1.4/chatgraph/messages/test_message_consumer.py +17 -0
- chatgraph-0.1.4/chatgraph/types/output_state.py +99 -0
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/types/route.py +4 -4
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/types/user_state.py +24 -4
- {chatgraph-0.1.2 → chatgraph-0.1.4}/pyproject.toml +1 -1
- chatgraph-0.1.2/chatgraph/types/output_state.py +0 -42
- {chatgraph-0.1.2 → chatgraph-0.1.4}/LICENSE +0 -0
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/__init__.py +0 -0
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/auth/credentials.py +0 -0
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/error/chatbot_error.py +0 -0
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/error/route_error.py +0 -0
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/messages/base_message_consumer.py +0 -0
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/messages/rabbitMQ_message_consumer.py +0 -0
- {chatgraph-0.1.2 → chatgraph-0.1.4}/chatgraph/types/message_types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: chatgraph
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: A user-friendly chatbot library
|
|
5
5
|
Home-page: https://github.com/irissonnlima/chatgraph
|
|
6
6
|
License: MIT
|
|
@@ -108,11 +108,11 @@ from chatgraph import ChatbotApp, ChatbotRouter, SimpleUserState, RabbitMessageC
|
|
|
108
108
|
# Definindo rotas com ChatbotRouter
|
|
109
109
|
router = ChatbotRouter()
|
|
110
110
|
|
|
111
|
-
@router.route("
|
|
111
|
+
@router.route("start")
|
|
112
112
|
def say_hello():
|
|
113
|
-
return ChatbotResponse(message="Hello! How can I assist you today?", route=".
|
|
113
|
+
return ChatbotResponse(message="Hello! How can I assist you today?", route=".help")
|
|
114
114
|
|
|
115
|
-
@router.route(".
|
|
115
|
+
@router.route(".help")
|
|
116
116
|
def provide_help():
|
|
117
117
|
return ChatbotResponse(message="Here are some things I can help with: ...")
|
|
118
118
|
|
|
@@ -91,11 +91,11 @@ from chatgraph import ChatbotApp, ChatbotRouter, SimpleUserState, RabbitMessageC
|
|
|
91
91
|
# Definindo rotas com ChatbotRouter
|
|
92
92
|
router = ChatbotRouter()
|
|
93
93
|
|
|
94
|
-
@router.route("
|
|
94
|
+
@router.route("start")
|
|
95
95
|
def say_hello():
|
|
96
|
-
return ChatbotResponse(message="Hello! How can I assist you today?", route=".
|
|
96
|
+
return ChatbotResponse(message="Hello! How can I assist you today?", route=".help")
|
|
97
97
|
|
|
98
|
-
@router.route(".
|
|
98
|
+
@router.route(".help")
|
|
99
99
|
def provide_help():
|
|
100
100
|
return ChatbotResponse(message="Here are some things I can help with: ...")
|
|
101
101
|
|
|
@@ -6,7 +6,7 @@ from logging import debug
|
|
|
6
6
|
from ..error.chatbot_error import ChatbotError, ChatbotMessageError
|
|
7
7
|
from ..messages.base_message_consumer import MessageConsumer
|
|
8
8
|
from ..types.message_types import Message
|
|
9
|
-
from ..types.output_state import ChatbotResponse, RedirectResponse
|
|
9
|
+
from ..types.output_state import ChatbotResponse, RedirectResponse, EndChatResponse, TransferToHuman
|
|
10
10
|
from ..types.route import Route
|
|
11
11
|
from ..types.user_state import UserState
|
|
12
12
|
from .chatbot_router import ChatbotRouter
|
|
@@ -38,16 +38,16 @@ class ChatbotApp(ABC):
|
|
|
38
38
|
prefix (str): O prefixo a ser adicionado às rotas do roteador.
|
|
39
39
|
|
|
40
40
|
Raises:
|
|
41
|
-
ChatbotError: Se a rota '
|
|
41
|
+
ChatbotError: Se a rota 'start' não for encontrada no roteador.
|
|
42
42
|
"""
|
|
43
|
-
if '
|
|
44
|
-
raise ChatbotError('Erro ao incluir rota,
|
|
43
|
+
if 'start' not in router.routes.keys():
|
|
44
|
+
raise ChatbotError('Erro ao incluir rota, start não encontrado!')
|
|
45
45
|
|
|
46
46
|
prefixed_routes = {
|
|
47
47
|
(
|
|
48
|
-
f'
|
|
49
|
-
if key.
|
|
50
|
-
else f'
|
|
48
|
+
f'start{prefix.lower()}'
|
|
49
|
+
if key.lower() == 'start'
|
|
50
|
+
else f'start{prefix.lower()}{key.lower().replace("start", "")}'
|
|
51
51
|
): value
|
|
52
52
|
for key, value in router.routes.items()
|
|
53
53
|
}
|
|
@@ -63,10 +63,10 @@ class ChatbotApp(ABC):
|
|
|
63
63
|
Returns:
|
|
64
64
|
function: O decorador que adiciona a função à rota especificada.
|
|
65
65
|
"""
|
|
66
|
-
route_name = route_name.strip().
|
|
66
|
+
route_name = route_name.strip().lower()
|
|
67
67
|
|
|
68
|
-
if '
|
|
69
|
-
route_name = f'
|
|
68
|
+
if 'start' not in route_name:
|
|
69
|
+
route_name = f'start{route_name}'
|
|
70
70
|
|
|
71
71
|
def decorator(func):
|
|
72
72
|
params = dict()
|
|
@@ -119,7 +119,7 @@ class ChatbotApp(ABC):
|
|
|
119
119
|
customer_id = message.customer_id
|
|
120
120
|
|
|
121
121
|
menu = self.__user_state.get_menu(customer_id)
|
|
122
|
-
menu = menu.
|
|
122
|
+
menu = menu.lower()
|
|
123
123
|
handler = self.__routes.get(menu, None)
|
|
124
124
|
|
|
125
125
|
if not handler:
|
|
@@ -143,11 +143,17 @@ class ChatbotApp(ABC):
|
|
|
143
143
|
elif type(message_response) == ChatbotResponse:
|
|
144
144
|
route = self.__adjust_route(message_response.route, menu)
|
|
145
145
|
self.__user_state.set_menu(customer_id, route)
|
|
146
|
-
return message_response.
|
|
146
|
+
return message_response.json()
|
|
147
147
|
elif type(message_response) == RedirectResponse:
|
|
148
148
|
route = self.__adjust_route(message_response.route, menu)
|
|
149
149
|
self.__user_state.set_menu(customer_id, route)
|
|
150
150
|
return self.process_message(message)
|
|
151
|
+
elif type(message_response) == EndChatResponse:
|
|
152
|
+
self.__user_state.delete_menu(customer_id)
|
|
153
|
+
return message_response.json()
|
|
154
|
+
elif type(message_response) == TransferToHuman:
|
|
155
|
+
self.__user_state.delete_menu(customer_id)
|
|
156
|
+
return message_response.json()
|
|
151
157
|
else:
|
|
152
158
|
raise ChatbotError('Tipo de retorno inválido!')
|
|
153
159
|
|
|
@@ -165,7 +171,7 @@ class ChatbotApp(ABC):
|
|
|
165
171
|
if not route:
|
|
166
172
|
return absolute_route
|
|
167
173
|
|
|
168
|
-
if '
|
|
174
|
+
if 'start' not in route:
|
|
169
175
|
route = absolute_route + route
|
|
170
176
|
|
|
171
177
|
return route
|
|
@@ -29,8 +29,8 @@ class ChatbotRouter:
|
|
|
29
29
|
Returns:
|
|
30
30
|
function: O decorador que adiciona a função à rota especificada.
|
|
31
31
|
"""
|
|
32
|
-
if '
|
|
33
|
-
route_name = f'
|
|
32
|
+
if 'start' not in route_name:
|
|
33
|
+
route_name = f'start{route_name}'
|
|
34
34
|
|
|
35
35
|
def decorator(func):
|
|
36
36
|
params = dict()
|
|
@@ -46,7 +46,7 @@ class ChatbotRouter:
|
|
|
46
46
|
params[param_type] = name
|
|
47
47
|
debug(f'Parameter: {name}, Type: {param_type}')
|
|
48
48
|
|
|
49
|
-
self.routes[route_name.strip().
|
|
49
|
+
self.routes[route_name.strip().lower()] = {
|
|
50
50
|
'function': func,
|
|
51
51
|
'params': params,
|
|
52
52
|
'return': output_param,
|
|
@@ -69,16 +69,16 @@ class ChatbotRouter:
|
|
|
69
69
|
prefix (str): O prefixo a ser adicionado às rotas do roteador.
|
|
70
70
|
|
|
71
71
|
Raises:
|
|
72
|
-
ChatbotError: Se a rota '
|
|
72
|
+
ChatbotError: Se a rota 'start' não for encontrada no roteador fornecido.
|
|
73
73
|
"""
|
|
74
|
-
if '
|
|
75
|
-
raise ChatbotError('Erro ao incluir rota,
|
|
74
|
+
if 'start' not in router.routes.keys():
|
|
75
|
+
raise ChatbotError('Erro ao incluir rota, start não encontrado!')
|
|
76
76
|
|
|
77
77
|
prefixed_routes = {
|
|
78
78
|
(
|
|
79
|
-
f'{prefix.
|
|
80
|
-
if key.
|
|
81
|
-
else f'
|
|
79
|
+
f'{prefix.lower()}'
|
|
80
|
+
if key.lower() == 'start'
|
|
81
|
+
else f'start{prefix.lower()}{key.lower().replace("start", "")}'
|
|
82
82
|
): value
|
|
83
83
|
for key, value in router.routes.items()
|
|
84
84
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from typing import Any, Callable
|
|
2
|
+
from .base_message_consumer import MessageConsumer
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class TestMessageConsumer(MessageConsumer):
|
|
6
|
+
"""
|
|
7
|
+
Classe de consumidor de mensagens de teste para uso em testes unitários.
|
|
8
|
+
"""
|
|
9
|
+
def __init__(self) -> None:
|
|
10
|
+
super().__init__()
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def load_dotenv(cls) -> 'TestMessageConsumer':
|
|
14
|
+
return cls()
|
|
15
|
+
|
|
16
|
+
def start_consume(self, process_message: Callable) -> Any:
|
|
17
|
+
return super().start_consume(process_message)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
messageTypes = Union[str, float, int, None]
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ChatbotResponse:
|
|
8
|
+
"""
|
|
9
|
+
Representa a resposta do chatbot, contendo a mensagem a ser enviada ao usuário e a rota a ser seguida.
|
|
10
|
+
|
|
11
|
+
Atributos:
|
|
12
|
+
message (messageTypes): A mensagem de resposta do chatbot. Pode ser uma string, um número, ou None.
|
|
13
|
+
route (str, opcional): A rota para a qual o chatbot deve direcionar após esta mensagem. Padrão é None.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, message: messageTypes = None, route: str = None) -> None:
|
|
17
|
+
"""
|
|
18
|
+
Inicializa a resposta do chatbot com uma mensagem e uma rota opcional.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
message (messageTypes, opcional): A mensagem a ser enviada ao usuário. Pode ser uma string, um número, ou None.
|
|
22
|
+
route (str, opcional): A rota para a qual o chatbot deve direcionar após esta mensagem. Padrão é None.
|
|
23
|
+
"""
|
|
24
|
+
self.message = message
|
|
25
|
+
self.route = route
|
|
26
|
+
|
|
27
|
+
def json(self):
|
|
28
|
+
'''
|
|
29
|
+
Retorna o objeto em formato json.
|
|
30
|
+
'''
|
|
31
|
+
return json.dumps({
|
|
32
|
+
'type': 'message',
|
|
33
|
+
'message': self.message,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class RedirectResponse:
|
|
38
|
+
"""
|
|
39
|
+
Representa uma resposta que redireciona o fluxo do chatbot para uma nova rota.
|
|
40
|
+
|
|
41
|
+
Atributos:
|
|
42
|
+
route (str): A rota para a qual o chatbot deve redirecionar.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, route: str) -> None:
|
|
46
|
+
"""
|
|
47
|
+
Inicializa a resposta de redirecionamento com a rota especificada.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
route (str): A rota para a qual o chatbot deve redirecionar.
|
|
51
|
+
"""
|
|
52
|
+
self.route = route
|
|
53
|
+
|
|
54
|
+
class EndChatResponse:
|
|
55
|
+
"""
|
|
56
|
+
Representa uma resposta que indica o fim do chatbot.
|
|
57
|
+
|
|
58
|
+
Atributos:
|
|
59
|
+
tabulation_id (str): O ID da tabulação do chatbot.
|
|
60
|
+
observations (str): As observações finais do chatbot.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
def __init__(self, tabulation_id: str, observations:str) -> None:
|
|
64
|
+
'''
|
|
65
|
+
Finzaliza e tabula as informações do chatbot.
|
|
66
|
+
'''
|
|
67
|
+
self.tabulation_id = tabulation_id
|
|
68
|
+
self.observations = observations
|
|
69
|
+
|
|
70
|
+
def json(self):
|
|
71
|
+
'''
|
|
72
|
+
Retorna o objeto em formato json.
|
|
73
|
+
'''
|
|
74
|
+
return json.dumps({
|
|
75
|
+
'type': 'tabulate',
|
|
76
|
+
'tabulation_id': self.tabulation_id,
|
|
77
|
+
'observations': self.observations,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
class TransferToHuman:
|
|
81
|
+
"""
|
|
82
|
+
Representa uma transferencia para um atendente humano.
|
|
83
|
+
"""
|
|
84
|
+
def __init__(self, campaign_id: str, observations:str) -> None:
|
|
85
|
+
'''
|
|
86
|
+
Finzaliza e tabula as informações do chatbot.
|
|
87
|
+
'''
|
|
88
|
+
self.campaign_id = campaign_id
|
|
89
|
+
self.observations = observations
|
|
90
|
+
|
|
91
|
+
def json(self):
|
|
92
|
+
'''
|
|
93
|
+
Retorna o objeto em formato json.
|
|
94
|
+
'''
|
|
95
|
+
return json.dumps({
|
|
96
|
+
'type': 'transfer',
|
|
97
|
+
'campaign_id': self.campaign_id,
|
|
98
|
+
'observations': self.observations,
|
|
99
|
+
})
|
|
@@ -28,13 +28,13 @@ class Route:
|
|
|
28
28
|
Retorna o caminho anterior ao caminho atual.
|
|
29
29
|
|
|
30
30
|
Raises:
|
|
31
|
-
RouteError: Se a rota atual for '
|
|
31
|
+
RouteError: Se a rota atual for 'start', indicando que não há caminho anterior.
|
|
32
32
|
|
|
33
33
|
Returns:
|
|
34
34
|
str: O caminho anterior à rota atual.
|
|
35
35
|
"""
|
|
36
|
-
if self.current == '
|
|
37
|
-
raise RouteError('Não há caminho anterior ao
|
|
36
|
+
if self.current == 'start':
|
|
37
|
+
raise RouteError('Não há caminho anterior ao start')
|
|
38
38
|
|
|
39
39
|
previous_route = self.separator.join(self.current.split(self.separator)[:-1])
|
|
40
40
|
return previous_route
|
|
@@ -52,7 +52,7 @@ class Route:
|
|
|
52
52
|
Returns:
|
|
53
53
|
str: O próximo caminho construído a partir da rota atual e da parte fornecida.
|
|
54
54
|
"""
|
|
55
|
-
next_part = next_part.strip().
|
|
55
|
+
next_part = next_part.strip().lower()
|
|
56
56
|
next_route = f"{self.current.rstrip(self.separator)}{next_part}"
|
|
57
57
|
if next_route not in self.routes:
|
|
58
58
|
raise RouteError(f'Rota não encontrada: {next_route}')
|
|
@@ -31,6 +31,16 @@ class UserState(ABC):
|
|
|
31
31
|
menu (str): O menu a ser definido para o cliente.
|
|
32
32
|
"""
|
|
33
33
|
pass
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def delete_menu(self, customer_id: str) -> None:
|
|
37
|
+
"""
|
|
38
|
+
Deleta o menu atual para o ID de cliente fornecido.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
customer_id (str): O ID do cliente.
|
|
42
|
+
"""
|
|
43
|
+
pass
|
|
34
44
|
|
|
35
45
|
|
|
36
46
|
class SimpleUserState(UserState):
|
|
@@ -49,7 +59,7 @@ class SimpleUserState(UserState):
|
|
|
49
59
|
|
|
50
60
|
def get_menu(self, customer_id: str) -> str:
|
|
51
61
|
"""
|
|
52
|
-
Retorna o menu atual para o ID de cliente fornecido. Se o cliente não tiver um menu definido, define '
|
|
62
|
+
Retorna o menu atual para o ID de cliente fornecido. Se o cliente não tiver um menu definido, define 'start' como padrão.
|
|
53
63
|
|
|
54
64
|
Args:
|
|
55
65
|
customer_id (str): O ID do cliente.
|
|
@@ -57,8 +67,8 @@ class SimpleUserState(UserState):
|
|
|
57
67
|
Returns:
|
|
58
68
|
str: O menu atual associado ao cliente.
|
|
59
69
|
"""
|
|
60
|
-
menu = self.states.get(customer_id, '
|
|
61
|
-
if menu == '
|
|
70
|
+
menu = self.states.get(customer_id, 'start')
|
|
71
|
+
if menu == 'start':
|
|
62
72
|
self.set_menu(customer_id, menu)
|
|
63
73
|
return menu
|
|
64
74
|
|
|
@@ -71,4 +81,14 @@ class SimpleUserState(UserState):
|
|
|
71
81
|
menu (str | None): O menu a ser definido para o cliente. Se None, não faz nenhuma alteração.
|
|
72
82
|
"""
|
|
73
83
|
if menu:
|
|
74
|
-
self.states[customer_id] = menu.
|
|
84
|
+
self.states[customer_id] = menu.lower()
|
|
85
|
+
|
|
86
|
+
def delete_menu(self, customer_id: str) -> None:
|
|
87
|
+
"""
|
|
88
|
+
Deleta o menu atual para o ID de cliente fornecido.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
customer_id (str): O ID do cliente.
|
|
92
|
+
"""
|
|
93
|
+
if customer_id in self.states:
|
|
94
|
+
self.states.pop(customer_id)
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
from typing import Union
|
|
2
|
-
|
|
3
|
-
messageTypes = Union[str, float, int, None]
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class ChatbotResponse:
|
|
7
|
-
"""
|
|
8
|
-
Representa a resposta do chatbot, contendo a mensagem a ser enviada ao usuário e a rota a ser seguida.
|
|
9
|
-
|
|
10
|
-
Atributos:
|
|
11
|
-
message (messageTypes): A mensagem de resposta do chatbot. Pode ser uma string, um número, ou None.
|
|
12
|
-
route (str, opcional): A rota para a qual o chatbot deve direcionar após esta mensagem. Padrão é None.
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
def __init__(self, message: messageTypes = None, route: str = None) -> None:
|
|
16
|
-
"""
|
|
17
|
-
Inicializa a resposta do chatbot com uma mensagem e uma rota opcional.
|
|
18
|
-
|
|
19
|
-
Args:
|
|
20
|
-
message (messageTypes, opcional): A mensagem a ser enviada ao usuário. Pode ser uma string, um número, ou None.
|
|
21
|
-
route (str, opcional): A rota para a qual o chatbot deve direcionar após esta mensagem. Padrão é None.
|
|
22
|
-
"""
|
|
23
|
-
self.message = message
|
|
24
|
-
self.route = route
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class RedirectResponse:
|
|
28
|
-
"""
|
|
29
|
-
Representa uma resposta que redireciona o fluxo do chatbot para uma nova rota.
|
|
30
|
-
|
|
31
|
-
Atributos:
|
|
32
|
-
route (str): A rota para a qual o chatbot deve redirecionar.
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
def __init__(self, route: str) -> None:
|
|
36
|
-
"""
|
|
37
|
-
Inicializa a resposta de redirecionamento com a rota especificada.
|
|
38
|
-
|
|
39
|
-
Args:
|
|
40
|
-
route (str): A rota para a qual o chatbot deve redirecionar.
|
|
41
|
-
"""
|
|
42
|
-
self.route = route
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|