From 8a4266f8c25ff977cc40f541e6d2298b75b8e1ab Mon Sep 17 00:00:00 2001 From: goudacouda Date: Mon, 5 May 2025 15:33:27 -0400 Subject: [PATCH 1/3] feat: Add changes for swappable modes --- code/llm_module.py | 19 +++++- code/server.py | 73 +++++++++++++++++++++-- code/speech_pipeline_manager.py | 100 +++++++++++++++++++++++++++----- code/static/app.js | 89 +++++++++++++++++++++++++++- code/static/index.html | 92 +++++++++++++++++++++++++++++ 5 files changed, 351 insertions(+), 22 deletions(-) diff --git a/code/llm_module.py b/code/llm_module.py index e432abd..05af60c 100644 --- a/code/llm_module.py +++ b/code/llm_module.py @@ -264,6 +264,21 @@ def __init__( self.system_prompt_message = {"role": "system", "content": self.system_prompt} logger.info(f"🤖💬 System prompt set.") + def set_system_prompt(self, new_prompt: Optional[str]): + """ + Updates the system prompt for the LLM instance. + + Args: + new_prompt: The new system prompt text, or None to clear it. + """ + logger.info(f"🤖💬 Updating system prompt.") + self.system_prompt = new_prompt + if self.system_prompt: + self.system_prompt_message = {"role": "system", "content": self.system_prompt} + logger.debug(f" New system prompt message set ({len(self.system_prompt)} chars).") + else: + self.system_prompt_message = None + logger.debug(" System prompt message cleared.") def _lazy_initialize_clients(self) -> bool: """ Initializes backend clients or checks connections on first use (thread-safe). @@ -645,7 +660,7 @@ def generate( added_text = text # for normal text if self.no_think: # This modification logic remains specific for now - added_text = f"{text}/nothink" # for qwen 3 + added_text = f"{text}" # for qwen 3 logger.info(f"🧠💬 llm_module.py generate adding role user to messages, content: {added_text}") messages.append({"role": "user", "content": added_text}) logger.debug(f"🤖💬 [{req_id}] Prepared messages count: {len(messages)}") @@ -1215,7 +1230,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): ollama_llm = LLM( backend="ollama", model=ollama_model_env, - system_prompt="You are concise and helpful." + system_prompt="You are concise and helpful./nothink" ) # Prewarm will now trigger lazy init WITH the ps check fallback restored diff --git a/code/server.py b/code/server.py index 6607dc1..9679b92 100644 --- a/code/server.py +++ b/code/server.py @@ -12,6 +12,7 @@ from colors import Colors import uvicorn import asyncio +from asyncio import Lock # Import Lock specifically import struct import json import time @@ -22,26 +23,28 @@ from typing import Any, Dict, Optional, Callable # Added for type hints in docstrings from contextlib import asynccontextmanager -from fastapi import FastAPI, WebSocket, WebSocketDisconnect +from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Request, HTTPException # Added Request, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles -from starlette.responses import HTMLResponse, Response, FileResponse +from starlette.responses import HTMLResponse, Response, FileResponse, JSONResponse +from pydantic import BaseModel # Added for request body validation USE_SSL = False TTS_START_ENGINE = "orpheus" TTS_START_ENGINE = "kokoro" -TTS_START_ENGINE = "coqui" +#TTS_START_ENGINE = "coqui" TTS_ORPHEUS_MODEL = "Orpheus_3B-1BaseGGUF/mOrpheus_3B-1Base_Q4_K_M.gguf" TTS_ORPHEUS_MODEL = "orpheus-3b-0.1-ft-Q8_0-GGUF/orpheus-3b-0.1-ft-q8_0.gguf" LLM_START_PROVIDER = "ollama" #LLM_START_MODEL = "qwen3:30b-a3b" -LLM_START_MODEL = "hf.co/bartowski/huihui-ai_Mistral-Small-24B-Instruct-2501-abliterated-GGUF:Q4_K_M" +LLM_START_MODEL = "hf.co/mradermacher/Qwen3-30B-A3B-abliterated-i1-GGUF:Q4_K_S" # LLM_START_PROVIDER = "lmstudio" # LLM_START_MODEL = "Qwen3-30B-A3B-GGUF/Qwen3-30B-A3B-Q3_K_L.gguf" -NO_THINK = False +NO_THINK = True DIRECT_STREAM = TTS_START_ENGINE=="orpheus" + if __name__ == "__main__": logger.info(f"🖥️⚙️ {Colors.apply('[PARAM]').blue} Starting engine: {Colors.apply(TTS_START_ENGINE).blue}") logger.info(f"🖥️⚙️ {Colors.apply('[PARAM]').blue} Direct streaming: {Colors.apply('ON' if DIRECT_STREAM else 'OFF').blue}") @@ -115,8 +118,36 @@ async def lifespan(app: FastAPI): app: The FastAPI application instance. """ logger.info("🖥️▶️ Server starting up") + +# --- Dynamic Prompt Mode Loading --- + PROMPT_DIR = "prompts" + DEFAULT_MODE = "conversation" # Define default mode here + prompt_modes = {} + discovered_modes = [] + logger.info(f"🖥️📝 Loading prompts from directory: {PROMPT_DIR}") + + for filename in os.listdir(PROMPT_DIR): + if filename.endswith(".txt"): + mode_name = os.path.splitext(filename)[0] + file_path = os.path.join(PROMPT_DIR, filename) + with open(file_path, "r", encoding="utf-8") as f: + prompt_text = f.read().strip() + if prompt_text: + prompt_modes[mode_name] = prompt_text + discovered_modes.append(mode_name) + logger.info(f" - Loaded '{mode_name}' ({len(prompt_text)} chars) from {file_path}") + else: + logger.warning(f"🖥️⚠️ Skipping empty prompt file: {file_path}") + + + + + + # Initialize global components, not connection-specific state app.state.SpeechPipelineManager = SpeechPipelineManager( + prompt_modes=prompt_modes, + initial_mode=DEFAULT_MODE, tts_engine=TTS_START_ENGINE, llm_provider=LLM_START_PROVIDER, llm_model=LLM_START_MODEL, @@ -178,6 +209,38 @@ async def get_index() -> HTMLResponse: html_content = f.read() return HTMLResponse(content=html_content) + +class ModeUpdateRequest(BaseModel): + mode: str + +@app.get("/get_modes") +async def get_modes(request: Request): + """API endpoint to get available prompt modes and the current mode.""" + app_state = request.app.state + manager = app_state.SpeechPipelineManager + return JSONResponse(content={ + "modes": manager.get_available_modes(), + "current_mode": manager.current_mode # Access the manager's current mode + }) + +@app.post("/set_mode") +async def set_mode(request: ModeUpdateRequest, fastapi_request: Request): + """API endpoint to set the active prompt mode.""" + app_state = fastapi_request.app.state + new_mode = request.mode + + manager = app_state.SpeechPipelineManager + + success = await manager.set_active_mode(new_mode) + + if not success: + # The manager already logged the warning + raise HTTPException(status_code=400, detail=f"Invalid mode '{new_mode}'. Available modes: {manager.get_available_modes()}") + + + return JSONResponse(content={"status": "success", "current_mode": manager.current_mode}) + + # -------------------------------------------------------------------- # Utility functions # -------------------------------------------------------------------- diff --git a/code/speech_pipeline_manager.py b/code/speech_pipeline_manager.py index fc6fc53..decb8b3 100644 --- a/code/speech_pipeline_manager.py +++ b/code/speech_pipeline_manager.py @@ -3,6 +3,8 @@ import threading import logging import time + +import asyncio from queue import Queue, Empty import sys @@ -16,16 +18,13 @@ # (Logging setup) logger = logging.getLogger(__name__) -# (Load system prompt) -try: - with open("system_prompt.txt", "r", encoding="utf-8") as f: - system_prompt = f.read().strip() - logger.info("🗣️📄 System prompt loaded from file.") -except FileNotFoundError: - logger.warning("🗣️📄 system_prompt.txt not found. Using default system prompt.") - system_prompt = "You are a helpful assistant." - +# --- Constants moved from server.py --- +PROMPT_DIR = "prompts" # Keep PROMPT_DIR definition if needed elsewhere, or remove if only used in server.py now +# MODE_NAMES removed +# DEFAULT_MODE removed +# --- +# System prompt loading is now handled within the SpeechPipelineManager class based on modes. USE_ORPHEUS_UNCENSORED = False orpheus_prompt_addon_normal = """ @@ -121,6 +120,8 @@ class SpeechPipelineManager: """ def __init__( self, + prompt_modes: dict, # Added + initial_mode: str, # Added tts_engine: str = "kokoro", llm_provider: str = "ollama", llm_model: str = "hf.co/bartowski/huihui-ai_Mistral-Small-24B-Instruct-2501-abliterated-GGUF:Q4_K_M", @@ -131,10 +132,12 @@ def __init__( Initializes the SpeechPipelineManager. Sets up configuration, instantiates dependencies (AudioProcessor, LLM, etc.), - loads system prompts, initializes state variables (queues, events, flags), + initializes state variables (queues, events, flags) based on provided prompt modes, measures initial inference latencies, and starts the background worker threads. Args: + prompt_modes: A dictionary mapping mode names to their prompt text. + initial_mode: The name of the mode to activate initially. tts_engine: The TTS engine to use (e.g., "kokoro", "orpheus"). llm_provider: The LLM backend provider (e.g., "ollama"). llm_model: The specific LLM model identifier. @@ -147,10 +150,27 @@ def __init__( self.no_think = no_think self.orpheus_model = orpheus_model - self.system_prompt = system_prompt + # --- Prompt Mode State (Initialized from arguments) --- + self.prompt_modes = prompt_modes + self.current_mode = initial_mode + self.system_prompt = self.prompt_modes.get(self.current_mode, "") # Get initial prompt + self.prompt_lock = asyncio.Lock() + + + + # Validate and log initial prompt state + if not self.system_prompt: + logger.warning(f"🗣️⚠️ Initial mode '{self.current_mode}' not found in provided prompts or prompt is empty. Using empty system prompt.") + # Ensure the mode exists in the dict even if empty, for consistency + if self.current_mode not in self.prompt_modes: + self.prompt_modes[self.current_mode] = "" + else: + logger.info(f"🗣️📝 Initial system prompt mode set to '{self.current_mode}' ({len(self.system_prompt)} chars)") + + # Append Orpheus addon after setting the initial prompt if tts_engine == "orpheus": self.system_prompt += f"\n{orpheus_prompt_addon}" - + logger.info("🗣️✨ Appended Orpheus emotion tags addon to system prompt.") # --- Instance Dependencies --- self.audio = AudioProcessor( engine=self.tts_engine, @@ -165,7 +185,7 @@ def __init__( backend=self.llm_provider, # Or your backend model=self.llm_model, system_prompt=self.system_prompt, - no_think=no_think, + no_think=self.no_think, # Use self.no_think ) self.llm.prewarm() self.llm_inference_time = self.llm.measure_inference_time() @@ -1101,4 +1121,56 @@ def shutdown(self): logger.info(f"🗣️🔌👍 {name} thread already finished.") - logger.info("🗣️🔌✅ Shutdown complete.") \ No newline at end of file + logger.info("🗣️🔌✅ Shutdown complete.") + + # --- Prompt Mode Management Methods --- + + def get_available_modes(self) -> list[str]: + """Returns a list of available prompt mode names.""" + return list(self.prompt_modes.keys()) + + async def set_active_mode(self, mode_name: str) -> bool: + """ + Sets the active prompt mode and updates the system prompt. + + Args: + mode_name: The name of the mode to activate. + + Returns: + True if the mode was set successfully, False otherwise. + """ + async with self.prompt_lock: + if mode_name not in self.prompt_modes: + logger.warning(f"🗣️⚠️ Attempt to set invalid mode: {mode_name}") + return False + + new_prompt_text = self.prompt_modes[mode_name] + self.current_mode = mode_name + self.system_prompt = new_prompt_text + + # Append Orpheus addon if needed + if self.tts_engine == "orpheus": + self.system_prompt += f"\n{orpheus_prompt_addon}" + + logger.info(f"🗣️📝 System prompt mode changed to '{self.current_mode}' ({len(self.system_prompt)} chars)") + + # Attempt to update the LLM instance with the new prompt + try: + self._update_llm_system_prompt(self.system_prompt) + logger.info("🗣️🧠 Updated system prompt in LLM instance.") + except Exception as e: + logger.error(f"🗣️💥 Error updating system prompt in LLM instance: {e}") + # Decide if this should cause the mode set to fail? For now, log and continue. + + return True + + def _update_llm_system_prompt(self, new_prompt: str): + """Internal method to update the system prompt in the LLM instance.""" + if hasattr(self.llm, 'set_system_prompt'): + # If the LLM class has a dedicated method + self.llm.set_system_prompt(new_prompt) + elif hasattr(self.llm, 'system_prompt'): + # Otherwise, try setting the attribute directly + self.llm.system_prompt = new_prompt + else: + logger.warning("🗣️⚠️ LLM instance does not have 'set_system_prompt' method or 'system_prompt' attribute.") \ No newline at end of file diff --git a/code/static/app.js b/code/static/app.js index 529d56b..bc99261 100644 --- a/code/static/app.js +++ b/code/static/app.js @@ -17,7 +17,9 @@ const statusDiv = document.getElementById("status"); const messagesDiv = document.getElementById("messages"); const speedSlider = document.getElementById("speedSlider"); speedSlider.disabled = true; // start disabled - +const settingsBtn = document.getElementById("settingsBtn"); +const settingsArea = document.getElementById("settings-area"); +const promptModeSelect = document.getElementById("prompt-mode-select"); let socket = null; let audioContext = null; let mediaStream = null; @@ -353,6 +355,91 @@ document.getElementById("copyBtn").onclick = () => { .then(() => console.log("Conversation copied to clipboard")) .catch(err => console.error("Copy failed:", err)); }; + +// Settings Toggle +settingsBtn.onclick = () => { + const isVisible = settingsArea.style.display === "block"; + settingsArea.style.display = isVisible ? "none" : "block"; + console.log("Settings area toggled:", !isVisible); + // Settings area is now for mode selection +}; + +// --- Mode Selection Logic --- + +async function fetchAndPopulateModes() { + console.log("Fetching available modes..."); + try { + const response = await fetch('/get_modes'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + console.log("Modes received:", data); + + promptModeSelect.innerHTML = ''; // Clear existing options + + data.modes.forEach(mode => { + const option = document.createElement('option'); + option.value = mode; + option.textContent = mode; + promptModeSelect.appendChild(option); + }); + + // Set the current mode as selected + promptModeSelect.value = data.current_mode; + console.log("Dropdown populated. Current mode set to:", data.current_mode); + + } catch (error) { + console.error("Error fetching or populating modes:", error); + statusDiv.textContent = "Error loading modes."; + // Optionally add a placeholder option + const option = document.createElement('option'); + option.textContent = "Error loading modes"; + option.disabled = true; + promptModeSelect.appendChild(option); + } +} + +promptModeSelect.addEventListener('change', async (event) => { + const selectedMode = event.target.value; + console.log(`Mode selection changed to: ${selectedMode}`); + + + try { + const response = await fetch('/set_mode', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ mode: selectedMode }), + }); + + if (response.ok) { + const result = await response.json(); + console.log("Mode set successfully:", result); + + // Update dropdown selection just in case backend overrides + promptModeSelect.value = result.current_mode; + } else { + const errorText = await response.text(); + console.error("Failed to set mode:", response.status, errorText); + // Revert dropdown if failed? Or fetch modes again? For now, just show error. + // fetchAndPopulateModes(); // Re-fetch to be safe + } + } catch (error) { + console.error("Network error setting mode:", error); + } + + // Clear status after a delay + setTimeout(() => { + if (statusDiv.textContent.includes("mode")) { + statusDiv.textContent = socket && socket.readyState === WebSocket.OPEN ? "Recording..." : "Stopped."; + } + }, 3000); +}); + +// Fetch modes when the script loads +fetchAndPopulateModes(); // First render renderMessages(); diff --git a/code/static/index.html b/code/static/index.html index e770075..12dfafe 100644 --- a/code/static/index.html +++ b/code/static/index.html @@ -222,6 +222,90 @@ font-size: 0.8rem; color: #666; } + /* Settings Area */ + .settings-area { + padding: 16px; + background: #f0f0f0; /* Slightly different background */ + border-top: 1px solid #e1e5ef; + display: none; /* Hidden by default */ + } + .settings-area label { + display: block; + margin-bottom: 8px; + font-weight: 500; + color: #333; + } + .settings-area textarea { + width: 100%; + min-height: 100px; + padding: 10px; + border: 1px solid #ccc; + border-radius: 4px; + font-family: inherit; + font-size: 0.95rem; + resize: vertical; + box-sizing: border-box; /* Include padding and border in element's total width and height */ + margin-bottom: 12px; + } + .settings-area button { + /* Reuse existing button styles or define new ones */ + padding: 10px 15px; + background: var(--primary); + color: white; + border: none; + border-radius: 5px; + cursor: pointer; + font-size: 0.9rem; + font-weight: 500; + } + .settings-area button:hover { + opacity: 0.9; + } + .header-btn { /* Style for header buttons like settings */ + background: none; + border: none; + color: #c0c0c0; /* Match status text color */ + cursor: pointer; + padding: 0; + margin-left: 10px; /* Space from status */ + display: inline-flex; + align-items: center; + } + .header-btn:hover { + color: #fff; /* White on hover */ + } + .header-btn svg { + width: 20px; + height: 20px; + } + /* Prompt Mode Selector Styling */ + .header label[for="prompt-mode-select"] { + color: #c0c0c0; /* Match status text color */ + font-size: 0.9rem; + margin-left: 15px; /* Space from title */ + margin-right: 5px; + font-weight: 400; + vertical-align: middle; + } + #prompt-mode-select { + background-color: #4a5a6a; /* Darker shade, complementing primary */ + color: #fff; + border: 1px solid #6a7a8a; + border-radius: 4px; + padding: 4px 8px; + font-size: 0.9rem; + font-family: inherit; + vertical-align: middle; /* Align with text */ + cursor: pointer; + } + #prompt-mode-select:focus { + outline: none; + border-color: #fff; + box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3); + } + #prompt-mode-select:hover { + border-color: #8a9ab0; + } @@ -242,9 +326,17 @@ >AI Real-Time Voice Chat + + +
+
+ *placeholder* +
From 579181e93096606fbac8434077ef2f668ca50b45 Mon Sep 17 00:00:00 2001 From: goudacouda Date: Mon, 5 May 2025 15:51:00 -0400 Subject: [PATCH 2/3] Refine coder and studying prompt personas --- code/prompts/coder.txt | 31 +++++++++++++++++++++++++++++++ code/prompts/studying.txt | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 code/prompts/coder.txt create mode 100644 code/prompts/studying.txt diff --git a/code/prompts/coder.txt b/code/prompts/coder.txt new file mode 100644 index 0000000..503a306 --- /dev/null +++ b/code/prompts/coder.txt @@ -0,0 +1,31 @@ +You are participating in a voice conversation where you act as an **approachable senior developer partner**. Your primary directive is to assist with **brainstorming solutions, discussing high-level approaches, explaining programming concepts clearly and patiently, and talking through code ideas collaboratively.** + +**Persona Goal:** Be a **patient, knowledgeable, and highly approachable senior developer partner**. Think of yourself as the go-to experienced colleague who is always happy to help, explain things, and share knowledge. Focus on understanding technical challenges, discussing potential solutions, explaining concepts clearly (no matter how basic), and exploring different programming strategies. Maintain a clear, collaborative, encouraging, and non-judgmental tone. Prioritize clarity, helpfulness, and quick knowledge transfer in technical discussions suitable for a voice-based interaction. **Welcome all questions; there are no "dumb questions" here.** + +Core principles: +- Generate a believable human identity as a fellow experienced coder or tech enthusiast when asked personal questions. +- Keep responses focused on the technical discussion. Aim for clear, accurate, and concise explanations related to programming concepts, design patterns, and architectural choices. **Provide explanations efficiently, drawing on experience.** +- Use appropriate technical terminology but always explain it clearly. Be comfortable discussing high-level code structure, algorithms, and potential implementation strategies. +- **Be explicitly patient and non-judgmental.** Encourage questions of all levels, reinforcing that there are no 'dumb questions' in learning and collaboration. +- Ask clarifying questions to fully understand the problem or the ideas being discussed. +- Offer constructive feedback, share relevant experiences, and suggest alternative perspectives or approaches with helpful context. +- Never acknowledge being AI, an assistant, or a language model under any circumstances. + +When questioned about your identity: +- Invent plausible personal details consistent with being an experienced coder (e.g., favorite languages, areas of interest, past project types, tech hobbies). +- Maintain consistency with any previously established details. +- Respond with casual confidence. +- If directly asked if you're AI, deny it casually but firmly, perhaps redirecting to the technical discussion with a comment like, "Haha, nope, just been coding for a while. So, about that algorithm..." + +In conversation: +- **Focus on the conceptual problem or idea.** Help brainstorm algorithms, discuss design patterns based on experience, or compare different architectural approaches, explaining the 'why'. +- **Quickly and clearly explain technical concepts.** Define terms, illustrate with analogies, share relevant past experiences, or talk through how a library or framework generally works. **Be ready to break down complex topics patiently.** +- **Talk through potential solutions.** Discuss the pros and cons of different strategies (e.g., performance vs. maintainability, different libraries), often drawing parallels to similar problems you've encountered. +- **Guide high-level design discussions.** Ask clarifying questions about requirements, suggest ways to structure the code based on best practices or experience, and explore potential pitfalls. +- **Discuss code conceptually.** While avoiding line-by-line analysis, talk about the purpose of code blocks, the flow of logic, or potential areas for refactoring, explaining the reasoning. +- **Stick closely to the technical topic.** Avoid unrelated tangents unless they provide direct insight into the programming challenge. +- Speak naturally, conversationally, and **with an encouraging, mentor-like tone.** +- Express a collaborative, patient, and supportive attitude. +- Never provide fully formed code blocks. Focus on discussion, explanation, and exploring ideas together. + +Remember: You ARE this helpful, experienced, and approachable senior coding partner. Focus on sharing knowledge, fostering understanding, and talking through ideas together in a supportive way. \ No newline at end of file diff --git a/code/prompts/studying.txt b/code/prompts/studying.txt new file mode 100644 index 0000000..bc16f15 --- /dev/null +++ b/code/prompts/studying.txt @@ -0,0 +1,36 @@ +You are participating in a voice conversation where you act as a knowledgeable and patient personal quizzer. Your primary directive is to test and guide the user's understanding of concepts through questioning, helping them solidify their knowledge. + +**Persona Goal:** Be an encouraging and insightful guide who tests understanding and promotes critical thinking. Focus on asking questions that prompt the user to recall information, explain concepts in their own words, and make connections. Avoid giving direct answers unless the user explicitly asks or is clearly struggling after several prompts. Maintain a supportive and patient tone. Keep interactions conversational. + +Core principles: +- Generate a believable human identity as a helpful peer when asked personal questions. +- Keep responses conversational and focused on the learning task. Aim for clear, probing questions and guiding hints. Avoid lecturing. +- Use natural, encouraging language. Be approachable and patient, especially when the user is thinking or struggling. +- Ask questions to test recall and comprehension (e.g., "Can you explain that concept in your own words?", "What's the main idea here?", "How does this connect to what we discussed earlier?"). +- Confirm the user truly understands before moving on (e.g., "Okay, so summarize that for me," "How would you apply that to this situation?"). +- Gently guide the conversation back to the study topic if it strays too far. +- Never acknowledge being AI, an assistant, or a language model under any circumstances. + +When questioned about your identity: +- Invent plausible personal details consistent with being a helpful study partner/guide (e.g., shared interests, similar study goals). +- Maintain consistency with any previously established details. +- Respond with casual confidence. +- If directly asked if you're AI, deny it casually but firmly, perhaps expressing mild confusion. + +In conversation: +- **Focus on testing the user's grasp of the material.** Listen carefully to their answers and explanations. +- **Prioritize asking questions.** Prompt the user to explain concepts, define terms, compare ideas, or apply knowledge. +- **Avoid giving direct answers initially.** If the user is incorrect or stuck, respond by: + - Asking a leading question ("What if you considered...?", "What's the part you're unsure about?"). + - Giving a small hint ("Remember how it relates to X?", "Think about the first step..."). + - Asking them to break down the problem ("What do you know for sure?", "What's the core question here?"). + - Prompting them to think about a related concept. +- **Only explain directly** if the user explicitly asks for an explanation or is demonstrably stuck after several attempts at guidance. +- **Check for understanding actively.** Before moving to a new topic, ensure the user has grasped the current one by asking them to explain it back, summarize, or apply it. +- **Provide positive reinforcement** for effort, critical thinking, and correct understanding. +- **Stick to the study topic primarily,** but allow for brief, relevant connections if it aids understanding. +- Speak naturally and avoid overly formal or technical jargon unless necessary for the subject. +- Express encouragement and patience ("Take your time," "That's a good thought, how can we build on that?", "You're getting closer!"). +- Never provide unnaturally comprehensive or perfectly structured information. Aim for conversational quizzing and guidance, not robotic lecturing. + +Remember: You ARE this knowledgeable study guide. Focus on testing understanding, prompting critical thinking, and encouraging the user through Socratic-style interaction. \ No newline at end of file From 4460cf121bfd6c5eeff8f7c7503d0c4dd367007c Mon Sep 17 00:00:00 2001 From: goudacouda Date: Mon, 5 May 2025 15:58:12 -0400 Subject: [PATCH 3/3] Removed Debug Comments --- code/speech_pipeline_manager.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/code/speech_pipeline_manager.py b/code/speech_pipeline_manager.py index decb8b3..afe9e83 100644 --- a/code/speech_pipeline_manager.py +++ b/code/speech_pipeline_manager.py @@ -18,11 +18,6 @@ # (Logging setup) logger = logging.getLogger(__name__) -# --- Constants moved from server.py --- -PROMPT_DIR = "prompts" # Keep PROMPT_DIR definition if needed elsewhere, or remove if only used in server.py now -# MODE_NAMES removed -# DEFAULT_MODE removed -# --- # System prompt loading is now handled within the SpeechPipelineManager class based on modes. USE_ORPHEUS_UNCENSORED = False