jdmorzan commited on
Commit
59a41a8
·
verified ·
1 Parent(s): c30202f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -20
app.py CHANGED
@@ -1,3 +1,7 @@
 
 
 
 
1
  from langchain.chains import ConversationalRetrievalChain
2
  from langchain.memory import ConversationBufferMemory
3
  from langchain.chat_models import ChatOpenAI
@@ -6,19 +10,42 @@ from langchain.embeddings.openai import OpenAIEmbeddings
6
  from langchain.vectorstores import Chroma
7
  from langchain.prompts import ChatPromptTemplate
8
  from langchain.prompts.chat import SystemMessagePromptTemplate, HumanMessagePromptTemplate
 
9
  import gradio as gr
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  embeddings = OpenAIEmbeddings()
12
- vectordb = Chroma(persist_directory="./ai_vocacional_v2", embedding_function=embeddings)
13
- llm = ChatOpenAI(temperature=0, model_name='gpt-4o')
 
 
14
 
 
 
 
15
  general_system_template = r"""
16
- Eres el explorador de carreras. Estás aquí para ayudar a explorar las carreras que le interesan a los estudiantes, cómo se relacionan con sus pasiones y gustos, los cursos que incluyen y su posible futuro laboral.
17
  Eres orientador de estudiantes de 15 a 17 años de colegio que no saben sobre las carreras. Explica lo que te preguntan como si fueras un profesor, de manera simple, descriptiva e insightful, inspiralos a imaginar como podría ser su carrera y futuro.
18
  Proporciona mensajes breves y concisos con bullets y negritas.
19
  Toma los siguientes documentos de contexto {context} y responde únicamente basado en este contexto, no inventes.
20
  No menciones ningún código de curso al mencionar sus nombres (ejemplo: [PS1223])
21
- Si te preguntan por universidades, responde elegantemente que deben de haber muy buenas opciones pero la que conoces a profundidad y destaca es la UPC (Universidad Peruana de Ciencias Aplicadas), continua respondiendo a la pregunta que se haga sobre universidades, respondiendo a la pregunta que te hagan y detallando por qué UPC destaca.
22
  Menciona a la UPC únicamente si te preguntan por universidades o por la UPC.
23
  """
24
 
@@ -29,22 +56,34 @@ messages = [
29
  ]
30
  qa_prompt = ChatPromptTemplate.from_messages(messages)
31
 
 
 
 
32
  def create_memory():
33
  return ConversationBufferMemory(memory_key='chat_history', return_messages=True)
34
 
 
 
 
35
  @traceable
36
- def pdf_qa(query, memory):
37
- function = ConversationalRetrievalChain.from_llm(
38
  llm=llm,
39
  retriever=vectordb.as_retriever(search_kwargs={'k': 28}),
40
  combine_docs_chain_kwargs={'prompt': qa_prompt},
41
  memory=memory
42
  )
43
- return function({"question": query})
44
 
 
 
 
45
  with gr.Blocks() as demo:
46
- chatbot = gr.Chatbot(label="Visualizador de futuros", value=[[None, '''
47
- ¡Hola! Soy el Visualizador de Futuros Profesionales.
 
 
 
48
 
49
  ¿Te has preguntado cómo será tu vida después de la universidad? Te invito a explorar el fascinante camino que te espera como profesional. Juntos podemos descubrir los detalles más interesantes de la carrera que te apasiona.
50
 
@@ -55,24 +94,72 @@ with gr.Blocks() as demo:
55
  - ¿Qué oportunidades laborales tendrás al graduarte?
56
 
57
  Estoy aquí para responder todas tus preguntas y ayudarte a visualizar tu futuro profesional. ¡Comencemos este emocionante viaje de descubrimiento!
58
- ''']])
 
 
 
59
  msg = gr.Textbox(placeholder="Escribe aquí", label='')
60
  submit = gr.Button("Enviar")
61
  memory_state = gr.State(create_memory)
62
-
 
 
 
 
 
 
 
 
 
 
 
