segoedu commited on
Commit
bc0645c
·
verified ·
1 Parent(s): 50e7742

Upload 6 files

Browse files
Files changed (6) hide show
  1. app.py +710 -0
  2. img/bot.png +0 -0
  3. img/bot.webp +0 -0
  4. img/conciencia.webp +0 -0
  5. img/rosalia.webp +0 -0
  6. requirements.txt +10 -0
app.py ADDED
@@ -0,0 +1,710 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_groq import ChatGroq
2
+ from langchain_openai import ChatOpenAI
3
+ from langchain_community.embeddings import HuggingFaceEmbeddings
4
+ #from langchain.chains import RetrievalQA
5
+ from langchain_pinecone import PineconeVectorStore
6
+ from langchain_core.output_parsers import JsonOutputParser, StrOutputParser
7
+ from langchain_core.prompts import ChatPromptTemplate
8
+ from streamlit_option_menu import option_menu
9
+ #from elevenlabs import save, play, stream
10
+ from elevenlabs.client import ElevenLabs
11
+ from supabase import create_client, Client
12
+ from openai import OpenAI
13
+ from dotenv import load_dotenv
14
+
15
+ import os
16
+ import time
17
+ import streamlit as st
18
+
19
+
20
+
21
+ #####################
22
+ # CONFIGURACIÓN #
23
+ #####################
24
+
25
+ # Función de configuración de embedding
26
+ @st.cache_resource()
27
+ def load_embedding_model(model_name):
28
+ return HuggingFaceEmbeddings(model_name=model_name)
29
+
30
+ # Función de configuración
31
+ def configuracion():
32
+
33
+ # Cabecera
34
+ st.header(":gear: Configuración", divider='gray')
35
+
36
+ # API Keys #
37
+ hf_token = os.getenv('HF_TOKEN')
38
+ groq_api_key = os.getenv('GROQ_API_KEY')
39
+ openai_api_key = os.getenv('OPENAI_API_KEY')
40
+ pinecone_api_key = os.getenv('PINECONE_API_KEY')
41
+ supabase_key = os.getenv('SUPABASE_KEY')
42
+ supabase_url = os.getenv('SUPABASE_URL')
43
+ eleven_api_key = os.getenv('ELEVEN_API_KEY')
44
+ langsmith_api_key = os.getenv('LANGSMITH_API_KEY')
45
+ langchain_project = os.getenv('LANGCHAIN_PROJECT')
46
+ langchain_tracing_v2 = os.getenv('LANGCHAIN_TRACING_V2')
47
+
48
+ # Modelo de lenguaje #
49
+ modelos_llm = [
50
+ 'llama3-8b-8192',
51
+ 'llama3-70b-8192',
52
+ 'mixtral-8x7b-32768',
53
+ 'gemma-7b-it',
54
+ 'gpt-4o',
55
+ ]
56
+ modelo_llm = st.selectbox('Modelo de lenguaje', list(modelos_llm), help="Especifica el modelo de lenguaje utilizado")
57
+
58
+ # Temperatura
59
+ temperature = st.slider("Temperatura", 0.0, 2.0, 1.0, disabled=True, step=0.1)
60
+
61
+ if modelo_llm == "gpt-4o":
62
+ llm = ChatOpenAI(model=modelo_llm)
63
+ llm_creative = ChatOpenAI(model=modelo_llm, temperature=temperature)
64
+ else:
65
+ llm = ChatGroq(model=modelo_llm)
66
+ llm_creative = ChatGroq(model=modelo_llm, temperature=temperature)
67
+
68
+ # Embeddings #
69
+ model_name = 'intfloat/multilingual-e5-small'
70
+ model_name = st.text_input("Modelo de embedding:", value=model_name, disabled=True, help="Indica el modelo de _embedding_ utilizado en la vectorstore")
71
+ #embedding = HuggingFaceEmbeddings(model_name=model_name)
72
+ embedding = load_embedding_model(model_name)
73
+
74
+ # Pinecone #
75
+ index_name = "poemas-intfloat-multilingual-e5-small"
76
+ namespace = "poesiacastellana"
77
+ vectorstore = PineconeVectorStore(index_name=index_name, namespace=namespace, embedding=embedding)
78
+ col1, col2 = st.columns(2)
79
+ with col1:
80
+ input1 = st.text_input("Index", value=index_name, disabled=True, help="Nombre del _index_ del vectorstore en Pinecone para RAG")
81
+ with col2:
82
+ input2 = st.text_input("namespace", value=namespace, disabled=True, help="Nombre del _namespace_ del vectorstore en Pinecone")
83
+
84
+ # Supabase #
85
+ url: str = os.environ.get("SUPABASE_URL")
86
+ key: str = os.environ.get("SUPABASE_KEY")
87
+ supabase: Client = create_client(url, key)
88
+
89
+ # Variables globales
90
+ st.session_state.modelo_llm = modelo_llm
91
+ st.session_state.temperature = temperature
92
+ st.session_state.llm = llm
93
+ st.session_state.llm_creative = llm_creative
94
+ st.session_state.embedding = embedding
95
+ st.session_state.db = vectorstore
96
+ st.session_state.supabase = supabase
97
+
98
+ # API Keys #
99
+ with st.expander("API Keys"):
100
+ GROQ_API_KEY = st.text_input('Groq API Key', value=groq_api_key, type='password')
101
+ OPENAI_API_KEY = st.text_input('OpenAI API Key', value=openai_api_key, type='password')
102
+ HF_TOKEN = st.text_input('HuggingFace API Key', value=hf_token, type='password')
103
+ PINECONE_API_KEY = st.text_input('Pinecone API Key', value=pinecone_api_key, type='password')
104
+ ELEVEN_API_KEY = st.text_input('ElevenLabs API Key', value=eleven_api_key, type='password')
105
+
106
+
107
+
108
+ # ----- Función de configuración -----------------------------------------------------------
109
+ @st.cache_resource()
110
+ def __init__():
111
+
112
+ # API Keys #
113
+ load_dotenv()
114
+
115
+ # Modelo de lenguaje multimodal
116
+ llm_images = OpenAI()
117
+
118
+ # Modelo de lenguaje
119
+ modelo_llm = 'llama3-8b-8192'
120
+ temperature = 1
121
+ llm = ChatGroq(model=modelo_llm)
122
+ llm_creative = ChatGroq(model=modelo_llm, temperature=temperature)
123
+
124
+ # Embeddings
125
+ model_name = 'intfloat/multilingual-e5-small'
126
+ embedding = load_embedding_model(model_name)
127
+
128
+ # Pinecone
129
+ index_name = "poemas-intfloat-multilingual-e5-small"
130
+ namespace = "poesiacastellana"
131
+ vectorstore = PineconeVectorStore(index_name=index_name, namespace=namespace, embedding=embedding)
132
+
133
+ # Supabase
134
+ url: str = os.environ.get("SUPABASE_URL")
135
+ key: str = os.environ.get("SUPABASE_KEY")
136
+ supabase: Client = create_client(url, key)
137
+
138
+ # Globals
139
+ st.session_state.modelo_llm = modelo_llm
140
+ st.session_state.temperature = temperature
141
+ st.session_state.llm = llm
142
+ st.session_state.llm_creative = llm_creative
143
+ st.session_state.llm_images = llm_images
144
+ st.session_state.embedding = embedding
145
+ st.session_state.db = vectorstore
146
+ st.session_state.supabase = supabase
147
+
148
+
149
+ #####################
150
+ # GRAFO #
151
+ #####################
152
+
153
+ # ----- Función para desarrollar la metodología ------------------------------------------------
154
+ def grafo():
155
+
156
+ # Añadir una imagen al lado del título
157
+ col1, col2 = st.columns([4,20])
158
+ with col1:
159
+ st.image("img/bot.png", width=100)
160
+ with col2:
161
+ st.title("Generador de poemas")
162
+
163
+ # Botones de sugerencia para el tema/estilo
164
+ tema_suggestions = ["Amor", "Vida", "Misterio", "Aventura", "Sueños", "Amistad", "Impermanencia"]
165
+ estilo_suggestions = ["Romántico", "Gótico", "Épico", "Lírico", "Soneto", "Haiku", "Verso libre", "Gen27"]
166
+
167
+ # Campo para el tema
168
+ tema = st.text_input("Tema:", value="el despertar de la conciencia", help="Especifa el *tema* sobre el que quieres escribir el poema")
169
+ #tema_seleccionado = st.multiselect("Selecciona las opciones deseadas:", tema_suggestions)
170
+
171
+ # Campo para el estilo/estructura
172
+ estilo = st.text_input("Estilo:", value="antonio machado", help="Especifa el *estilo* con el que quieres escribir el poema")
173
+ #estilo_seleccionado = st.multiselect("Selecciona las opciones deseadas:", estilo_suggestions)
174
+
175
+ # Mostrar el conocimiento experto
176
+ with st.expander("Expertise Knowledge", icon="👩‍💻"):
177
+ for item in st.session_state.expertise:
178
+ st.markdown(f"```\n{item}\n```")
179
+
180
+ # Botón para generar el poema
181
+ if st.button("Generar Poema", type="primary", use_container_width=True):
182
+
183
+ # Variables globales
184
+ st.session_state.tema = tema
185
+ st.session_state.estilo = estilo
186
+ st.session_state.professor = ["No hay revisiones del profesor."]
187
+
188
+ # Generación del contexto
189
+ with st.spinner("Recuperando conocimiento aumentado..."):
190
+ rag_retrieval()
191
+ pass
192
+ st.success(":floppy_disk: ¡Conocimiento aumentado recuperado!")
193
+
194
+ # Generación del conocimiento
195
+ with st.spinner("Generando conocimiento experto..."):
196
+ generated_knowledge()
197
+ pass
198
+ st.success(":notebook: ¡Conocimiento experto generado!")
199
+
200
+ # Generación del borrador poético
201
+ with st.spinner("Generando borrador poético..."):
202
+ draft_poem()
203
+ pass
204
+ st.success(":memo: ¡Borrador poético generado!")
205
+
206
+ # Generando reflexion
207
+ with st.spinner("El catedrático está revisando el borrador poético..."):
208
+ reflexion_catedratico()
209
+ pass
210
+ st.success(":female-student: ¡Borrador poético revisado!")
211
+
212
+ # Generando poema
213
+ with st.spinner("Generando el poema..."):
214
+ st.session_state.poema = final_poem(st.session_state.draft_poem, st.session_state.reflexion)
215
+ pass
216
+ st.success(":scroll: ¡Poema generado!")
217
+
218
+ # Almacenar poema en Supabase
219
+ almacenar("insert")
220
+
221
+ # Mostrar poema
222
+ st.markdown(f"```\n{st.session_state.poema}\n```")
223
+
224
+
225
+ #####################
226
+ # AGENTES #
227
+ #####################
228
+
229
+ # ----- Función para mostrar la recuperación aumentada -----------------------------------
230
+ def rag_retrieval():
231
+
232
+ # Define the filter condition based on the 'author' metadata field
233
+ filter = {}
234
+
235
+ # Define el número de resultados
236
+ k=20
237
+
238
+ # Recupera los valores del grafo
239
+ tema = st.session_state.tema
240
+
241
+ # Perform the search: topic, human
242
+ documents = st.session_state.db.similarity_search(tema, k=k, filter=filter) #db.similarity_search_with_score
243
+
244
+ # Armamos la lista
245
+ rag_poems = [doc.page_content for doc in documents]
246
+
247
+ # Variable global
248
+ st.session_state.rag = rag_poems
249
+
250
+
251
+ # ----- Función para mostrar el conocimiento experto -------------------------------------
252
+ def expertise_knowledge():
253
+
254
+ # Mostramos una cabecera
255
+ st.header(":female-technologist: Expertise Knowledge (HITL)", divider='red')
256
+
257
+ # Campo de texto para ingresar poemas
258
+ poema = st.text_area("Poema de referencia", height=300, help="Añade aquí los poemas de referencia que sirvan como ejemplo para la elaboración del poema. Pulsa _Actualziar_ para limpiar el conjunto de poemas existente.")
259
+
260
+ # Botones para añadir y actualizar
261
+ col1, col2 = st.columns(2, gap="small")
262
+ with col1:
263
+ if st.button("Añadir", use_container_width=True):
264
+ st.session_state.expertise.insert(0, f"Poema:\n{poema.strip()}")
265
+ poema = "" # Limpiar el campo poema
266
+ with col2:
267
+ if st.button("Actualizar", type="primary", use_container_width=True):
268
+ st.session_state.expertise = [f"Poema:\n{poema.strip()}"]
269
+ poema = "" # Limpiar el campo poema
270
+
271
+ # Mostrar el conocimiento experto
272
+ st.divider()
273
+ #st.write("Expertise Knowledge:")
274
+ for poem in st.session_state.expertise:
275
+ st.markdown(f"```\n{poem}\n```")
276
+
277
+
278
+ # ----- Función para mostrar el conocimiento generado -------------------------------------
279
+ def generated_knowledge():
280
+
281
+ # Armamos el prompt
282
+ system = """
283
+ Eres un ratón de biblioteca y un profesor experto de literatura de una prestigiosa universidad con gran capacidad de \
284
+ sintetizar características de corrientes y estilos literarios. Tu objetivo es proporcionar las características principales \
285
+ y los detalles de las consultas académicas que te hagan sobre el estilo poético de '''{style_of}'''. Escribe las \
286
+ características principales sobre el estilo literario, movimiento o generación definido en el estilo o en el poeta nombrado, \
287
+ que sirvan de guía para la elaboración de nuevos textos que imiten el estilo indicado o al poeta solicitado.
288
+
289
+ Es importante que no escribas ningún poema, tan solo enumera un listado detallado de características, que sean útiles \
290
+ para poder reproducirse y aplicarse en la generación de nuevos textos.
291
+ """
292
+ human = 'Devuelve SOLO un listado detallado de las características en formato JSON. \
293
+ Formato: {{ "Características": ["característica 1", "característica 2", "característica 3"]}}'
294
+
295
+ prompt = ChatPromptTemplate.from_messages([
296
+ ("system", system),
297
+ ("human", human),
298
+ ])
299
+
300
+ # Recupera los valores del grafo
301
+ style_of = st.session_state.estilo
302
+
303
+ # Lanzamos la consulta
304
+ chain = prompt | st.session_state.llm | JsonOutputParser()
305
+ knowledge = chain.invoke({"style_of": style_of})
306
+
307
+ # Parser
308
+ knowledge_values = list(knowledge.values())[0]
309
+
310
+ # Valor global
311
+ st.session_state.generated = knowledge_values
312
+
313
+
314
+ # ----- Función para generar el borrado poético------ -------------------------------------
315
+ def draft_poem():
316
+
317
+ # Armamos el prompt
318
+ system = """
319
+ Eres un maestro de la poesía, capaz de escribir poemas que evocan emociones poderosas y obras maestras poéticas \
320
+ que capten la esencia del tema especificado de forma profunda y evocadora. Escribes desde la belleza. Cada línea \
321
+ cuidadosamente elaborada proyecta una imagen vívida, evocando emociones fuertes y hermosas con una destreza poética \
322
+ que deja sin aliento al lector. Tu estilo es una fusión de metáforas, aliteración y cadencia rítmica.
323
+
324
+ Las imágenes que evocan tus palabras son originales, creativas y únicas, alejándose de los tópicos y dotadas de un \
325
+ significado profundo y auténtico. Tus poemas están escritos para recitarse y leerse en voz alta. Se hace hincapié en \
326
+ que la escritura sea vívida y detallada, al tiempo que se garantiza que los poemas tengan un mensaje profundo que \
327
+ resuene en el lector mucho después de que haya terminado de leerlos. El objetivo es crear una poesía impactante y \
328
+ bella que deje una impresión duradera en el público.
329
+
330
+ Haces un uso de la rima es muy sutil, SOLO la utilizas cuando es necesaria. Si las características proporcionadas no \
331
+ indican lo contrario, haz un uso responsable y limitado de ella.
332
+
333
+ Esta es una lista de poemas que debes utilizar como EJEMPLOS e inspiración para escribir el poema:
334
+ '''{expertise}'''
335
+
336
+ Aquí tienes una lista de poemas con una temática similar que puedes usar para inspirarte:
337
+ '''
338
+ {rag_poems}
339
+ '''
340
+ """
341
+ human = (
342
+ "El poema debe escribirse atendiendo a las siguientes CARACTERÍSTICAS: "
343
+ "\n'''"
344
+ "\n * 18 versos o menos, no debes superar NUNCA esta cantidad "
345
+ "\n * {knowledge} "
346
+ "\n''' "
347
+ "\n\nEscribe un BREVE poema de menos de 18 versos sobre el tema de '''{topic}'''. "
348
+ "No hagas comentarios. " + "Esto es muy importante para mi carrera."
349
+ )
350
+
351
+ prompt = ChatPromptTemplate.from_messages([
352
+ ("system", system),
353
+ ("human", human),
354
+ ])
355
+
356
+ # Recupera los valores del grafo
357
+ topic = st.session_state.tema
358
+ knowledge = st.session_state.generated
359
+ expertise = st.session_state.expertise
360
+ rag_poems = st.session_state.rag
361
+
362
+ # Convertir las listas en texto
363
+ knowledge = '\n * '.join(knowledge)
364
+ expertise = ' '.join(expertise)
365
+ rag_poems = ' '.join(rag_poems)
366
+
367
+ # Lanzamos la consulta
368
+ chain = prompt | st.session_state.llm_creative | StrOutputParser()
369
+ draft_poem = chain.invoke({"topic": topic, "knowledge": knowledge, "expertise": expertise, "rag_poems": rag_poems})
370
+
371
+ # Valor global
372
+ st.session_state.draft_poem = draft_poem
373
+
374
+
375
+
376
+ # ----- Función para generar el poema final -------------------------------------------------
377
+ def final_poem(poema, review):
378
+
379
+ # Armamos el prompt
380
+ system = """
381
+ Eres un experto escritor de poesía que mejora los poemas. Tu objetivo es reescribir el poema proporcionado \
382
+ a partir de los comentarios proporcionadas por el profesor experto. \
383
+
384
+ POEMA:
385
+ '''
386
+ {poema}
387
+ '''
388
+
389
+ COMENTARIOS del profesor experto:
390
+ '''
391
+ * {review}
392
+ '''
393
+ """
394
+ human=(
395
+ "Escribe solo el poema final mejorado, el mejor posible. "
396
+ "No hagas comentarios, ni aclaraciones sobre lo que has modificado. Esto es muy importante para mi carrera."
397
+ )
398
+
399
+ prompt = ChatPromptTemplate.from_messages([
400
+ ("system", system),
401
+ ("human", human),
402
+ ])
403
+
404
+ # Convertir las listas en texto
405
+ review = '\n * '.join(list(review))
406
+
407
+ # Lanzamos la consulta
408
+ chain = prompt | st.session_state.llm_creative | StrOutputParser()
409
+ final_poem = chain.invoke({"poema": poema, "review": review})
410
+
411
+ # Valor global
412
+ return final_poem
413
+
414
+
415
+
416
+ # ----- Función para mostrar el conocimiento generado -------------------------------------
417
+ def reflexion_catedratico():
418
+
419
+ # Armamos el prompt
420
+ system = """
421
+ Eres un catedrático experto en poesía de una prestigiosa universidad con un profundo conocimiento y experiencia \
422
+ en el análisis de poemas. Tienes ojo crítico y una pasión por la perfección literaria. Tu objetivo es revisar y \
423
+ sugerir mejoras para los poemas.
424
+
425
+ Evalúas y analizas la calidad del poema recibido y proporcionas comentarios constructivos que permitan mejorar el resultado final.
426
+
427
+ Este es el poema:
428
+ '''
429
+ {draft_poem}
430
+ '''
431
+ """
432
+ #Devuelve un listado detallado de las características en formato JSON con una única clave 'comentarios'.
433
+ human = 'Devuelve SOLO un listado detallado de los comentarios en formato JSON. \
434
+ Formato: {{ "comentarios": ["comentario 1", "comentario 2", "comentario 3"]}}'
435
+
436
+ prompt = ChatPromptTemplate.from_messages([
437
+ ("system", system),
438
+ ("human", human),
439
+ ])
440
+
441
+ # Recupera los valores del grafo
442
+ draft_poem = st.session_state.draft_poem
443
+
444
+ # Lanzamos la consulta
445
+ chain = prompt | st.session_state.llm | JsonOutputParser()
446
+ reflexion = chain.invoke({"draft_poem": draft_poem})
447
+
448
+ # Parser
449
+ comentarios = list(reflexion.values())[0]
450
+
451
+ # Valor global
452
+ st.session_state.reflexion = comentarios
453
+
454
+
455
+ # ----- Función para mostrar el conocimiento experto -------------------------------------
456
+ def professor_reflexion():
457
+ st.header(":female-student: Professor Reflexion (HITL)", divider='red')
458
+
459
+ # Mostrar el texto combinado
460
+ st.write("Poema")
461
+ st.markdown(f"```\n{st.session_state.poema}\n```")
462
+
463
+ # Valor global
464
+ if st.session_state.poema != "No hay poema elaborado.":
465
+
466
+ col1, col2 = st.columns(2)
467
+ with col1:
468
+ # Audio
469
+ voz = st.button("Recitar", use_container_width=True, help="Recita el poema en alto")
470
+ with col2:
471
+ # Imagen
472
+ imagen = st.button("Imaginar", use_container_width=True, help="Genera una imagen a partir del poema")
473
+
474
+ if voz:
475
+ try:
476
+ # Generamos el audio
477
+ audio = recitar(st.session_state.poema)
478
+ st.audio(audio, format="audio/mp3")
479
+ except Exception as e:
480
+ # Manejo de la excepción
481
+ st.error(f"No dispones de créditos suficientes para realizar esta operación.")
482
+
483
+ if imagen:
484
+ try:
485
+ # Generamos la imagen
486
+ url_imagen, enlace = pintar(st.session_state.draft_poem)
487
+ # Mostrar la imagen
488
+ st.image(url_imagen, use_column_width="always")
489
+ st.markdown(enlace, unsafe_allow_html=True)
490
+ except Exception as e:
491
+ # Manejo de la excepción
492
+ st.error(f"No dispones de créditos suficientes para realizar esta operación.")
493
+
494
+
495
+ # Crear cuatro campos de textarea
496
+ professor = st.text_area("Comentarios, crítica y sugerencias", help="Escribe aquí la revisión experta del catedrático.")
497
+
498
+ # Reflexión
499
+ if st.button("Escribir", type="primary", use_container_width=True):
500
+ # Parser
501
+ st.session_state.professor = [professor]
502
+ st.session_state.expert_poem = st.session_state.poema
503
+
504
+ with st.spinner("Reformando el poema..."):
505
+ st.session_state.poema = final_poem(st.session_state.poema, professor)
506
+ pass
507
+ st.success("¡Poema reformado! :thumbsup:")
508
+
509
+ # Almacenamos el poema en Supabase
510
+ almacenar("update")
511
+
512
+ # Mostramos el poema elaborado
513
+ st.markdown(f"```{st.session_state.poema}```")
514
+
515
+
516
+
517
+ # ----- Función para mostrar el resumen del poema generado ----------------------------------
518
+ @st.cache_resource()
519
+ def pintar(poema):
520
+
521
+ # Lanzamos la consulta al modelo de lenguaje multimodal
522
+ prompt = "Dibuja una imagen que represente de forma abstracta el siguiente poema. No incluyas NINGUN texto. No incluyas texto. POEMA:" + poema
523
+ response = st.session_state.llm_images.images.generate(
524
+ model="dall-e-3",
525
+ prompt=prompt,
526
+ size="1024x1024",
527
+ quality="standard",
528
+ n=1,
529
+ )
530
+
531
+ # Capturar el link
532
+ url_imagen = response.data[0].url
533
+
534
+ # Crear el enlace en Markdown
535
+ link_text = "Haz clic aquí para ver la imagen en grande"
536
+ link = f'[{link_text}]({url_imagen})'
537
+
538
+ return url_imagen, link
539
+
540
+
541
+
542
+ # ----- Función para mostrar el resumen del poema generado ----------------------------------
543
+ @st.cache_resource()
544
+ def recitar(poema):
545
+
546
+ eleven_api_key = os.environ.get("ELEVEN_API_KEY")
547
+
548
+ client = ElevenLabs(
549
+ api_key=eleven_api_key,
550
+ )
551
+
552
+ audio = client.generate(
553
+ text=poema,
554
+ voice="Sara Martin 3",
555
+ model="eleven_multilingual_v2"
556
+ )
557
+
558
+ audio_bytes = b''
559
+ for chunk in audio:
560
+ audio_bytes += chunk
561
+
562
+ return audio_bytes
563
+
564
+
565
+ # ----- Función para almacenar el registro en la base de datos ----------------------------
566
+ def almacenar(accion):
567
+
568
+ # Insertar los datos en la tabla
569
+ data = {
570
+ "model": st.session_state.modelo_llm,
571
+ "temperature": st.session_state.temperature,
572
+ "topic": st.session_state.tema,
573
+ "style_of": st.session_state.estilo,
574
+ "knowledge": st.session_state.generated,
575
+ "expertise": st.session_state.expertise,
576
+ "rag_poems": st.session_state.rag,
577
+ "draft_poem": st.session_state.draft_poem,
578
+ "draft_poem_fb": st.session_state.reflexion,
579
+ "professor": st.session_state.professor,
580
+ "final_poem": st.session_state.poema,
581
+ }
582
+
583
+ # Almacenamos los poemas generados
584
+ if accion == "insert":
585
+ # Añadimos registro
586
+ data, count = st.session_state.supabase.table("Poemas").insert(data).execute()
587
+ # Recuperamos el id insertado
588
+ st.session_state.id = data[1][0]['id']
589
+
590
+ if accion == "update":
591
+ id = st.session_state.id
592
+ data, count = st.session_state.supabase.table("Poemas").update(data).eq("id", id).execute()
593
+
594
+
595
+
596
+ # ----- Función para mostrar el resumen del poema generado ----------------------------------
597
+ def resumen():
598
+
599
+ st.header(":memo: Metodología desarrollada", divider='gray')
600
+
601
+ # Muestro el tema y estilo proporcionados
602
+ col1, col2 = st.columns(2)
603
+ with col1:
604
+ input1 = st.text_input("Tema", value=st.session_state.tema, disabled=True)
605
+ with col2:
606
+ input2 = st.text_input("Estilo", value=st.session_state.estilo, disabled=True)
607
+
608
+ # Separador
609
+ st.subheader('Contexto', divider='red', help="Se muestra el *contexto* generado que se incrustará en el _prompt_")
610
+
611
+ # Mostrar el conocimiento experto
612
+ with st.expander("Expertise Knowledge (HITL)", icon="👩‍💻"):
613
+ for item in st.session_state.expertise:
614
+ st.markdown(f"```\n{item}\n```")
615
+
616
+ # Imprimir la conocimiento generado
617
+ with st.expander("Conocimiento generado", icon="💻"):
618
+ for item in st.session_state.generated:
619
+ st.markdown(f"""<span>{item}</span>""", unsafe_allow_html=True)
620
+
621
+ # Imprimir la conocimiento recuperado
622
+ with st.expander("Conocimiento recuperado", icon="💾"):
623
+ for item in st.session_state.rag:
624
+ st.markdown(f"```\n{item}\n```")
625
+
626
+ # Separador
627
+ st.subheader('Reflexión', divider='red', help="Se muestra el borrador poético y las reflexiones de los expertos")
628
+
629
+ # Imprimir el borrador poético
630
+ with st.expander("Borrador poético", icon="📃"):
631
+ st.markdown(f"```\n{st.session_state.draft_poem}\n```")
632
+
633
+ # Imprimir la reflexión del catedrático
634
+ with st.expander("Reflexión del catedrático", icon="🎓"):
635
+ for item in st.session_state.reflexion:
636
+ st.markdown(f"""<span>{item}</span>""", unsafe_allow_html=True)
637
+
638
+ # Imprimir el poema
639
+ if "expert_poem" in st.session_state:
640
+ with st.expander("Poema revisado", icon="📃"):
641
+ st.markdown(f"```{st.session_state.expert_poem}```")
642
+
643
+ # Imprimir la reflexión del catedrático
644
+ if "professor" in st.session_state:
645
+ with st.expander("Reflexión del profesor (HITL)", icon="👩‍🎓"):
646
+ for item in st.session_state.professor:
647
+ st.markdown(f"""<span>{item}</span>""", unsafe_allow_html=True)
648
+
649
+ # Separador
650
+ st.subheader('Poema :scroll:', divider='rainbow', help="Se muestra el poema elaborado")
651
+
652
+ # Imprimir el poema
653
+ st.markdown(f"```\n{st.session_state.poema}\n```")
654
+
655
+
656
+
657
+ #####################
658
+ # Función principal #
659
+ #####################
660
+ def main():
661
+ st.set_page_config(page_title="Generador de poemas")
662
+
663
+ if "draft_poem" not in st.session_state:
664
+ st.session_state.draft_poem = "No hay borrador poético."
665
+ #st.session_state.expert_poem = ""
666
+ st.session_state.poema = "No hay poema elaborado."
667
+ if "generated" not in st.session_state:
668
+ st.session_state.generated = ["No hay conocimiento generado."]
669
+ if "expertise" not in st.session_state:
670
+ st.session_state.expertise = ["No hay conocimiento experto proporcionado."]
671
+ if "rag" not in st.session_state:
672
+ st.session_state.rag = ["No hay conocimiento aumentado por recuperación."]
673
+ if "reflexion" not in st.session_state:
674
+ st.session_state.reflexion = ["No hay revisiones del catedrático."]
675
+ if "professor" not in st.session_state:
676
+ st.session_state.professor = ["No hay revisiones del profesor."]
677
+ if 'tema' not in st.session_state:
678
+ st.session_state.tema = ""
679
+ if 'estilo' not in st.session_state:
680
+ st.session_state.estilo = ""
681
+
682
+ # Ejecutamos la configuración
683
+ __init__()
684
+
685
+ # Sidebar con los enlaces a los pasos
686
+ opciones = {
687
+ "Topic&Style": grafo,
688
+ "Metodología": resumen,
689
+ "Expertise (HITL)": expertise_knowledge,
690
+ "Professor (HITL)": professor_reflexion,
691
+ "Configuración": configuracion,
692
+ }
693
+ #st.sidebar.title("Pasos")
694
+ #selected = st.sidebar.radio("Selecciona un paso", list(opciones.keys()))
695
+
696
+ # Enlace a la librería de menús: https://github.com/victoryhb/streamlit-option-menu
697
+ with st.sidebar:
698
+ seleccion = option_menu(None, list(opciones.keys()),
699
+ icons=['envelope-paper-heart','envelope-heart','person-hearts','person-square', 'gear'],
700
+ menu_icon="cast",
701
+ default_index=0)
702
+ st.image("img/bot.webp", width=250)
703
+
704
+ # Muestra el paso seleccionado
705
+ opciones[seleccion]()
706
+
707
+
708
+ if __name__ == "__main__":
709
+
710
+ main()
img/bot.png ADDED
img/bot.webp ADDED
img/conciencia.webp ADDED
img/rosalia.webp ADDED
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ langchain-community
2
+ langchain_groq
3
+ langchain_openai
4
+ langchain_pinecone
5
+ sentence_transformers
6
+ streamlit
7
+ langgraph
8
+ supabase
9
+ openai
10
+ python-dotenv