<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vikas Srivastava</title>
    <description>The latest articles on DEV Community by Vikas Srivastava (@vikassri).</description>
    <link>https://dev.to/vikassri</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1175999%2Feeeefb91-e40d-4df1-8553-cf3c5721ce56.png</url>
      <title>DEV Community: Vikas Srivastava</title>
      <link>https://dev.to/vikassri</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vikassri"/>
    <language>en</language>
    <item>
      <title>Your Agent Benchmark Pauses the World. Production Doesn't.</title>
      <dc:creator>Vikas Srivastava</dc:creator>
      <pubDate>Sun, 18 Oct 2026 09:58:10 +0000</pubDate>
      <link>https://dev.to/vikassri/your-agent-benchmark-pauses-the-world-production-doesnt-2bf3</link>
      <guid>https://dev.to/vikassri/your-agent-benchmark-pauses-the-world-production-doesnt-2bf3</guid>
      <description>&lt;h2&gt;
  
  
  Your evals assume the world holds still
&lt;/h2&gt;

&lt;p&gt;Almost every agent benchmark in wide use is turn-based. The harness hands the model an observation, the model emits an action, the harness applies the action, and then — crucially — nothing happens until the model produces its next token. The environment is a pure function of the interaction history. Time is logical, not physical.&lt;/p&gt;

&lt;p&gt;That is a deliberate and usually correct simplification. It isolates reasoning from scheduling noise, it makes runs reproducible, and it lets you compare two checkpoints without worrying that one got a slower GPU. It is also a bad model of deployment.&lt;/p&gt;

&lt;p&gt;In production, the world keeps moving while your agent thinks. A price changes between the quote and the order. A lease expires. A human answers the email you were drafting a reply to. Another replica of your own agent takes the lock you were about to take. A recent preprint, "The World Won't Wait: Evaluating and Teaching Agents Under a Live Clock," takes this mismatch as its starting point. The title names the problem precisely enough that the engineering consequences are worth spelling out on their own.&lt;/p&gt;

&lt;h2&gt;
  
  
  What wall-clock time actually breaks
&lt;/h2&gt;

&lt;p&gt;Two distinct failures get conflated under "the agent is slow," and separating them is the first useful step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Staleness.&lt;/strong&gt; An observation is a claim about the world at some instant. Turn-based harnesses make it a claim about the world &lt;em&gt;now&lt;/em&gt;, forever. Once you add a clock, every observation carries an implicit age, and the agent's context becomes a mix of fresh and expired beliefs with no visual difference between them. A log line, a search result, and a file listing taken ninety seconds apart look identical to a transformer. The model has no way to discount the stale ones unless you tell it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validity windows.&lt;/strong&gt; Some actions are only meaningful within a time band. A session token, a signed upload URL, a pagination cursor, a reservation hold, a one-time code — all of these are affordances that exist at &lt;em&gt;t&lt;/em&gt; and are gone at &lt;em&gt;t + Δ&lt;/em&gt;. In a frozen environment, a failed tool call means the agent made a mistake. In a live environment, it might just mean the agent deliberated too long.&lt;/p&gt;

&lt;p&gt;The concrete failure modes that show up once you stop freezing the world:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read-modify-write races.&lt;/strong&gt; The agent reads state, spends seconds reasoning, then writes back a value derived from a snapshot that no longer exists.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate side effects.&lt;/strong&gt; A tool call times out. The agent retries. The first call had actually succeeded, and now the customer has two orders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expired affordances.&lt;/strong&gt; The plan is right, but step four uses a handle that expired during step three.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blocking serialization.&lt;/strong&gt; The agent waits on a synchronous tool while an independent subtask could have progressed in parallel — the plan is fine, the schedule is not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deadline overrun.&lt;/strong&gt; The answer is correct and arrives after the SLA it was supposed to satisfy. Under a turn-based scorer, this is a perfect score.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What a live-clock evaluation requires
&lt;/h2&gt;