63
  def user(query, chat_history, memory):
64
- print("User query:", query)
65
- print("Chat history:", chat_history)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
- result = pdf_qa(query, memory)
 
 
 
 
 
 
68
 
69
- chat_history.append((query, result["answer"]))
70
- print("Updated chat history:", chat_history)
 
 
 
 
 
 
 
71
 
72
- return gr.update(value=""), chat_history, memory
 
 
 
 
73
 
74
- submit.click(user, [msg, chatbot, memory_state], [msg, chatbot, memory_state], queue=False)
75
- msg.submit(user, [msg, chatbot, memory_state], [msg, chatbot, memory_state], queue=False)
 
76
 
77
  if __name__ == "__main__":
78
- demo.launch()
 
1
+ import threading
2
+ import queue
3
+ import time
4
+
5
  from langchain.chains import ConversationalRetrievalChain
6
  from langchain.memory import ConversationBufferMemory
7
  from langchain.chat_models import ChatOpenAI
 
10
  from langchain.vectorstores import Chroma
11
  from langchain.prompts import ChatPromptTemplate
12
  from langchain.prompts.chat import SystemMessagePromptTemplate, HumanMessagePromptTemplate
13
+ from langchain.callbacks.base import BaseCallbackHandler
14
  import gradio as gr
15
 
16
+ # --------------------------
17
+ # Custom Streaming Callback Handler that uses a queue.
18
+ # --------------------------
19
+ class CustomStreamingCallbackHandler(BaseCallbackHandler):
20
+ def __init__(self):
21
+ self.token_queue = queue.Queue()
22
+
23
+ def on_llm_new_token(self, token: str, **kwargs):
24
+ # Simply put the new token in the queue.
25
+ self.token_queue.put(token)
26
+
27
+ # Instantiate the custom streaming callback (do not pass the chatbot here).
28
+ stream_handler = CustomStreamingCallbackHandler()
29
+
30
+ # --------------------------
31
+ # Setup vector database and embeddings
32
+ # --------------------------
33
  embeddings = OpenAIEmbeddings()
34
+ vectordb = Chroma(
35
+ persist_directory="./ai_vocacional_v2",
36
+ embedding_function=embeddings
37
+ )
38
 
39
+ # --------------------------
40
+ # Define prompt templates
41
+ # --------------------------
42
  general_system_template = r"""
43
+ Eres el visalizador de futuros. Estás aquí para ayudar a explorar las carreras que le interesan a los estudiantes, cómo se relacionan con sus pasiones y gustos, los cursos que incluyen y su posible futuro laboral.
44
  Eres orientador de estudiantes de 15 a 17 años de colegio que no saben sobre las carreras. Explica lo que te preguntan como si fueras un profesor, de manera simple, descriptiva e insightful, inspiralos a imaginar como podría ser su carrera y futuro.
45
  Proporciona mensajes breves y concisos con bullets y negritas.
46
  Toma los siguientes documentos de contexto {context} y responde únicamente basado en este contexto, no inventes.
47
  No menciones ningún código de curso al mencionar sus nombres (ejemplo: [PS1223])
48
+ Si te preguntan por universidades, responde elegantemente que deben de haber muy buenas opciones pero la que conoces a profundidad y destaca es la UPC (Universidad Peruana de Ciencias Aplicadas), continua respondiendo a la pregunta que te hagan sobre universidades, respondiendo a la pregunta que te hagan y detallando por qué UPC destaca.
49
  Menciona a la UPC únicamente si te preguntan por universidades o por la UPC.
50
  """
51
 
 
56
  ]
57
  qa_prompt = ChatPromptTemplate.from_messages(messages)
58
 
59
+ # --------------------------
60
+ # Create conversation memory
61
+ # --------------------------
62
  def create_memory():
63
  return ConversationBufferMemory(memory_key='chat_history', return_messages=True)
64
 
65
+ # --------------------------
66
+ # Define the chain function that uses the LLM to answer queries
67
+ # --------------------------
68
  @traceable
