|
|
|
""" |
|
Smart Auto-Complete - Main Application |
|
A context-aware text completion tool built with Gradio |
|
""" |
|
|
|
from typing import List, Tuple |
|
|
|
from config.settings import AppSettings |
|
from src.autocomplete import SmartAutoComplete |
|
from src.utils import setup_logging |
|
|
|
import gradio as gr |
|
|
|
|
|
logger = setup_logging() |
|
|
|
|
|
settings = AppSettings() |
|
autocomplete = SmartAutoComplete(settings) |
|
|
|
|
|
class AutoCompleteApp: |
|
def __init__(self): |
|
self.last_request_time = 0 |
|
self.current_suggestions = [] |
|
|
|
def get_suggestions( |
|
self, text: str, context: str, output_tokens: int = 150, user_context: str = "" |
|
) -> Tuple[List[str], str]: |
|
""" |
|
Get auto-complete suggestions for the given text and context |
|
Returns: (suggestions_list, status_message) |
|
""" |
|
try: |
|
|
|
if not text or len(text.strip()) < 2: |
|
return [], "โ๏ธ Please enter some text to get suggestions..." |
|
|
|
if len(text) > settings.MAX_INPUT_LENGTH: |
|
return ( |
|
[], |
|
f"โ ๏ธ Text too long (max {settings.MAX_INPUT_LENGTH} characters)", |
|
) |
|
|
|
|
|
suggestions = autocomplete.get_suggestions( |
|
text=text, |
|
context=context, |
|
max_tokens=output_tokens, |
|
user_context=user_context, |
|
) |
|
|
|
self.current_suggestions = suggestions |
|
|
|
if suggestions: |
|
status = f"โ
Found {len(suggestions)} suggestions" |
|
else: |
|
status = "๐ค No suggestions available for this text" |
|
|
|
return suggestions, status |
|
|
|
except Exception as e: |
|
logger.error(f"Error getting suggestions: {str(e)}") |
|
return [], f"โ Error: {str(e)}" |
|
|
|
def get_suggestions_with_custom_prompts( |
|
self, |
|
text: str, |
|
context: str, |
|
output_tokens: int = 150, |
|
user_context: str = "", |
|
custom_prompts: dict = None, |
|
) -> Tuple[List[str], str]: |
|
""" |
|
Get auto-complete suggestions with custom prompts |
|
Returns: (suggestions_list, status_message) |
|
""" |
|
try: |
|
|
|
if not text or len(text.strip()) < 2: |
|
return [], "โ๏ธ Please enter some text to get suggestions..." |
|
|
|
if len(text) > settings.MAX_INPUT_LENGTH: |
|
return ( |
|
[], |
|
f"โ ๏ธ Text too long (max {settings.MAX_INPUT_LENGTH} characters)", |
|
) |
|
|
|
|
|
temp_autocomplete = SmartAutoComplete(settings) |
|
if custom_prompts: |
|
temp_autocomplete.CONTEXT_PROMPTS = custom_prompts |
|
|
|
|
|
suggestions = temp_autocomplete.get_suggestions( |
|
text=text, |
|
context=context, |
|
max_tokens=output_tokens, |
|
user_context=user_context, |
|
) |
|
|
|
self.current_suggestions = suggestions |
|
|
|
if suggestions: |
|
status = f"โ
Found {len(suggestions)} suggestions" |
|
else: |
|
status = "๐ค No suggestions available for this text" |
|
|
|
return suggestions, status |
|
|
|
except Exception as e: |
|
logger.error(f"Error getting suggestions with custom prompts: {str(e)}") |
|
return [], f"โ Error: {str(e)}" |
|
|
|
def insert_suggestion( |
|
self, current_text: str, suggestion: str, cursor_position: int = None |
|
) -> str: |
|
"""Insert the selected suggestion into the current text""" |
|
try: |
|
|
|
if not current_text: |
|
return suggestion |
|
|
|
|
|
words = current_text.split() |
|
if words and not current_text.endswith((".", "!", "?", "\n")): |
|
|
|
return current_text + " " + suggestion.strip() |
|
else: |
|
return current_text + " " + suggestion.strip() |
|
|
|
except Exception as e: |
|
logger.error(f"Error inserting suggestion: {str(e)}") |
|
return current_text |
|
|
|
|
|
def create_interface(): |
|
"""Create and configure the Gradio interface""" |
|
|
|
app_instance = AutoCompleteApp() |
|
|
|
|
|
custom_css = """ |
|
.suggestion-box { |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
border-radius: 10px; |
|
padding: 15px; |
|
margin: 10px 0; |
|
color: white; |
|
cursor: pointer; |
|
transition: transform 0.2s; |
|
} |
|
.suggestion-box:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15); |
|
} |
|
.context-selector { |
|
margin-bottom: 20px; |
|
} |
|
.main-input { |
|
border-radius: 10px; |
|
border: 2px solid #e1e5e9; |
|
font-size: 16px; |
|
} |
|
""" |
|
|
|
with gr.Blocks( |
|
title="๐ Smart Auto-Complete", theme=gr.themes.Soft(), css=custom_css |
|
) as interface: |
|
|
|
gr.Markdown(""" |
|
# ๐ Smart Auto-Complete |
|
|
|
**Intelligent text completion powered by AI** |
|
|
|
Choose your context, enter your text, and click submit to get AI-powered completions! โจ |
|
""") |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=2): |
|
|
|
context_selector = gr.Radio( |
|
choices=[ |
|
("๐ง Email Writing", "email"), |
|
("โ๏ธ Creative Writing", "creative"), |
|
("๐ General Text", "general"), |
|
], |
|
value="email", |
|
label="Select Context", |
|
elem_classes=["context-selector"], |
|
) |
|
|
|
|
|
context_input = gr.Textbox( |
|
label="๐ Reference Information (Optional)", |
|
placeholder="Add any background information, previous context, or references that should inform the writing...", |
|
lines=4, |
|
elem_classes=["context-input"], |
|
) |
|
|
|
|
|
text_input = gr.Textbox( |
|
label="โ๏ธ Enter your text here...", |
|
placeholder="Enter your text and click Submit to get suggestions!", |
|
lines=8, |
|
elem_classes=["main-input"], |
|
) |
|
|
|
|
|
submit_btn = gr.Button( |
|
"๐ Get Suggestions", variant="primary", size="lg" |
|
) |
|
|
|
|
|
with gr.Accordion("โ๏ธ Settings", open=False): |
|
output_length = gr.Slider( |
|
minimum=50, |
|
maximum=500, |
|
value=150, |
|
step=10, |
|
label="Output Length (tokens)", |
|
) |
|
|
|
gr.Checkbox(label="Show debug information", value=False) |
|
|
|
|
|
with gr.Accordion("๐ง Edit Context Prompts", open=False): |
|
gr.Markdown( |
|
"**Customize your writing style for each context type. Changes apply immediately.**" |
|
) |
|
|
|
with gr.Tab("๐ง Email Context"): |
|
email_system_prompt = gr.Textbox( |
|
label="System Prompt", |
|
value="""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.""", |
|
lines=8, |
|
placeholder="Enter the system prompt for email context...", |
|
) |
|
email_user_template = gr.Textbox( |
|
label="User Message Template", |
|
value="Complete this email text naturally and professionally with approximately {max_tokens} tokens: {text}", |
|
lines=3, |
|
placeholder="Enter the user message template...", |
|
) |
|
|
|
with gr.Tab("๐จ Creative Context"): |
|
creative_system_prompt = gr.Textbox( |
|
label="System Prompt", |
|
value="""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.""", |
|
lines=8, |
|
placeholder="Enter the system prompt for creative context...", |
|
) |
|
creative_user_template = gr.Textbox( |
|
label="User Message Template", |
|
value="Continue this creative writing piece naturally with approximately {max_tokens} tokens: {text}", |
|
lines=3, |
|
placeholder="Enter the user message template...", |
|
) |
|
|
|
with gr.Tab("๐ General Context"): |
|
general_system_prompt = gr.Textbox( |
|
label="System Prompt", |
|
value="""You are a helpful writing assistant. Generate natural, |
|
contextually appropriate text completions. Focus on: |
|
- Natural language flow |
|
- Contextual relevance |
|
- Clarity and coherence |
|
- Appropriate tone |
|
|
|
IMPORTANT: Generate a completion that is approximately {max_tokens} tokens long. |
|
Adjust your response length accordingly - shorter for fewer tokens, longer for more tokens.""", |
|
lines=8, |
|
placeholder="Enter the system prompt for general context...", |
|
) |
|
general_user_template = gr.Textbox( |
|
label="User Message Template", |
|
value="Complete this text naturally with approximately {max_tokens} tokens: {text}", |
|
lines=3, |
|
placeholder="Enter the user message template...", |
|
) |
|
|
|
with gr.Column(scale=1): |
|
|
|
status_display = gr.Textbox( |
|
label="๐ Status", |
|
value="Ready to help! Start typing...", |
|
interactive=False, |
|
lines=2, |
|
) |
|
|
|
|
|
copy_textbox = gr.Textbox( |
|
label="๐ Generated Text (Select All and Copy with Ctrl+C/Cmd+C)", |
|
placeholder="Generated suggestions will appear here for easy copying...", |
|
lines=8, |
|
max_lines=15, |
|
interactive=True, |
|
visible=False, |
|
) |
|
|
|
|
|
with gr.Accordion("๐ฏ Try These Examples", open=False): |
|
gr.Examples( |
|
examples=[ |
|
[ |
|
"Meeting scheduled for next Tuesday to discuss the quarterly budget review", |
|
"Dear Mr. Johnson,\n\nI hope this email finds you well. I wanted to follow up on", |
|
"email", |
|
], |
|
[ |
|
"Fantasy adventure story with magical creatures and brave heroes", |
|
"Once upon a time, in a kingdom far away, there lived a", |
|
"creative", |
|
], |
|
[ |
|
"Academic research paper on technology trends", |
|
"The impact of artificial intelligence on modern society", |
|
"general", |
|
], |
|
], |
|
inputs=[context_input, text_input, context_selector], |
|
label="Click any example to try it out!", |
|
) |
|
|
|
|
|
def update_suggestions( |
|
text, |
|
context, |
|
output_tokens, |
|
user_context, |
|
email_sys, |
|
email_user, |
|
creative_sys, |
|
creative_user, |
|
general_sys, |
|
general_user, |
|
): |
|
"""Update suggestions based on input with custom prompts""" |
|
logger.info( |
|
f"Getting suggestions with context: '{user_context[:50] if user_context else 'None'}...'" |
|
) |
|
logger.info(f"Requested output tokens: {output_tokens}") |
|
|
|
|
|
custom_prompts = { |
|
"email": { |
|
"system_prompt": email_sys, |
|
"user_template": email_user, |
|
"temperature": 0.6, |
|
}, |
|
"creative": { |
|
"system_prompt": creative_sys, |
|
"user_template": creative_user, |
|
"temperature": 0.8, |
|
}, |
|
"general": { |
|
"system_prompt": general_sys, |
|
"user_template": general_user, |
|
"temperature": 0.7, |
|
}, |
|
} |
|
|
|
suggestions, status = app_instance.get_suggestions_with_custom_prompts( |
|
text, context, output_tokens, user_context, custom_prompts |
|
) |
|
|
|
|
|
if suggestions: |
|
copy_text = suggestions[0] if suggestions else "" |
|
copy_visible = True |
|
else: |
|
copy_text = "" |
|
copy_visible = False |
|
|
|
|
|
copy_update = gr.update(visible=copy_visible, value=copy_text) |
|
return status, copy_update |
|
|
|
|
|
submit_btn.click( |
|
fn=update_suggestions, |
|
inputs=[ |
|
text_input, |
|
context_selector, |
|
output_length, |
|
context_input, |
|
email_system_prompt, |
|
email_user_template, |
|
creative_system_prompt, |
|
creative_user_template, |
|
general_system_prompt, |
|
general_user_template, |
|
], |
|
outputs=[status_display, copy_textbox], |
|
) |
|
|
|
|
|
gr.Markdown(""" |
|
--- |
|
|
|
### ๐ฎ How to Use: |
|
1. **Select your context** (Email, Creative, or General) |
|
2. **Add context information** (optional) - background info, references, or previous context |
|
3. **Enter your text** in the main text area |
|
4. **Adjust output length** (50-500 tokens) in settings |
|
5. **Customize prompts** (optional) - edit AI prompts in "Edit Context Prompts" section |
|
6. **Click "Get Suggestions"** to generate completions |
|
7. **Copy from the generated text box** (Select All + Ctrl+C/Cmd+C) |
|
|
|
### ๐ Pro Tips: |
|
- **Context Window**: Add background info, previous conversations, or references to improve suggestions |
|
- **Email**: Try starting with "Dear..." or "I hope..." + add meeting context |
|
- **Creative**: Start with "Once upon a time..." + add story background |
|
- **General**: Works great for any type of text! + add relevant context |
|
- **Output Length**: Adjust the token slider for longer or shorter completions |
|
- **Custom Prompts**: Edit the AI prompts to customize behavior for your specific needs |
|
|
|
### ๐ง Built With: |
|
- **Gradio** for the beautiful interface |
|
- **OpenAI GPT** for intelligent completions |
|
- **Python** for robust backend processing |
|
|
|
--- |
|
<div style='text-align: center; color: #666;'> |
|
Made with โค๏ธ for writers, developers, and creators everywhere |
|
</div> |
|
""") |
|
|
|
return interface |
|
|
|
|
|
def main(): |
|
"""Main function to run the application""" |
|
try: |
|
|
|
if not settings.validate_api_keys(): |
|
logger.error("No valid API keys found. Please configure your API keys.") |
|
print("โ Error: No valid API keys configured!") |
|
print("Please set OPENAI_API_KEY or ANTHROPIC_API_KEY in your .env file") |
|
return |
|
|
|
logger.info("Starting Smart Auto-Complete application...") |
|
|
|
|
|
interface = create_interface() |
|
|
|
interface.launch( |
|
server_name="0.0.0.0", |
|
server_port=7860, |
|
share=False, |
|
show_error=True, |
|
) |
|
|
|
except Exception as e: |
|
logger.error(f"Failed to start application: {str(e)}") |
|
print(f"โ Error starting application: {str(e)}") |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |
|
|