Spaces:
Sleeping
Sleeping
| """Main query engine for persona-based responses""" | |
| from typing import Optional, Dict, Any | |
| from pydantic import BaseModel | |
| from datetime import datetime | |
| from ..personas.database import PersonaDatabase | |
| from ..context.database import ContextDatabase | |
| from ..llm.anthropic_client import AnthropicClient | |
| from ..llm.prompt_builder import PromptBuilder | |
| class QueryResponse(BaseModel): | |
| """Structured response from a persona query""" | |
| persona_id: str | |
| persona_name: str | |
| persona_role: str | |
| question: str | |
| response: str | |
| context_id: Optional[str] = None | |
| timestamp: str | |
| model_used: str | |
| metadata: Dict[str, Any] = {} | |
| class Config: | |
| """Pydantic config""" | |
| json_schema_extra = { | |
| "example": { | |
| "persona_id": "sarah_chen", | |
| "persona_name": "Sarah Chen", | |
| "persona_role": "Urban Planner", | |
| "question": "What do you think about the bike lane proposal?", | |
| "response": "I strongly support this bike lane proposal...", | |
| "context_id": "downtown_district", | |
| "timestamp": "2024-03-15T10:30:00", | |
| "model_used": "claude-3-5-sonnet-20241022", | |
| } | |
| } | |
| class QueryEngine: | |
| """Main engine for querying personas and generating responses""" | |
| def __init__( | |
| self, | |
| persona_db: Optional[PersonaDatabase] = None, | |
| context_db: Optional[ContextDatabase] = None, | |
| llm_client: Optional[AnthropicClient] = None, | |
| ): | |
| """ | |
| Initialize query engine | |
| Args: | |
| persona_db: Persona database instance (creates default if None) | |
| context_db: Context database instance (creates default if None) | |
| llm_client: LLM client instance (creates default if None) | |
| """ | |
| self.persona_db = persona_db or PersonaDatabase() | |
| self.context_db = context_db or ContextDatabase() | |
| self.llm_client = llm_client or AnthropicClient() | |
| self.prompt_builder = PromptBuilder() | |
| def query( | |
| self, | |
| persona_id: str, | |
| question: str, | |
| context_id: Optional[str] = None, | |
| scenario_description: Optional[str] = None, | |
| temperature: Optional[float] = None, | |
| max_tokens: Optional[int] = None, | |
| ) -> QueryResponse: | |
| """ | |
| Query a persona with a question | |
| Args: | |
| persona_id: ID of persona to query | |
| question: Question to ask the persona | |
| context_id: Optional environmental context ID | |
| scenario_description: Optional scenario description | |
| temperature: Optional temperature override | |
| max_tokens: Optional max_tokens override | |
| Returns: | |
| QueryResponse object with the persona's response | |
| Raises: | |
| ValueError: If persona not found | |
| """ | |
| # Get persona | |
| persona = self.persona_db.get_persona(persona_id) | |
| if persona is None: | |
| available = ", ".join(self.persona_db.list_persona_ids()) | |
| raise ValueError( | |
| f"Persona '{persona_id}' not found. " | |
| f"Available personas: {available}" | |
| ) | |
| # Get context if specified | |
| context = None | |
| if context_id: | |
| context = self.context_db.get_context(context_id) | |
| if context is None: | |
| print(f"Warning: Context '{context_id}' not found, proceeding without context") | |
| # Build prompts | |
| system_prompt = self.prompt_builder.build_persona_system_prompt( | |
| persona=persona, | |
| context=context, | |
| ) | |
| user_message = self.prompt_builder.build_contextual_query( | |
| question=question, | |
| scenario_description=scenario_description, | |
| ) | |
| # Generate response | |
| response_text = self.llm_client.generate_response( | |
| system_prompt=system_prompt, | |
| user_message=user_message, | |
| temperature=temperature, | |
| max_tokens=max_tokens, | |
| ) | |
| # Build response object | |
| return QueryResponse( | |
| persona_id=persona.persona_id, | |
| persona_name=persona.name, | |
| persona_role=persona.role, | |
| question=question, | |
| response=response_text, | |
| context_id=context_id, | |
| timestamp=datetime.now().isoformat(), | |
| model_used=self.llm_client.model, | |
| metadata={ | |
| "scenario_description": scenario_description, | |
| "temperature": temperature or self.llm_client.temperature, | |
| "max_tokens": max_tokens or self.llm_client.max_tokens, | |
| }, | |
| ) | |
| def query_multiple( | |
| self, | |
| persona_ids: list[str], | |
| question: str, | |
| context_id: Optional[str] = None, | |
| scenario_description: Optional[str] = None, | |
| ) -> list[QueryResponse]: | |
| """ | |
| Query multiple personas with the same question | |
| Args: | |
| persona_ids: List of persona IDs to query | |
| question: Question to ask all personas | |
| context_id: Optional environmental context ID | |
| scenario_description: Optional scenario description | |
| Returns: | |
| List of QueryResponse objects | |
| """ | |
| responses = [] | |
| for persona_id in persona_ids: | |
| try: | |
| response = self.query( | |
| persona_id=persona_id, | |
| question=question, | |
| context_id=context_id, | |
| scenario_description=scenario_description, | |
| ) | |
| responses.append(response) | |
| except Exception as e: | |
| print(f"Error querying persona {persona_id}: {e}") | |
| return responses | |
| def list_available_personas(self) -> list[tuple[str, str, str]]: | |
| """ | |
| List all available personas | |
| Returns: | |
| List of (persona_id, name, role) tuples | |
| """ | |
| personas = self.persona_db.get_all_personas() | |
| return [ | |
| (p.persona_id, p.name, p.role) | |
| for p in personas | |
| ] | |
| def list_available_contexts(self) -> list[str]: | |
| """ | |
| List all available contexts | |
| Returns: | |
| List of context IDs | |
| """ | |
| return self.context_db.list_context_ids() | |
| def test_system(self) -> bool: | |
| """ | |
| Test that all system components are working | |
| Returns: | |
| True if system is operational | |
| """ | |
| try: | |
| # Check personas loaded | |
| personas = self.persona_db.get_all_personas() | |
| if not personas: | |
| print("Error: No personas loaded") | |
| return False | |
| print(f"✓ Loaded {len(personas)} personas") | |
| # Check contexts loaded (optional) | |
| contexts = self.context_db.get_all_contexts() | |
| print(f"✓ Loaded {len(contexts)} contexts") | |
| # Check LLM connection | |
| if self.llm_client.test_connection(): | |
| print(f"✓ LLM client connected ({self.llm_client.model})") | |
| else: | |
| print("Error: LLM client connection failed") | |
| return False | |
| return True | |
| except Exception as e: | |
| print(f"System test failed: {e}") | |
| return False | |