Pecximenes commited on
Commit
0746d2c
1 Parent(s): 70a5baf

Adding feedback's and login's features

Browse files
interface/app.py CHANGED
@@ -9,6 +9,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
9
 
10
  # Importando m贸dulos necess谩rios
11
  from interface.chatbot import Chatbot
 
12
 
13
 
14
  def display_message(message):
@@ -33,21 +34,30 @@ def display_page_message(message):
33
 
34
  def main():
35
  app = Chatbot()
36
-
37
- with st.sidebar:
38
- app.create_sidebar()
39
-
40
- app.mount_chatbot()
41
-
42
- if app.response:
43
- app.add_to_history(app.response, role="user")
44
- app.generate_awnser(app.response)
45
- app.response = "" # Zerando a vari谩vel ap贸s uso
46
 
47
- for message in st.session_state.chat_history:
48
- display_message(message)
49
- if message["type"] == "page" and message == st.session_state.chat_history[-1]:
50
- app.display_suggestions(app.links)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
 
53
  if __name__ == "__main__":
 
9
 
10
  # Importando m贸dulos necess谩rios
11
  from interface.chatbot import Chatbot
12
+ from interface.login import Login
13
 
14
 
15
  def display_message(message):
 
34
 
35
  def main():
36
  app = Chatbot()
37
+ login = Login()
 
 
 
 
 
 
 
 
 
38
 
39
+ if not st.session_state.user_authorized:
40
+ login.mount_login_page()
41
+
42
+ else:
43
+ with st.sidebar:
44
+ app.create_sidebar() # Corrigido para chamar o m茅todo que cria o sidebar
45
+
46
+ app.mount_chatbot() # Recebe o input de texto feito pelo usu谩rio
47
+
48
+ if app.response:
49
+ app.add_to_history(app.response, role="user")
50
+ app.generate_answer(app.response)
51
+ app.response = "" # Zerando a vari谩vel ap贸s uso
52
+ st.session_state.is_feedback_active = True # Ativando o feedback
53
+
54
+ for message in st.session_state.chat_history:
55
+ display_message(message)
56
+ if message["type"] == "page" and message == st.session_state.chat_history[-1]:
57
+ app.display_suggestions(app.links)
58
+
59
+ if st.session_state.is_feedback_active:
60
+ app.display_feedback()
61
 
62
 
63
  if __name__ == "__main__":
interface/auxiliary_functions.py CHANGED
@@ -1,9 +1,13 @@
1
- # Fun莽玫es utilit谩rias
2
  import re
3
  import requests
4
  from bs4 import BeautifulSoup
5
  from urllib.parse import urlparse, unquote
6
 
 
 
 
 
 
7
 
8
  def extract_content(text, tag):
9
  """Extrai conte煤do de um texto com base na tag fornecida."""
@@ -12,29 +16,78 @@ def extract_content(text, tag):
12
  return match.group(1).strip() if match else None
13
 
14
  def fetch_webpage_content(url):
15
- """Obt茅m o conte煤do HTML de uma URL e retorna o conte煤do principal."""
16
  try:
17
  response = requests.get(url)
18
  response.raise_for_status()
 
 
19
  soup = BeautifulSoup(response.text, 'html.parser')
 
 
20
  main_content = soup.find('div', id='main')
21
 
22
  if main_content:
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  body_tag = soup.find('body')
24
  if body_tag:
25
  body_tag.clear()
26
  body_tag.append(main_content)
27
- return str(soup)
28
- return "<html><body><p>Could not find main content on the page.</p></body></html>"
 
 
 
 
 
29
  except requests.RequestException as e:
30
- return f"<html><body><p>Error fetching the webpage: {str(e)}</p></body></html>"
 
 
31
 
32
  def extract_links(html_content):
33
  """Extrai todos os links (URLs) de um conte煤do HTML."""
34
  soup = BeautifulSoup(html_content, 'html.parser')
35
  return [a_tag['href'] for a_tag in soup.find_all('a', href=True)]
36
 
 
37
  def url_to_suggestion(url):
38
- """Converte uma URL longa em uma sugest茫o amig谩vel."""
39
  path = unquote(urlparse(url).path).strip('/').split('/')
