|
|
@ -6,7 +6,7 @@ Exposes a ws endpoint called /user. Things from there go into the queue. We also
|
|
|
|
In a while loop we watch the queue and handle it.
|
|
|
|
In a while loop we watch the queue and handle it.
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
from starlette.websockets import WebSocketDisconnect
|
|
|
|
import ast
|
|
|
|
import ast
|
|
|
|
import json
|
|
|
|
import json
|
|
|
|
import time
|
|
|
|
import time
|
|
|
@ -21,12 +21,12 @@ from starlette.websockets import WebSocket
|
|
|
|
from create_interpreter import create_interpreter
|
|
|
|
from create_interpreter import create_interpreter
|
|
|
|
from stt import stt
|
|
|
|
from stt import stt
|
|
|
|
from tts import tts
|
|
|
|
from tts import tts
|
|
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
# Create interpreter
|
|
|
|
# Create interpreter
|
|
|
|
interpreter = create_interpreter()
|
|
|
|
interpreter = create_interpreter()
|
|
|
|
|
|
|
|
|
|
|
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
conversation_history_path = Path(__file__).parent / 'conversations' / 'user.json'
|
|
|
|
conversation_history_path = os.path.join(script_dir, 'conversations', 'user.json')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create Queue objects
|
|
|
|
# Create Queue objects
|
|
|
|
to_user = queue.Queue()
|
|
|
|
to_user = queue.Queue()
|
|
|
@ -49,11 +49,16 @@ async def read_computer(item: dict):
|
|
|
|
async def websocket_endpoint(websocket: WebSocket):
|
|
|
|
async def websocket_endpoint(websocket: WebSocket):
|
|
|
|
await websocket.accept()
|
|
|
|
await websocket.accept()
|
|
|
|
while True:
|
|
|
|
while True:
|
|
|
|
|
|
|
|
try:
|
|
|
|
data = await websocket.receive_json()
|
|
|
|
data = await websocket.receive_json()
|
|
|
|
to_assistant.put(data)
|
|
|
|
to_assistant.put(data)
|
|
|
|
while not to_user.empty():
|
|
|
|
while not to_user.empty():
|
|
|
|
message = to_user.get()
|
|
|
|
message = to_user.get()
|
|
|
|
|
|
|
|
print("sending a message!")
|
|
|
|
await websocket.send_json(message)
|
|
|
|
await websocket.send_json(message)
|
|
|
|
|
|
|
|
except WebSocketDisconnect:
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def queue_listener():
|
|
|
|
def queue_listener():
|
|
|
|
audio_file = bytearray()
|
|
|
|
audio_file = bytearray()
|
|
|
@ -89,25 +94,32 @@ def queue_listener():
|
|
|
|
|
|
|
|
|
|
|
|
accumulated_text = ""
|
|
|
|
accumulated_text = ""
|
|
|
|
|
|
|
|
|
|
|
|
for chunk in interpreter.chat(messages):
|
|
|
|
for chunk in interpreter.chat(messages, stream=True):
|
|
|
|
|
|
|
|
|
|
|
|
# Send it to the user
|
|
|
|
# Send it to the user
|
|
|
|
to_user.put(chunk)
|
|
|
|
to_user.put(chunk)
|
|
|
|
|
|
|
|
|
|
|
|
# Speak full sentences out loud
|
|
|
|
# Speak full sentences out loud
|
|
|
|
if chunk["type"] == "assistant":
|
|
|
|
if chunk["role"] == "assistant" and "content" in chunk:
|
|
|
|
|
|
|
|
print("Chunk role is assistant and content is present in chunk.")
|
|
|
|
accumulated_text += chunk["content"]
|
|
|
|
accumulated_text += chunk["content"]
|
|
|
|
|
|
|
|
print("Accumulated text: ", accumulated_text)
|
|
|
|
sentences = split_into_sentences(accumulated_text)
|
|
|
|
sentences = split_into_sentences(accumulated_text)
|
|
|
|
|
|
|
|
print("Sentences after splitting: ", sentences)
|
|
|
|
if is_full_sentence(sentences[-1]):
|
|
|
|
if is_full_sentence(sentences[-1]):
|
|
|
|
|
|
|
|
print("Last sentence is a full sentence.")
|
|
|
|
for sentence in sentences:
|
|
|
|
for sentence in sentences:
|
|
|
|
for audio_chunk in tts(sentence):
|
|
|
|
print("Streaming sentence: ", sentence)
|
|
|
|
to_user.put(audio_chunk)
|
|
|
|
stream_tts_to_user(sentence)
|
|
|
|
accumulated_text = ""
|
|
|
|
accumulated_text = ""
|
|
|
|
|
|
|
|
print("Reset accumulated text.")
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
|
|
|
|
print("Last sentence is not a full sentence.")
|
|
|
|
for sentence in sentences[:-1]:
|
|
|
|
for sentence in sentences[:-1]:
|
|
|
|
for audio_chunk in tts(sentence):
|
|
|
|
print("Streaming sentence: ", sentence)
|
|
|
|
to_user.put(audio_chunk)
|
|
|
|
stream_tts_to_user(sentence)
|
|
|
|
accumulated_text = sentences[-1]
|
|
|
|
accumulated_text = sentences[-1]
|
|
|
|
|
|
|
|
print("Accumulated text is now the last sentence: ", accumulated_text)
|
|
|
|
|
|
|
|
|
|
|
|
# If we have a new message, save our progress and go back to the top
|
|
|
|
# If we have a new message, save our progress and go back to the top
|
|
|
|
if not to_assistant.empty():
|
|
|
|
if not to_assistant.empty():
|
|
|
@ -115,6 +127,12 @@ def queue_listener():
|
|
|
|
json.dump(interpreter.messages, file)
|
|
|
|
json.dump(interpreter.messages, file)
|
|
|
|
break
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def stream_tts_to_user(sentence):
|
|
|
|
|
|
|
|
to_user.put({"role": "assistant", "type": "audio", "format": "audio/mp3", "start": True})
|
|
|
|
|
|
|
|
audio_bytes = tts(sentence)
|
|
|
|
|
|
|
|
to_user.put({"role": "assistant", "type": "audio", "format": "audio/mp3", "content": str(audio_bytes)})
|
|
|
|
|
|
|
|
to_user.put({"role": "assistant", "type": "audio", "format": "audio/mp3", "end": True})
|
|
|
|
|
|
|
|
|
|
|
|
# Create a thread for the queue listener
|
|
|
|
# Create a thread for the queue listener
|
|
|
|
queue_thread = Thread(target=queue_listener)
|
|
|
|
queue_thread = Thread(target=queue_listener)
|
|
|
|
|
|
|
|
|
|
|
|