&lt;p&gt;Mechanically, there are three ways to build one, and they trade off differently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real time.&lt;/strong&gt; Run the harness against actual concurrent processes and score on wall-clock. Highest fidelity, lowest reproducibility: your numbers now depend on your serving stack, your network, and your machine's load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Virtual-but-live time.&lt;/strong&gt; Introduce a clock abstraction, let the environment advance on its own simulated ticks, and give the agent a monotonic clock it can read through the tool layer. This is the interesting design point. If the agent can query time and always gets a frozen value, you have reverted to turn-based evaluation with extra steps. The clock must be &lt;em&gt;observable&lt;/em&gt; to the agent but not &lt;em&gt;controllable&lt;/em&gt; by it, exactly like environment state. Observations must carry timestamps and the agent must be able to act on them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recorded timelines with replay.&lt;/strong&gt; Log real interactions with their timestamps, then replay them against a controllable clock for scoring. Cheap, reproducible, and it lets you sweep the agent's own latency without re-running the world.&lt;/p&gt;

&lt;p&gt;Two scoring decisions follow. First, a live-clock eval cannot report a single number. It should report a latency-accuracy curve: what fraction of tasks complete correctly within a budget, at several budgets. Second, because the interleaving of agent deliberation and environment change is nondeterministic, you need seeded scheduling and a distribution over seeds rather than one run. Some of those seeds should be adversarial — a change landing just after the agent reads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teaching, not just measuring
&lt;/h2&gt;

&lt;p&gt;Training under a live clock changes the objective, not just the test. Latency becomes part of the action space: how long to deliberate, when to re-check before committing, when to act on a stale-but-good-enough belief.&lt;/p&gt;

&lt;p&gt;Concretely, that means putting a clock reading into the observation, charging wall-clock time into the reward rather than treating it as free, and being careful about credit assignment. The outcome of an action depends on the state at the moment the action landed, not the state at episode start. Standard advantage estimation over a trajectory silently assumes those are the same, and under a live clock they are not.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do before the benchmark exists
&lt;/h2&gt;

&lt;p&gt;You do not need a research harness to get most of the benefit. Start here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Timestamp every observation&lt;/strong&gt; you put in context, and state freshness requirements in the tool description ("this cursor is valid for 60 seconds").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer compare-and-swap and idempotency keys&lt;/strong&gt; over blind writes in your tool implementations, so retries are safe by construction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make timeouts return a distinguishable unknown&lt;/strong&gt;, not a generic failure, and teach the agent to re-check rather than assume failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log wall-clock per step.&lt;/strong&gt; The histogram usually has a long tail that dominates the total, and it is often a small number of tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add one eval where the environment mutates on a timer&lt;/strong&gt; independent of your agent, and measure whether the agent notices.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Open questions
&lt;/h2&gt;

&lt;p&gt;Is live-clock performance a capability axis or a robustness axis? It plausibly needs to be reported separately, because a slower model with better staleness handling can beat a faster one on the same tasks. Reproducibility is unresolved: seeded nondeterminism may be the honest default, but the community has no convention for it yet. Transfer is unproven — latency distributions in production are heavy-tailed and machine-specific, so training on one clock may not survive another. And multi-agent settings turn the environment from a Markov decision process into a game, where the other players also own clocks.&lt;/p&gt;

</description>
      <category>transformers</category>
      <category>agents</category>
      <category>benchmark</category>
      <category>testing</category>
    </item>
    <item>
      <title>When AI Reviewers Find More Bugs Than Teams Can Fix</title>
      <dc:creator>Vikas Srivastava</dc:creator>
      <pubDate>Sun, 18 Oct 2026 09:57:29 +0000</pubDate>
      <link>https://dev.to/vikassri/when-ai-reviewers-find-more-bugs-than-teams-can-fix-4pgk</link>
      <guid>https://dev.to/vikassri/when-ai-reviewers-find-more-bugs-than-teams-can-fix-4pgk</guid>
      <description>&lt;h2&gt;
  
  
  The bottleneck moved from finding defects to closing them
&lt;/h2&gt;

&lt;p&gt;For most of the history of software engineering, the hard part of quality assurance has been discovery. Static analyzers, fuzzers, and human reviewers all share a common failure mode: they miss things. Teams invested enormous effort in raising recall — more coverage, more instrumentation, more reviewers — because a bug you never find is a bug you never fix.&lt;/p&gt;

