File size: 7,344 Bytes
c76bbac
 
 
 
 
 
348d961
 
 
 
 
 
ae5207e
348d961
ae5207e
 
 
 
348d961
 
 
 
ae5207e
348d961
ae5207e
348d961
 
 
 
c76bbac
 
 
 
 
 
6d6ad89
 
c76bbac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d8f563a
 
 
15d4fae
d8f563a
6a4a20b
c76bbac
 
6a4a20b
c76bbac
6a4a20b
c76bbac
 
 
 
 
6a4a20b
c76bbac
 
6a4a20b
c76bbac
 
2e09065
 
 
 
 
 
 
1fbc32c
6a4a20b
c76bbac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6d6ad89
c76bbac
 
6a4a20b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c76bbac
6d6ad89
c76bbac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7cd6dbd
 
 
 
 
c76bbac
 
 
 
 
 
5effcd8
c76bbac
 
7cd6dbd
 
c76bbac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import time
import os
import joblib
import streamlit as st
import google.generativeai as genai
from dotenv import load_dotenv

# Función para cargar CSS personalizado
def load_css(file_path):
    with open(file_path) as f:
        st.markdown(f'<style>{f.read()}</style>', unsafe_allow_html=True)

# Intentar cargar el CSS personalizado con ruta absoluta para mayor seguridad
try:
    css_path = os.path.join(os.path.dirname(__file__), 'static', 'css', 'style.css')
    load_css(css_path)
except Exception as e:
    print(f"Error al cargar CSS: {e}")
    # Si el archivo no existe, crear un estilo básico en línea
    st.markdown("""
    <style>
    .robocopy-title {
        color: #4ECDC4 !important;
        font-weight: bold;
        font-size: 2em;
    }
    </style>
    """, unsafe_allow_html=True)

load_dotenv()
GOOGLE_API_KEY=os.environ.get('GOOGLE_API_KEY')
genai.configure(api_key=GOOGLE_API_KEY)

new_chat_id = f'{time.time()}'
MODEL_ROLE = 'ai'
AI_AVATAR_ICON = '🤖'  # Cambia el emoji por uno de robot para coincidir con tu logo
USER_AVATAR_ICON = '👤'  # Añade un avatar para el usuario

# Create a data/ folder if it doesn't already exist
try:
    os.mkdir('data/')
except:
    # data/ folder already exists
    pass

# Load past chats (if available)
try:
    past_chats: dict = joblib.load('data/past_chats_list')
except:
    past_chats = {}

# Sidebar allows a list of past chats
with st.sidebar:
    # Centrar el logo y eliminar el título de RoboCopy
    col1, col2, col3 = st.columns([1, 2, 1])
    with col2:
        st.image("assets/robocopy_logo.png", width=300)
    
    st.write('# Chats Anteriores')
    if st.session_state.get('chat_id') is None:
        st.session_state.chat_id = st.selectbox(
            label='Selecciona un chat anterior',
            options=[new_chat_id] + list(past_chats.keys()),
            format_func=lambda x: past_chats.get(x, 'Nuevo Chat'),
            placeholder='_',
        )
    else:
        # This will happen the first time AI response comes in
        st.session_state.chat_id = st.selectbox(
            label='Selecciona un chat anterior',
            options=[new_chat_id, st.session_state.chat_id] + list(past_chats.keys()),
            index=1,
            format_func=lambda x: past_chats.get(x, 'Nuevo Chat' if x != st.session_state.chat_id else st.session_state.chat_title),
            placeholder='_',
        )
    
    # Inicializar el título de chat si es necesario
    if st.session_state.get('chat_title') is None:
        if st.session_state.chat_id in past_chats:
            st.session_state.chat_title = past_chats[st.session_state.chat_id]
        else:
            st.session_state.chat_title = 'Nuevo Chat'
   
st.write('# Chatea con Gemini')

# Chat history (allows to ask multiple questions)
try:
    st.session_state.messages = joblib.load(
        f'data/{st.session_state.chat_id}-st_messages'
    )
    st.session_state.gemini_history = joblib.load(
        f'data/{st.session_state.chat_id}-gemini_messages'
    )
    print('old cache')
