Spaces:
Running
Running
jarvisemitra
feat: optimize latency, implement global MutationObserver for instant audio play, and add user interrupt handlers for click and spacebar
e7c0595 | import os | |
| import json | |
| import requests | |
| from dotenv import load_dotenv | |
| from app.models import Message, ChatResponse | |
| from app.catalog import Catalog, get_catalog | |
| from app.retrieval import HybridRetriever | |
| from app.analyzer import ConversationAnalyzer | |
| from app.safety import SafetyGuard | |
| from app.prompts import build_system_prompt, build_catalog_context | |
| from app.validator import ResponseValidator | |
| load_dotenv() | |
| class SHLAgent: | |
| """ | |
| The core SHL Assessment Recommender agent powered by Gemma via NVIDIA NIM API. | |
| """ | |
| def __init__(self): | |
| # Initialize components | |
| self.catalog: Catalog = get_catalog() | |
| self.retriever = HybridRetriever(self.catalog) | |
| self.analyzer = ConversationAnalyzer() | |
| self.safety = SafetyGuard() | |
| self.validator = ResponseValidator(self.catalog) | |
| # Configure NVIDIA API | |
| self.api_key = os.getenv("NVIDIA_API_KEY", "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") | |
| self.invoke_url = "https://integrate.api.nvidia.com/v1/chat/completions" | |
| self.model_name = "google/diffusiongemma-26b-a4b-it" | |
| # Build retrieval index at initialization | |
| self.retriever.build_index() | |
| print(f"[Agent] Initialized successfully with NVIDIA NIM API using {self.model_name}") | |
| def process(self, messages: list[Message]) -> ChatResponse: | |
| """ | |
| Process a chat request and return a response. | |
| """ | |
| try: | |
| return self._process_internal(messages) | |
| except Exception as e: | |
| import traceback | |
| print(f"[Agent] Top-level error: {e}") | |
| traceback.print_exc() | |
| return self.validator.create_safe_response( | |
| reply=f"Sorry, an internal error occurred: {str(e)}" | |
| ) | |
| def _process_internal(self, messages: list[Message]) -> ChatResponse: | |
| """Internal processing pipeline.""" | |
| # --- Step 1: Safety Check --- | |
| print("[Agent] Step 1: Safety check...") | |
| latest_user_msg = self.analyzer.get_latest_user_message(messages) | |
| print(f"[Agent] Latest user msg: {latest_user_msg[:100] if latest_user_msg else 'EMPTY'}") | |
| is_safe, refusal_msg = self.safety.check(latest_user_msg) | |
| if not is_safe: | |
| print(f"[Agent] Safety refusal: {refusal_msg}") | |
| return self.validator.create_refusal_response(refusal_msg) | |
| print("[Agent] Step 1: PASSED") | |
| # --- Step 2: Extract Slots --- | |
| print("[Agent] Step 2: Extract slots...") | |
| slots = self.analyzer.extract_slots(messages) | |
| print(f"[Agent] Step 2: DONE - confidence={slots.confidence}") | |
| # --- Step 3: Classify Intent --- | |
| print("[Agent] Step 3: Classify intent...") | |
| intent = self.analyzer.classify_intent(messages) | |
| print(f"[Agent] Step 3: DONE - intent={intent}") | |
| # --- Step 4: Retrieve Relevant Assessments --- | |
| print("[Agent] Step 4: Retrieve assessments...") | |
| search_queries = slots.build_search_queries() | |
| if latest_user_msg: | |
| search_queries.append(latest_user_msg) | |
| print(f"[Agent] Search queries: {search_queries}") | |
| retrieved_items = self.retriever.search_multi_query( | |
| search_queries, top_k=8 | |
| ) | |
| print(f"[Agent] Step 4: DONE - retrieved {len(retrieved_items)} items") | |
| # --- Step 5: Build Prompt --- | |
| print("[Agent] Step 5: Build prompt...") | |
| slots_summary = slots.to_summary() | |
| catalog_context = build_catalog_context(retrieved_items) | |
| system_prompt = build_system_prompt( | |
| slots_summary=slots_summary, | |
| catalog_context=catalog_context, | |
| intent=intent, | |
| ) | |
| print(f"[Agent] Step 5: DONE - prompt length={len(system_prompt)} chars") | |
| # --- Step 6: LLM Call --- | |
| print("[Agent] Step 6: LLM call...") | |
| raw_response = self._call_llm(messages, system_prompt) | |
| print(f"[Agent] Step 6: DONE - response length={len(raw_response)} chars") | |
| print(f"[Agent] Raw LLM response (first 300 chars): {raw_response[:300].encode('ascii', 'replace').decode('ascii')}") | |
| # --- Step 7: Validate and Return --- | |
| print("[Agent] Step 7: Parse and validate...") | |
| try: | |
| parsed = self.validator.parse_llm_output(raw_response) | |
| response = self.validator.validate_and_fix(parsed) | |
| print(f"[Agent] Step 7: DONE - reply length={len(response.reply)}, recs={len(response.recommendations)}") | |
| except Exception as e: | |
| print(f"[Agent] LLM output parsing failed: {e}") | |
| # Fallback: use the raw LLM text directly instead of generic error | |
| response = self.validator.create_safe_response( | |
| reply=raw_response if raw_response.strip() else None | |
| ) | |
| return response | |
| def _call_llm(self, messages: list[Message], system_prompt: str) -> str: | |
| """ | |
| Make a single call to diffusiongemma-26b-a4b-it via NVIDIA API. | |
| """ | |
| try: | |
| headers = { | |
| "Authorization": f"Bearer {self.api_key}", | |
| "Accept": "application/json", | |
| "Content-Type": "application/json" | |
| } | |
| # Construct model chat payload | |
| api_messages = [ | |
| {"role": "system", "content": system_prompt} | |
| ] | |
| for msg in messages: | |
| role = "assistant" if msg.role == "assistant" else "user" | |
| api_messages.append({"role": role, "content": msg.content}) | |
| payload = { | |
| "model": self.model_name, | |
| "messages": api_messages, | |
| "max_tokens": 500, | |
| "temperature": 0.3, | |
| "top_p": 0.95, | |
| "stream": False, | |
| } | |
| response = requests.post(self.invoke_url, headers=headers, json=payload) | |
| response.raise_for_status() | |
| result = response.json() | |
| return result["choices"][0]["message"]["content"] | |
| except Exception as e: | |
| print(f"[Agent] NVIDIA LLM call failed: {e}") | |
| raise | |
| # Singleton agent instance | |
| _agent: SHLAgent | None = None | |
| def get_agent() -> SHLAgent: | |
| """Get or initialize the agent singleton.""" | |
| global _agent | |
| if _agent is None: | |
| _agent = SHLAgent() | |
| return _agent | |