&lt;p&gt;The PostgreSQL 19 release cycle reportedly slipped for the opposite reason. AI-assisted review surfaced more candidate defects than the maintainers could triage and fix inside the release window. That inverts the usual assumption. It also generalizes: any project that wires a high-recall machine reviewer into a process whose throughput is set by human triage will eventually hit the same wall.&lt;/p&gt;

&lt;h2&gt;
  
  
  A review pipeline is a queue, and the queue is the release gate
&lt;/h2&gt;

&lt;p&gt;Model the review process as a queueing system. Candidate defects arrive at some rate. Each one costs a human some amount of time to triage, and the real ones cost additional time to fix and verify. If the arrival rate exceeds the service rate, the backlog grows without bound.&lt;/p&gt;

&lt;p&gt;What makes this sharp in practice is that release criteria are usually defined over the queue, not over the arrival rate. "No known release-blocking defects" is a statement about the state of the backlog. So a tool that doubles discovery without changing triage or fix capacity does not make the software better faster. It makes the release later, because the gate cannot close until the queue drains.&lt;/p&gt;

&lt;p&gt;This is a throughput mismatch, not a tooling failure. The tool is doing what it was asked to do. The process around it was sized for a world where discovery was the constraint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why machine review inflates the queue faster than it drains it
&lt;/h2&gt;

&lt;p&gt;Several mechanisms compound.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Generation is cheap; falsification is expensive.&lt;/strong&gt; A model can emit a plausible-sounding defect report in milliseconds. Deciding whether it is real requires reading surrounding code, understanding intent, building or reproducing, and often asking the original author. The cost asymmetry is several orders of magnitude.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reviewers are tuned for recall, and recall buys precision loss.&lt;/strong&gt; Any detector optimized not to miss things will produce a long tail of low-confidence findings. Each one still costs a human minutes to dismiss, and dismissal is invisible work that produces no artifact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicates multiply.&lt;/strong&gt; Multiple detectors, multiple prompts, multiple runs on the same diff will surface the same root cause repeatedly. Without clustering by root cause, N tools produce roughly N times the triage load for one bug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Findings without reproducers are not actionable.&lt;/strong&gt; "This looks like a race" is a hypothesis. A failing input or a deterministic interleaving is a work item. The former consumes triage time; the latter consumes fix time. Conflating them hides where the capacity actually goes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Severity is uncalibrated.&lt;/strong&gt; Models have no shared notion of what blocks a release. Without a severity gate, everything is nominally a candidate blocker, and the queue never has a floor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Some findings are not bugs.&lt;/strong&gt; A reviewer can correctly identify that a code path is fragile, under-documented, or relies on an invariant nobody enforces. Those are real observations that cannot be resolved by a patch. They need a design decision, which is a different and much slower process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The net effect: the queue grows in units of human attention, and human attention is the one input the tool cannot supply.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing the pipeline so the queue stays drainable
&lt;/h2&gt;

&lt;p&gt;The goal is not to suppress findings. It is to convert findings into work at a rate the team can absorb, and to make the conversion itself cheap.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deduplicate by root cause, not by text similarity.&lt;/strong&gt; Cluster findings that point at the same line, the same invariant, or the same failing input, and present one entry per cluster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Require evidence before human triage.&lt;/strong&gt; A finding enters the human queue only with a reproducer, a failing test, or a concrete input. Everything else goes to a machine-triaged backlog.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rank by reachability and blast radius.&lt;/strong&gt; A defect in a hot path that ships to users outranks a defect in a rarely exercised error branch, regardless of how confident the model is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make the fix, not the finding, the unit of work.&lt;/strong&gt; Auto-generated candidate patches are useful because they let a human verify rather than author. Verification is faster than construction, and it keeps accountability with the person who merges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cap work in progress.&lt;/strong&gt; An unbounded queue destroys prioritization. Explicit WIP limits force the team to decide what actually blocks the release.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure precision per detector and turn off the noisy ones.&lt;/strong&gt; If a detector's findings are dismissed more than some fraction of the time, it is consuming capacity, not adding safety.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Verification is the scarce resource, and that is the real story
&lt;/h2&gt;

