feat: integrate JV Voice Profile cloning, Voicebox research, and ensure session voice/markdown prompt nudge
This commit is contained in:
+28
-1
@@ -50,6 +50,17 @@ SESSION_ID_REGEX = re.compile(r"\bsession_id:\s*([^\s]+)", re.IGNORECASE)
|
||||
|
||||
|
||||
|
||||
VOICE_PROMPT_NUDGE = """[System Instruction / Voice & UI Context:
|
||||
You are communicating with the user in a real-time voice conversation over microphone and TTS, while displaying formatted responses in the Companion Web UI.
|
||||
- Keep spoken responses natural, concise, and conversational (1-2 sentences per turn unless details are requested).
|
||||
- Use clean Markdown formatting (bolding, code blocks, bullet points) for readability in the Web UI.
|
||||
- Write text meant to be read aloud using clear, natural phrasing and conversational contractions.
|
||||
- Avoid repetitive filler openers like "Certainly!", "Absolutely!", or "Great question!".
|
||||
- Perform any required tools or file operations silently without narrating step-by-step internal execution.]
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def _strip_ansi(text: str) -> str:
|
||||
if not text:
|
||||
return ""
|
||||
@@ -220,6 +231,8 @@ class HermesLLM(FrameProcessor):
|
||||
# Hermes conversations.
|
||||
self._session_state_file = self._cwd / ".hermes-voice-session.json"
|
||||
|
||||
self._nudge_sent = False
|
||||
|
||||
# Persisted session ID
|
||||
self._session_id: str | None = self._load_session_id()
|
||||
if self._session_id:
|
||||
@@ -230,6 +243,7 @@ class HermesLLM(FrameProcessor):
|
||||
logger.info("Resetting active Hermes session state...")
|
||||
self._session_id = None
|
||||
self._session_renamed = False
|
||||
self._nudge_sent = False
|
||||
self._history.clear()
|
||||
if self._proc:
|
||||
asyncio.create_task(self._stop_persistent_proc())
|
||||
@@ -246,6 +260,7 @@ class HermesLLM(FrameProcessor):
|
||||
logger.info(f"Hermes session state updated from disk: {self._session_id} -> {disk_sid}")
|
||||
self._session_id = disk_sid
|
||||
self._session_renamed = False
|
||||
self._nudge_sent = False
|
||||
self._history.clear()
|
||||
if self._proc:
|
||||
asyncio.create_task(self._stop_persistent_proc())
|
||||
@@ -522,6 +537,11 @@ class HermesLLM(FrameProcessor):
|
||||
if not messages or messages[-1].get("content") != utterance:
|
||||
messages.append({"role": "user", "content": utterance})
|
||||
|
||||
if not self._nudge_sent and messages:
|
||||
messages[0]["content"] = VOICE_PROMPT_NUDGE + messages[0]["content"]
|
||||
self._nudge_sent = True
|
||||
logger.info("Injecting voice & markdown interaction context nudge into Hermes session.")
|
||||
|
||||
payload = {
|
||||
"model": "hermes-agent" if not self._model or self._model.lower() in ("default", "none", "") else self._model,
|
||||
"messages": messages,
|
||||
@@ -675,7 +695,14 @@ class HermesLLM(FrameProcessor):
|
||||
"""Run turn via Hermes CLI using persistent session tracking."""
|
||||
if spoken_chunks is None:
|
||||
spoken_chunks = chunks
|
||||
cmd = [self._cli_path, "chat", "-q", utterance, "-Q", "--source", "voice", "--reasoning", "none"]
|
||||
|
||||
prompt_to_send = utterance
|
||||
if not self._nudge_sent:
|
||||
prompt_to_send = VOICE_PROMPT_NUDGE + utterance
|
||||
self._nudge_sent = True
|
||||
logger.info("Initializing Hermes turn with voice & markdown interaction context nudge.")
|
||||
|
||||
cmd = [self._cli_path, "chat", "-q", prompt_to_send, "-Q", "--source", "voice"]
|
||||
if self._session_id:
|
||||
cmd.extend(["-r", self._session_id])
|
||||
if self._model and self._model.lower() not in ("default", "none", ""):
|
||||
|
||||
Reference in New Issue
Block a user