jdmorzan commited on
Commit
f5a7225
·
verified ·
1 Parent(s): 08ab286

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -28
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,50 +56,109 @@ 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="Explorador de carreras", value=[[None, '''
47
- ¡Hola! Soy el Explorador de Carreras.
48
-
49
- Sé que elegir una carrera puede ser un gran desafío, pero estoy aquí para ayudarte a descubrir el camino que mejor se ajuste a ti. Juntos podemos explorar todas las opciones que te interesan.
50
-
51
- ¿Te gustaría saber...?
52
-
53
- - ¿Qué habilidades necesitas para destacar en tu futura carrera?
54
- - ¿Cuáles son los cursos más importantes que llevarás?
55
- - ¿Cómo es la vida diaria de un estudiante universitario?
 
 
 
 
 
 
 
56
 
57
- No dudes en preguntarme lo que quieras. ¡Exploremos juntos todas las posibilidades que el mundo profesional tiene para ti!
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 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.
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="Explorador de carreras",
85
+ value=[[None,
86
+ '''¡Hola! Soy el Explorador de Carreras.
87
+
88
+ Sé que elegir una carrera puede ser un gran desafío, pero estoy aquí para ayudarte a descubrir el camino que mejor se ajuste a ti. Juntos podemos explorar todas las opciones que te interesan.
89
+
90
+ ¿Te gustaría saber...?
91
+
92
+ - **¿Qué habilidades necesitas para destacar en tu futura carrera?**
93
+ - **¿Cuáles son los cursos más importantes que llevarás?**
94
+ - **¿Cómo es la vida diaria de un estudiante universitario?**
95
+
96
+ No dudes en preguntarme lo que quieras. ¡Exploremos juntos todas las posibilidades que el mundo profesional tiene para ti!'''
97
+ ]]
98
+ )
99
 
 
 
100
  msg = gr.Textbox(placeholder="Escribe aquí", label='')
101
  submit = gr.Button("Enviar")
102
  memory_state = gr.State(create_memory)
103
+
104
+ # Create the ChatOpenAI model with streaming enabled and our custom callback.
105
+ llm = ChatOpenAI(
106
+ temperature=0,
107
+ model_name='gpt-4o',
108
+ streaming=True,
109
+ callbacks=[stream_handler]
110
+ )
111
+
112
+ # --------------------------
113
+ # Generator function that runs the chain in a separate thread and polls the token queue.
114
+ # --------------------------
115
  def user(query, chat_history, memory):
116
+ # Append the user's message with an empty bot response.
117
+ chat_history.append((query, ""))
118
+ # Immediately yield an update so the user's message appears.
119
+ yield "", chat_history, memory
120
+
121
+ # Container for the final chain result.
122
+ final_result = [None]
123
+
124
+ # Define a helper function to run the chain.
125
+ def run_chain():
126
+ result = pdf_qa(query, memory, llm)
127
+ final_result[0] = result
128
+ # Signal end-of-stream by putting a sentinel value.
129
+ stream_handler.token_queue.put(None)
130
+
131
+ # Run the chain in a separate thread.
132
+ thread = threading.Thread(target=run_chain)
133
+ thread.start()
134
 
135
+ # Poll the token queue for new tokens and yield updated chat history.
136
+ current_response = ""
137
+ while True:
138
+ try:
139
+ token = stream_handler.token_queue.get(timeout=0.1)
140
+ except queue.Empty:
141
+ token = None
142
 
143
+ # A None token is our signal for end-of-stream.
144
+ if token is None:
145
+ if not thread.is_alive():
146
+ break
147
+ else:
148
+ continue
149
+ current_response += token
150
+ chat_history[-1] = (query, current_response)
151
+ yield "", chat_history, memory
152
 
153
+ thread.join()
154
+ # Optionally, update the final answer if it differs from the streaming tokens.
155
+ if final_result[0] and "answer" in final_result[0]:
156
+ chat_history[-1] = (query, final_result[0]["answer"])
157
+ yield "", chat_history, memory
158
 
159
+ # Wire up the generator function to Gradio components with queue enabled.
160
+ submit.click(user, [msg, chatbot, memory_state], [msg, chatbot, memory_state], queue=True)
161
+ msg.submit(user, [msg, chatbot, memory_state], [msg, chatbot, memory_state], queue=True)
162
 
163
  if __name__ == "__main__":
164
+ demo.queue(concurrency_count=16).launch(debug=True, height=800)