Pijush2023 commited on
Commit
165cb65
·
verified ·
1 Parent(s): 69278eb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +193 -39
app.py CHANGED
@@ -2,11 +2,10 @@ import gradio as gr
2
  import os
3
  import logging
4
  from langchain_core.prompts import ChatPromptTemplate
5
- from langchain.memory import ConversationBufferWindowMemory
6
  from langchain_core.output_parsers import StrOutputParser
 
7
  from langchain_community.graphs import Neo4jGraph
8
- from langchain_groq import ChatGroq
9
- from langchain.chains import GraphCypherQAChain
10
  from pydantic import BaseModel, Field
11
  from langchain_core.messages import AIMessage, HumanMessage
12
  from langchain_core.runnables import (
@@ -16,25 +15,25 @@ from langchain_core.runnables import (
16
  RunnableParallel,
17
  )
18
  from langchain_core.prompts.prompt import PromptTemplate
 
19
  import tempfile
 
20
  import time
21
- import threading
 
22
  import torch
23
- import numpy as np
24
- import requests
25
  from transformers import pipeline, AutoModelForSpeechSeq2Seq, AutoProcessor
26
- from typing import List, Tuple
27
-
28
 
29
- # Setup logging to a file to capture debug information
30
- logging.basicConfig(filename='neo4j_retrieval.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
31
 
32
- # Setup for conversational memory
33
  conversational_memory = ConversationBufferWindowMemory(
34
- memory_key='chat_history',
35
- k=10,
36
- return_messages=True
37
- )
38
 
39
  # Setup Neo4j
40
  graph = Neo4jGraph(
@@ -43,10 +42,6 @@ graph = Neo4jGraph(
43
  password="Z10duoPkKCtENuOukw3eIlvl0xJWKtrVSr-_hGX1LQ4"
44
  )
45
 
46
- # Setup the Groq model
47
- groq_api_key = os.getenv('GROQ_API_KEY')
48
- llm = ChatGroq(groq_api_key=groq_api_key, model_name="Gemma2-9b-It")
49
-
50
  # Define entity extraction and retrieval functions
51
  class Entities(BaseModel):
52
  names: List[str] = Field(
@@ -58,7 +53,8 @@ entity_prompt = ChatPromptTemplate.from_messages([
58
  ("human", "Use the given format to extract information from the following input: {question}"),
59
  ])
60
 
61
- entity_chain = entity_prompt | llm.with_structured_output(Entities)
 
62
 
63
  def remove_lucene_chars(input: str) -> str:
64
  return input.translate(str.maketrans({
@@ -76,6 +72,9 @@ def generate_full_text_query(input: str) -> str:
76
  full_text_query += f" {words[-1]}~2"
77
  return full_text_query.strip()
78
 
 
 
 
79
  def structured_retriever(question: str) -> str:
80
  result = ""
81
  entities = entity_chain.invoke({"question": question})
@@ -104,7 +103,7 @@ def retriever_neo4j(question: str):
104
  logging.debug(f"Structured data: {structured_data}")
105
  return structured_data
106
 
107
- # Condense follow-up questions to standalone
108
  _template = """Given the following conversation and a follow-up question, rephrase the follow-up question to be a standalone question,
109
  in its original language.
110
  Chat History:
@@ -130,19 +129,20 @@ _search_query = RunnableBranch(
130
  chat_history=lambda x: _format_chat_history(x["chat_history"])
131
  )
132
  | CONDENSE_QUESTION_PROMPT
133
- | llm
134
  | StrOutputParser(),
135
  ),
136
  RunnableLambda(lambda x: x["question"]),
137
  )
138
 
139
- # Define the prompt for response generation
140
  template = """I am a guide for Birmingham, Alabama. I can provide recommendations and insights about the city, including events and activities.
141
- Ask your question directly, and I'll provide a precise, short, and crisp response in a conversational way without any greeting.
142
  {context}
143
  Question: {question}
144
  Answer:"""
145
 
 
146
  qa_prompt = ChatPromptTemplate.from_template(template)
147
 
148
  # Define the chain for Neo4j-based retrieval and response generation
@@ -154,7 +154,7 @@ chain_neo4j = (
154
  }
155
  )
156
  | qa_prompt
157
- | llm
158
  | StrOutputParser()
159
  )
160
 
@@ -163,20 +163,31 @@ def get_response(question):
163
  try:
164
  return chain_neo4j.invoke({"question": question})
165
  except Exception as e:
166
- logging.error(f"Error generating response: {str(e)}")
167
  return f"Error: {str(e)}"
168
 
169
  # Define the function to clear input and output
170
  def clear_fields():
171
- return [], "", None
172
 
173
  # Function to generate audio with Eleven Labs TTS
174
  def generate_audio_elevenlabs(text):
175
  XI_API_KEY = os.environ['ELEVENLABS_API']
176
  VOICE_ID = 'ehbJzYLQFpwbJmGkqbnW'
177
  tts_url = f"https://api.elevenlabs.io/v1/text-to-speech/{VOICE_ID}/stream"
178
- headers = {"Accept": "application/json", "xi-api-key": XI_API_KEY}
179
- data = {"text": str(text), "model_id": "eleven_multilingual_v2", "voice_settings": {"stability": 1.0}}
 
 
 
 
 
 
 
 
 
 
 
 
180
  response = requests.post(tts_url, headers=headers, json=data, stream=True)
181
  if response.ok:
182
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as f:
@@ -185,32 +196,175 @@ def generate_audio_elevenlabs(text):
185
  f.write(chunk)
186
  audio_path = f.name
187
  logging.debug(f"Audio saved to {audio_path}")
188
- return audio_path # Return audio path for playback
189
  else:
190
  logging.error(f"Error generating audio: {response.text}")
191
  return None
192
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  # Create the Gradio Blocks interface
194
  with gr.Blocks(theme="rawrsor1/Everforest") as demo:
195
  chatbot = gr.Chatbot([], elem_id="RADAR", bubble_full_width=False)
196
  with gr.Row():
197
  with gr.Column():
198
- question_input = gr.Textbox(label="Ask a Question", placeholder="Type your question here...")
199
- with gr.Column():
200
- audio_output = gr.Audio(label="Audio", type="filepath", autoplay=True, interactive=False)
201
 
 
 
 
 
 
202
  with gr.Row():
203
  with gr.Column():
204
  get_response_btn = gr.Button("Get Response")
 
 
205
  with gr.Column():
206
  generate_audio_btn = gr.Button("Generate Audio")
207
  with gr.Column():
208
- clear_state_btn = gr.Button("Clear State")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
210
- # Define interactions for buttons
211
- get_response_btn.click(fn=get_response, inputs=question_input, outputs=chatbot)
212
- generate_audio_btn.click(fn=generate_audio_elevenlabs, inputs=chatbot, outputs=audio_output)
213
- clear_state_btn.click(fn=clear_fields, outputs=[chatbot, question_input, audio_output])
214
 
215
  # Launch the Gradio interface
216
- demo.launch(show_error=True)
 
2
  import os
3
  import logging
4
  from langchain_core.prompts import ChatPromptTemplate
 
5
  from langchain_core.output_parsers import StrOutputParser
6
+ from langchain_openai import ChatOpenAI
7
  from langchain_community.graphs import Neo4jGraph
8
+ from typing import List, Tuple
 
9
  from pydantic import BaseModel, Field
10
  from langchain_core.messages import AIMessage, HumanMessage
11
  from langchain_core.runnables import (
 
15
  RunnableParallel,
16
  )
17
  from langchain_core.prompts.prompt import PromptTemplate
18
+ import requests
19
  import tempfile
20
+ from langchain.memory import ConversationBufferWindowMemory
21
  import time
22
+ import logging
23
+ from langchain.chains import ConversationChain
24
  import torch
25
+ import torchaudio
 
26
  from transformers import pipeline, AutoModelForSpeechSeq2Seq, AutoProcessor
27
+ import numpy as np
28
+ import threading
29
 
 
 
30
 
31
+ #code for history
32
  conversational_memory = ConversationBufferWindowMemory(
33
+ memory_key='chat_history',
34
+ k=10,
35
+ return_messages=True
36
+ )
37
 
38
  # Setup Neo4j
39
  graph = Neo4jGraph(
 
42
  password="Z10duoPkKCtENuOukw3eIlvl0xJWKtrVSr-_hGX1LQ4"
43
  )
44
 
 
 
 
 
45
  # Define entity extraction and retrieval functions
46
  class Entities(BaseModel):
47
  names: List[str] = Field(
 
53
  ("human", "Use the given format to extract information from the following input: {question}"),
54
  ])
55
 
56
+ chat_model = ChatOpenAI(temperature=0, model_name="gpt-4o", api_key=os.environ['OPENAI_API_KEY'])
57
+ entity_chain = entity_prompt | chat_model.with_structured_output(Entities)
58
 
59
  def remove_lucene_chars(input: str) -> str:
60
  return input.translate(str.maketrans({
 
72
  full_text_query += f" {words[-1]}~2"
73
  return full_text_query.strip()
74
 
75
+ # Setup logging to a file to capture debug information
76
+ logging.basicConfig(filename='neo4j_retrieval.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
77
+
78
  def structured_retriever(question: str) -> str:
79
  result = ""
80
  entities = entity_chain.invoke({"question": question})
 
103
  logging.debug(f"Structured data: {structured_data}")
104
  return structured_data
105
 
106
+ # Setup for condensing the follow-up questions
107
  _template = """Given the following conversation and a follow-up question, rephrase the follow-up question to be a standalone question,
108
  in its original language.
109
  Chat History:
 
129
  chat_history=lambda x: _format_chat_history(x["chat_history"])
130
  )
131
  | CONDENSE_QUESTION_PROMPT
132
+ | ChatOpenAI(temperature=0, api_key=os.environ['OPENAI_API_KEY'])
133
  | StrOutputParser(),
134
  ),
135
  RunnableLambda(lambda x: x["question"]),
136
  )
137
 
138
+
139
  template = """I am a guide for Birmingham, Alabama. I can provide recommendations and insights about the city, including events and activities.
140
+ Ask your question directly, and I'll provide a precise and quick,short and crisp response in a conversational way without any Greet.
141
  {context}
142
  Question: {question}
143
  Answer:"""
144
 
145
+
146
  qa_prompt = ChatPromptTemplate.from_template(template)
147
 
148
  # Define the chain for Neo4j-based retrieval and response generation
 
154
  }
155
  )
156
  | qa_prompt
157
+ | chat_model
158
  | StrOutputParser()
159
  )
160
 
 
163
  try:
164
  return chain_neo4j.invoke({"question": question})
165
  except Exception as e:
 
166
  return f"Error: {str(e)}"
167
 
168
  # Define the function to clear input and output
169
  def clear_fields():
170
+ return [],"",None
171
 
172
  # Function to generate audio with Eleven Labs TTS
173
  def generate_audio_elevenlabs(text):
174
  XI_API_KEY = os.environ['ELEVENLABS_API']
175
  VOICE_ID = 'ehbJzYLQFpwbJmGkqbnW'
176
  tts_url = f"https://api.elevenlabs.io/v1/text-to-speech/{VOICE_ID}/stream"
177
+ headers = {
178
+ "Accept": "application/json",
179
+ "xi-api-key": XI_API_KEY
180
+ }
181
+ data = {
182
+ "text": str(text),
183
+ "model_id": "eleven_multilingual_v2",
184
+ "voice_settings": {
185
+ "stability": 1.0,
186
+ "similarity_boost": 0.0,
187
+ "style": 0.60,
188
+ "use_speaker_boost": False
189
+ }
190
+ }
191
  response = requests.post(tts_url, headers=headers, json=data, stream=True)
192
  if response.ok:
193
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as f:
 
196
  f.write(chunk)
197
  audio_path = f.name
198
  logging.debug(f"Audio saved to {audio_path}")
199
+ return audio_path # Return audio path for automatic playback
200
  else:
201
  logging.error(f"Error generating audio: {response.text}")
202
  return None
203
 
204
+ # Function to add a user's message to the chat history and clear the input box
205
+ def add_message(history, message):
206
+ if message.strip():
207
+ history.append((message, None)) # Add the user's message to the chat history only if it's not empty
208
+ return history, "" # Clear the input box
209
+
210
+ # Define function to generate a streaming response
211
+ def chat_with_bot(messages):
212
+ user_message = messages[-1][0] # Get the last user message (input)
213
+ messages[-1] = (user_message, "") # Prepare the placeholder for the bot's response
214
+
215
+ response = get_response(user_message)
216
+
217
+
218
+
219
+ # Simulate streaming response by iterating over each character in the response
220
+ for character in response:
221
+ messages[-1] = (user_message, messages[-1][1] + character)
222
+ yield messages # Stream each character
223
+ time.sleep(0.05) # Adjust delay as needed for real-time effect
224
+
225
+ yield messages # Final yield to ensure the full response is displayed
226
+
227
+
228
+ # Function to generate audio with Eleven Labs TTS from the last bot response
229
+ def generate_audio_from_last_response(history):
230
+ # Get the most recent bot response from the chat history
231
+ if history and len(history) > 0:
232
+ recent_response = history[-1][1] # The second item in the tuple is the bot response text
233
+ if recent_response:
234
+ return generate_audio_elevenlabs(recent_response)
235
+ return None
236
+
237
+ # Define example prompts
238
+ examples = [
239
+ ["What are some popular events in Birmingham?"],
240
+ ["Who are the top players of the Crimson Tide?"],
241
+ ["Where can I find a hamburger?"],
242
+ ["What are some popular tourist attractions in Birmingham?"],
243
+ ["What are some good clubs in Birmingham?"],
244
+ ["Is there a farmer's market or craft fair in Birmingham, Alabama?"],
245
+ ["Are there any special holiday events or parades in Birmingham, Alabama, during December?"],
246
+ ["What are the best places to enjoy live music in Birmingham, Alabama?"]
247
+
248
+ ]
249
+
250
+ # Function to insert the prompt into the textbox when clicked
251
+ def insert_prompt(current_text, prompt):
252
+ return prompt[0] if prompt else current_text
253
+
254
+
255
+ # Define the ASR model with Whisper
256
+ model_id = 'openai/whisper-large-v3'
257
+ device = "cuda:0" if torch.cuda.is_available() else "cpu"
258
+ torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float32
259
+ model = AutoModelForSpeechSeq2Seq.from_pretrained(model_id, torch_dtype=torch_dtype).to(device)
260
+ processor = AutoProcessor.from_pretrained(model_id)
261
+
262
+ pipe_asr = pipeline(
263
+ "automatic-speech-recognition",
264
+ model=model,
265
+ tokenizer=processor.tokenizer,
266
+ feature_extractor=processor.feature_extractor,
267
+ max_new_tokens=128,
268
+ chunk_length_s=15,
269
+ batch_size=16,
270
+ torch_dtype=torch_dtype,
271
+ device=device,
272
+ return_timestamps=True
273
+ )
274
+
275
+ # Define the function to reset the state after 10 seconds
276
+ def auto_reset_state():
277
+ time.sleep(5)
278
+ return None, "" # Reset the state and clear input text
279
+
280
+
281
+ def transcribe_function(stream, new_chunk):
282
+ try:
283
+ sr, y = new_chunk[0], new_chunk[1]
284
+ except TypeError:
285
+ print(f"Error chunk structure: {type(new_chunk)}, content: {new_chunk}")
286
+ return stream, "", None
287
+
288
+ # Ensure y is not empty and is at least 1-dimensional
289
+ if y is None or len(y) == 0:
290
+ return stream, "", None
291
+
292
+ y = y.astype(np.float32)
293
+ max_abs_y = np.max(np.abs(y))
294
+ if max_abs_y > 0:
295
+ y = y / max_abs_y
296
+
297
+ # Ensure stream is also at least 1-dimensional before concatenation
298
+ if stream is not None and len(stream) > 0:
299
+ stream = np.concatenate([stream, y])
300
+ else:
301
+ stream = y
302
+
303
+ # Process the audio data for transcription
304
+ result = pipe_asr({"array": stream, "sampling_rate": sr}, return_timestamps=False)
305
+ full_text = result.get("text", "")
306
+
307
+ # Start a thread to reset the state after 10 seconds
308
+ threading.Thread(target=auto_reset_state).start()
309
+
310
+ return stream, full_text, full_text
311
+
312
+
313
+
314
+ # Define the function to clear the state and input text
315
+ def clear_transcription_state():
316
+ return None, ""
317
+
318
+
319
+
320
  # Create the Gradio Blocks interface
321
  with gr.Blocks(theme="rawrsor1/Everforest") as demo:
322
  chatbot = gr.Chatbot([], elem_id="RADAR", bubble_full_width=False)
323
  with gr.Row():
324
  with gr.Column():
325
+ question_input = gr.Textbox(label="Ask a Question", placeholder="Type your question here...")
326
+ audio_input = gr.Audio(sources=["microphone"],streaming=True,type='numpy',every=0.1,label="Speak to Ask")
 
327
 
328
+
329
+
330
+ with gr.Column():
331
+ audio_output = gr.Audio(label="Audio", type="filepath",autoplay=True,interactive=False)
332
+
333
  with gr.Row():
334
  with gr.Column():
335
  get_response_btn = gr.Button("Get Response")
336
+ with gr.Column():
337
+ clear_state_btn = gr.Button("Clear State")
338
  with gr.Column():
339
  generate_audio_btn = gr.Button("Generate Audio")
340
  with gr.Column():
341
+ clean_btn = gr.Button("Clean")
342
+
343
+ with gr.Row():
344
+ with gr.Column():
345
+ gr.Markdown("<h1 style='color: red;'>Example Prompts</h1>", elem_id="Example-Prompts")
346
+ gr.Examples(examples=examples, fn=insert_prompt, inputs=question_input, outputs=question_input,api_name="api_insert_example")
347
+
348
+ # Define interactions
349
+ # Define interactions for clicking the button
350
+ get_response_btn.click(fn=add_message, inputs=[chatbot, question_input], outputs=[chatbot, question_input],api_name="api_add_message_on_button_click")\
351
+ .then(fn=chat_with_bot, inputs=[chatbot], outputs=chatbot,api_name="api_get response_on_button")
352
+ # Define interaction for hitting the Enter key
353
+ question_input.submit(fn=add_message, inputs=[chatbot, question_input], outputs=[chatbot, question_input],api_name="api_add_message_on _enter")\
354
+ .then(fn=chat_with_bot, inputs=[chatbot], outputs=chatbot,api_name="api_get response_on_enter")
355
+
356
+ # Speech-to-Text functionality
357
+ state = gr.State()
358
+ audio_input.stream(transcribe_function, inputs=[state, audio_input], outputs=[state, question_input],api_name="api_voice_to_text")
359
+
360
+
361
+ generate_audio_btn.click(fn=generate_audio_from_last_response, inputs=chatbot, outputs=audio_output,api_name="api_generate_text_to_audio")
362
+ clean_btn.click(fn=clear_fields, inputs=[], outputs=[chatbot, question_input, audio_output],api_name="api_clear_textbox")
363
+
364
+
365
+ # Clear state interaction
366
+ clear_state_btn.click(fn=clear_transcription_state, outputs=[question_input, state],api_name="api_clean_state_transcription")
367
 
 
 
 
 
368
 
369
  # Launch the Gradio interface
370
+ demo.launch(show_error=True)