vsj0702 commited on
Commit
4e847b8
Β·
verified Β·
1 Parent(s): ab2413a

Adding voice bot

Browse files
Files changed (1) hide show
  1. chatbot.py +54 -47
chatbot.py CHANGED
@@ -9,7 +9,7 @@ import asyncio
9
  import os
10
  import uuid
11
 
12
- GROQ_API_KEY = os.getenv('GROQ_API_KEY')
13
 
14
  class CodeAssistantBot:
15
  def __init__(self):
@@ -19,7 +19,7 @@ class CodeAssistantBot:
19
  ("system",
20
  "You are a skilled coding assistant. Use the following context and user input to help."
21
  " Refer to previous summary and recent interactions to make answers accurate."
22
- " Keep your response short, relevant, and conversational β€” smaller is better if it covers what's needed."),
23
  ("user",
24
  "Code: {code}\nOutput: {output}\nError: {error}\n"
25
  "Summary: {summary}\nRecent: {recent}\nQuestion: {question}")
@@ -28,32 +28,46 @@ class CodeAssistantBot:
28
  ("system", "Summarize key technical points from the conversation so far."),
29
  ("user", "Conversation: {conversation}")
30
  ])
 
 
 
 
 
 
 
 
 
31
 
32
  def analyze_code(self, code, output, error, question, summary="", history=None):
33
- try:
34
- parser = StrOutputParser()
35
- recent = "\n".join([f"User: {q}\nBot: {a}" for q, a in (history or [])[-4:]])
36
- chain = self.analysis_prompt | self.model | parser
37
- return chain.invoke({
38
- 'code': code,
39
- 'output': output,
40
- 'error': error,
41
- 'summary': summary,
42
- 'recent': recent,
43
- 'question': question
44
- })
45
- except Exception as e:
46
- return f"Error: {e}"
 
 
 
 
 
 
 
 
47
 
48
  async def text_to_speech(text, filename):
49
- voice = "en-US-AriaNeural"
50
  communicate = edge_tts.Communicate(text, voice)
51
  await communicate.save(filename)
52
 
53
  def render_chatbot(code, output, error):
54
- """Render the chatbot UI with code-block support and a scrollable chat container."""
55
-
56
- # CSS Styling
57
  st.markdown("""
58
  <style>
59
  .chat-container {
@@ -83,51 +97,43 @@ def render_chatbot(code, output, error):
83
  </style>
84
  """, unsafe_allow_html=True)
85
 
86
- # Session state
87
  st.session_state.setdefault('conversation', [])
88
  st.session_state.setdefault('chat_summary', "")
89
  st.session_state.setdefault('chat_display_count', 5)
90
 
91
- # Chat input
92
  c1, c2 = st.columns([4, 1], gap='small')
93
  with c1:
94
  question = st.text_input("Ask something about your code...", key="chat_input")
95
  with c2:
96
  send = st.button("πŸš€")
97
 
98
- # Process question
99
  if send and question:
100
  bot = CodeAssistantBot()
101
  history = st.session_state.conversation[-4:]
102
  summary = st.session_state.chat_summary
103
-
104
  response = bot.analyze_code(code, output, error, question, summary, history)
105
-
106
  st.session_state.conversation.append((question, response))
107
  st.session_state.chat_display_count = 5
108
-
109
  if len(st.session_state.conversation) >= 3:
110
  try:
111
  full_chat = "\n".join([f"User: {q}\nBot: {a}" for q, a in st.session_state.conversation[-10:]])
112
- parser = StrOutputParser()
113
- summarizer = bot.summary_prompt | bot.model | parser
114
  st.session_state.chat_summary = summarizer.invoke({'conversation': full_chat})
115
  except:
116
  pass
117
 
118
- # Display conversation
119
- total_messages = len(st.session_state.conversation)
120
- start_idx = max(0, total_messages - st.session_state.chat_display_count)
121
- visible_conversation = st.session_state.conversation[start_idx:]
122
 
123
- for i, (q, a) in enumerate(reversed(visible_conversation)):
124
  st.markdown(f'<div class="chat-message user-message">{escape(q)}</div>', unsafe_allow_html=True)
125
 
126
- def format_response(text):
127
- parts = text.split('```')
128
  result = ''
129
- for i, part in enumerate(parts):
130
- if i % 2 == 1:
131
  lines = part.splitlines()
132
  if lines and lines[0].isalpha():
133
  lines = lines[1:]
@@ -140,18 +146,19 @@ def render_chatbot(code, output, error):
140
  formatted = format_response(a)
141
  st.markdown(f'<div class="chat-message bot-message">{formatted}</div>', unsafe_allow_html=True)
142
 
143
- # πŸ”Š Speak Answer Button
144
- audio_filename = f"audio_response_{uuid.uuid4().hex}.mp3"
145
- if st.button(f"πŸ”Š Speak Answer #{i+1}"):
146
- asyncio.run(text_to_speech(a, audio_filename))
147
- st.audio(audio_filename)
 
 
 
148
 
149
- if start_idx > 0:
150
- if st.button("πŸ”½ Show more"):
151
- st.session_state.chat_display_count += 5
152
- st.rerun()
153
 
