Svngoku's picture
Update app.py
59ab50d verified
raw
history blame
10.4 kB
import gradio as gr
from dotenv import load_dotenv
import os
import logging
from typing import Dict, Any, Optional
from proctor import (
CompositeTechnique,
RolePrompting,
ChainOfThought,
ChainOfVerification,
SelfAsk,
EmotionPrompting,
ZeroShotCoT,
list_techniques,
)
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Load environment variables
load_dotenv()
# Check for OpenRouter API key
openrouter_key = os.environ.get("OPENROUTER_API_KEY")
if not openrouter_key:
raise ValueError("OPENROUTER_API_KEY not set. Please set it in your .env file.")
# Available models and techniques
MODELS = {
"Google Gemini 2.5 Flash": "openrouter/google/gemini-2.5-flash-preview-05-20",
"Claude 4 Sonnet": "openrouter/anthropic/claude-sonnet-4",
"DeepSeek R1": "openrouter/deepseek/deepseek-r1-0528",
"Llama 4 Scout": "openrouter/meta-llama/llama-4-scout",
"Mistral Small 3.1 24B": "openrouter/mistralai/mistral-small-3.1-24b-instruct",
}
TECHNIQUES = list_techniques()
# Model configurations with optimized parameters
MODEL_CONFIGS = {
"openrouter/google/gemini-2.5-flash-preview-05-20": {
"api_base": "https://openrouter.ai/api/v1",
"api_key": openrouter_key,
"temperature": 0.3,
"max_tokens": 15000,
},
"openrouter/anthropic/claude-sonnet-4": {
"api_base": "https://openrouter.ai/api/v1",
"api_key": openrouter_key,
"temperature": 0.7,
"max_tokens": 12000,
},
"openrouter/deepseek/deepseek-r1-0528": {
"api_base": "https://openrouter.ai/api/v1",
"api_key": openrouter_key,
"temperature": 0.6,
"max_tokens": 8000,
},
"openrouter/meta-llama/llama-4-scout": {
"api_base": "https://openrouter.ai/api/v1",
"api_key": openrouter_key,
"temperature": 0.6,
"max_tokens": 12500,
},
"openrouter/mistralai/mistral-small-3.1-24b-instruct": {
"api_base": "https://openrouter.ai/api/v1",
"api_key": openrouter_key,
"temperature": 0.8,
"max_tokens": 1000,
},
}
# Composite technique definitions
TECHNIQUE_CONFIGS = {
"Expert Chain-of-Thought": CompositeTechnique(
name="Expert Chain-of-Thought",
identifier="custom-expert-cot",
techniques=[RolePrompting(), ChainOfThought(), ChainOfVerification()],
),
"Deep Reasoning Analysis": CompositeTechnique(
name="Deep Reasoning Analysis",
identifier="deep-reasoning",
techniques=[ChainOfThought(), SelfAsk(), ChainOfVerification()],
),
"ChainOfThought": ChainOfThought(),
"EmotionPrompting": EmotionPrompting(),
"RolePrompting": RolePrompting(),
"SelfAsk": SelfAsk(),
"ZeroShotCoT": ZeroShotCoT(),
}
def format_as_markdown(response: str) -> str:
"""
Format the response as Markdown for better readability.
Args:
response: The raw response text to format
Returns:
Formatted markdown string
"""
if not response:
return ""
lines = response.split("\n")
formatted_lines = []
in_list = False
for line in lines:
line = line.strip()
if not line:
in_list = False
formatted_lines.append("")
continue
# Check for headings (e.g., "Target Market:")
if line.endswith(":") and not line.startswith("-") and len(line) < 100:
formatted_lines.append(f"### {line}")
continue
# Check for list items (e.g., "- Item" or "1. Item")
if line.startswith("-") or (line and line[0].isdigit() and len(line) > 2 and line[1:3] in [". ", ".("]):
in_list = True
formatted_lines.append(line)
continue
# If not a heading or list item, treat as a paragraph
if in_list:
in_list = False
formatted_lines.append("")
formatted_lines.append(line)
return "\n".join(formatted_lines)
def validate_inputs(problem: str, technique_name: str, model_name: str) -> Optional[str]:
"""
Validate user inputs and return error message if invalid.
Args:
problem: The problem statement
technique_name: Selected technique name
model_name: Selected model name
Returns:
Error message if validation fails, None otherwise
"""
if not problem or not problem.strip():
return "Please enter a problem statement."
if technique_name not in TECHNIQUE_CONFIGS:
return f"Technique '{technique_name}' not found."
if model_name not in MODELS:
return f"Model '{model_name}' not found."
return None
def process_problem(
problem: str,
technique_name: str,
model_name: str,
role: str = "",
emotion: str = ""
) -> str:
"""
Process the problem using the selected technique and model.
Args:
problem: The problem statement to solve
technique_name: Name of the prompting technique to use
model_name: Name of the model to use
role: Role for role prompting (optional)
emotion: Emotion for emotion prompting (optional)
Returns:
Formatted response or error message
"""
# Validate inputs
validation_error = validate_inputs(problem, technique_name, model_name)
if validation_error:
return f"**Error**: {validation_error}"
technique = TECHNIQUE_CONFIGS[technique_name]
model_id = MODELS[model_name]
llm_config = MODEL_CONFIGS[model_id]
try:
# Prepare kwargs for technique execution
kwargs = {"llm_config": llm_config}
# Add technique-specific parameters
if technique_name == "RolePrompting":
kwargs["role"] = role.strip() or "Expert"
elif technique_name == "EmotionPrompting":
kwargs["emotion"] = emotion.strip() or "thoughtful and methodical"
elif technique_name == "Expert Chain-of-Thought":
kwargs["role"] = role.strip() or "Expert"
logger.info(f"Processing problem with {technique_name} using {model_name}")
response = technique.execute(problem.strip(), **kwargs)
# Format and return the response
markdown_response = format_as_markdown(response)
logger.info("Successfully processed problem")
return markdown_response
except Exception as e:
error_msg = f"Error processing request: {str(e)}"
logger.error(error_msg)
return f"**Error**: {error_msg}"
def update_input_visibility(technique: str) -> Dict[str, Any]:
"""
Update visibility of role and emotion inputs based on selected technique.
Args:
technique: Selected technique name
Returns:
Dictionary with visibility updates for inputs
"""
show_role = technique in ["RolePrompting", "Expert Chain-of-Thought"]
show_emotion = technique == "EmotionPrompting"
return {
role_input: gr.update(visible=show_role),
emotion_input: gr.update(visible=show_emotion)
}
# Create Gradio interface with improved styling
with gr.Blocks(
title="Proctor AI Prompt Engineering App",
theme=gr.themes.Soft(),
css="""
.gradio-container {
max-width: 1200px !important;
margin: auto !important;
}
"""
) as interface:
gr.Markdown(
"""
# 🤖 Proctor AI Prompt Engineering App
**Enhance your problem-solving with advanced AI prompting techniques**
Enter a problem, select a technique and model, and get intelligent responses powered by OpenRouter.
"""
)
with gr.Row():
with gr.Column(scale=2):
problem_input = gr.Textbox(
label="Problem Statement",
placeholder="e.g., How to build a sustainable house for a family of 4?",
lines=3,
max_lines=5
)
with gr.Row():
technique_dropdown = gr.Dropdown(
choices=list(TECHNIQUE_CONFIGS.keys()),
label="Prompting Technique",
value=list(TECHNIQUE_CONFIGS.keys())[0] if TECHNIQUE_CONFIGS else None
)
model_dropdown = gr.Dropdown(
choices=list(MODELS.keys()),
label="Model",
value=list(MODELS.keys())[0] if MODELS else None
)
role_input = gr.Textbox(
label="Role (for RolePrompting or Expert CoT)",
placeholder="e.g., Expert Architect",
visible=False
)
emotion_input = gr.Textbox(
label="Emotion (for EmotionPrompting)",
placeholder="e.g., thoughtful and methodical",
visible=False
)
submit_button = gr.Button(
"🚀 Generate Response",
variant="primary",
size="lg"
)
with gr.Column(scale=3):
output = gr.Markdown(
label="Response",
value="*Your response will appear here...*"
)
# Event handlers
technique_dropdown.change(
fn=update_input_visibility,
inputs=technique_dropdown,
outputs=[role_input, emotion_input]
)
submit_button.click(
fn=process_problem,
inputs=[problem_input, technique_dropdown, model_dropdown, role_input, emotion_input],
outputs=output
)
# Add examples
gr.Examples(
examples=[
["How can I improve team productivity in a remote work environment?", "Expert Chain-of-Thought", "Claude 4 Sonnet", "Management Consultant", ""],
["What are the key factors to consider when starting a tech startup?", "Deep Reasoning Analysis", "Google Gemini 2.5 Flash", "", ""],
["How do I create a sustainable garden in a small urban space?", "RolePrompting", "DeepSeek R1", "Urban Gardening Expert", ""],
],
inputs=[problem_input, technique_dropdown, model_dropdown, role_input, emotion_input],
)
# Launch the app
if __name__ == "__main__":
interface.launch(
share=True,
)