feat: real-time reasoning speech, dynamic voice tags, and unified web UI bubbles
This commit is contained in:
@@ -80,7 +80,8 @@ 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, shell execution) whenever the user asks about files, commands, CLI tools (such as Paseo), 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).
|
||||
- You can dynamically change your spoken voice mid-response! Use markdown tags like `[Voice:af_bella]` or `[Voice:am_michael]` inline to switch voices (e.g. `[Voice:af_bella] Hello from Bella! [Voice:am_michael] And hello from Michael!`). The active voice will persist until you change it again.
|
||||
- You can change your default voice! If the user asks to list available voices or switch voice permanently, 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).
|
||||
- You can change your AI model on the fly! If the user asks to list available models or change model, run `python bin/model_tool.py list` or `python bin/model_tool.py set <model_name>` (models: luna, gemma, deepseek, gpt-oss, sonnet, etc.).
|
||||
- You can reset or start a fresh conversation session! If the user asks to start a fresh session, reset the conversation, or clear session context, run `python bin/session_tool.py reset`.
|
||||
- You can switch Hermes agent profiles! If the user asks to list Hermes profiles or switch profile, run `python bin/profile_tool.py list` or `python bin/profile_tool.py set <profile_name>`.
|
||||
@@ -287,6 +288,18 @@ def parse_args() -> argparse.Namespace:
|
||||
action="store_true",
|
||||
help="Disable the Companion Web Chat UI server.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dual-engine",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Enable dual-engine mode: instant macOS foundation model (<400ms) + deep Hermes reasoning.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-dual-engine",
|
||||
action="store_false",
|
||||
dest="dual_engine",
|
||||
help="Disable dual-engine mode and run single engine directly.",
|
||||
)
|
||||
parser.add_argument("--log-level", default="INFO")
|
||||
return parser.parse_args()
|
||||
|
||||
@@ -520,17 +533,28 @@ def build_llm(
|
||||
model = (model_manager.load_saved_model() if model_manager else None) or getattr(args, "hermes_model", "hermes-3")
|
||||
if args.llm_engine in ("hermes", "ollama"):
|
||||
from hermes_llm import HermesLLM, probe_hermes
|
||||
from dual_engine import DualEngineProcessor
|
||||
|
||||
available, reason = probe_hermes(model)
|
||||
logger.info(f"LLM: Hermes ({reason})")
|
||||
# Hermes handles persona, personality, and memory natively.
|
||||
return HermesLLM(
|
||||
|
||||
deep_llm = HermesLLM(
|
||||
model=model,
|
||||
cwd=args.cwd,
|
||||
session_name="Voice Agent",
|
||||
observer=observer,
|
||||
)
|
||||
|
||||
if getattr(args, "dual_engine", False):
|
||||
from apple_llm import MacOSLLM, probe_apple_llm
|
||||
fast_available, fast_reason = probe_apple_llm()
|
||||
if fast_available:
|
||||
logger.info(f"Dual-Engine: Pairing Hermes with fast macOS Foundation Model ({fast_reason})")
|
||||
fast_llm = MacOSLLM(model=args.mlx_model, system_prompt="You are a fast voice assistant.")
|
||||
return DualEngineProcessor(fast_llm=fast_llm, deep_llm=deep_llm, observer=observer)
|
||||
|
||||
return deep_llm
|
||||
|
||||
if args.llm_engine in ("apple", "macos"):
|
||||
from apple_llm import MacOSLLM, probe_apple_llm
|
||||
|
||||
|
||||
Reference in New Issue
Block a user