&lt;p&gt;The same pattern shows up wherever models generate artifacts faster than humans can check them: generated code, generated tests, generated pull requests. Generation has become abundant. Verification has not, and there is no obvious reason it will, because verification requires the very judgment that makes the work hard in the first place.&lt;/p&gt;

&lt;p&gt;That reframes what these tools are for. A reviewer that finds more bugs is only useful if the pipeline can turn findings into merged fixes. Otherwise it is a machine for manufacturing guilt — a growing list of known problems that nobody has time to address.&lt;/p&gt;

&lt;p&gt;The open questions are uncomfortable. Can models be calibrated to emit only high-precision findings, or is triage itself the thing to automate, with a second model filtering the first? Who owns a regression that an AI reviewer flagged and a human dismissed? Does a backlog of machine-found defects eventually get paid down, or does it become a permanent, growing liability that teams learn to ignore? And how do you measure any of this — findings per change, triage minutes per finding, precision at the release-blocking threshold — in a way that tells you whether the tool is actually helping?&lt;/p&gt;

&lt;p&gt;The queue is the artifact. Everything else is upstream of it.&lt;/p&gt;

</description>
      <category>transformers</category>
      <category>rag</category>
      <category>promptengineering</category>
      <category>postgres</category>
    </item>
    <item>
      <title>When AI Reviewers Find More Bugs Than Maintainers Can Fix</title>
      <dc:creator>Vikas Srivastava</dc:creator>
      <pubDate>Sun, 18 Oct 2026 09:38:35 +0000</pubDate>
      <link>https://dev.to/vikassri/when-ai-reviewers-find-more-bugs-than-maintainers-can-fix-1pae</link>
      <guid>https://dev.to/vikassri/when-ai-reviewers-find-more-bugs-than-maintainers-can-fix-1pae</guid>
      <description>&lt;h2&gt;
  
  
  The bottleneck moved, and nobody re-planned for it
&lt;/h2&gt;

&lt;p&gt;For most of the history of software quality, finding bugs was the expensive part. You wrote tests, you ran fuzzers, you paid a security firm, you waited for a user to file a weird crash report. Fixing was comparatively cheap: once a defect is isolated with a reproduction, a competent maintainer can usually reason about it and write a patch.&lt;/p&gt;

&lt;p&gt;AI-assisted review breaks that assumption. A language model reading a diff, or an agent that can execute code and mutate inputs, can generate candidate defects far faster than a human reviewer can evaluate them. The output is not a finished bug report. It is a claim: &lt;em&gt;this code may be wrong, for this reason, under these conditions.&lt;/em&gt; Some fraction of those claims are correct and important. Some fraction are correct but already known. Some fraction are technically true but irrelevant. And some fraction are confidently wrong.&lt;/p&gt;

&lt;p&gt;The Postgres 19 release slipping because AI reviewers surfaced more issues than the project could work through is the visible version of a dynamic that is quietly arriving in every large codebase. The headline sounds like a success story for AI. It is closer to a queueing problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AI review produces a flood, not a fix
&lt;/h2&gt;

&lt;p&gt;To see why, it helps to be precise about the mechanism. There are two distinct techniques getting lumped together.&lt;/p&gt;

&lt;p&gt;The first is &lt;strong&gt;static review by a language model&lt;/strong&gt;. You feed a diff plus surrounding context and ask for defects. This scales trivially — you can run it on every commit, with several models, at several temperatures, and get several different answers. Recall goes up. So does noise. These systems cannot run the test suite, cannot check whether a code path is reachable in production, and cannot know that the project deliberately made a tradeoff four years ago. They are pattern matchers over text that resembles buggy code.&lt;/p&gt;

&lt;p&gt;The second is &lt;strong&gt;agentic or fuzzing-based discovery&lt;/strong&gt;, where the model writes inputs, runs the program, observes crashes or assertion failures, and iterates. This is slower and more expensive per finding, but the findings tend to be reproducible, because the agent had to actually trigger the failure to report it.&lt;/p&gt;

&lt;p&gt;The first technique is what generates the flood. And a flood of unreproduced claims is the worst possible input to a review process, because evaluating a claim costs almost as much as fixing the bug if the claim is real.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes a finding actionable
&lt;/h2&gt;

