Add voice management tool bin/voice_tool.py and dynamic voice switching system
This commit is contained in:
@@ -18,6 +18,7 @@ from claude_agent_sdk import ClaudeAgentOptions, SandboxSettings
|
||||
from loguru import logger
|
||||
|
||||
from brain import Brain
|
||||
from voice_manager import VoiceManager
|
||||
from claude_llm import ClaudeCodeLLM
|
||||
from echo_guard import EchoGuardUserMuteStrategy
|
||||
from pipecat.audio.vad.silero import SileroVADAnalyzer
|
||||
@@ -70,6 +71,7 @@ say them:
|
||||
- Spell out things that only make sense visually. Say "line forty-two of
|
||||
bot dot py" rather than pasting a path.
|
||||
- Use your available tools (listing directories, searching, reading files) whenever the user asks about files or workspace tasks.
|
||||
- You can change your own voice! If the user asks to list available voices or switch voice, run `python bin/voice_tool.py list` or `python bin/voice_tool.py set <voice_name>` (voices: af_heart, af_bella, am_michael, am_fenrir, am_puck, bf_emma, bm_george, Moira, Daniel).
|
||||
- Complete multi-step tool calls fully before speaking your response. Do not stop halfway to ask if you should continue.
|
||||
- Be strictly truthful about your findings and never invent fake file contents.
|
||||
- The user's words reach you through speech recognition, so expect occasional
|
||||
@@ -326,7 +328,7 @@ def build_stt(args: argparse.Namespace, vocabulary):
|
||||
return WhisperSTTService(settings=WhisperSTTService.Settings(model=model, language=Language.EN))
|
||||
|
||||
|
||||
def build_tts(args: argparse.Namespace):
|
||||
def build_tts(args: argparse.Namespace, voice_manager=None):
|
||||
if args.tts == "apple":
|
||||
from apple_tts import AppleTTSService, find_voice
|
||||
|
||||
@@ -339,12 +341,15 @@ def build_tts(args: argparse.Namespace):
|
||||
|
||||
if args.voice_rate:
|
||||
logger.warning("--voice-rate only applies to --tts apple; ignoring it.")
|
||||
voice = args.voice or "af_heart"
|
||||
voice = (voice_manager.load_saved_voice() if voice_manager else None) or args.voice or "af_heart"
|
||||
logger.info(f"Text to speech: Kokoro {voice}")
|
||||
return KokoroTTSService(
|
||||
tts = KokoroTTSService(
|
||||
settings=KokoroTTSService.Settings(voice=voice, language=Language.EN),
|
||||
text_filters=[SpokenTextFilter()],
|
||||
)
|
||||
if voice_manager:
|
||||
voice_manager.set_tts_processor(tts)
|
||||
return tts
|
||||
|
||||
|
||||
def build_turn_taking(args: argparse.Namespace):
|
||||
@@ -580,9 +585,9 @@ async def main() -> int:
|
||||
if vocabulary:
|
||||
vocabulary.observe(text)
|
||||
|
||||
voice_manager = VoiceManager(workspace)
|
||||
llm = build_llm(args, vocabulary, brain, observer=on_reply)
|
||||
|
||||
tts = build_tts(args)
|
||||
tts = build_tts(args, voice_manager=voice_manager)
|
||||
|
||||
# Claude keeps its own history; this context exists so Pipecat can decide
|
||||
# when a turn has ended.
|
||||
|
||||
Reference in New Issue
Block a user