40
- return path[-1].replace('-', ' ').replace('_', ' ').capitalize() if path else url
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import re
2
  import requests
3
  from bs4 import BeautifulSoup
4
  from urllib.parse import urlparse, unquote
5
 
6
+ import streamlit as st
7
+ from openai import OpenAI
8
+ from qdrant_client import QdrantClient
9
+ import edgedb
10
+ import os
11
 
12
  def extract_content(text, tag):
13
  """Extrai conte煤do de um texto com base na tag fornecida."""
 
16
  return match.group(1).strip() if match else None
17
 
18
  def fetch_webpage_content(url):
19
+ """Obt茅m o conte煤do HTML de uma URL e retorna o conte煤do principal, desativando links espec铆ficos, mas mantendo os links originais para sugest玫es."""
20
  try:
21
  response = requests.get(url)
22
  response.raise_for_status()
23
+
24
+ # Usando BeautifulSoup para processar o HTML
25
  soup = BeautifulSoup(response.text, 'html.parser')
26
+
27
+ # Localiza o conte煤do principal pelo ID 'main'
28
  main_content = soup.find('div', id='main')
29
 
30
  if main_content:
31
+ # Armazenar os links originais para sugest玫es
32
+ original_links = [link['href'] for link in main_content.find_all('a', class_='govbr-card-content')]
33
+
34
+ # Desativar links com a classe "govbr-card-content" (apenas visualmente)
35
+ for link in main_content.find_all('a', class_='govbr-card-content'):
36
+ link['href'] = 'javascript:void(0);' # Impede a navega莽茫o
37
+ link['style'] = 'pointer-events: none; cursor: not-allowed;' # Estilo para desativar visualmente
38
+
39
+ # Remover elementos espec铆ficos (exemplo: div com a classe 'outstanding-header')
40
+ for unwanted_element in main_content.find_all('div', class_='outstanding-header'):
41
+ unwanted_element.decompose() # Remove o elemento do DOM
42
+
43
+ # Limpa o conte煤do do <body> e insere o conte煤do principal
44
  body_tag = soup.find('body')
45
  if body_tag:
46
  body_tag.clear()
47
  body_tag.append(main_content)
48
+
49
+ # Retorna o conte煤do modificado e os links originais
50
+ return str(soup), original_links
51
+
52
+ # Mensagem de erro caso n茫o encontre o conte煤do principal
53
+ return "<html><body><p>Could not find main content on the page.</p></body></html>", []
54
+
55
  except requests.RequestException as e:
56
+ # Retorna uma mensagem de erro em caso de falha na requisi莽茫o
57
+ return f"<html><body><p>Error fetching the webpage: {str(e)}</p></body></html>", []
58
+
59
 
60
  def extract_links(html_content):
61
  """Extrai todos os links (URLs) de um conte煤do HTML."""
62
  soup = BeautifulSoup(html_content, 'html.parser')
63
  return [a_tag['href'] for a_tag in soup.find_all('a', href=True)]
64
 
65
+
66
  def url_to_suggestion(url):
67
+ """Converte uma URL longa em uma sugest茫o amig谩vel e natural."""
68
  path = unquote(urlparse(url).path).strip('/').split('/')
69
+
70
+ # Garantir que h谩 pelo menos duas partes significativas no caminho
71
+ if len(path) > 2:
72
+ # Remover h铆fens e capitalizar cada palavra
73
+ section = path[-2].replace('-', ' ').title()
74
+ subsection = path[-1].replace('-', ' ').title()
75
+
76
+ # Formatar a sugest茫o de forma mais natural
77
+ return f"Acesso 脿 se莽茫o '{section}' sobre '{subsection}'"
78
+ return None
79
+
80
+ @st.cache_resource
81
+ def connect_to_services():
82
+ oa_client = OpenAI(
83
+ api_key=os.environ.get("OPENAI_API_KEY")
84
+ )
85
+
86
+ qdrant_client = QdrantClient(
87
+ url=os.environ.get("QDRANT_URL"),
88
+ api_key=os.environ.get("QDRANT_KEY")
89
+ )
90
+
91
+ edgedb_client = edgedb.create_client()
92
+
93
+ return oa_client, qdrant_client, edgedb_client
interface/chatbot.py CHANGED
@@ -14,8 +14,7 @@ from interface.auxiliary_functions import (
14
  url_to_suggestion
15
  )
