7 Commits

Author SHA1 Message Date
486acb5c14 Fix reply-context speaker confusion with structured metadata pipeline
Previously, when a user replied to Miku's message via Discord's reply
feature, Miku's quoted words were embedded directly into the user's
message text using the format:
  [Replying to your message: "Miku's words"] User's response

This caused two problems:
1. The LLM had to parse "your message" to determine the quoted text
   was MIKU's words — fragile and frequently misattributed
2. When stored in episodic memory as [User]: ..., Miku's quoted words
   were permanently mislabeled under the user's speaker prefix

Now reply context flows through as structured metadata:
- bot/bot.py captures the replied-to text WITHOUT embedding it in prompt
- cat_client.py passes it as discord_reply_context in the WebSocket payload
- discord_bridge.py injects it as agent_input['reply_context'] — a
  CLEARLY LABELED note: [The user is replying to what you (Miku) said — ...]
- miku_personality.py + evil_miku_personality.py render it via
  {reply_context} placeholder in the prompt suffix, between memory
  context and conversation history

This keeps Miku's words as a separate context note, never mixed into
the user's HumanMessage. Episodic memory only stores the user's actual
words. The fallback path (when Cat is unavailable) also uses a cleaner
format with explicit speaker labels.
2026-06-03 22:50:03 +03:00
9d2c14fa0b Fix vision pipeline: ffmpeg removal by autoremove, increase vision timeout, reduce frame count, add Discord activity awareness
- bot/Dockerfile: Add ffmpeg to reinstall line after apt-get autoremove
  (autoremove was sweeping up ffmpeg as 'no longer needed' after playwright install)
- bot/utils/image_handling.py: Increase video analysis timeout 120s→300s, 6→3 for Tenor GIFs (GTX 1660 VRAM constraint)
- bot/utils/activities.py: Add _activity_changed_at timestamp tracking,
  get_current_activity_label() and get_current_activity_fresh() with 30-min decay
- bot/utils/cat_client.py: Pass current Discord activity to Cheshire Cat pipeline
- bot/utils/llm.py: Inject current Discord activity into system prompt
- cat-plugins/*: Forward Discord activity through working_memory to personality plugins
- bot/persona/*/preamble.txt: Add Discord status usage guidelines for character prompts
- llama-swap-rocm-config.yaml: Add qwen3.5 model entry for ComfyUI prompt generation
- AGENTS.md: New project documentation file
2026-05-27 01:18:12 +03:00
e1f81e52e5 Fix Miku confusing who said what in conversations
Three interrelated fixes for speaker attribution confusion:

1. Fix misleading episodic memory header (discord_bridge.py):
   The Cat core hardcodes '## Context of things the Human said in the past:'
   when formatting recalled conversations. Our plugins store BOTH user messages
   ([User]: prefix) AND Miku's own responses ([Miku]: prefix) in episodic memory.
   This misleading header primes the LLM to attribute Miku's words to the user.
   Replaced with '## Past conversation excerpts (prefixed by who said what):'
   which accurately describes the mixed-speaker content.

2. Tighten episodic recall (discord_bridge.py):
   Added before_cat_recalls_episodic_memories hook setting threshold=0.75
   (vs default 0.7) to reduce the chance of Miku's own just-uttered response
   being recalled on the very next user message, which would feed her own
   words back as misleading context.

3. Add role clarification (miku_personality.py & evil_miku_personality.py):
   Added a clarifying note after '# Conversation until now:' in the prompt
   suffix to explicitly tell the model that 'Human = the user, AI = you (Miku)',
   helping it reconcile the two labeling systems (episodic [User]/[Miku] prefixes
   vs conversation history Human/AI roles).
2026-05-22 16:38:34 +03:00
27f0659cc8 fix: Evil Miku now ignores questions — restore engagement + remove suffix hammer
Preamble:
- Sentence limit 1-3 → 2-4 (revert to original 'sting, then land' range)
- Remove 'if you can say it in one, say it in one' (encouraged lazy dismissals)
- Add engagement rule: 'Always engage with what was said — acknowledge the
  question or statement, then twist the knife. Ignoring isn\'t sharp, it\'s lazy.'

Suffix:
- Remove '[Keep responses short and cutting — 1-3 sentences. No monologues.]'
  The suffix was the LAST thing the model processed, so its brevity hammer
  overpowered the preamble's engagement instruction. Preamble alone is enough.
2026-05-18 11:09:24 +03:00
6b6d705024 fix: Evil Miku wordiness regression from username prompt changes
Five targeted fixes:

1. discord_bridge (priority 100): Skip 'cheerful virtual idol' wrapper and
   'CRITICAL INSTRUCTION' about facts when evil_mode is active. Evil Miku
   gets her own prompt from evil_miku_personality plugin.

2. memory_consolidation (priority 10): Soften fact-usage pressure:
   'Use THESE facts when answering' → 'You may reference these facts if
   relevant to the conversation'. Also soften username command tone.

3. evil_miku_personality (priority 100→101): Bump above discord_bridge
   so Evil Miku's prefix replacement deterministically discards any
   Miku-mode wrappers regardless of plugin load order.

4. evil preamble: Restructure for brevity — add 'Be SHORT and SHARP'
   declaration, move RESPONSE RULES before mood, tighten sentence limit
   from 2-4 to 1-3 with 'if you can say it in one, say it in one.'

5. evil suffix: Add final brevity reminder '[Keep responses short and
   cutting — 1-3 sentences. No monologues.]' right before conversation
   for maximum recency influence.
2026-05-18 10:56:07 +03:00
8b3bc02f9e refactor: DRY system prompts into shared preamble files
Step 4 of memory system overhaul: single source of truth for prompts.

Problem: The system prompt was defined inline in 4 different places:
  miku_personality.py, evil_miku_personality.py, llm.py, discord_bridge.py.
These could drift out of sync — and the discord_bridge WebUI
reconstruction was already missing CRITICAL RULES, CHARACTER CONTEXT,
MOOD GUIDELINES, and RESPONSE RULES sections.

Fix:
- Create persona/miku/preamble.txt — canonical normal Miku preamble
- Create persona/evil/preamble.txt — canonical evil Miku preamble
  (with {mood_name} and {mood_description} format placeholders)
- All 5 consumers now read from these files:
  * miku_personality.py (Cat plugin, primary path)
  * evil_miku_personality.py (Cat plugin, primary path)
  * discord_bridge.py (WebUI 'Last Prompt' reconstruction)
  * llm.py (fallback path, normal Miku)
  * evil_mode.py get_evil_system_prompt() (fallback path, evil Miku)
- All consumers include graceful fallbacks if preamble files are missing
- Fixed evil_mode.py discrepancy: 'body and size' now matches canonical

The preamble files are Docker volume-mounted into both containers:
  bot/persona/ → /app/persona/ (bot, via Dockerfile COPY)
  bot/persona/ → /app/cat/data/ (Cat, via docker-compose volume mount)
Editing the preamble file on the host immediately updates the Cat path
(bot path requires rebuild due to COPY).
2026-05-15 14:43:19 +03:00
9038f442a3 feat(evil-miku): add 10-mood system and Evil Miku Cat plugin
- Add 6 new evil mood files: bored, contemptuous, jealous, manic,
  melancholic, playful_cruel
- Rewrite 4 existing mood files: aggressive, cunning, evil_neutral,
  sarcastic (shorter, more focused descriptions)
- Add evil_miku_personality Cat plugin (parallel to miku_personality)
  with mood-aware system prompt, softened height rule, and balanced
  response length rules (2-4 sentences)
2026-02-27 13:11:37 +02:00