&lt;p&gt;A bug report is a unit of work, and its cost is dominated by triage. The properties that make one cheap to process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reproducibility.&lt;/strong&gt; A failing test case, a minimal input, a stack trace. Anything the maintainer can run in under a minute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reachability.&lt;/strong&gt; Evidence the code path is actually exercised, not just theoretically present.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Severity framing.&lt;/strong&gt; Data corruption and remote crashes are different from a misleading log line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deduplication.&lt;/strong&gt; Ten reports of the same off-by-one are one report. Models are extremely good at rediscovering the same issue across runs and across files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provenance.&lt;/strong&gt; Which model, which prompt, which commit — so you can calibrate trust in the source over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most AI review output has none of these by default. It arrives as prose. Someone has to turn prose into a ticket, and that someone is a maintainer who would rather be writing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The practical implications
&lt;/h2&gt;

&lt;p&gt;If you are running AI review on your own repository, the design decisions that matter are mostly about queue management, not model quality.&lt;/p&gt;

&lt;p&gt;Run review in a branch or a shadow pipeline and &lt;strong&gt;do not auto-file issues&lt;/strong&gt;. Auto-filing converts model output directly into human obligation, which is how you burn out a team.&lt;/p&gt;

&lt;p&gt;Cluster before you surface. Embed the findings, dedupe by similarity, and rank by a signal you trust — reachability, whether the flagged line changed recently, whether the file has a history of defects. A ranked list of twenty beats an unranked list of two hundred.&lt;/p&gt;

&lt;p&gt;Prefer the expensive agent that reproduces over the cheap one that speculates, at least for anything you intend to act on. A finding with a failing test attached is worth an order of magnitude more than a finding with a paragraph attached.&lt;/p&gt;

&lt;p&gt;Budget for remediation, not detection. Detection is now nearly free and getting cheaper. The line item that grows is engineer hours spent reading, reproducing, and patching — plus the regression risk of landing a large batch of fixes under time pressure, which is its own kind of hazard in a project with a long backpatch history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open questions
&lt;/h2&gt;

&lt;p&gt;Who is accountable for a defect that a model reported, a human deprioritized, and an attacker later exploited? Disclosure norms assume a reporter and a maintainer. Adding a third party that can generate findings at arbitrary volume, with no stake in the project, has no precedent.&lt;/p&gt;

&lt;p&gt;Can the same tooling that finds bugs help fix them? Early experience suggests models are better at locating a defect than at producing a patch that respects a codebase's conventions and does not introduce a subtler problem. Reviewing a generated patch is cheaper than writing one, but not free.&lt;/p&gt;

&lt;p&gt;And the calibration question: how do you know your reviewer's precision? Without a labeled set of known-real and known-false findings from your own repository, you cannot set a threshold, and you will either drown in noise or ignore real defects. Building that set is unglamorous work, and it is probably the highest-leverage thing a team adopting AI review can do first.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>rag</category>
      <category>promptengineering</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Build a Tiny Causal Transformer from Scratch</title>
      <dc:creator>Vikas Srivastava</dc:creator>
      <pubDate>Sun, 18 Oct 2026 05:44:07 +0000</pubDate>
      <link>https://dev.to/vikassri/build-a-tiny-causal-transformer-from-scratch-2hhj</link>
      <guid>https://dev.to/vikassri/build-a-tiny-causal-transformer-from-scratch-2hhj</guid>
      <description>&lt;h2&gt;
  
  
  The concrete problem: predicting the next token
&lt;/h2&gt;

&lt;p&gt;A language model has a simple training objective: given a sequence of tokens, predict the token that comes next. In a character-level model, a token is one character, so the task might be predicting &lt;code&gt;e&lt;/code&gt; after &lt;code&gt;th&lt;/code&gt;. The same objective applies when tokens represent words or subword pieces; only the vocabulary and sequence length change.&lt;/p&gt;

&lt;p&gt;The engineering challenge is making each prediction depend on the useful parts of the preceding context without allowing the model to read the future. During training, the model receives many positions at once, but the prediction at position 10 must be based only on positions 1 through 10. This information boundary is what makes the model causal.&lt;/p&gt;