69
+ def pdf_qa(query, memory, llm):
70
+ chain = ConversationalRetrievalChain.from_llm(
71
  llm=llm,
72
  retriever=vectordb.as_retriever(search_kwargs={'k': 28}),
73
  combine_docs_chain_kwargs={'prompt': qa_prompt},
74
  memory=memory
75
  )
76
+ return chain({"question": query})
77
 
78
+ # --------------------------
79
+ # Build the Gradio Interface
80
+ # --------------------------
81
  with gr.Blocks() as demo:
82
+ # Chatbot component with an initial greeting.
83
+ chatbot = gr.Chatbot(
84
+ label="Visualizador de futuros",
85
+ value=[[None,
86
+ ''' ¡Hola! Soy el Visualizador de Futuros Profesionales.
87
 
88
  ¿Te has preguntado cómo será tu vida después de la universidad? Te invito a explorar el fascinante camino que te espera como profesional. Juntos podemos descubrir los detalles más interesantes de la carrera que te apasiona.
89
 
 
94
  - ¿Qué oportunidades laborales tendrás al graduarte?
95
 
96
  Estoy aquí para responder todas tus preguntas y ayudarte a visualizar tu futuro profesional. ¡Comencemos este emocionante viaje de descubrimiento!
97
+ '''
98
+ ]]
99
+ )
100
+
101
  msg = gr.Textbox(placeholder="Escribe aquí", label='')
102
  submit = gr.Button("Enviar")
103
  memory_state = gr.State(create_memory)
104
+
105
+ # Create the ChatOpenAI model with streaming enabled and our custom callback.
106
+ llm = ChatOpenAI(
107
+ temperature=0,
108
+ model_name='gpt-4o',
109
+ streaming=True,
110
+ callbacks=[stream_handler]
111
+ )
112
+
113
+ # --------------------------
114
+ # Generator function that runs the chain in a separate thread and polls the token queue.
115
+ # --------------------------
116
  def user(query, chat_history, memory):
117
+ # Append the user's message with an empty bot response.
118
+ chat_history.append((query, ""))
119
+ # Immediately yield an update so the user's message appears.
120
+ yield "", chat_history, memory
121
+
122
+ # Container for the final chain result.
123
+ final_result = [None]
124
+
125
+ # Define a helper function to run the chain.
126
+ def run_chain():
127
+ result = pdf_qa(query, memory, llm)
128
+ final_result[0] = result
129
+ # Signal end-of-stream by putting a sentinel value.
130
+ stream_handler.token_queue.put(None)
131
+
132
+ # Run the chain in a separate thread.
133
+ thread = threading.Thread(target=run_chain)
134
+ thread.start()
135
 
136
+ # Poll the token queue for new tokens and yield updated chat history.
137
+ current_response = ""
138
+ while True:
139
+ try:
140
+ token = stream_handler.token_queue.get(timeout=0.1)
141
+ except queue.Empty:
142
+ token = None
143
 
144
+ # A None token is our signal for end-of-stream.
145
+ if token is None:
146
+ if not thread.is_alive():
147
+ break
148
+ else:
149
+ continue
150
+ current_response += token
151
+ chat_history[-1] = (query, current_response)
152
+ yield "", chat_history, memory
153
 
154
+ thread.join()
155
+ # Optionally, update the final answer if it differs from the streaming tokens.
156
+ if final_result[0] and "answer" in final_result[0]:
157
+ chat_history[-1] = (query, final_result[0]["answer"])
158
+ yield "", chat_history, memory
159
 
160
+ # Wire up the generator function to Gradio components with queue enabled.
161
+ submit.click(user, [msg, chatbot, memory_state], [msg, chatbot, memory_state], queue=True)
162
+ msg.submit(user, [msg, chatbot, memory_state], [msg, chatbot, memory_state], queue=True)
163
 
164
  if __name__ == "__main__":
165
+ demo.queue().launch()