16
 
17
-
18
- class Chatbot():
19
  def __init__(self):
20
  # Configura莽茫o inicial do hist贸rico de chat
21
  if "chat_history" not in st.session_state:
@@ -29,55 +28,33 @@ class Chatbot():
29
  # Conte煤do dos bot玫es do sidebar
30
  if "topics" not in st.session_state:
31
  st.session_state["topics"] = [
32
- "Niveis da conta govbr.",
33
  "D煤vidas no reconhecimento facial.",
34
  "Como recuperar minha conta gov.br",
35
- "D煤vidas para aumentar o n铆vel com a cin."
36
  ]
37
 
 
 
 
38
  # Pergunta do usu谩rio no chatbot
39
  self.response = ""
40
  self.links = []
41
-
42
-
43
- def display_suggestions(self, links):
44
- suggestions = [(link, url_to_suggestion(link)) for link in links if url_to_suggestion(link)]
45
- st.subheader("Sugest玫es de Passos:")
46
- if suggestions:
47
- st.write("Voc锚 tamb茅m pode se interessar em:")
48
- for link, suggestion in suggestions:
49
- st.write(f"- {suggestion}")
50
- else:
51
- st.write("N茫o h谩 sugest玫es dispon铆veis no momento.")
52
-
53
-
54
- def mount_chatbot(self):
55
- # Exibi莽茫o do t铆tulo e subt铆tulo
56
- st.title("Bem-vindo 脿 ajuda do gov.br")
57
- st.caption("馃挰 Qual a sua dificuldade hoje? Estou aqui para ajudar!")
58
 
59
- # Exibi莽茫o do espa莽o para mandar mensagem
60
- if user_query := st.chat_input(placeholder="Digite sua mensagem"):
61
- st.session_state.chat_history.append({"type": "text","role": "user", "content": user_query})
62
-
63
- #TODO Aplicar o llm_rag nessa parte
64
- full_link = self.generate_awnser(user_query)
65
-
66
-
67
  def create_sidebar(self):
 
68
  st.image('https://www.gov.br/++theme++padrao_govbr/img/govbr-logo-large.png', width=200)
69
  st.header("T贸picos frequentes")
70
-
71
- for topic in st.session_state.topics:
72
  if st.button(topic, key=topic):
73
  self.response = topic
74
 
75
-
76
  # Espa莽os em branco para organiza莽茫o
77
  for _ in range(5):
78
  st.write("")
79
-
80
- # Bot茫o centralizado
81
  col1, col2, col3 = st.columns([1, 2, 1])
82
  with col2:
83
  if st.button("LIMPAR HIST脫RICO"):
@@ -87,21 +64,52 @@ class Chatbot():
87
  "content": "Como eu posso ajudar?",
88
  "links": []
89
  }]
 
90
 
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  def add_to_history(self, message, role="user", type="text"):
 
93
  st.session_state.chat_history.append({
94
  "role": role,
95
  "type": type,
96
  "content": message
97
- })
98
-
99
-
100
- def generate_awnser(self, input_message):
101
- # Retorna o caminho do site gov que responde a pergunta
102
  response_text = send_message(input_message, pipeline)
103
 
104
- # Armazena a resposta do agent com a tag <path>
105
  self.add_to_history(response_text, role="assistant")
106
 
107
  # Extra莽茫o do caminho da resposta do bot
@@ -109,11 +117,57 @@ class Chatbot():
109
  if path:
110
  base_url = "https://www.gov.br/governodigital/pt-br/"
111
  full_url = base_url + path
 
 
 
 
112
  with st.spinner("Obtendo conte煤do da p谩gina..."):
113
- content = fetch_webpage_content(full_url)
114
 
 
115
  self.add_to_history(content, role="assistant", type="page")
116
 
117
-
118
  extracted_links = extract_links(content)
