sohojoe commited on
Commit
87dcd10
1 Parent(s): 5ea3bc3

feature: agent response to help with debugging

Browse files
agent_response.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ class AgentResponse(dict):
4
+ def __init__(self, prompt=None, **kwargs):
5
+ super().__init__(**kwargs)
6
+ if prompt is not None:
7
+ self['prompt'] = prompt
8
+ self['llm_preview'] = ''
9
+ self['llm_sentence'] = ''
10
+ self['llm_sentence_id'] = 0
11
+ self['llm_sentences'] = []
12
+ self['tts_raw_chunk'] = None
13
+ self['tts_raw_chunk_id'] = 0
14
+
15
+ def make_copy(self):
16
+ new_instance = self.__class__.__new__(self.__class__)
17
+ new_instance.update(self.copy())
18
+ return new_instance
19
+
20
+ def to_json(self):
21
+ return json.dumps(self)
chat_service.py CHANGED
@@ -4,6 +4,7 @@ import json
4
  import os
5
  import torch
6
  import openai
 
7
 
8
  class ChatService:
9
  def __init__(self, api="openai", model_id = "gpt-3.5-turbo"):
@@ -101,9 +102,9 @@ I fell off the pink step, and I had an accident.
101
  return True
102
  return False
103
 
104
- async def get_responses_as_sentances_async(self, prompt, cancel_event):
105
- self._messages.append({"role": "user", "content": prompt})
106
- agent_response = ""
107
  current_sentence = ""
108
  delay = 0.1
109
 
@@ -123,17 +124,23 @@ I fell off the pink step, and I had an accident.
123
  if 'content' in chunk_message:
124
  chunk_text = chunk_message['content']
125
  current_sentence += chunk_text
126
- agent_response += chunk_text
 
127
  text_to_speak = self._should_we_send_to_voice(current_sentence)
128
  if text_to_speak:
129
- yield text_to_speak
130
  current_sentence = current_sentence[len(text_to_speak):]
 
 
 
 
 
131
 
132
  if cancel_event.is_set():
133
  return
134
  if len(current_sentence) > 0:
135
- yield current_sentence
136
- self._messages.append({"role": "assistant", "content": agent_response})
 
137
  return
138
 
139
  except openai.error.APIError as e:
 
4
  import os
5
  import torch
6
  import openai
7
+ from agent_response import AgentResponse
8
 
9
  class ChatService:
10
  def __init__(self, api="openai", model_id = "gpt-3.5-turbo"):
 
102
  return True
103
  return False
104
 
105
+ async def get_responses_as_sentances_async(self, agent_response:AgentResponse, cancel_event):
106
+ self._messages.append({"role": "user", "content": agent_response['prompt']})
107
+ llm_response = ""
108
  current_sentence = ""
109
  delay = 0.1
110
 
 
124
  if 'content' in chunk_message:
125
  chunk_text = chunk_message['content']
126
  current_sentence += chunk_text
127
+ llm_response += chunk_text
128
+ agent_response['llm_preview'] = current_sentence
129
  text_to_speak = self._should_we_send_to_voice(current_sentence)
130
  if text_to_speak:
 
131
  current_sentence = current_sentence[len(text_to_speak):]
132
+ agent_response['llm_preview'] = ''
133
+ agent_response['llm_sentence'] = text_to_speak
134
+ agent_response['llm_sentences'].append(text_to_speak)
135
+ yield agent_response
136
+ agent_response['llm_sentence_id'] += 1
137
 
138
  if cancel_event.is_set():
139
  return
140
  if len(current_sentence) > 0:
141
+ agent_response['llm_sentence'] = current_sentence
142
+ yield agent_response
143
+ self._messages.append({"role": "assistant", "content": llm_response})
144
  return
145
 
146
  except openai.error.APIError as e:
respond_to_prompt_actor.py CHANGED
@@ -7,6 +7,8 @@ from chat_service import ChatService
7
  import asyncio
8
  # from ray.actor import ActorHandle
9
  from ffmpeg_converter_actor import FFMpegConverterActor
 
 
10
 
11
  @ray.remote
12
  class PromptToLLMActor:
@@ -21,11 +23,13 @@ class PromptToLLMActor:
21
  while True:
22
  prompt = await self.input_queue.get_async()
23
  self.cancel_event = asyncio.Event()
24
- async for sentence in self.chat_service.get_responses_as_sentances_async(prompt, self.cancel_event):
25
- if self.chat_service.ignore_sentence(sentence):
 
26
  continue
27
- print(f"{sentence}")
28
- await self.output_queue.put_async(sentence)
 
29
 
30
  async def cancel(self):
31
  if self.cancel_event:
