-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdata_utils.py
More file actions
137 lines (118 loc) · 4.71 KB
/
data_utils.py
File metadata and controls
137 lines (118 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import sqlite3
from datetime import datetime, timedelta
import config
# --- SETUP ---
def setup_database():
""" Cria as tabelas 'memories' e 'cache' na BD se não existirem. """
try:
conn = sqlite3.connect(config.DB_PATH)
cursor = conn.cursor()
# Tabela de Memórias (RAG)
cursor.execute("""
CREATE TABLE IF NOT EXISTS memories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME NOT NULL,
text TEXT NOT NULL
);
""")
# Tabela de Cache (Respostas Rápidas) - AS FUNÇÕES EM FALTA DEPENDEM DISTO
cursor.execute("""
CREATE TABLE IF NOT EXISTS cache (
prompt TEXT PRIMARY KEY,
response TEXT NOT NULL,
timestamp DATETIME NOT NULL
);
""")
conn.commit()
conn.close()
print(f"Base de dados e Cache inicializadas em '{config.DB_PATH}'.")
except Exception as e:
print(f"ERRO: Falha ao inicializar a base de dados SQLite: {e}")
# --- RAG (MEMÓRIA DE LONGO PRAZO) ---
def save_fact_to_rag(text):
"""
Tenta extrair apenas o facto antes de guardar.
Se a resposta contiver 'Sombra' ou 'Silêncio', limpamos antes de indexar.
"""
# Remove a persona da resposta antes de a tornar uma 'memória' permanente
clean_text = re.sub(r'(Sombra|Silêncio|Fúria|Eco).*?[\.\!\?]', '', text, flags=re.IGNORECASE)
if len(clean_text.strip()) > 5:
# Lógica de insert original...
pass
def retrieve_from_rag(prompt, max_results=5):
"""
Recupera memórias relevantes com TIMESTAMPS para dar contexto temporal.
"""
try:
# Filtro de palavras curtas para evitar ruído
keywords = [word for word in prompt.lower().split() if len(word) > 3]
if not keywords:
return ""
conn = sqlite3.connect(config.DB_PATH)
cursor = conn.cursor()
query_parts = []
params = []
for word in keywords:
query_parts.append("text LIKE ?")
params.append(f"%{word}%")
# Selecionamos também o timestamp
sql_query = f"SELECT timestamp, text FROM memories WHERE {' OR '.join(query_parts)} ORDER BY timestamp DESC LIMIT {max_results}"
cursor.execute(sql_query, params)
results = cursor.fetchall()
conn.close()
if results:
context_str = "MEMÓRIAS PESSOAIS DO UTILIZADOR (Ordenadas da mais recente para a antiga):\n"
context_str += "NOTA: Se houver contradições, a informação com a DATA MAIS RECENTE é a verdadeira.\n\n"
for row in results:
ts = row[0]
try:
if isinstance(ts, str):
ts = ts.split('.')[0] # Limpa milissegundos
except: pass
context_str += f"- [{ts}] {row[1]}\n"
print(f"RAG: Contexto recuperado.")
return context_str
else:
return ""
except Exception as e:
print(f"ERRO: Falha ao recuperar da BD RAG: {e}")
return ""
# --- CACHE (RESPOSTAS RÁPIDAS) - AS FUNÇÕES QUE FALTAVAM ---
def get_cached_response(prompt):
""" Tenta recuperar uma resposta exata da cache (válida por 24h). """
try:
conn = sqlite3.connect(config.DB_PATH)
cursor = conn.cursor()
cursor.execute("SELECT response, timestamp FROM cache WHERE prompt = ?", (prompt,))
row = cursor.fetchone()
conn.close()
if row:
response, timestamp_str = row
# Verifica validade (ex: 24 horas)
try:
cached_time = datetime.strptime(timestamp_str, "%Y-%m-%d %H:%M:%S.%f")
if datetime.now() - cached_time < timedelta(hours=24):
print("CACHE: Resposta recuperada da base de dados.")
return response
except:
# Se falhar a data, usa na mesma
return response
return None
except Exception as e:
print(f"AVISO: Erro ao ler cache: {e}")
return None
def save_cached_response(prompt, response):
""" Guarda uma resposta na cache para uso futuro. """
if not prompt or not response: return
try:
conn = sqlite3.connect(config.DB_PATH)
cursor = conn.cursor()
# INSERT OR REPLACE atualiza se a chave (prompt) já existir
cursor.execute(
"INSERT OR REPLACE INTO cache (prompt, response, timestamp) VALUES (?, ?, ?)",
(prompt, response, datetime.now())
)
conn.commit()
conn.close()
except Exception as e:
print(f"AVISO: Erro ao gravar cache: {e}")