Each row below is one example the model sees before your query. Add or remove examples, change the rule, then hit Predict — the simulated model will complete the pattern using only what is in the context.
<!-- In-context learning demo: simulate few-shot pattern completion -->
<p class="hint">Add <b>input → output</b> examples below to teach the pattern, then enter a new input and hit <b>Predict</b>. No weights are updated — only the context changes.</p>
<div id="examples-container">
<div class="section-label">Context (few-shot examples)</div>
<div id="examples-list"></div>
<button id="add-example" type="button" class="ghost">+ Add example</button>
</div>
<div class="query-row">
<div class="section-label">Your query</div>
<div class="query-line">
<input id="query-input" type="text" placeholder="new input…" autocomplete="off" />
<span class="arrow">→</span>
<span id="prediction" class="prediction-box">—</span>
</div>
</div>
<div class="btns">
<button id="predict-btn" type="button">Predict</button>
<button id="reset-btn" type="button" class="ghost">Reset</button>
</div>
<div id="status" class="status"></div>
/* Layout and color styles for the ICL demo. */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .8rem; line-height: 1.5; }
.section-label { font-size: .75rem; font-weight: 700; text-transform: uppercase;
letter-spacing: .05em; color: #5a7088; margin-bottom: .35rem; }
#examples-container { background: #f4f7fa; border-radius: 10px; padding: .7rem .85rem .5rem;
margin-bottom: .7rem; }
#examples-list { display: flex; flex-direction: column; gap: .35rem; margin-bottom: .45rem; }
.example-row { display: flex; align-items: center; gap: .4rem; }
.example-row input { flex: 1; padding: .32rem .55rem; border: 1px solid #cdd9e3; border-radius: 6px;
font: 14px ui-monospace, monospace; background: #fff; }
.example-row .arrow { color: #5a7088; font-size: 1rem; }
.example-row .del-btn { background: none; border: none; color: #c92f3c; font-size: 1.1rem;
cursor: pointer; padding: 0 .2rem; line-height: 1; }
.query-row { margin-bottom: .7rem; }
.query-line { display: flex; align-items: center; gap: .5rem; }
.query-line input { flex: 1; padding: .38rem .6rem; border: 1.5px solid #1d3557; border-radius: 6px;
font: 14px ui-monospace, monospace; background: #fff; }
.arrow { color: #5a7088; font-size: 1rem; }
.prediction-box { flex: 1; min-height: 2rem; display: flex; align-items: center;
padding: .32rem .6rem; background: #e8eef3; border-radius: 6px;
font: 600 14px ui-monospace, monospace; color: #1d3557; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .4rem; }
button { font: 600 14px system-ui, sans-serif; padding: .42rem .9rem; border: 1px solid #1d3557;
background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
.status { font-size: .9rem; font-weight: 600; min-height: 1.3em; color: #0a7d33; }
.status.bad { color: #c92f3c; }
// In-context learning: adapt to a new task from prompt examples alone.
// The real mechanism uses induction heads in transformer attention layers.
const DEFAULT_EXAMPLES = [
['cat', 'feline'],
['dog', 'canine'],
['eagle', 'avian'],
];
let examples = DEFAULT_EXAMPLES.map(e => [...e]);
// Render the editable example rows.
function renderExamples() {
const list = document.getElementById('examples-list');
list.innerHTML = '';
examples.forEach((pair, i) => {
const row = document.createElement('div');
row.className = 'example-row';
const inInput = document.createElement('input');
inInput.type = 'text';
inInput.value = pair[0];
inInput.placeholder = 'input';
inInput.addEventListener('input', () => { examples[i][0] = inInput.value; });
const arrow = document.createElement('span');
arrow.className = 'arrow';
arrow.textContent = '→';
const outInput = document.createElement('input');
outInput.type = 'text';
outInput.value = pair[1];
outInput.placeholder = 'output';
outInput.addEventListener('input', () => { examples[i][1] = outInput.value; });
const del = document.createElement('button');
del.className = 'del-btn';
del.textContent = '✕';
del.title = 'Remove example';
del.addEventListener('click', () => { examples.splice(i, 1); renderExamples(); });
row.appendChild(inInput);
row.appendChild(arrow);
row.appendChild(outInput);
row.appendChild(del);
list.appendChild(row);
});
}
document.getElementById('add-example').addEventListener('click', () => {
examples.push(['', '']);
renderExamples();
});
// Predict: exact match first, then majority-vote fallback.
// This mirrors induction heads: copy the output that follows the best-matching input.
function predict(query) {
const q = query.trim().toLowerCase();
if (!q) return '';
// exact match — induction head finds the last identical token in context
for (let i = examples.length - 1; i >= 0; i--) {
if (examples[i][0].trim().toLowerCase() === q) return examples[i][1].trim();
}
// fallback: vote on outputs seen in examples
const freq = {};
examples.forEach(([inp, out]) => {
if (!inp || !out) return;
const o = out.trim();
freq[o] = (freq[o] || 0) + 1;
});
if (Object.keys(freq).length === 0) return '';
// return the most common output (majority vote)
return Object.keys(freq).reduce((a, b) => freq[a] >= freq[b] ? a : b);
}
document.getElementById('predict-btn').addEventListener('click', () => {
const q = document.getElementById('query-input').value;
const result = predict(q);
const predBox = document.getElementById('prediction');
const status = document.getElementById('status');
if (!q.trim()) {
predBox.textContent = '—';
status.textContent = 'Enter a query first.';
status.className = 'status bad';
console.log('Predict called with empty query.');
return;
}
if (!result) {
predBox.textContent = '—';
status.textContent = 'Add at least one example with an output.';
status.className = 'status bad';
console.log('No usable examples found.');
return;
}
predBox.textContent = result;
status.textContent = 'Predicted from context — no weights changed.';
status.className = 'status';
console.log('ICL prediction:', q, '→', result);
});
document.getElementById('reset-btn').addEventListener('click', () => {
examples = DEFAULT_EXAMPLES.map(e => [...e]);
renderExamples();
document.getElementById('query-input').value = '';
document.getElementById('prediction').textContent = '—';
document.getElementById('status').textContent = '';
document.getElementById('status').className = 'status';
console.log('Demo reset to defaults.');
});
renderExamples();
<!-- In-context learning demo: simulate few-shot pattern completion -->
<p class="hint">Add <b>input → output</b> examples below to teach the pattern, then enter a new input and hit <b>Predict</b>. No weights are updated — only the context changes.</p>
<div id="examples-container">
<div class="section-label">Context (few-shot examples)</div>
<div id="examples-list"></div>
<button id="add-example" type="button" class="ghost">+ Add example</button>
</div>
<div class="query-row">
<div class="section-label">Your query</div>
<div class="query-line">
<input id="query-input" type="text" placeholder="new input…" autocomplete="off" />
<span class="arrow">→</span>
<span id="prediction" class="prediction-box">—</span>
</div>
</div>
<div class="btns">
<button id="predict-btn" type="button">Predict</button>
<button id="reset-btn" type="button" class="ghost">Reset</button>
</div>
<div id="status" class="status"></div>
/* Layout and color styles for the ICL demo. */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .8rem; line-height: 1.5; }
.section-label { font-size: .75rem; font-weight: 700; text-transform: uppercase;
letter-spacing: .05em; color: #5a7088; margin-bottom: .35rem; }
#examples-container { background: #f4f7fa; border-radius: 10px; padding: .7rem .85rem .5rem;
margin-bottom: .7rem; }
#examples-list { display: flex; flex-direction: column; gap: .35rem; margin-bottom: .45rem; }
.example-row { display: flex; align-items: center; gap: .4rem; }
.example-row input { flex: 1; padding: .32rem .55rem; border: 1px solid #cdd9e3; border-radius: 6px;
font: 14px ui-monospace, monospace; background: #fff; }
.example-row .arrow { color: #5a7088; font-size: 1rem; }
.example-row .del-btn { background: none; border: none; color: #c92f3c; font-size: 1.1rem;
cursor: pointer; padding: 0 .2rem; line-height: 1; }
.query-row { margin-bottom: .7rem; }
.query-line { display: flex; align-items: center; gap: .5rem; }
.query-line input { flex: 1; padding: .38rem .6rem; border: 1.5px solid #1d3557; border-radius: 6px;
font: 14px ui-monospace, monospace; background: #fff; }
.arrow { color: #5a7088; font-size: 1rem; }
.prediction-box { flex: 1; min-height: 2rem; display: flex; align-items: center;
padding: .32rem .6rem; background: #e8eef3; border-radius: 6px;
font: 600 14px ui-monospace, monospace; color: #1d3557; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .4rem; }
button { font: 600 14px system-ui, sans-serif; padding: .42rem .9rem; border: 1px solid #1d3557;
background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
.status { font-size: .9rem; font-weight: 600; min-height: 1.3em; color: #0a7d33; }
.status.bad { color: #c92f3c; }
// In-context learning: adapt to a new task from prompt examples alone.
// The real mechanism uses induction heads in transformer attention layers.
const DEFAULT_EXAMPLES = [
['cat', 'feline'],
['dog', 'canine'],
['eagle', 'avian'],
];
let examples = DEFAULT_EXAMPLES.map(e => [...e]);
// Render the editable example rows.
function renderExamples() {
const list = document.getElementById('examples-list');
list.innerHTML = '';
examples.forEach((pair, i) => {
const row = document.createElement('div');
row.className = 'example-row';
const inInput = document.createElement('input');
inInput.type = 'text';
inInput.value = pair[0];
inInput.placeholder = 'input';
inInput.addEventListener('input', () => { examples[i][0] = inInput.value; });
const arrow = document.createElement('span');
arrow.className = 'arrow';
arrow.textContent = '→';
const outInput = document.createElement('input');
outInput.type = 'text';
outInput.value = pair[1];
outInput.placeholder = 'output';
outInput.addEventListener('input', () => { examples[i][1] = outInput.value; });
const del = document.createElement('button');
del.className = 'del-btn';
del.textContent = '✕';
del.title = 'Remove example';
del.addEventListener('click', () => { examples.splice(i, 1); renderExamples(); });
row.appendChild(inInput);
row.appendChild(arrow);
row.appendChild(outInput);
row.appendChild(del);
list.appendChild(row);
});
}
document.getElementById('add-example').addEventListener('click', () => {
examples.push(['', '']);
renderExamples();
});
// Predict: exact match first, then majority-vote fallback.
// This mirrors induction heads: copy the output that follows the best-matching input.
function predict(query) {
const q = query.trim().toLowerCase();
if (!q) return '';
// exact match — induction head finds the last identical token in context
for (let i = examples.length - 1; i >= 0; i--) {
if (examples[i][0].trim().toLowerCase() === q) return examples[i][1].trim();
}
// fallback: vote on outputs seen in examples
const freq = {};
examples.forEach(([inp, out]) => {
if (!inp || !out) return;
const o = out.trim();
freq[o] = (freq[o] || 0) + 1;
});
if (Object.keys(freq).length === 0) return '';
// return the most common output (majority vote)
return Object.keys(freq).reduce((a, b) => freq[a] >= freq[b] ? a : b);
}
document.getElementById('predict-btn').addEventListener('click', () => {
const q = document.getElementById('query-input').value;
const result = predict(q);
const predBox = document.getElementById('prediction');
const status = document.getElementById('status');
if (!q.trim()) {
predBox.textContent = '—';
status.textContent = 'Enter a query first.';
status.className = 'status bad';
console.log('Predict called with empty query.');
return;
}
if (!result) {
predBox.textContent = '—';
status.textContent = 'Add at least one example with an output.';
status.className = 'status bad';
console.log('No usable examples found.');
return;
}
predBox.textContent = result;
status.textContent = 'Predicted from context — no weights changed.';
status.className = 'status';
console.log('ICL prediction:', q, '→', result);
});
document.getElementById('reset-btn').addEventListener('click', () => {
examples = DEFAULT_EXAMPLES.map(e => [...e]);
renderExamples();
document.getElementById('query-input').value = '';
document.getElementById('prediction').textContent = '—';
document.getElementById('status').textContent = '';
document.getElementById('status').className = 'status';
console.log('Demo reset to defaults.');
});
renderExamples();
Notice that changing even one example rewires the answer immediately. The "model" here uses simple frequency counting — a toy version of what real induction heads do when they copy patterns from earlier in the context. What is striking in both cases is that no parameter was touched: the behavior changed purely because the context changed.
Comments
Loading comments...