119
- self.links = extracted_links
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  url_to_suggestion
15
  )
16
 
17
+ class Chatbot:
 
18
  def __init__(self):
19
  # Configura莽茫o inicial do hist贸rico de chat
20
  if "chat_history" not in st.session_state:
 
28
  # Conte煤do dos bot玫es do sidebar
29
  if "topics" not in st.session_state:
30
  st.session_state["topics"] = [
31
+ "N铆veis da conta govbr.",
32
  "D煤vidas no reconhecimento facial.",
33
  "Como recuperar minha conta gov.br",
34
+ "D煤vidas para aumentar o n铆vel com a CIN."
35
  ]
36
 
37
+ if "is_feedback_active" not in st.session_state:
38
+ st.session_state.is_feedback_active = False
39
+
40
  # Pergunta do usu谩rio no chatbot
41
  self.response = ""
42
  self.links = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
 
 
 
 
 
 
 
 
44
  def create_sidebar(self):
45
+ """Cria o sidebar com t贸picos e op莽玫es."""
46
  st.image('https://www.gov.br/++theme++padrao_govbr/img/govbr-logo-large.png', width=200)
47
  st.header("T贸picos frequentes")
48
+
49
+ for topic in st.session_state["topics"]:
50
  if st.button(topic, key=topic):
51
  self.response = topic
52
 
 
53
  # Espa莽os em branco para organiza莽茫o
54
  for _ in range(5):
55
  st.write("")
56
+
57
+ # Bot茫o centralizado para limpar hist贸rico
58
  col1, col2, col3 = st.columns([1, 2, 1])
59
  with col2:
60
  if st.button("LIMPAR HIST脫RICO"):
 
64
  "content": "Como eu posso ajudar?",
65
  "links": []
66
  }]
67
+ st.session_state.is_feedback_active = False
68
 
69
 
70
+ def display_suggestions(self, links):
71
+ """Exibe as sugest玫es de links no chat."""
72
+ if links:
73
+ st.subheader("Voc锚 pode acessar a p谩gina na web em:")
74
+ st.write(links[0]) # O primeiro link ser谩 o da p谩gina principal
75
+
76
+ st.subheader("Pr贸ximos Passos:")
77
+ suggestions = [(link, url_to_suggestion(link)) for link in links[1:] if url_to_suggestion(link)]
78
+
79
+ if suggestions:
80
+ st.write("Voc锚 tamb茅m pode se interessar em:")
81
+ for link, suggestion in suggestions:
82
+ st.write(f"- [{suggestion}]({link})") # Exibe os links clic谩veis no formato Markdown
83
+ else:
84
+ st.write("N茫o h谩 sugest玫es de navega莽茫o adicionais.")
85
+ else:
86
+ st.write("N茫o h谩 links dispon铆veis para exibi莽茫o.")
87
+
88
+ def mount_chatbot(self):
89
+ """Configura o chatbot com t铆tulo, subt铆tulo e espa莽o de entrada."""
90
+ st.title("Bem-vindo 脿 ajuda do gov.br")
91
+ st.caption("馃挰 Qual a sua dificuldade hoje? Estou aqui para ajudar!")
92
+
93
+ # Exibi莽茫o do espa莽o para mandar mensagem
94
+ if user_query := st.chat_input(placeholder="Digite sua mensagem"):
95
+ st.session_state.chat_history.append({"type": "text", "role": "user", "content": user_query})
96
+ self.generate_answer(user_query)
97
+ st.session_state.is_feedback_active = True # Ativando o feedback
98
+
99
  def add_to_history(self, message, role="user", type="text"):
100
+ """Adiciona uma mensagem ao hist贸rico de chat."""
101
  st.session_state.chat_history.append({
102
  "role": role,
103
  "type": type,
104
  "content": message
105
+ })
106
+
107
+ def generate_answer(self, input_message):
108
+ """Gera uma resposta para a consulta do usu谩rio."""
109
+ # Chama o pipeline para obter a resposta
110
  response_text = send_message(input_message, pipeline)
111
 
112
+ # Armazena a resposta do agente com a tag <path>
113
  self.add_to_history(response_text, role="assistant")