154
- # Auto-scroll (optional)
155
  st.markdown("""
156
  <script>
157
  const c = window.parent.document.querySelector('.chat-container');
 
9
  import os
10
  import uuid
11
 
12
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
13
 
14
  class CodeAssistantBot:
15
  def __init__(self):
 
19
  ("system",
20
  "You are a skilled coding assistant. Use the following context and user input to help."
21
  " Refer to previous summary and recent interactions to make answers accurate."
22
+ " Keep your response short, relevant, and conversational."),
23
  ("user",
24
  "Code: {code}\nOutput: {output}\nError: {error}\n"
25
  "Summary: {summary}\nRecent: {recent}\nQuestion: {question}")
 
28
  ("system", "Summarize key technical points from the conversation so far."),
29
  ("user", "Conversation: {conversation}")
30
  ])
31
+ self.voice_prompt = ChatPromptTemplate.from_messages([
32
+ ("system",
33
+ "You are a friendly narrator voice bot. Given a technical answer and its context,"
34
+ " explain it aloud like you're helping someone understand the topic clearly and confidently."
35
+ " Keep it spoken, not codey. Emphasize pauses, clarity, and voice modulation."),
36
+ ("user",
37
+ "Code: {code}\nOutput: {output}\nError: {error}\n"
38
+ "Conversation so far: {summary}\nAnswer to explain: {answer}")
39
+ ])
40
 
41
  def analyze_code(self, code, output, error, question, summary="", history=None):
42
+ parser = StrOutputParser()
43
+ recent = "\n".join([f"User: {q}\nBot: {a}" for q, a in (history or [])[-4:]])
44
+ chain = self.analysis_prompt | self.model | parser
45
+ return chain.invoke({
46
+ 'code': code,
47
+ 'output': output,
48
+ 'error': error,
49
+ 'summary': summary,
50
+ 'recent': recent,
51
+ 'question': question
52
+ })
53
+
54
+ def narrate_response(self, code, output, error, answer, summary=""):
55
+ parser = StrOutputParser()
56
+ narration_chain = self.voice_prompt | self.model | parser
57
+ return narration_chain.invoke({
58
+ 'code': code,
59
+ 'output': output,
60
+ 'error': error,
61
+ 'summary': summary,
62
+ 'answer': answer
63
+ })
64
 
65
  async def text_to_speech(text, filename):
66
+ voice = "fr-FR-VivienneMultilingualNeural"
67
  communicate = edge_tts.Communicate(text, voice)
68
  await communicate.save(filename)
69
 
70
  def render_chatbot(code, output, error):
 
 
 
71
  st.markdown("""
72
  <style>
73
  .chat-container {
 
97
  </style>
98
  """, unsafe_allow_html=True)
99
 
 
100
  st.session_state.setdefault('conversation', [])
101
  st.session_state.setdefault('chat_summary', "")
102
  st.session_state.setdefault('chat_display_count', 5)
103
 
 
104
  c1, c2 = st.columns([4, 1], gap='small')
105
  with c1:
106
  question = st.text_input("Ask something about your code...", key="chat_input")
107
  with c2:
108
  send = st.button("πŸš€")
109
 
 
110
  if send and question:
111
  bot = CodeAssistantBot()
112
  history = st.session_state.conversation[-4:]
113
  summary = st.session_state.chat_summary
 
114
  response = bot.analyze_code(code, output, error, question, summary, history)
 
115
  st.session_state.conversation.append((question, response))
116
  st.session_state.chat_display_count = 5
 
117
  if len(st.session_state.conversation) >= 3:
118
  try:
119
  full_chat = "\n".join([f"User: {q}\nBot: {a}" for q, a in st.session_state.conversation[-10:]])
120
+ summarizer = bot.summary_prompt | bot.model | StrOutputParser()
 
121
  st.session_state.chat_summary = summarizer.invoke({'conversation': full_chat})
122
  except:
123
  pass
124
 
125
+ total = len(st.session_state.conversation)
126
+ start = max(0, total - st.session_state.chat_display_count)
127
+ visible = st.session_state.conversation[start:]
 
128
 
129
+ for i, (q, a) in enumerate(reversed(visible)):
130
  st.markdown(f'<div class="chat-message user-message">{escape(q)}</div>', unsafe_allow_html=True)
131
 
132
+ def format_response(txt):
133
+ parts = txt.split('```')
134
  result = ''
135
+ for j, part in enumerate(parts):
136
+ if j % 2 == 1:
137
  lines = part.splitlines()
138
  if lines and lines[0].isalpha():
139
  lines = lines[1:]
 
146
  formatted = format_response(a)
147
  st.markdown(f'<div class="chat-message bot-message">{formatted}</div>', unsafe_allow_html=True)
148
 
149
+ # πŸ”Š Speak
150
+ speak_btn = st.button(f"πŸ”Š Narrate #{i+1}")
151
+ if speak_btn:
152
+ bot = CodeAssistantBot()
153
+ narration = bot.narrate_response(code, output, error, a, st.session_state.chat_summary)
154
+ audio_filename = f"audio_{uuid.uuid4().hex}.mp3"
155
+ asyncio.run(text_to_speech(narration, audio_filename))
156
+ st.audio(audio_filename, format="audio/mp3", autoplay=True)
157
 
158
+ if start > 0 and st.button("πŸ”½ Show more"):
159
+ st.session_state.chat_display_count += 5
160
+ st.rerun()
 
161
 
 
162
  st.markdown("""
163
  <script>
164
  const c = window.parent.document.querySelector('.chat-container');