Blog JSystems - uwalniamy wiedzę!
Blog JSystems - uwalniamy wiedzę!
Kurs Claude Code - Lekcja 28 z 28
Ten artykuł jest częścią bezpłatnego kursu Claude Code - największej polskojęzycznej serii 28 lekcji dla programistów. Od pierwszego uruchomienia do autonomicznych agentów AI.
<-- Spis wszystkich lekcji
Cały kod, jeden plik HTML gotowy do uruchomienia (skopiuj, wklej do pliku .html i otwórz w przeglądarce):
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wizualizator algorytmów sortowania</title>
<style>
:root{
--bg:#0f1117; --panel:#171a23; --panel2:#1e222e; --line:#2a2f3d;
--text:#e6e8ee; --muted:#9aa3b2; --accent:#6ea8fe;
--bar:#4f8cff; --cmp:#ffcc4d; --swap:#ff5c7a; --sorted:#37d67a;
}
*{box-sizing:border-box}
body{
margin:0; background:linear-gradient(180deg,#0d0f15,#12141c 40%,#0f1117);
color:var(--text); font-family:'Segoe UI',system-ui,Arial,sans-serif; padding:24px;
}
.wrap{max-width:1000px;margin:0 auto}
h1{font-size:1.4rem;margin:0 0 4px;font-weight:700}
.sub{color:var(--muted);font-size:.9rem;margin:0 0 20px}
.panel{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:18px 20px;margin-bottom:18px}
.controls{display:flex;flex-wrap:wrap;gap:18px 24px;align-items:flex-end}
.ctl{display:flex;flex-direction:column;gap:6px}
.ctl label{font-size:.75rem;color:var(--muted);text-transform:uppercase;letter-spacing:.5px}
select,button{font-family:inherit;font-size:.9rem;border-radius:9px;border:1px solid var(--line);background:var(--panel2);color:var(--text);padding:9px 14px;cursor:pointer;transition:.15s}
select{min-width:180px}
button{font-weight:600}
button:hover:not(:disabled){border-color:var(--accent);color:#fff}
button:disabled{opacity:.4;cursor:not-allowed}
#start{background:linear-gradient(135deg,#3f7bff,#5a4fff);border:none;color:#fff}
#shuffle{background:var(--panel2)}
input[type=range]{width:150px;accent-color:var(--accent);cursor:pointer}
.val{font-size:.85rem;color:var(--accent);font-weight:600;min-width:34px;display:inline-block}
.stats{display:flex;gap:26px;margin-top:2px}
.stat b{font-size:1.5rem;color:#fff;font-weight:700}
.stat span{display:block;font-size:.72rem;color:var(--muted);text-transform:uppercase;letter-spacing:.5px}
.status{color:var(--muted);font-size:.85rem;margin-left:auto}
.explain{font-size:.9rem;color:var(--muted);margin:0 0 12px;line-height:1.5}
.explain b{color:var(--text)}
.legend{display:flex;flex-wrap:wrap;gap:16px;margin:0 0 14px;font-size:.82rem}
.legend span{display:inline-flex;align-items:center;gap:7px;color:var(--muted)}
.sw{width:15px;height:15px;border-radius:4px;display:inline-block}
.chart-area{display:flex;gap:10px}
.yaxis{position:relative;width:44px;flex:0 0 44px}
.ytitle{position:absolute;left:-6px;top:50%;transform:rotate(-90deg) translateX(50%);transform-origin:left center;
font-size:.72rem;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;white-space:nowrap}
.ytick{position:absolute;right:2px;font-size:.72rem;color:var(--muted);transform:translateY(50%)}
.plot{flex:1}
.bars{height:340px;display:flex;align-items:flex-end;gap:2px;
border-left:1px solid var(--line);border-bottom:1px solid var(--line);
background:
linear-gradient(var(--line) 1px,transparent 1px) 0 0/100% 25% ;
background-position:0 100%;padding:0 2px}
.bar{flex:1 1 0;background:var(--bar);border-radius:3px 3px 0 0;transition:height .06s linear, background .06s}
.bar.cmp{background:var(--cmp)}
.bar.swap{background:var(--swap)}
.bar.sorted{background:var(--sorted)}
.xtitle{text-align:center;font-size:.72rem;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin-top:8px}
</style>
</head>
<body>
<div class="wrap">
<h1>Wizualizator algorytmów sortowania</h1>
<p class="sub">Zobacz krok po kroku, jak działają klasyczne algorytmy sortowania.</p>
<div class="panel">
<div class="controls">
<div class="ctl">
<label for="algo">Algorytm</label>
<select id="algo">
<option value="bubble">Sortowanie bąbelkowe</option>
<option value="insertion">Sortowanie przez wstawianie</option>
<option value="quick">Sortowanie szybkie (quicksort)</option>
<option value="merge">Sortowanie przez scalanie</option>
</select>
</div>
<div class="ctl">
<label for="size">Rozmiar tablicy: <span class="val" id="sizeVal">40</span></label>
<input type="range" id="size" min="5" max="120" value="40">
</div>
<div class="ctl">
<label for="speed">Prędkość: <span class="val" id="speedVal">50</span></label>
<input type="range" id="speed" min="1" max="100" value="50">
</div>
<div class="ctl">
<label> </label>
<button id="shuffle">Losuj</button>
</div>
<div class="ctl">
<label> </label>
<button id="start">Start</button>
</div>
<div class="status" id="status">Gotowe</div>
</div>
<div class="stats">
<div class="stat"><b id="cmp">0</b><span>Porównania</span></div>
<div class="stat"><b id="swp">0</b><span>Zamiany</span></div>
</div>
</div>
<div class="panel">
<p class="explain">Każdy <b>słupek to jeden element tablicy</b>, a jego <b>wysokość odpowiada jego wartości</b> (im wyższy, tym większa liczba). Sortowanie ustawia słupki rosnąco, od lewej do prawej.</p>
<div class="legend">
<span><i class="sw" style="background:var(--cmp)"></i>element porównywany</span>
<span><i class="sw" style="background:var(--swap)"></i>element zamieniany</span>
<span><i class="sw" style="background:var(--sorted)"></i>już posortowany</span>
</div>
<div class="chart-area">
<div class="yaxis" id="yaxis">
<div class="ytitle">wartość</div>
</div>
<div class="plot">
<div class="bars" id="bars"></div>
<div class="xtitle">indeks elementu w tablicy</div>
</div>
</div>
</div>
</div>
<script>
(function(){
const MAXV = 100; // maksymalna wartosc elementu (skala osi Y)
const barsEl = document.getElementById('bars');
const yaxisEl = document.getElementById('yaxis');
const cmpEl = document.getElementById('cmp');
const swpEl = document.getElementById('swp');
const statusEl = document.getElementById('status');
const algoEl = document.getElementById('algo');
const sizeEl = document.getElementById('size');
const speedEl = document.getElementById('speed');
const sizeVal = document.getElementById('sizeVal');
const speedVal = document.getElementById('speedVal');
const startBtn = document.getElementById('shuffle') && document.getElementById('start');
const shuffleBtn = document.getElementById('shuffle');
let arr = [], bars = [], running = false, token = 0;
let comparisons = 0, swaps = 0;
function delay(){ return 210 - speedEl.value * 2; } // wiekszy suwak = szybciej
const sleep = ms => new Promise(r => setTimeout(r, ms));
function buildYAxis(){
// usun stare ticki (zachowaj tytul)
yaxisEl.querySelectorAll('.ytick').forEach(e=>e.remove());
for(let p=0;p<=4;p++){
const t=document.createElement('div');
t.className='ytick';
t.style.top=(p*25)+'%';
t.textContent=Math.round(MAXV*(1-p/4));
yaxisEl.appendChild(t);
}
yaxisEl.style.height='340px';
}
function render(){
barsEl.innerHTML='';
bars=[];
for(let i=0;i<arr.length;i++){
const b=document.createElement('div');
b.className='bar';
b.style.height=(arr[i]/MAXV*100)+'%';
barsEl.appendChild(b);
bars.push(b);
}
}
function shuffle(){
if(running) return;
const n=+sizeEl.value;
arr=Array.from({length:n},()=>5+Math.floor(Math.random()*(MAXV-4)));
comparisons=0; swaps=0; updateStats();
buildYAxis(); render();
statusEl.textContent='Gotowe';
}
function updateStats(){ cmpEl.textContent=comparisons; swpEl.textContent=swaps; }
function alive(t){ return t===token && running; }
function setH(i){ bars[i].style.height=(arr[i]/MAXV*100)+'%'; }
function cls(i,c){ bars[i].className='bar'+(c?' '+c:''); }
async function compare(i,j,t){
comparisons++; updateStats();
if(bars[i]) cls(i,'cmp'); if(bars[j]) cls(j,'cmp');
await sleep(delay());
return alive(t);
}
function clear(i,j){ if(bars[i]&&!bars[i].classList.contains('sorted')) cls(i,''); if(bars[j]&&!bars[j].classList.contains('sorted')) cls(j,''); }
async function swap(i,j,t){
swaps++; updateStats();
cls(i,'swap'); cls(j,'swap');
const tmp=arr[i]; arr[i]=arr[j]; arr[j]=tmp;
setH(i); setH(j);
await sleep(delay());
return alive(t);
}
async function overwrite(i,value,t){
swaps++; updateStats();
arr[i]=value; setH(i); cls(i,'swap');
await sleep(delay());
if(!bars[i].classList.contains('sorted')) cls(i,'');
return alive(t);
}
function markSorted(i){ if(bars[i]) cls(i,'sorted'); }
// --- algorytmy (zwracaja false gdy przerwane) ---
async function bubble(t){
const n=arr.length;
for(let i=0;i<n-1;i++){
for(let j=0;j<n-1-i;j++){
if(!await compare(j,j+1,t)) return false;
if(arr[j]>arr[j+1]){ if(!await swap(j,j+1,t)) return false; }
clear(j,j+1);
}
markSorted(n-1-i);
}
markSorted(0); return true;
}
async function insertion(t){
const n=arr.length;
for(let i=1;i<n;i++){
let j=i;
while(j>0){
if(!await compare(j-1,j,t)) return false;
if(arr[j-1]>arr[j]){ if(!await swap(j-1,j,t)) return false; clear(j-1,j); j--; }
else { clear(j-1,j); break; }
}
}
for(let i=0;i<n;i++) markSorted(i);
return true;
}
async function quick(t){
async function part(lo,hi){
const pivot=arr[hi]; let i=lo-1;
for(let j=lo;j<hi;j++){
if(!await compare(j,hi,t)) return -1;
if(arr[j]<pivot){ i++; if(i!==j){ if(!await swap(i,j,t)) return -1; } clear(i,j); }
clear(j,hi);
}
if(!await swap(i+1,hi,t)) return -1;
return i+1;
}
async function qs(lo,hi){
if(lo>hi) return true;
if(lo===hi){ markSorted(lo); return true; }
const p=await part(lo,hi);
if(p<0) return false;
markSorted(p);
if(!await qs(lo,p-1)) return false;
if(!await qs(p+1,hi)) return false;
return true;
}
const ok=await qs(0,arr.length-1);
if(ok) for(let i=0;i<arr.length;i++) markSorted(i);
return ok;
}
async function merge(t){
async function ms(lo,hi){
if(lo>=hi) return true;
const mid=(lo+hi)>>1;
if(!await ms(lo,mid)) return false;
if(!await ms(mid+1,hi)) return false;
const left=arr.slice(lo,mid+1), right=arr.slice(mid+1,hi+1);
let i=0,j=0,k=lo;
while(i<left.length && j<right.length){
comparisons++; updateStats();
cls(k,'cmp'); await sleep(delay()); if(!alive(t)) return false;
if(left[i]<=right[j]){ if(!await overwrite(k,left[i],t)) return false; i++; }
else { if(!await overwrite(k,right[j],t)) return false; j++; }
k++;
}
while(i<left.length){ if(!await overwrite(k,left[i],t)) return false; i++; k++; }
while(j<right.length){ if(!await overwrite(k,right[j],t)) return false; j++; k++; }
return true;
}
const ok=await ms(0,arr.length-1);
if(ok) for(let i=0;i<arr.length;i++) markSorted(i);
return ok;
}
const ALGOS={bubble,insertion,quick,merge};
async function start(){
if(running){ return; }
// jesli juz posortowane / chcemy od nowa - odswiez kolory ale zachowaj uklad
running=true; token++; const t=token;
comparisons=0; swaps=0; updateStats();
for(let i=0;i<bars.length;i++) cls(i,'');
setControls(true);
statusEl.textContent='Sortowanie: '+algoEl.options[algoEl.selectedIndex].text;
const ok=await ALGOS[algoEl.value](t);
if(t===token){
running=false; setControls(false);
statusEl.textContent = ok ? 'Posortowane' : 'Przerwane';
}
}
function setControls(dis){
startBtn.disabled=dis; algoEl.disabled=dis; sizeEl.disabled=dis;
document.getElementById('start').textContent = dis ? 'Sortuję...' : 'Start';
}
// eventy
document.getElementById('start').addEventListener('click',start);
shuffleBtn.addEventListener('click',()=>{ token++; running=false; setControls(false); shuffle(); });
sizeEl.addEventListener('input',()=>{ sizeVal.textContent=sizeEl.value; if(!running) shuffle(); });
speedEl.addEventListener('input',()=>{ speedVal.textContent=speedEl.value; });
// init
sizeVal.textContent=sizeEl.value; speedVal.textContent=speedEl.value;
shuffle();
})();
</script>
</body>
</html>
9 czerwca 2026 roku Anthropic pokazał model, który wyłamuje się z dotychczasowego schematu. Zwykle nowa wersja jest „następcą” poprzedniej - Fable 5 został pozycjonowany o całą klasę wyżej niż Opus, w nowej rodzinie o nazwie Mythos. Na chwilę zniknął z dystrybucji (kontrole eksportu ze strony administracji USA), ale od 1 lipca 2026 jest znów dostępny - także na kontach abonamentowych. W tym artykule pokażemy, co ten model wnosi, jak wypada na benchmarkach i czym różni się od Opus 4.8. Wszystkie zrzuty pochodzą z naszego konta na claude.ai, z modelem ustawionym kolejno na Fable 5 i - dla porównania - Opus 4.8.
Ten artykuł jest częścią bezpłatnego kursu Claude Code
Zastanawiasz się, którego modelu użyć na co dzień i jak wycisnąć z niego maksimum? Zebraliśmy to w praktycznych lekcjach:
Do tej pory najmocniejsze modele Anthropic należały do klasy Opus. Fable 5 otwiera nową, wyższą klasę o nazwie Mythos. Ważne, żeby nie pomylić dwóch nazw, bo chodzi o ten sam „mózg” w dwóch wydaniach:
Zanim przejdziemy dalej, dwa pojęcia po polsku, bo będą wracać. Token to najmniejsza porcja tekstu, jaką przetwarza model - z grubsza kawałek słowa. Okno kontekstu to ilość tekstu, jaką model widzi naraz (im większe, tym więcej dokumentów, kodu czy historii rozmowy zmieści się w jednym zadaniu).
Na naszym koncie Fable 5 pojawia się w liście wyboru modeli, opisany jako „do Twoich najtrudniejszych wyzwań” - nad Opus 4.8 „do złożonych zadań”:
Od strony parametrów Fable 5 obsługuje okno kontekstu do 1 miliona tokenów i potrafi wygenerować w jednej odpowiedzi do 128 tysięcy tokenów. Przyjmuje tekst i obrazy (jest multimodalny). Ale najważniejsza zmiana nie kryje się w liczbach, tylko w tym, jak długo model potrafi pracować nad jednym zadaniem.
Chodzi o zadania agentowe o długim horyzoncie. To takie, w których model wykonuje wiele kroków po kolei, przez dłuższy czas, pilnując celu i wracając do wcześniejszych ustaleń. Anthropic podaje, że Fable „utrzymuje uwagę przez miliony tokenów” - potrafi prowadzić jedno długie, wieloetapowe zadanie bez gubienia wcześniejszych ustaleń, od pierwszego kroku aż po gotowy wynik.
Kilka innych obszarów, w których model pokazuje pazur:
Tak wygląda praca z Fable 5 w oknie rozmowy: po lewej polecenie i odpowiedź modelu, po prawej gotowy, wyrenderowany wynik (tutaj grafika, którą model przygotował na podstawie opisu):
Anthropic pokazuje Fable 5 jako model osiągający czołowe wyniki na większości testów. Dwie liczby, w których widać różnicę wobec Opus 4.8 najwyraźniej, dotyczą kodowania:
Poza kodowaniem Anthropic raportuje, że na teście FrontierCode (od twórców Cognition) Fable ma najwyższy wynik wśród czołowych modeli nawet przy średnim poziomie wysiłku, w analityce jako pierwszy przekroczył 90% (skok o 10 punktów nad Opus), a w zadaniach finansowych osiągnął najwyższy wynik w rozumowaniu na poziomie seniora. Reguła, która się z tego wyłania, jest prosta: im dłuższe i bardziej złożone zadanie, tym większa przewaga Fable. Na krótkich, prostych poleceniach różnica potrafi być niewielka - co za chwilę zobaczymy na żywym przykładzie.
Fable to nie „nowy Opus”, tylko wyższa półka za wyższą cenę. Najkrócej różnice wyglądają tak:
| Cecha | Fable 5 | Opus 4.8 |
|---|---|---|
| Pozycja | rodzina Mythos - o klasę wyżej | dotychczasowa klasa premium |
| Cena wejścia / wyjścia | 10 / 50 USD za mln tokenów | 5 / 25 USD za mln tokenów |
| Cache (odczyt / zapis) | 1,00 / 12,50 USD za mln | 0,50 / 6,25 USD za mln |
| Okno kontekstu | 1 mln tokenów | 1 mln tokenów |
| Modalności | tekst + obrazy | tekst + obrazy |
| Wysiłek rozumowania | regulowany | regulowany |
| Bezpieczeństwo | klasyfikator kieruje wrażliwe tematy do Opus 4.8; retencja 30 dni | dostępna zerowa retencja danych |
| Najlepszy do | najdłuższych, najbardziej złożonych zadań agentowych i naukowych | codziennych złożonych zadań, gdzie liczy się koszt i prywatność |
Cena jest kluczowa: Fable kosztuje mniej więcej dwa razy więcej. Opus 4.8 zostaje więc bardzo sensownym wyborem tam, gdzie liczą się koszty albo zerowa retencja danych - zresztą sam Fable używa Opusa jako „hamulca bezpieczeństwa” (o tym w następnej sekcji).
Żeby pokazać różnicę na żywo, daliśmy obu modelom dokładnie to samo polecenie przy tym samym, wysokim poziomie wysiłku: „narysuj kota jadącego na rowerze jako grafikę SVG”. To proste, żartobliwe zadanie rysowania kodem - najważniejsze, że oba modele dostały identyczne polecenie. Oto wyniki obok siebie:
Obie wersje wyszły dobrze - każdy model podszedł do tematu inaczej: Fable postawił na dynamiczną, pochyloną pozę z liniami ruchu, Opus dorzucił pełniejsze tło ze słońcem i łąką. Na tak krótkim zadaniu różnica jest w zasadzie kosmetyczna - i dobrze to ilustruje wcześniejszy wniosek: prawdziwy dystans między tymi modelami widać dopiero na długich, wieloetapowych zadaniach, a nie na jednym poleceniu.
Skoro Mythos to mocniejsza klasa, Anthropic obudował publiczny wariant dodatkowym mechanizmem. W Fable 5 działa klasyfikator (mały model pomocniczy oceniający treść zapytania), który wrażliwe zapytania - z trzech wąskich obszarów wysokiego ryzyka, wymienionych niżej - kieruje do bezpieczniejszego Opus 4.8. Wygląda to tak:
Każde Twoje polecenie przechodzi najpierw przez wbudowany klasyfikator bezpieczeństwa.
Za wrażliwe uznaje trzy tematy: cyberbezpieczeństwo ofensywne (pomoc w atakach), biologię i chemię wysokiego ryzyka oraz próby skopiowania samego modelu (tzw. distillation - „wyciągnięcie” jego zdolności, żeby wytrenować własny). Zwykłe pytania - programowanie, analiza danych, pisanie - wrażliwe nie są.
Jeśli klasyfikator wykryje temat z tych trzech obszarów, odpowiedź przejmuje Opus 4.8. Jeśli nie - a to ponad 95% sesji - odpowiada Fable 5.
Mechanizm uruchamia się rzadko: średnio w mniej niż 5% sesji. Wszystkie zapytania i odpowiedzi klasy Mythos Anthropic przechowuje u siebie przez 30 dni (to tzw. retencja danych - czas, po którym są kasowane) i nie używa ich do trenowania modeli. Odporność na obejścia zabezpieczeń wygląda solidnie - w ponad tysiącu godzin płatnego programu wyszukiwania błędów nie znaleziono uniwersalnego „jailbreaka”, a wobec 30 publicznych technik obchodzenia zabezpieczeń model nie wygenerował ani jednej szkodliwej odpowiedzi w pojedynczej turze. To także powód, dla którego Opus 4.8 - którego można używać z zerową retencją, czyli w ogóle bez zapisywania danych - bywa lepszym wyborem dla danych wrażliwych.
Cały ten artykuł zbudowaliśmy na dwóch zadaniach uruchomionych na naszym koncie - oto one w pigułce:
Z tego wychodzi praktyczna wskazówka, kiedy w ogóle sięgać po droższy model. Fable 5 zwróci swoją wyższą cenę tam, gdzie zadanie jest naprawdę długie i złożone: duży refaktor, wieloetapowa praca agentowa, trudna analiza czy badania naukowe. Do codziennych zadań, gdzie różnica jakości i tak nie przeważy dwukrotnego kosztu, Opus 4.8 albo Sonnet najczęściej w zupełności wystarczą. Warto też pamiętać, że model to jedno, a umiejętność pracy z nim to drugie - dopiero dobrze poprowadzony agent (jasny cel, kontekst, ograniczenia) pokazuje, na co go stać.
Jeśli chcesz zobaczyć na żywo, jak pracować z takimi modelami Anthropic w praktyce - od pojedynczego polecenia po zespoły agentów w narzędziu Claude Code - mamy na to konkretne szkolenie. Szczegóły o samym modelu znajdziesz też na oficjalnej stronie Anthropic.
Praca z modelami Anthropic (w tym Fable) w praktyce: polecenia, kontekst, tryby uprawnień, MCP, hooki i systemy multi-agent - na żywym kodzie podczas trzydniowego szkolenia. Prowadzi Łukasz Matuszewski. Szkolenie ma termin gwarantowany - odbędzie się niezależnie od liczby zgłoszeń.
Szkolenie Claude CodePoprzednia lekcja
<-- Lekcja 27: Claude Code vs Copilot vs CursorTo ostatnia lekcja
Wróć do spisu kursu
Komentarze (0)
Brak komentarzy...