import os from dotenv import load_dotenv import gradio as gr from proctor import ( CompositeTechnique, RolePrompting, ChainOfThought, ChainOfVerification, SelfAsk, EmotionPrompting, list_techniques, ) # Load environment variables (.env should contain OPENROUTER_API_KEY) load_dotenv() openrouter_key = os.environ.get("OPENROUTER_API_KEY") # Check API key if not openrouter_key: raise RuntimeError( "❌ OPENROUTER_API_KEY not set. Please set it in your .env file." ) # ----- Model Configs ----- MODEL_CONFIGS = { "gemini": { "model": "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": 1500, }, "claude": { "model": "openrouter/anthropic/claude-sonnet-4", "api_base": "https://openrouter.ai/api/v1", "api_key": openrouter_key, "temperature": 0.7, "max_tokens": 2000, }, "deepseek": { "model": "openrouter/deepseek/deepseek-r1-0528", "api_base": "https://openrouter.ai/api/v1", "api_key": openrouter_key, "temperature": 0.6, "max_tokens": 3000, }, "llama": { "model": "openrouter/meta-llama/llama-4-scout", "api_base": "https://openrouter.ai/api/v1", "api_key": openrouter_key, "temperature": 0.6, "max_tokens": 2500, }, "mistral": { "model": "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, }, } # ----- Tool Functions ----- def proctor_expert_cot(problem: str) -> dict: """ Chain-of-Thought, Verification, and Role Prompting on Gemini. """ technique = CompositeTechnique( name="Expert Chain-of-Thought", identifier="custom-expert-cot", techniques=[ RolePrompting(), ChainOfThought(), ChainOfVerification(), ], ) response = technique.execute( problem, llm_config=MODEL_CONFIGS["gemini"], role="Expert House Builder and Construction Manager" ) return { "model": "Google Gemini 2.5 Flash", "technique": "Expert Chain-of-Thought", "response": response } def proctor_claude_cot(problem: str) -> dict: """ Chain-of-Thought with Claude 4 Sonnet. """ technique = ChainOfThought() response = technique.execute(problem, llm_config=MODEL_CONFIGS["claude"]) return { "model": "Claude 4 Sonnet", "technique": "Chain-of-Thought", "response": response } def proctor_deepseek_reasoning(problem: str) -> dict: """ Deep reasoning with DeepSeek R1: CoT, SelfAsk, Verification. """ technique = CompositeTechnique( name="Deep Reasoning Analysis", identifier="deep-reasoning", techniques=[ ChainOfThought(), SelfAsk(), ChainOfVerification(), ], ) response = technique.execute(problem, llm_config=MODEL_CONFIGS["deepseek"]) return { "model": "DeepSeek R1", "technique": "Deep Reasoning Analysis", "response": response } def proctor_llama_emotion(problem: str) -> dict: """ Emotion Prompting with Llama 4 Scout. """ technique = EmotionPrompting() response = technique.execute( problem, llm_config=MODEL_CONFIGS["llama"], emotion="thoughtful and methodical" ) return { "model": "Llama 4 Scout", "technique": "Emotion Prompting", "response": response } def proctor_mistral_tips(problem: str) -> dict: """ Fast Role Prompting with Mistral Small (for quick suggestions). """ technique = RolePrompting() response = technique.execute( problem, llm_config=MODEL_CONFIGS["mistral"], role="Construction Project Manager" ) return { "model": "Mistral Small 3.1 24B", "technique": "Role Prompting", "response": response } # Optionally, expose a unified tool for arbitrary model/technique selection: def proctor_flexible( problem: str, model: str = "gemini", technique: str = "ChainOfThought", role: str = "", emotion: str = "" ) -> dict: """ Flexible interface for any model/technique combo. """ technique_map = { "ChainOfThought": ChainOfThought, "RolePrompting": RolePrompting, "EmotionPrompting": EmotionPrompting, "SelfAsk": SelfAsk, "ChainOfVerification": ChainOfVerification, } if technique == "CompositeExpert": tech = CompositeTechnique( name="Expert Chain-of-Thought", identifier="custom-expert-cot", techniques=[ RolePrompting(), ChainOfThought(), ChainOfVerification(), ], ) response = tech.execute(problem, llm_config=MODEL_CONFIGS[model], role=role) elif technique == "DeepReasoning": tech = CompositeTechnique( name="Deep Reasoning Analysis", identifier="deep-reasoning", techniques=[ ChainOfThought(), SelfAsk(), ChainOfVerification(), ], ) response = tech.execute(problem, llm_config=MODEL_CONFIGS[model]) else: tech_cls = technique_map.get(technique, ChainOfThought) if technique == "RolePrompting": response = tech_cls().execute(problem, llm_config=MODEL_CONFIGS[model], role=role) elif technique == "EmotionPrompting": response = tech_cls().execute(problem, llm_config=MODEL_CONFIGS[model], emotion=emotion) else: response = tech_cls().execute(problem, llm_config=MODEL_CONFIGS[model]) return { "model": MODEL_CONFIGS[model]["model"], "technique": technique, "response": response } # ----- Gradio/MCP Interface ----- with gr.Blocks() as demo: gr.Markdown("# 🏗️ Proctor AI MCP Server\nAdvanced prompt engineering tools via OpenRouter and Proctor AI.\n\n*Try from an MCP-compatible client or the web UI below!*") with gr.Tab("Gemini (Expert CoT)"): gr.Interface(fn=proctor_expert_cot, inputs=gr.Textbox(label="Problem"), outputs=gr.JSON(), allow_flagging="never") with gr.Tab("Claude 4 (Chain-of-Thought)"): gr.Interface(fn=proctor_claude_cot, inputs=gr.Textbox(label="Problem"), outputs=gr.JSON(), allow_flagging="never") with gr.Tab("DeepSeek R1 (Deep Reasoning)"): gr.Interface(fn=proctor_deepseek_reasoning, inputs=gr.Textbox(label="Problem"), outputs=gr.JSON(), allow_flagging="never") with gr.Tab("Llama 4 (Emotion Prompting)"): gr.Interface(fn=proctor_llama_emotion, inputs=gr.Textbox(label="Problem"), outputs=gr.JSON(), allow_flagging="never") with gr.Tab("Mistral (Quick Tips)"): gr.Interface(fn=proctor_mistral_tips, inputs=gr.Textbox(label="Problem (tips request)"), outputs=gr.JSON(), allow_flagging="never") with gr.Tab("Flexible (Advanced)"): model_dropdown = gr.Dropdown(choices=list(MODEL_CONFIGS.keys()), value="gemini", label="Model") technique_dropdown = gr.Dropdown( choices=["ChainOfThought", "RolePrompting", "EmotionPrompting", "SelfAsk", "ChainOfVerification", "CompositeExpert", "DeepReasoning"], value="ChainOfThought", label="Technique" ) role_input = gr.Textbox(label="Role (optional)", value="") emotion_input = gr.Textbox(label="Emotion (optional)", value="") flexible_iface = gr.Interface( fn=proctor_flexible, inputs=[gr.Textbox(label="Problem"), model_dropdown, technique_dropdown, role_input, emotion_input], outputs=gr.JSON(), allow_flagging="never" ) if __name__ == "__main__": demo.launch(mcp_server=True)