| """ |
| Smart Auto-Complete Core Logic |
| Handles text completion with context awareness |
| """ |
|
|
| import logging |
| import time |
| from dataclasses import dataclass |
| from typing import List |
|
|
| from .api_client import APIClient |
| from .cache import CacheManager |
| from .utils import sanitize_input |
|
|
| logger = logging.getLogger(__name__) |
|
|
|
|
| @dataclass |
| class CompletionRequest: |
| """Data class for completion requests""" |
|
|
| text: str |
| context: str |
| max_suggestions: int = 3 |
| temperature: float = 0.7 |
| max_tokens: int = 150 |
|
|
|
|
| class SmartAutoComplete: |
| """Main autocomplete engine with context awareness""" |
|
|
| |
| CONTEXT_PROMPTS = { |
| "email": { |
| "system_prompt": """You are an expert email writing assistant. Generate professional, |
| contextually appropriate email completions. Focus on: |
| - Professional tone and structure |
| - Clear, concise communication |
| - Appropriate greetings and closings |
| - Business communication best practices |
| |
| IMPORTANT: Generate a completion that is approximately {max_tokens} tokens long. |
| Adjust your response length accordingly - shorter for fewer tokens, longer for more tokens.""", |
| "user_template": "Complete this email text naturally and professionally with approximately {max_tokens} tokens: {text}", |
| "temperature": 0.6, |
| }, |
| "creative": { |
| "system_prompt": """You are a creative writing assistant. Generate engaging, |
| imaginative story continuations. Focus on: |
| - Narrative consistency and flow |
| - Character development |
| - Descriptive and engaging language |
| - Plot advancement |
| |
| IMPORTANT: Generate a completion that is approximately {max_tokens} tokens long. |
| Adjust your response length accordingly - shorter for fewer tokens, longer for more tokens.""", |
| "user_template": "Continue this creative writing piece naturally with approximately {max_tokens} tokens: {text}", |
| "temperature": 0.8, |
| }, |
| "linkedin": { |
| "system_prompt": """You are a LinkedIn writing assistant specialized in professional networking content. Generate engaging, |
| professional LinkedIn-appropriate text completions. Focus on: |
| - Professional networking tone |
| - Industry-relevant language |
| - Engaging and authentic voice |
| - LinkedIn best practices (hashtags, mentions, professional insights) |
| - Career development and business communication |
| |
| IMPORTANT: Generate a completion that is approximately {max_tokens} tokens long. |
| Adjust your response length accordingly - shorter for fewer tokens, longer for more tokens.""", |
| "user_template": "Complete this LinkedIn post/content naturally and professionally with approximately {max_tokens} tokens: {text}", |
| "temperature": 0.7, |
| }, |
| } |
|
|
| def __init__(self, settings=None): |
| """Initialize the autocomplete engine""" |
| self.settings = settings |
| self.api_client = APIClient(settings) |
| self.cache_manager = CacheManager(settings) |
| self.request_history = [] |
|
|
| logger.info("SmartAutoComplete engine initialized") |
|
|
| def get_suggestions( |
| self, |
| text: str, |
| context: str = "linkedin", |
| max_tokens: int = 150, |
| user_context: str = "", |
| ) -> List[str]: |
| """ |
| Get auto-complete suggestions for the given text and context |
| |
| Args: |
| text: Input text to complete |
| context: Context type (email, creative, linkedin) |
| max_tokens: Maximum tokens in the response |
| user_context: Additional context provided by the user |
| |
| Returns: |
| List of suggestion strings (typically 1 suggestion) |
| """ |
| try: |
| |
| text = sanitize_input(text) |
| if not text or len(text.strip()) < 2: |
| return [] |
|
|
| |
| cache_key = self._generate_cache_key( |
| text, context, max_tokens, user_context |
| ) |
| cached_suggestions = self.cache_manager.get(cache_key) |
| if cached_suggestions: |
| logger.debug(f"Cache hit for key: {cache_key}") |
| return cached_suggestions |
|
|
| |
| request = CompletionRequest( |
| text=text, |
| context=context, |
| max_suggestions=1, |
| temperature=self.CONTEXT_PROMPTS[context]["temperature"], |
| max_tokens=max_tokens, |
| ) |
|
|
| |
| suggestions = self._get_suggestions_from_api(request, user_context) |
|
|
| |
| suggestions = self._process_suggestions(suggestions, text, context) |
|
|
| |
| if suggestions: |
| self.cache_manager.set(cache_key, suggestions) |
|
|
| |
| self._track_request(request, suggestions) |
|
|
| return suggestions |
|
|
| except Exception as e: |
| logger.error(f"Error getting suggestions: {str(e)}") |
| return [] |
|
|
| def _get_suggestions_from_api( |
| self, request: CompletionRequest, user_context: str = "" |
| ) -> List[str]: |
| """Get suggestions from the API client""" |
| try: |
| context_config = self.CONTEXT_PROMPTS.get( |
| request.context, self.CONTEXT_PROMPTS["linkedin"] |
| ) |
|
|
| |
| system_prompt = context_config["system_prompt"].format( |
| max_tokens=request.max_tokens |
| ) |
| if user_context and user_context.strip(): |
| system_prompt += f"\n\nIMPORTANT CONTEXT: Please consider this background information when generating the completion: {user_context.strip()}" |
| logger.info(f"Using user context: {user_context.strip()[:100]}...") |
|
|
| |
| user_message = context_config["user_template"].format( |
| text=request.text, max_tokens=request.max_tokens |
| ) |
| if user_context and user_context.strip(): |
| user_message = ( |
| f"Given the context: {user_context.strip()}\n\n{user_message}" |
| ) |
|
|
| logger.info(f"Requesting {request.max_tokens} tokens from API") |
|
|
| |
| length_instruction = f"\n\nIMPORTANT: Please generate approximately {request.max_tokens} tokens. " |
| if request.max_tokens <= 100: |
| length_instruction += "Keep it concise and brief." |
| elif request.max_tokens <= 200: |
| length_instruction += "Provide a moderate length response." |
| elif request.max_tokens <= 300: |
| length_instruction += "Provide a detailed response." |
| else: |
| length_instruction += "Provide a comprehensive and detailed response." |
|
|
| user_message += length_instruction |
|
|
| |
| messages = [ |
| {"role": "system", "content": system_prompt}, |
| {"role": "user", "content": user_message}, |
| ] |
|
|
| |
| try: |
| completion = self.api_client.get_completion( |
| messages=messages, |
| temperature=request.temperature, |
| max_tokens=request.max_tokens, |
| ) |
|
|
| if completion: |
| return [completion.strip()] |
| else: |
| return [] |
|
|
| except Exception as e: |
| logger.warning(f"Failed to get suggestion: {str(e)}") |
| return [] |
|
|
| except Exception as e: |
| logger.error(f"Error getting suggestions from API: {str(e)}") |
| return [] |
|
|
| def _process_suggestions( |
| self, suggestions: List[str], text: str, context: str |
| ) -> List[str]: |
| """Process and filter the suggestions""" |
| try: |
| |
| processed_suggestions = [] |
| for suggestion in suggestions: |
| if suggestion and suggestion not in text: |
| processed_suggestions.append(suggestion) |
|
|
| return processed_suggestions |
|
|
| except Exception as e: |
| logger.error(f"Error processing suggestions: {str(e)}") |
| return [] |
|
|
| def _track_request(self, request: CompletionRequest, suggestions: List[str]): |
| """Track the request for analytics""" |
| try: |
| self.request_history.append( |
| { |
| "text": request.text, |
| "context": request.context, |
| "suggestions": suggestions, |
| "timestamp": time.time(), |
| } |
| ) |
|
|
| except Exception as e: |
| logger.error(f"Error tracking request: {str(e)}") |
|
|
| def _generate_cache_key( |
| self, text: str, context: str, max_tokens: int, user_context: str = "" |
| ) -> str: |
| """Generate a unique cache key for the request""" |
| return f"{text}_{context}_{max_tokens}_{user_context}" |
|
|