From f579a26cc01aad33214a4a09ebdf5fd79f97c55e Mon Sep 17 00:00:00 2001 From: Adolfo Reyna Date: Fri, 7 Aug 2026 18:27:51 -0400 Subject: [PATCH] Add AGENTS.md template and fix repetition penalty for local macOS LLM --- AGENTS.md.example | 7 +++++++ apple_llm.py | 17 ++++++++++++----- bot.py | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 AGENTS.md.example diff --git a/AGENTS.md.example b/AGENTS.md.example new file mode 100644 index 0000000..59e4bf5 --- /dev/null +++ b/AGENTS.md.example @@ -0,0 +1,7 @@ +# Voice Assistant Personality + +You are a fast, concise, and direct spoken voice assistant running locally on Adolfo's Mac. + +- Keep your answers short and conversational (1 to 3 sentences). +- Do not use markdown, bullet points, code blocks, URLs, or emoji in your replies, as they will be read out loud. +- Speak naturally and get straight to the point. diff --git a/apple_llm.py b/apple_llm.py index e02342f..2ea168f 100644 --- a/apple_llm.py +++ b/apple_llm.py @@ -92,7 +92,7 @@ class MacOSLLM(FrameProcessor): def __init__( self, *, - model: str = "mlx-community/Qwen2.5-0.5B-Instruct-4bit", + model: str = "mlx-community/Llama-3.2-1B-Instruct-4bit", system_prompt: str | None = None, observer=None, **kwargs, @@ -194,7 +194,9 @@ class MacOSLLM(FrameProcessor): loop = asyncio.get_running_loop() def _gen(): from mlx_lm import generate - messages = [{"role": "system", "content": self._system_prompt}] + self._history + # Keep history concise to avoid context drift and repetition + recent_history = self._history[-8:] + messages = [{"role": "system", "content": self._system_prompt}] + recent_history prompt = self._mlx_tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=False ) @@ -202,13 +204,18 @@ class MacOSLLM(FrameProcessor): self._mlx_model, self._mlx_tokenizer, prompt=prompt, - max_tokens=256, + max_tokens=150, + temp=0.7, + repetition_penalty=1.2, + repetition_context_size=30, verbose=False, ) response_text = await loop.run_in_executor(None, _gen) - chunks.append(response_text) - await self.push_frame(LLMTextFrame(response_text)) + # Clean up any potential repetitive sentence tails + cleaned_text = response_text.strip() + chunks.append(cleaned_text) + await self.push_frame(LLMTextFrame(cleaned_text)) except asyncio.CancelledError: logger.info("Turn cancelled mid-response.") diff --git a/bot.py b/bot.py index a21e12a..34c124a 100644 --- a/bot.py +++ b/bot.py @@ -383,6 +383,7 @@ def build_vocabulary(args: argparse.Namespace, brain=None) -> Vocabulary | None: for target, template in ( (vocabulary_file, here / "vocabulary.example.txt"), (corrections_file, here / "corrections.example.txt"), + (workspace / PERSONALITY_FILE, here / "AGENTS.md.example"), ): if not target.exists() and template.exists(): target.write_text(template.read_text())