Erudition Logo
<< Back to EdUp Articles
AI Tutor and Prompt Engineering

August 18, 2025

Build Your Own AI Tutor

In the world of artificial intelligence, the quality of your input directly dictates the quality of your output. This simple truth is the foundation of prompt engineering, the crucial skill of crafting clear, effective instructions for AI models like Gemini. While you can learn through trial and error, a more structured approach can rapidly accelerate your progress.

One of the best ways to learn is by building a tool that teaches you. The "Prompt Enhancer" is more than just a utility; it's an interactive tutor. It doesn't just give you a better prompt—it shows you the blueprint. This article will break down how you can implement a similar tool and use it to transform yourself into a skilled prompt engineer.

"The tool creates a powerful feedback loop. You start with an idea, see it professionally enhanced, understand the principles, and apply that knowledge."

The Dual Power of a Prompt Enhancer

A well-designed prompt enhancer serves two primary functions:

Generation

It takes a basic idea and transforms it into several detailed, structured prompts, each with a different style or angle. This immediately gives you better inputs to use in your work.

Education

It deconstructs the enhancement process, explaining why the new prompts are more effective. This is where the real learning happens.

How It Teaches You: The Core Learning Mechanics

The educational value of the Prompt Enhancer comes from its ability to make abstract concepts concrete. It shows you how to move from a simple phrase like "a story about a robot" to a rich, detailed scenario by adding context, tone, persona, and constraints.

Implementing Your Own Prompt Enhancer

Building this tool is surprisingly straightforward. It consists of a simple HTML front-end and a few clever API calls to Gemini. The "magic" is orchestrated by three distinct, parallel requests to the Gemini API, all triggered when you click "Enhance Prompt."

Download the Tool

You can set this tool up in your own Gemini environment to use and modify. Copy the complete code from the expandable section below and paste it into a new immersive document.

Click to Expand/Collapse Application Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Prompt Enhancer</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
    <style>
        body {
            font-family: 'Inter', sans-serif;
        }
        .loader {
            border-color: #e5e7eb; /* A light gray for the non-animated part */
            border-top-color: #881437; /* The secondary color for the spinning part */
            -webkit-animation: spin 1s linear infinite;
            animation: spin 1s linear infinite;
        }
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
    </style>
