willsh1997 commited on
Commit
72e17aa
·
1 Parent(s): 819f473

:sparkles: init commit

Browse files
Files changed (3) hide show
  1. groq-voicechat-demo.py +165 -0
  2. kokoro_support.py +31 -0
  3. whisper_support.py +25 -0
groq-voicechat-demo.py ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from groq import Groq
3
+ import os
4
+ from whisper_support import transcribe
5
+ from kokoro_support import generate_tts
6
+
7
+ groq_api_key = os.environ.get("GROQ_API_KEY")
8
+
9
+ client = Groq(api_key = groq_api_key)
10
+
11
+ model_list =[
12
+ 'openai/gpt-oss-120b',
13
+ 'moonshotai/kimi-k2-instruct',
14
+ 'meta-llama/llama-4-scout-17b-16e-instruct',
15
+ 'openai/gpt-oss-20b',
16
+ 'qwen/qwen3-32b',
17
+ 'llama-3.3-70b-versatile',
18
+ 'moonshotai/kimi-k2-instruct-0905',
19
+ 'allam-2-7b',
20
+ 'meta-llama/llama-4-maverick-17b-128e-instruct',
21
+ 'llama-3.1-8b-instant',
22
+ ]
23
+
24
+ reasoning_models = [
25
+ 'openai/gpt-oss-120b',
26
+ 'openai/gpt-oss-20b',
27
+ 'qwen/qwen3-32b',
28
+ ]
29
+
30
+ default_sys_prompt = """You are a helpful chatbot. You help the end user to the best of your ability."""
31
+ chat_history = []
32
+
33
+ def groq_voicechat(new_message: tuple, chat_history: list[dict], model: str, system_prompt: str, ):
34
+ '''
35
+ Groq chat API call wrapper.
36
+
37
+ inputs:
38
+ - model [str]: model from model_list (cbf static typing from the list)
39
+ - chat_history [list[dict]]: list of dictionaries of chat hist, needs "role" and "content" vars as strings
40
+ - new_message [tuple]: new user input message (assuming we're only accepting user inputs) from voice recording, to be transcribed.
41
+ - system prompt [str]: optional system prompt for whatever chat you're using
42
+
43
+ outputs:
44
+ - "" - used to delete old input msg in chat textbox lol
45
+ - nonsys_msg_hist [list[dict]]: updated chat history
46
+ '''
47
+ if model not in model_list:
48
+ raise ValueError(f"model must be in model_list: {model_list}")
49
+ return
50
+
51
+ #augment chat hist
52
+
53
+ nonsys_msg_hist = [{key: x[key] for key in ["role", "content"] if key in x} for x in chat_history] #clean the chatbot bullshit out
54
+ print(nonsys_msg_hist)
55
+
56
+ text_input = transcribe(new_message)
57
+ if transcription:
58
+ if transcription.startswith("Error"):
59
+ transcription = "Error in audio transcription."
60
+ return "error lol idk make this better later"
61
+ nonsys_msg_hist.extend(
62
+ [
63
+ {
64
+ "role": "user",
65
+ "content": text_input,
66
+ }
67
+ ]
68
+ )
69
+
70
+ # use sys prompt
71
+ input_msg_hist = [
72
+ {
73
+ "role": "system",
74
+ "content": system_prompt,
75
+ }
76
+ ]
77
+
78
+ input_msg_hist.extend(nonsys_msg_hist)
79
+
80
+ if model in reasoning_models:
81
+ chat_completion = client.chat.completions.create(
82
+ messages = input_msg_hist,
83
+ model = model,
84
+ include_reasoning = False, #removes reasoning tokens from output because I'm lazy
85
+ )
86
+ else:
87
+ chat_completion = client.chat.completions.create(
88
+ messages = input_msg_hist,
89
+ model = model,
90
+ # include_reasoning = False, #removes reasoning tokens from output because I'm lazy
91
+ )
92
+ output_msg = chat_completion.choices[0].message.content
93
+
94
+ # add to chat hist
95
+ nonsys_msg_hist.extend(
96
+ [
97
+ {
98
+ "role": "assistant",
99
+ "content": output_msg
100
+ }
101
+ ]
102
+ )
103
+ return nonsys_msg_hist
104
+
105
+
106
+ def create_demo():
107
+ with gr.Blocks() as demo:
108
+ with gr.Row():
109
+ model = gr.Dropdown(model_list,
110
+ )
111
+ with gr.Row():
112
+ system_prompt = gr.Textbox(
113
+ value=default_sys_prompt,
114
+ interactive=True
115
+ )
116
+ with gr.Row():
117
+ chatbot = gr.Chatbot(label="Conversation", type="messages")
118
+ with gr.Row():
119
+ voiceinput = gr.Audio(
120
+ label="Input Audio",
121
+ sources=["microphone"],
122
+ type="numpy",
123
+ streaming=False,
124
+ )
125
+ with gr.Row():
126
+ clear = gr.ClearButton([voiceinput, chatbot], variant = 'stop')
127
+
128
+ with gr.Row():
129
+ playback_button = gr.Button("playback last message")
130
+ with gr.Row():
131
+ audio_out = gr.Audio(
132
+ label = "Output Audio",
133
+ interactive = False,
134
+ autoplay = True
135
+ )
136
+
137
+ voiceinput.stop_recording(
138
+ groq_voicechat,
139
+ [voiceinput, chatbot, model, system_prompt, ],
140
+ [chatbot]
141
+ ) #WHAT AM I DOING LOL - COME BACK TO THIS
142
+
143
+ def playback_last_message(chat_history):
144
+ if len(chat_history) > 0:
145
+ last_message = chat_history[-1]['content']
146
+ return generate_tts(last_message)
147
+ return None
148
+
149
+ playback_button.click(
150
+ playback_last_message,
151
+ inputs=[chatbot],
152
+ outputs=[audio_out]
153
+ )
154
+
155
+ return demo
156
+
157
+ if __name__ == "__main__":
158
+ demo = create_demo()
159
+ demo.launch(
160
+ auth=("DigitalChild", "IhateBroccoli123"),
161
+ ssr_mode=False,
162
+ share=True,
163
+ )
164
+
165
+
kokoro_support.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import spaces
2
+ from kokoro import KModel, KPipeline
3
+ import os
4
+ import random
5
+ import torch
6
+ import numpy as np
7
+ import kokoro
8
+ import misaki
9
+
10
+
11
+ model = KModel().to('cpu').eval()
12
+ pipeline = KPipeline(lang_code='a', model=False)
13
+
14
+ def generate_tts(text, voice='af_heart', speed=1):
15
+ pack = pipeline.load_voice(voice)
16
+ audio_chunks = []
17
+ for _, ps, _ in pipeline(text, voice, speed):
18
+ ref_s = pack[len(ps)-1]
19
+ try:
20
+ audio = model(ps, ref_s, speed)
21
+ audio_chunks.append(audio.numpy())
22
+ except:
23
+ print("lol there was an issue idk")
24
+ # yield 24000, audio.numpy()
25
+ if audio_chunks:
26
+ concatenated_audio = np.concatenate(audio_chunks)
27
+ print(concatenated_audio.shape)
28
+ return 24000, concatenated_audio
29
+ else:
30
+ return 24000, np.array([])
31
+
whisper_support.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from faster_whisper import WhisperModel
2
+ import numpy as np
3
+ import scipy.signal
4
+
5
+ model_size = "base.en"
6
+
7
+ model = WhisperModel(model_size, device="cpu", compute_type="float32")
8
+
9
+ def process_audio(audio_file):
10
+ sample_rate, audio_data = audio_file
11
+
12
+ if audio_data.ndim > 1 and audio_data.shape[1] > 1:
13
+ # Mix stereo channels by averaging them
14
+ audio_data = np.mean(audio_data, axis=1)
15
+
16
+ #normalise audio data
17
+ np_audio_float32 = audio_data.astype(np.float32) / 32768.0
18
+
19
+ np_audio_16k = scipy.signal.resample(np_audio_float32, int(len(np_audio_float32) * 16000 / sample_rate))
20
+ return np_audio_16k
21
+
22
+ def transcribe(audio):
23
+ segments, info = model.transcribe(process_audio(audio), beam_size=5, language='en')
24
+ text = "".join([segment.text for segment in segments])
25
+ return text