&lt;p&gt;We can build a small causal transformer to make that mechanism tangible. It will read a text file, encode characters as integers, train on randomly selected context windows, and generate new text one character at a time. Because every component is visible, the relationship between the data, objective, architecture, and generated output is easier to inspect than in a large prebuilt system.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The model first maps each token ID to a learned vector. Token IDs themselves have no useful numeric meaning, so the embedding gives each character a trainable representation. It adds a learned positional vector because attention alone does not know whether a token appeared first or last. The resulting sequence is passed through transformer blocks, with one vector for each position.&lt;/p&gt;

&lt;p&gt;Each attention head creates queries, keys, and values by multiplying the token representations by learned matrices. Query-key dot products measure which earlier positions are relevant to the current position; softmax turns those scores into weights; the weighted values are combined into a new representation. Different heads can learn different relationships, such as nearby character patterns or recurring delimiters.&lt;/p&gt;

&lt;p&gt;Causal masking is the critical constraint. Before softmax, positions to the right of each token receive negative infinity, so their probability becomes zero. During training, every position can therefore predict its next token in parallel while still obeying the same information boundary used during generation. Without this mask, the model could use the answer it is supposed to predict and would not be learning the intended task.&lt;/p&gt;

&lt;p&gt;A block adds the attention result back to its input, then applies a position-wise feed-forward network and another residual connection. Layer normalization stabilizes these transformations. The final linear layer converts each hidden vector into logits over the vocabulary, and cross-entropy compares those logits with the known next characters. The training target is the input sequence shifted one position to the left: each character supplies context for the character that follows it.&lt;/p&gt;

&lt;p&gt;Here is a complete miniature implementation. Put training text in &lt;code&gt;input.txt&lt;/code&gt;; the code uses only PyTorch and the Python standard library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.nn&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.nn.functional&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;

&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manual_seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cuda&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;chars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;stoi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="n"&gt;itos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stoi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;stoi&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batch_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;starts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;starts&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;starts&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head_size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tril&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ones&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;
        &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;masked_fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-inf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Block&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;heads&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;heads&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;heads&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ModuleList&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;heads&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ReLU&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                                &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LayerNorm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LayerNorm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;n1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;heads&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;n2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;heads&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Block&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;heads&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lm_head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LayerNorm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;logits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lm_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;targets&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cross_entropy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loss&lt;/span&gt;
    &lt;span class="nd"&gt;@torch.no_grad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;block_size&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
            &lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;self&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;probs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;multinomial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;opt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;optim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AdamW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;lr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3e-4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zero_grad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_to_none&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;itos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;batch&lt;/code&gt; function selects independent windows and creates the shifted targets. The &lt;code&gt;generate&lt;/code&gt; method uses only the most recent &lt;code&gt;block_size&lt;/code&gt; characters, computes probabilities for the final position, samples one character, and appends it before repeating. That loop is the training objective made operational: predict one next token, then use it as part of the next context.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the evidence actually shows
&lt;/h2&gt;

&lt;p&gt;This experiment demonstrates the architecture, not a competitive language model. On a small corpus, the model can learn spelling patterns, punctuation, local syntax, and recurring sequences; with enough capacity and training, it may mostly memorize the data. A convincing-looking sample can therefore reflect familiarity with the corpus rather than broad language understanding.&lt;/p&gt;

&lt;p&gt;The useful evidence is in the loss and generated samples. Training loss should generally decline, while validation loss reveals whether the model is learning reusable structure or simply fitting the training text. The two views answer different questions: training loss describes optimization on seen examples, while validation loss tests behavior on held-out positions from the same data source.&lt;/p&gt;

&lt;p&gt;If generated output becomes coherent only on familiar phrases, the model has learned distributional regularities but not robust generalization. Conversely, imperfect samples do not necessarily mean the mechanism is wrong; the corpus, number of updates, vocabulary, and context length all shape what the small model can learn. Samples are most useful when read alongside the loss.&lt;/p&gt;