</head>
<body class="bg-gray-100 text-gray-800">

    <div class="container mx-auto p-4 sm:p-6 md:p-8 max-w-4xl">
        <header class="p-6 rounded-xl shadow-lg shadow-[#881437]/10 flex items-center justify-start text-white" style="background-color: #005a91;">
            <img src="https://erudition.ca/images/ED%20logo%20-%20Copy.png" alt="Erudition Logo" class="h-12 mr-4 flex-shrink-0" onerror="this.style.display='none'">
            <div class="w-full text-right">
                <h1 class="text-4xl font-bold">Prompt Enhancer</h1>
                <p class="text-lg opacity-90 mt-1">Craft better prompts, get better results.</p>
            </div>
        </header>

        <main class="mt-8">
            <div class="bg-white p-6 rounded-xl shadow-lg shadow-[#881437]/10">
                <h2 class="text-2xl font-semibold mb-4 text-gray-800">Your Prompt Idea</h2>
                <textarea id="userInput" class="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#881437] focus:border-[#881437] transition duration-200" rows="4" placeholder="e.g., 'write a story about a robot'"></textarea>
                <button id="generateBtn" class="mt-4 w-full bg-blue-600 text-white font-bold py-3 px-4 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition duration-200 flex items-center justify-center">
                    <span id="btn-text">Enhance Prompt</span>
                    <div id="loader" class="loader rounded-full border-4 h-6 w-6 ml-3 hidden"></div>
                </button>
            </div>

            <div id="results" class="mt-8 hidden">
                 <div class="grid md:grid-cols-2 gap-8 mb-8">
                    <div id="promptTypeSection">
                        <h2 class="text-2xl font-semibold mb-2 text-gray-800">🔍 Identified Prompt Type</h2>
                        <p id="promptTypeText" class="text-lg font-medium p-4 rounded-lg text-[#881437] bg-[#881437]/10 border border-[#881437]/20"></p>
                    </div>
                     <div id="promptRatingSection">
                        <h2 class="text-2xl font-semibold mb-2 text-gray-800">⭐ Prompt Rating</h2>
                        <p id="promptRatingText" class="text-lg font-medium p-4 rounded-lg text-[#881437] bg-[#881437]/10 border border-[#881437]/20"></p>
                    </div>
                </div>

                <div id="enhancedPrompts" class="mb-8">
                    <h2 class="text-2xl font-semibold mb-4 text-gray-800">✨ Enhanced Prompts</h2>
                    <div id="promptList" class="space-y-4">
                        <!-- Enhanced prompts will be injected here -->
                    </div>
                </div>

                <div id="promptEducation" class="bg-white p-6 rounded-xl shadow-lg shadow-[#881437]/10">
                    <h2 class="text-2xl font-semibold mb-4 text-gray-800">🧠 How We Enhanced Your Prompt</h2>
                    <div id="educationContent" class="prose max-w-none text-gray-700">
                        <!-- Prompting education will be injected here -->
                    </div>
                </div>
            </div>
             <div id="error-message" class="hidden mt-4 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-lg" role="alert">
                <strong class="font-bold">Oops!</strong>
                <span class="block sm:inline">Something went wrong. Please try again later.</span>
            </div>
        </main>
    </div>

    <script>
        const generateBtn = document.getElementById('generateBtn');
        const userInput = document.getElementById('userInput');
        const resultsDiv = document.getElementById('results');
        const promptList = document.getElementById('promptList');
        const educationContent = document.getElementById('educationContent');
        const promptEducationDiv = document.getElementById('promptEducation');
        const loader = document.getElementById('loader');
        const btnText = document.getElementById('btn-text');
        const errorMessage = document.getElementById('error-message');
        const promptTypeText = document.getElementById('promptTypeText');
        const promptRatingText = document.getElementById('promptRatingText');

        // --- Gemini API Call Function ---
        async function callGemini(prompt, retries = 3, delay = 1000) {
            const apiKey = ""; // API key will be injected by the environment
            const apiUrl = \`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent?key=\${apiKey}\`;
            
            const payload = {
                contents: [{ role: "user", parts: [{ text: prompt }] }]
            };

            for (let i = 0; i < retries; i++) {
                try {
                    const response = await fetch(apiUrl, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(payload)
                    });

                    if (!response.ok) {
                        throw new Error(\`HTTP error! status: \${response.status}\`);
                    }

                    const result = await response.json();
                    if (result.candidates && result.candidates.length > 0 &&
                        result.candidates[0].content && result.candidates[0].content.parts &&
                        result.candidates[0].content.parts.length > 0) {
                        return result.candidates[0].content.parts[0].text;
                    } else {
                        throw new Error("Invalid response structure from API.");
                    }
                } catch (error) {
                    if (i === retries - 1) {
                         console.error("API call failed after multiple retries:", error);
                         errorMessage.classList.remove('hidden');
                         return null;
                    }
                    await new Promise(res => setTimeout(res, delay * Math.pow(2, i)));
                }
            }
        }


        generateBtn.addEventListener('click', async () => {
            const originalPrompt = userInput.value.trim();
            if (!originalPrompt) {
                alert("Please enter a prompt idea first!");
                return;
            }

            // --- UI updates for loading state ---
            generateBtn.disabled = true;
            loader.classList.remove('hidden');
            btnText.textContent = 'Generating...';
            resultsDiv.classList.add('hidden');
            errorMessage.classList.add('hidden');
            promptList.innerHTML = '';
            educationContent.innerHTML = '';

            // --- Prompts for Gemini ---
            const ratingPrompt = \`
                Analyze the user's prompt and rate its quality on a scale of Beginner, Intermediate, or Advanced.
                - **Beginner:** Lacks detail, is very short, or is ambiguous (e.g., "write a story").
                - **Intermediate:** Has some detail but could be more specific about tone, format, or context (e.g., "write a funny story about a robot who wants to be a chef").
                - **Advanced:** Is highly detailed, specific, and provides clear constraints, context, and persona (e.g., "Act as a food critic and write a humorous, scathing review of a new restaurant run by a robot chef who can only cook using motor oil and bolts.").
                Respond with ONLY the rating (Beginner, Intermediate, or Advanced).

                User Prompt: "\${originalPrompt}"
                Rating:\`;
            
            const ratingResult = await callGemini(ratingPrompt);
            const rating = ratingResult ? ratingResult.trim() : 'Intermediate'; // Default to Intermediate if rating fails
            promptRatingText.textContent = rating;

            let educationPrompt = null;
            if (rating === 'Beginner') {
                promptEducationDiv.classList.remove('hidden');
                educationPrompt = \`
                    The user provided the initial prompt: "\${originalPrompt}". I have generated several enhanced versions. Now, act as a prompt engineering expert and write a brief, educational breakdown explaining *why* the enhancements are effective. Structure your response with Markdown.

                    Start with a section titled "Key Prompting Principles". In this section, explain 3-4 core concepts like:
                    - **Specificity & Context:** Why adding details matters.
                    - **Defining the Persona/Role:** Telling the AI who to be (e.g., 'Act as an expert...').
                    - **Setting the Tone & Style:** How to guide the emotional feel of the output.
                    - **Providing Constraints & Format:** Why defining the output format (e.g., 'a list', 'a JSON object') is useful.

                    Then, add a section titled "How Your Prompt Was Improved". Analyze the user's original prompt ("\${originalPrompt}") and explain how the new, enhanced prompts apply the principles above to create a more effective result. Avoid making assumptions or using phrases like 'you probably meant' or 'you included words like'. Focus on a direct comparison between the original and the enhanced versions. Be encouraging and clear.
                \`;
            } else if (rating === 'Intermediate') {
                promptEducationDiv.classList.remove('hidden');
                educationPrompt = \`
                    The user provided an intermediate-level prompt: "\${originalPrompt}". Briefly summarize the key enhancements made in the new versions. Focus only on the main changes, like adding a specific persona, defining a clearer goal, or setting a more vivid scene. Keep it concise (2-3 sentences).
                \`;
            } else { // Advanced
                promptEducationDiv.classList.add('hidden');
            }

            const enhancementPrompt = \`
                Based on the user's initial prompt idea: "\${originalPrompt}", generate 3 distinct, enhanced prompts. Each prompt should be significantly more detailed and effective. For each prompt, provide a one-sentence "style" description. Structure the output as a JSON array of objects, where each object has "style" and "prompt" keys.
            \`;
            
            const typeIdentificationPrompt = \`
                Analyze the following user prompt and classify it into one primary category. Respond with ONLY the category name. Categories: Image or Video Generation, Creative Writing, Code Generation, Research & Summarization, Question & Answer, Text Analysis & Transformation, General Conversation. User Prompt: "\${originalPrompt}" Category:\`;

            // --- API Calls ---
            const apiCalls = [
                callGemini(enhancementPrompt),
                callGemini(typeIdentificationPrompt)
            ];

            if (educationPrompt) {
                apiCalls.push(callGemini(educationPrompt));
            }

            const [enhancedResult, typeResult, educationResult] = await Promise.all(apiCalls);


            // --- Revert UI from loading state ---
            generateBtn.disabled = false;
            loader.classList.add('hidden');
            btnText.textContent = 'Enhance Prompt';

            // --- Process and Display Results ---
            if (typeResult) {
                promptTypeText.textContent = typeResult.trim();
            } else {
                promptTypeText.textContent = "Could not be determined.";
            }

            if (enhancedResult) {
                try {
                    const cleanedJsonString = enhancedResult.replace(/```json/g, '').replace(/```/g, '').trim();
                    const prompts = JSON.parse(cleanedJsonString);

                    prompts.forEach(p => {
                        const promptCard = document.createElement('div');
                        promptCard.className = 'bg-gray-50 p-4 rounded-lg border border-gray-200';
                        
                        promptCard.innerHTML = \`
                            <p class="font-semibold text-[#881437]">\${p.style}</p>
                            <p class="my-2 text-gray-700">\${p.prompt}</p>
                            <button class="copy-btn mt-2 bg-gray-200 text-gray-700 text-sm font-medium py-1 px-3 rounded-md hover:bg-gray-300 transition duration-200" data-prompt="\${p.prompt.replace(/"/g, '&quot;')}">
                                Copy Prompt
                            </button>
                        \`;
                        promptList.appendChild(promptCard);
                    });
                } catch (e) {
                    console.error("Failed to parse enhanced prompts JSON:", e);
                    errorMessage.classList.remove('hidden');
                    promptList.innerHTML = \`<p class="text-red-500">Sorry, there was an issue generating the prompts. The model returned an unexpected format.</p>\`;
                }
            }
            
            if (educationResult) {
                let formattedEducation = educationResult
                    .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
                    .replace(/\n/g, '<br>');
                educationContent.innerHTML = formattedEducation;
            }
            
            resultsDiv.classList.remove('hidden');

            // Add event listeners to new copy buttons
            document.querySelectorAll('.copy-btn').forEach(button => {
                button.addEventListener('click', (e) => {
                    const promptText = e.target.getAttribute('data-prompt');
                    const textArea = document.createElement('textarea');
                    textArea.value = promptText;
                    document.body.appendChild(textArea);
                    textArea.select();
                    try {
                        document.execCommand('copy');
                        e.target.textContent = 'Copied!';
                        setTimeout(() => {
                            e.target.textContent = 'Copy Prompt';
                        }, 2000);
                    } catch (err) {
                        console.error('Failed to copy text: ', err);
                    }
                    document.body.removeChild(textArea);
                });
            });
        });

    </script>
</body>
</html>