114
 
115
  # Extra莽茫o do caminho da resposta do bot
 
117
  if path:
118
  base_url = "https://www.gov.br/governodigital/pt-br/"
119
  full_url = base_url + path
120
+
121
+ # Armazena o link principal
122
+ self.links = [full_url]
123
+
124
  with st.spinner("Obtendo conte煤do da p谩gina..."):
125
+ content, original_links = fetch_webpage_content(full_url) # Agora retornando tamb茅m os links desativados
126
 
127
+ # Adiciona o conte煤do da p谩gina ao hist贸rico do chatbot
128
  self.add_to_history(content, role="assistant", type="page")
129
 
130
+ # Extrai links ativos do conte煤do da p谩gina e armazena para sugest玫es
131
  extracted_links = extract_links(content)
132
+
133
+ # Combinar links ativos e links inibidos
134
+ all_links = extracted_links + original_links
135
+ self.links.extend(all_links)
136
+
137
+ def display_feedback(self):
138
+ user_input = st.session_state.chat_history[-2]["content"]
139
+ bot_output = st.session_state.chat_history[-1]["content"]
140
+
141
+ with st.expander("Avalia莽茫o do atendimento"):
142
+ # st.write(f'O que achou da resposta para a pergunta "{user_input}"?')
143
+ st.write(f'O que achou da resposta para a pergunta?')
144
+
145
+ rate = st.feedback("stars")
146
+ # rate = st.feedback("faces")
147
+
148
+ text_feedback = st.text_input("Coment谩rios extras:")
149
+
150
+ # Bot茫o para confirmar a avalia莽茫o
151
+ if rate is not None:
152
+ if st.button("Enviar Avalia莽茫o"):
153
+ try:
154
+ feedback_rate = rate + 1
155
+ # TODO Colocar nessa parte a estrutura para adicionar o feedback_data ao banco de dados
156
+ # st.session_state.services["edgedb_client"].query('''
157
+ # INSERT Feedback {
158
+ # rating := <int16>$rating,
159
+ # content := <str>$content,
160
+ # message := <str>$content
161
+ # }
162
+ # ''',
163
+ # message_id=bot_output,
164
+ # rating=feedback_rate,
165
+ # content=text_feedback,
166
+ # )
167
+ # st.session_state.chat_history
168
+ st.success(f"Avalia莽茫o enviada!")
169
+ except Exception as e:
170
+ print(e)
171
+ st.error("Erro ao enviar avalia莽茫o!")
172
+
173
+ st.session_state.is_feedback_active = False # Desativando o feedback
interface/login.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import sys
3
+ import os
4
+ import bcrypt
5
+
6
+ # Add the parent directory to the Python path
7
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
8
+
9
+ from auxiliary_functions import connect_to_services
10
+
11
+
12
+ class Login:
13
+ def __init__(self):
14
+ if "username" not in st.session_state:
15
+ st.session_state.username = ""
16
+
17
+ if "user_authorized" not in st.session_state:
18
+ st.session_state.user_authorized = False
19
+
20
+ if "services" not in st.session_state:
21
+ oa_client, qdrant_client, edgedb_client = connect_to_services()
22
+ st.session_state.services = {
23
+ "oa_client": oa_client,
24
+ "qdrant_client": qdrant_client,
25
+ "edgedb_client": edgedb_client
26
+ }
27
+
28
+
29
+ self.username = ""
30
+ self.password = ""
31
+
32
+
33
+ def mount_login_page(self):
34
+ # Exibi莽茫o do t铆tulo e subt铆tulo
35
+ st.title("Bem-vindo 脿 ajuda do gov.br")
36
+ with st.form("login_form"):
37
+ st.title("Login")
38
+
39
+ username = st.text_input('E-mail:')
40
+ password = st.text_input('Senha:', type='password')
41
+ submitted = st.form_submit_button("Entrar")
42
+ st.text("N茫o possui uma conta?")
43
+ create_account = st.form_submit_button("Criar uma conta")
44
+
45
+ if create_account:
46
+ if not username:
47
+ st.warning("Digite um email para cadastrar a conta.")
48
+
49
+ if not password:
50
+ st.warning("Digite uma senha para cadastrar a conta.")
51
+
52
+ if username and password:
53
+ if "@" not in username:
54
+ st.warning("Digite um email v谩lido para cadastrar a conta.")
55
+
56
+ else:
57
+ user = self.validate_credentials(username, password, return_just_user=True)
58
+ if user:
59
+ st.warning("J谩 existe uma conta usando este email")
60
+ else:
61
+ # Gerando senha encriptada
62
+ hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
63
+ hashed_password_str = hashed_password.decode('utf-8')
64
+
65
+ st.session_state.services["edgedb_client"].query('''
66
+ INSERT User {
67
+ username := <str>$username,
68
+ password := <str>$password
69
+ }
70
+ ''',
71
+ username=username, \
72
+ password=hashed_password_str, \
73
+ )
74
+
75
+ st.success("Conta cadastrada com sucesso.")
76
+
77
+ if submitted:
78
+ if username and password:
79
+ checked = self.validate_credentials(username, password)
80
+ if checked:
81
+ st.success("Usu谩rio logado!")
82
+ st.session_state.user_authorized = True
83
+ st.session_state.username = username
84
+ st.rerun()
85
+
86
+ else:
87
+ st.error("Nome de usu谩rio ou senha inv谩lidos.")
88
+
89
+ else:
90
+ st.warning("Digite o nome do usu谩rio e a senha.")
91
+
92
+
93
+ def validate_credentials(self, username, password, return_just_user=False):
94
+ user = st.session_state.services["edgedb_client"].query('''
95
+ SELECT User {
96
+ username,
97
+ password
98
+ } FILTER .username = <str>$username
99
+ ''', username=username)
100
+
101
+ if return_just_user:
102
+ if not user:
103
+ return False
104
+
105
+ return True
106
+
107
+ if not user or not bcrypt.checkpw(password.encode('utf-8'), user[0].password.encode('utf-8')):
108
+ return False
109
+
110
+ return True
interface/main.py DELETED
@@ -1,122 +0,0 @@
1
- import streamlit as st
2
- import streamlit.components.v1 as components
3
- import re
4
- import sys
5
- import os
6
- import requests
7
- from bs4 import BeautifulSoup
8
- import difflib
9
- from urllib.parse import urlparse, unquote
10
- from pipelines.message import send_message
11
- from agent import pipeline, knowledge, graph, graph_data
12
-
13
- # Configura莽茫o do caminho
14
- sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
15
-
16
- # Substitui o caminho do gr谩fico pelo conte煤do do graph_data
17
- graph = graph.replace('"../memory/graph_data.json"', f'{graph_data}')
18
-
19
- # Vari谩veis globais
20
- extracted_links = []
21
-
22
- # Configura莽茫o inicial do hist贸rico de chat
23
- if "chat_history" not in st.session_state:
24
- st.session_state.chat_history = []
25
-
26
- # Fun莽玫es utilit谩rias
27
- def extract_content(text, tag):
28
- """Extrai conte煤do de um texto com base na tag fornecida."""
29
- pattern = rf'<{tag}>(.*?)</{tag}>'
30
- match = re.search(pattern, text, re.DOTALL)
31
- return match.group(1).strip() if match else None
32
-
33
- def fetch_webpage_content(url):
34
- """Obt茅m o conte煤do HTML de uma URL e retorna o conte煤do principal."""
35
- try:
36
- response = requests.get(url)
37
- response.raise_for_status()
38
- soup = BeautifulSoup(response.text, 'html.parser')
39
- main_content = soup.find('div', id='main')
40
-
41
- if main_content:
42
- body_tag = soup.find('body')
43
- if body_tag:
44
- body_tag.clear()
45
- body_tag.append(main_content)
46
- return str(soup)
47
- return "<html><body><p>Could not find main content on the page.</p></body></html>"
48
- except requests.RequestException as e:
49
- return f"<html><body><p>Error fetching the webpage: {str(e)}</p></body></html>"
50
-
51
- def extract_links(html_content):
52
- """Extrai todos os links (URLs) de um conte煤do HTML."""
53
- soup = BeautifulSoup(html_content, 'html.parser')
54
- return [a_tag['href'] for a_tag in soup.find_all('a', href=True)]
55
-
56
- def url_to_suggestion(url):
57
- """Converte uma URL longa em uma sugest茫o amig谩vel."""
58
- path = unquote(urlparse(url).path).strip('/').split('/')
59
- return path[-1].replace('-', ' ').replace('_', ' ').capitalize() if path else url
60
-
61
- def display_suggestions(links):
62
- """Exibe sugest玫es para o usu谩rio com base nos links extra铆dos."""
63
- suggestions = [(link, url_to_suggestion(link)) for link in links if url_to_suggestion(link)]
64
- st.subheader("Sugest玫es de Passos:")
65
- if suggestions:
66
- st.write("Voc锚 tamb茅m pode se interessar em:")
67
- for link, suggestion in suggestions:
68
- st.write(f"- {suggestion}")
69
- else:
70
- st.write("N茫o h谩 sugest玫es dispon铆veis no momento.")
71
-
72
- def display_knowledge_tree(structure):
73
- """Exibe a estrutura de conhecimento na barra lateral do Streamlit."""
74
- with st.sidebar.expander("Knowledge Structure", expanded=True):
75
- components.html(graph, height=600, scrolling=True)
76
- st.markdown(structure)
77
-
78
- def navigate_page(full_url):
79
- """Fun莽茫o para navegar para uma nova p谩gina e atualizar o conte煤do."""
80
- global extracted_links
81
- with st.spinner("Obtendo conte煤do da p谩gina..."):
82
- content = fetch_webpage_content(full_url)
83
- extracted_links = extract_links(content)
84
- st.session_state.chat_history.append({"type": "page", "content": content, "links": extracted_links})
85
- st.subheader("Conte煤do da P谩gina Web:")
86
- components.html(content, height=600, scrolling=True)
87
- display_suggestions(extracted_links)
88
- st.subheader("URL Completa:")
89
- st.write(full_url)
90
-
91
- def main():
92
- st.title("Alfred - Assistente de IA para Servi莽os gov.br")
93
- st.write("Qual a sua dificuldade hoje? Estou aqui para ajudar!")
94
- display_knowledge_tree(knowledge)
95
-
96
- # Exibe o hist贸rico do chat
97
- for message in st.session_state.chat_history:
98
- if message["type"] == "text":
99
- st.markdown(message["content"])
100
- elif message["type"] == "page":
101
- st.subheader("Conte煤do da P谩gina Web:")
102
- components.html(message["content"], height=400, scrolling=True)
103
-
104
- with st.form(key='user_input_form', clear_on_submit=True):
105
- user_query = st.text_input("Digite sua mensagem aqui:")
106
- submit_button = st.form_submit_button(label='Enviar')
107
- if submit_button and user_query:
108
- response_text = send_message(user_query, pipeline)
109
- st.write("Bot:", response_text)
110
- st.session_state.chat_history.append({"type": "text", "content": f"**Voc锚:** {user_query}"})
111
-
112
- # Extra莽茫o do caminho da resposta do bot
113
- path = extract_content(response_text, "path")
114
- if path:
115
- base_url = "https://www.gov.br/governodigital/pt-br/"
116
- full_url = base_url + path
117
- navigate_page(full_url)
118
-
119
- st.session_state.chat_history.append({"type": "text", "content": f"**Bot:** {response_text}"})
120
-
121
- if __name__ == "__main__":
122
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -13,6 +13,8 @@ docker==7.1.0
13
  paramiko==3.4.0
14
  duckduckgo_search==6.1.12
15
  inputimeout==1.0.4
16
- streamlit==1.25.0
17
  beautifulsoup4==4.12.3
18
- bs4==0.0.2
 
 
 
13
  paramiko==3.4.0
14
  duckduckgo_search==6.1.12
15
  inputimeout==1.0.4
16
+ streamlit==1.39.0
17
  beautifulsoup4==4.12.3
18
+ bs4==0.0.2
19
+ qdrant-client==1.12.0
20
+ edgedb==2.1.0