except:
    st.session_state.messages = []
    st.session_state.gemini_history = []
    print('new_cache made')
st.session_state.model = genai.GenerativeModel('gemini-2.0-flash')
st.session_state.chat = st.session_state.model.start_chat(
    history=st.session_state.gemini_history,
)

# Display chat messages from history on app rerun
for message in st.session_state.messages:
    with st.chat_message(
        name=message['role'],
        avatar=message.get('avatar'),
    ):
        st.markdown(message['content'])

# React to user input
if prompt := st.chat_input('¿En qué puedo ayudarte hoy?'):  # Mensaje más amigable
    # Save this as a chat for later
    if st.session_state.chat_id not in past_chats.keys():
        # Es una nueva conversación, generemos un título basado en el primer mensaje
        # Primero, guardamos un título temporal
        temp_title = f'SesiónChat-{st.session_state.chat_id}'
        past_chats[st.session_state.chat_id] = temp_title
        
        # Generamos un título basado en el contenido del mensaje
        try:
            # Usamos el mismo modelo para generar un título corto
            title_generator = genai.GenerativeModel('gemini-2.0-flash')
            title_response = title_generator.generate_content(
                f"Genera un título corto (máximo 5 palabras) que describa de qué trata esta consulta, sin usar comillas ni puntuación: '{prompt}'")
            
            # Obtenemos el título generado
            generated_title = title_response.text.strip()
            
            # Actualizamos el título en past_chats
            if generated_title:
                st.session_state.chat_title = generated_title
                past_chats[st.session_state.chat_id] = generated_title
            else:
                st.session_state.chat_title = temp_title
        except Exception as e:
            print(f"Error al generar título: {e}")
            st.session_state.chat_title = temp_title
    else:
        # Ya existe esta conversación, usamos el título guardado
        st.session_state.chat_title = past_chats[st.session_state.chat_id]
    
    joblib.dump(past_chats, 'data/past_chats_list')
    
    # Display user message in chat message container
    with st.chat_message('user', avatar=USER_AVATAR_ICON):  # Añade el avatar del usuario
        st.markdown(prompt)
    # Add user message to chat history
    st.session_state.messages.append(
        dict(
            role='user',
            content=prompt,
        )
    )
    ## Send message to AI
    response = st.session_state.chat.send_message(
        prompt,
        stream=True,
    )
    # Display assistant response in chat message container
    with st.chat_message(
        name=MODEL_ROLE,
        avatar=AI_AVATAR_ICON,
    ):
        message_placeholder = st.empty()
        full_response = ''
        assistant_response = response
        
        # Añade un indicador de "escribiendo..."
        typing_indicator = st.empty()
        typing_indicator.markdown("*RoboCopy está escribiendo...*")
        
        # Streams in a chunk at a time
        for chunk in response:
            # Simulate stream of chunk
            # TODO: Chunk missing `text` if API stops mid-stream ("safety"?)
            for ch in chunk.text.split(' '):
                full_response += ch + ' '
                time.sleep(0.1)  # Aumentado de 0.05 a 0.1 segundos para una velocidad más lenta
                # Rewrites with a cursor at end
                message_placeholder.write(full_response + '▌')
        # Elimina el indicador de escritura
        typing_indicator.empty()
        # Write full message with placeholder
        message_placeholder.write(full_response)

    # Add assistant response to chat history
    st.session_state.messages.append(
        dict(
            role=MODEL_ROLE,
            content=st.session_state.chat.history[-1].parts[0].text,
            avatar=AI_AVATAR_ICON,
        )
    )
    st.session_state.gemini_history = st.session_state.chat.history
    # Save to file
    joblib.dump(
        st.session_state.messages,
        f'data/{st.session_state.chat_id}-st_messages',
    )
    joblib.dump(
        st.session_state.gemini_history,
        f'data/{st.session_state.chat_id}-gemini_messages',
    )