| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <title>Semantic Kernel TicTacToe</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| </head> |
| <body class="bg-gradient-to-br from-sky-50 to-indigo-100 flex items-center justify-center min-h-screen"> |
| <div class="max-w-5xl w-full bg-white rounded-2xl shadow-lg p-6"> |
| <h1 class="text-3xl font-extrabold mb-4 text-center text-indigo-800">Semantic Kernel TicTacToe</h1> |
| <p class="text-center text-sm text-gray-600 mb-4"> |
| Source: <a href="https://www.linkedin.com/pulse/illustrated-introduction-semantic-kernel-michael-lively-yogge/" |
| class="text-blue-600 underline" target="_blank" rel="noopener"> |
| An Illustrated Introduction to Semantic Kernel (LinkedIn) |
| </a> |
| </p> |
|
|
| <div id="banner" class="hidden bg-green-100 border border-green-300 text-green-800 font-bold text-center py-2 rounded mb-4"></div> |
|
|
| <div class="flex flex-col md:flex-row items-start justify-center md:space-x-4 space-y-4 md:space-y-0"> |
| <div id="board" class="grid grid-cols-3 gap-1 border-4 border-gray-300 rounded-lg p-2 bg-white mx-auto"></div> |
| <div id="questionPanel" class="md:w-1/2 w-full bg-gray-50 rounded-lg shadow p-4"> |
| <h2 id="panelQuestion" class="text-xl font-semibold text-gray-800">Select a square to view the question</h2> |
| <ul id="panelChoices" class="mt-4 space-y-2"></ul> |
| <p id="panelHint" class="mt-3 text-sm text-gray-600 hidden"></p> |
| <button id="hintBtn" class="mt-4 px-3 py-1 bg-gray-200 text-gray-700 rounded hover:bg-gray-300">Show Hint</button> |
| </div> |
| </div> |
|
|
| <div class="flex justify-between mt-6"> |
| <p id="status" class="text-lg font-medium text-gray-800"></p> |
| <button id="restartBtn" class="px-4 py-2 bg-indigo-700 text-white rounded hover:bg-indigo-800">Restart</button> |
| </div> |
| </div> |
|
|
| <script> |
| |
| const questions = [ |
| { |
| question: 'In the article, what problem does Semantic Kernel (SK) primarily solve?', |
| choices: [ |
| 'Rendering front-end UI components', |
| 'Bridging AI intelligence with real-world actions and system integration', |
| 'Replacing databases with vector search', |
| 'Training new foundation models from scratch' |
| ], |
| answer: 2, |
| hint: 'It’s about orchestration, not model training.' |
| }, |
| { |
| question: 'Which analogy best describes SK in the article?', |
| choices: [ |
| 'AI as the conductor, SK as the audience', |
| 'SK as the conductor coordinating models (soloist) and plugins (instruments)', |
| 'Plugins as the stage, SK as the spotlight', |
| 'The Kernel as the ticket booth' |
| ], |
| answer: 2, |
| hint: 'Conductor ↔ orchestra.' |
| }, |
| { |
| question: 'What is the Kernel’s role?', |
| choices: [ |
| 'Only routes HTTP requests', |
| 'Central orchestrator that selects models, prepares prompts, calls plugins, and returns results', |
| 'Persistent data store for embeddings', |
| 'Front-end renderer for chat UIs' |
| ], |
| answer: 2, |
| hint: 'Think “mission control.”' |
| }, |
| { |
| question: 'Which is NOT listed as one of the five main components?', |
| choices: [ |
| 'AI Connectors', |
| 'Plugins', |
| 'Prompt Templates', |
| 'GPU Schedulers' |
| ], |
| answer: 4, |
| hint: 'Components include connectors, plugins, prompts, memory, planners.' |
| }, |
| { |
| question: 'AI Connectors are primarily used to…', |
| choices: [ |
| 'Switch or add models without rewriting the entire app', |
| 'Compile TypeScript to JavaScript', |
| 'Encrypt database backups', |
| 'Render SVG charts' |
| ], |
| answer: 1, |
| hint: 'They link the Kernel to Azure OpenAI/OpenAI/etc.' |
| }, |
| { |
| question: 'Plugins give the AI the power to…', |
| choices: [ |
| 'Change GPU clock speeds', |
| 'Perform real-world actions like API calls or database queries', |
| 'Alter the operating system kernel', |
| 'Format CSS variables' |
| ], |
| answer: 2, |
| hint: 'Think “tools” the model can call.' |
| }, |
| { |
| question: 'Prompt templates in SK are described as…', |
| choices: [ |
| 'Randomized prompts for model robustness', |
| 'Static instructions only', |
| 'Structured instructions blending guidance with dynamic inputs', |
| 'A replacement for function calling' |
| ], |
| answer: 3, |
| hint: 'Recipe + ingredients.' |
| }, |
| { |
| question: 'Memory in SK enables…', |
| choices: [ |
| 'GPU memory pooling', |
| 'Storing and retrieving context across interactions (e.g., via vector DBs)', |
| 'Only short-term cache of HTTP responses', |
| 'Compiling kernel modules' |
| ], |
| answer: 2, |
| hint: 'Continuity for users over time.' |
| }, |
| { |
| question: 'Planners are used for…', |
| choices: [ |
| 'Choosing CSS themes', |
| 'Breaking tasks into steps and deciding plugin call order', |
| 'Encrypting traffic between services', |
| 'Scaling Kubernetes pods' |
| ], |
| answer: 2, |
| hint: 'Multi-step task strategy.' |
| }, |
| { |
| question: 'Which sequence best matches the “How it connects” flow?', |
| choices: [ |
| 'Plugins → Planner → Memory → Connectors → Prompt → Output', |
| 'User request → Connectors/model select → Prompt template → Plugins → Memory (context) → Planner (multi-step) → Output', |
| 'User request → Memory only → Output', |
| 'Planner → Connectors → User request → Output' |
| ], |
| answer: 2, |
| hint: 'Start with the user request and end with output.' |
| }, |
| { |
| question: 'Which is a listed real-world use case in the article?', |
| choices: [ |
| 'Terraform plan generation', |
| 'Quantum circuit compilation', |
| 'Retail order/return handling via service bots', |
| '3D graphics rendering' |
| ], |
| answer: 3, |
| hint: 'Retail shows up alongside finance/healthcare/education.' |
| }, |
| { |
| question: 'What differentiates SK according to the article’s “Framework for the Future” section?', |
| choices: [ |
| 'It is locked to one provider and one memory store', |
| 'Modularity and adaptability—swap models/tools without starting from scratch', |
| 'Only supports text modality', |
| 'Requires rewriting for every model update' |
| ], |
| answer: 2, |
| hint: 'Modular, provider-agnostic design.' |
| } |
| ]; |
| |
| let currentPlayer, boardState, cellQuestions, selectedCell; |
| |
| const boardEl = document.getElementById('board'); |
| const statusEl = document.getElementById('status'); |
| const bannerEl = document.getElementById('banner'); |
| const hintBtn = document.getElementById('hintBtn'); |
| const panelQuestion = document.getElementById('panelQuestion'); |
| const panelChoices = document.getElementById('panelChoices'); |
| const panelHint = document.getElementById('panelHint'); |
| const restartBtn = document.getElementById('restartBtn'); |
| |
| function initGame() { |
| currentPlayer = 'X'; |
| boardState = Array(9).fill(''); |
| bannerEl.classList.add('hidden'); |
| statusEl.innerText = ''; |
| const shuffled = questions.sort(() => 0.5 - Math.random()); |
| cellQuestions = shuffled.slice(0, 9); |
| panelQuestion.innerText = 'Select a square to view the question'; |
| panelChoices.innerHTML = ''; |
| panelHint.classList.add('hidden'); |
| renderBoard(); |
| } |
| |
| function renderBoard() { |
| boardEl.innerHTML = ''; |
| boardState.forEach((mark, idx) => { |
| const btn = document.createElement('button'); |
| let cls = 'bg-white h-24 w-24 flex items-center justify-center text-2xl font-bold rounded-lg shadow hover:bg-gray-100'; |
| if (mark === 'X') cls += ' text-blue-600'; |
| if (mark === 'O') cls += ' text-red-600'; |
| btn.className = cls; |
| btn.innerText = mark; |
| btn.disabled = mark !== ''; |
| btn.addEventListener('click', () => openQuestion(idx)); |
| boardEl.appendChild(btn); |
| }); |
| statusEl.innerText = `Current: ${currentPlayer}`; |
| } |
| |
| function openQuestion(idx) { |
| selectedCell = idx; |
| const q = cellQuestions[idx]; |
| panelQuestion.innerText = q.question; |
| panelChoices.innerHTML = ''; |
| panelHint.classList.add('hidden'); |
| panelHint.innerText = q.hint || ''; |
| q.choices.forEach((c, i) => { |
| const li = document.createElement('li'); |
| const btn = document.createElement('button'); |
| btn.innerText = c; |
| btn.className = 'w-full text-left px-4 py-2 bg-gray-100 rounded hover:bg-gray-200'; |
| btn.addEventListener('click', () => handleAnswer(i + 1)); |
| li.appendChild(btn); |
| panelChoices.appendChild(li); |
| }); |
| } |
| |
| function handleAnswer(choice) { |
| const q = cellQuestions[selectedCell]; |
| if (choice === q.answer) { |
| boardState[selectedCell] = currentPlayer; |
| renderBoard(); |
| if (checkWin()) return endGame(`${currentPlayer} wins!`); |
| if (boardState.every(c => c)) return endGame('Stalemate!'); |
| } else { |
| alert('Incorrect! Turn missed.'); |
| } |
| currentPlayer = currentPlayer === 'X' ? 'O' : 'X'; |
| statusEl.innerText = `Current: ${currentPlayer}`; |
| } |
| |
| function checkWin() { |
| const wins = [ |
| [0,1,2],[3,4,5],[6,7,8], |
| [0,3,6],[1,4,7],[2,5,8], |
| [0,4,8],[2,4,6] |
| ]; |
| return wins.some(combo => combo.every(i => boardState[i] === currentPlayer)); |
| } |
| |
| function endGame(msg) { |
| bannerEl.innerText = `🎉 ${msg}`; |
| bannerEl.classList.remove('hidden'); |
| document.querySelectorAll('#board button').forEach(b => b.disabled = true); |
| } |
| |
| hintBtn.addEventListener('click', () => panelHint.classList.toggle('hidden')); |
| restartBtn.addEventListener('click', initGame); |
| initGame(); |
| </script> |
| </body> |
| </html> |
|
|