File size: 8,161 Bytes
173384d
d7ea2f7
 
173384d
 
 
 
 
 
 
 
 
 
d7ea2f7
173384d
 
 
d7ea2f7
 
 
 
 
173384d
d7ea2f7
173384d
d7ea2f7
 
173384d
 
 
d7ea2f7
173384d
d7ea2f7
 
173384d
 
 
d7ea2f7
173384d
d7ea2f7
 
173384d
 
 
d7ea2f7
173384d
d7ea2f7
 
173384d
 
 
d7ea2f7
173384d
d7ea2f7
 
173384d
 
 
 
 
 
 
d7ea2f7
 
 
 
 
 
 
173384d
 
d7ea2f7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173384d
d7ea2f7
a59fbdd
d7ea2f7
a59fbdd
d7ea2f7
 
 
 
 
 
 
a59fbdd
d7ea2f7
59ab50d
d7ea2f7
59ab50d
d7ea2f7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59ab50d
d7ea2f7
59ab50d
d7ea2f7
59ab50d
d7ea2f7
 
 
 
 
 
 
 
 
 
 
173384d
d7ea2f7
59ab50d
d7ea2f7
59ab50d
d7ea2f7
 
 
 
 
 
59ab50d
d7ea2f7
 
 
59ab50d
 
d7ea2f7
 
 
 
 
 
 
 
59ab50d
d7ea2f7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173384d
 
d7ea2f7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
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)