@@ -46,10 +50,11 @@ class LLMSentanceToSpeechActor:
46
 
47
  async def run(self):
48
  while True:
49
- sentance = await self.input_queue.get_async()
50
  self.cancel_event = asyncio.Event()
51
- async for chunk in self.tts_service.get_speech_chunks_async(sentance, self.cancel_event):
52
- await self.output_queue.put_async(chunk)
 
53
 
54
  async def cancel(self):
55
  if self.cancel_event:
@@ -89,8 +94,8 @@ class SpeechToConverterActor:
89
  await self.ffmpeg_converter_actor.start_process.remote()
90
  self.ffmpeg_converter_actor.run.remote()
91
  while True:
92
- audio_chunk = await self.input_queue.get_async()
93
- # print (f"Got audio chunk {len(audio_chunk)}")
94
  await self.ffmpeg_converter_actor.push_chunk.remote(audio_chunk)
95
 
96
  async def cancel(self):
 
7
  import asyncio
8
  # from ray.actor import ActorHandle
9
  from ffmpeg_converter_actor import FFMpegConverterActor
10
+ from agent_response import AgentResponse
11
+
12
 
13
  @ray.remote
14
  class PromptToLLMActor:
 
23
  while True:
24
  prompt = await self.input_queue.get_async()
25
  self.cancel_event = asyncio.Event()
26
+ agent_response = AgentResponse(prompt)
27
+ async for sentence_response in self.chat_service.get_responses_as_sentances_async(agent_response, self.cancel_event):
28
+ if self.chat_service.ignore_sentence(sentence_response['llm_sentence']):
29
  continue
30
+ print(f"{sentence_response['llm_sentence']} id: {agent_response['llm_sentence_id']} from prompt: {agent_response['prompt']}")
31
+ sentence_response = sentence_response.make_copy()
32
+ await self.output_queue.put_async(sentence_response)
33
 
34
  async def cancel(self):
35
  if self.cancel_event:
 
50
 
51
  async def run(self):
52
  while True:
53
+ sentence_response = await self.input_queue.get_async()
54
  self.cancel_event = asyncio.Event()
55
+ async for chunk_response in self.tts_service.get_speech_chunks_async(sentence_response, self.cancel_event):
56
+ chunk_response = chunk_response.make_copy()
57
+ await self.output_queue.put_async(chunk_response)
58
 
59
  async def cancel(self):
60
  if self.cancel_event:
 
94
  await self.ffmpeg_converter_actor.start_process.remote()
95
  self.ffmpeg_converter_actor.run.remote()
96
  while True:
97
+ chunk_response = await self.input_queue.get_async()
98
+ audio_chunk = chunk_response['tts_raw_chunk']
99
  await self.ffmpeg_converter_actor.push_chunk.remote(audio_chunk)
100
 
101
  async def cancel(self):
text_to_speech_service.py CHANGED
@@ -4,6 +4,7 @@ import os
4
  from elevenlabs import generate, play
5
  from elevenlabs import set_api_key
6
  from elevenlabs import generate, stream
 
7
 
8
 
9
  class TextToSpeechService:
@@ -46,7 +47,8 @@ class TextToSpeechService:
46
  )
47
  return audio_stream
48
 
49
- async def get_speech_chunks_async(self, text_to_speak, cancel_event):
 
50
  stream = self.stream(text_to_speak)
51
  stream, stream_backup = itertools.tee(stream)
52
  while True:
@@ -58,6 +60,8 @@ class TextToSpeechService:
58
 
59
  # Run next(stream) in a separate thread to avoid blocking the event loop
60
  chunk = await asyncio.to_thread(next, stream)
 
61
  if cancel_event.is_set():
62
  return
63
- yield chunk
 
 
4
  from elevenlabs import generate, play
5
  from elevenlabs import set_api_key
6
  from elevenlabs import generate, stream
7
+ from agent_response import AgentResponse
8
 
9
 
10
  class TextToSpeechService:
 
47
  )
48
  return audio_stream
49
 
50
+ async def get_speech_chunks_async(self, sentence_response:AgentResponse, cancel_event):
51
+ text_to_speak = sentence_response['llm_sentence']
52
  stream = self.stream(text_to_speak)
53
  stream, stream_backup = itertools.tee(stream)
54
  while True:
 
60
 
61
  # Run next(stream) in a separate thread to avoid blocking the event loop
62
  chunk = await asyncio.to_thread(next, stream)
63
+ sentence_response['tts_raw_chunk'] = chunk
64
  if cancel_event.is_set():
65
  return
66
+ yield sentence_response
67
+ sentence_response['tts_raw_chunk_id'] += 1