&lt;p&gt;The original transformer result established that attention-based sequence models could replace recurrent computation for major sequence tasks. Subsequent systems showed that increasing data, parameters, context, and training quality can produce much broader capabilities, but those results do not imply that a four-layer toy model will reason like a production model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using it
&lt;/h2&gt;

&lt;p&gt;Start with a corpus large enough to fill many context windows, but small enough that iteration is quick. Plain text is useful because character tokenization removes vocabulary and tokenizer dependencies; it is also inefficient, since common words consume many positions. The character vocabulary is easy to inspect, but the model must spend several predictions spelling a word that a subword tokenizer might represent more compactly.&lt;/p&gt;

&lt;p&gt;Watch the loss rather than treating a single sample as a metric. Add a validation batch and periodically evaluate it with &lt;code&gt;model.eval()&lt;/code&gt; and &lt;code&gt;torch.no_grad()&lt;/code&gt; in a real experiment. Save checkpoints containing &lt;code&gt;model.state_dict()&lt;/code&gt; and the optimizer state so an interrupted run can resume. A checkpoint also lets you compare generations from the same trained state instead of accidentally comparing different training runs.&lt;/p&gt;

&lt;p&gt;Change one variable at a time. Increase &lt;code&gt;dim&lt;/code&gt; or the number of heads to test capacity, increase &lt;code&gt;block_size&lt;/code&gt; to test longer dependencies, and adjust the learning rate before simply training longer. The attention matrix is also worth inspecting: it can show whether heads focus locally, attend to delimiters, or spread attention across the available context. Such inspection connects an abstract matrix operation to recognizable patterns in the text.&lt;/p&gt;

&lt;p&gt;For reproducible comparisons, fix the random seed, keep the train/validation split stable, and record the parameter count, corpus, context length, and number of optimization steps. Generation temperature belongs to sampling, not training: lower values make output more predictable, while higher values explore lower-probability tokens. Keeping sampling settings fixed prevents a change in temperature from being mistaken for a change in model quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations and failure modes
&lt;/h2&gt;

&lt;p&gt;This implementation omits several production necessities. It uses character tokens, no dropout, no learning-rate schedule, no mixed precision, no distributed training, and no efficient attention kernel. Its feed-forward activation and normalization order are also deliberately simple. These omissions keep the implementation readable, but they also mean that training behavior and performance should not be generalized to larger systems.&lt;/p&gt;

&lt;p&gt;Small datasets make memorization likely, and random context sampling can hide problems with document boundaries or duplicated text. A model may achieve a lower loss by exploiting formatting artifacts without learning the behavior you care about. Always inspect held-out examples and check whether generated text reproduces sensitive training material. Random windows can also mix contexts in ways that are convenient for training but do not represent the original document task.&lt;/p&gt;

&lt;p&gt;The code assumes &lt;code&gt;input.txt&lt;/code&gt; is longer than the context window and that its encoding is valid UTF-8. Larger models also make the quadratic attention cost visible: a sequence twice as long requires roughly four times as many pairwise attention scores per layer, before memory and optimization overheads. The context window therefore affects both what the model can connect and how expensive each forward pass becomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to watch
&lt;/h2&gt;

&lt;p&gt;The next useful step is not adding arbitrary layers; it is measuring what each change buys. Compare character and subword tokenization, visualize attention under controlled prompts, and test whether validation loss improves when the corpus contains longer-range structure. A controlled prompt makes it easier to distinguish a stable attention pattern from an appealing interpretation of one random sample.&lt;/p&gt;

&lt;p&gt;From there, implement checkpointing and evaluation before scaling. A transformer becomes easier to reason about when its data pipeline, objective, masking rule, and sampling procedure are all small enough to inspect. Each change should have a corresponding observation: a loss curve, a held-out example, an attention visualization, or a generation under fixed sampling settings.&lt;/p&gt;

&lt;p&gt;That discipline turns the miniature model into more than a toy. It provides a compact environment for asking concrete questions about context, capacity, optimization, and data quality, while keeping the code short enough that the answer can be traced back to a particular component.&lt;/p&gt;

</description>
      <category>transformers</category>
      <category>pytorch</category>
      <category>languagemodels</category>
    </item>
  </channel>
</rss>
