{
  "source_file": "0930",
  "source_platform": "Dev.to",
  "author": "Vuk Rosić",
  "title_listed": "Attention Mechanism Tutorial: From Simple to Advanced",
  "keywords": "",
  "domain": "大模型算法",
  "content_type": "深度技术解析",
  "is_paid_flag": "否",
  "url": "https://dev.to/vuk_rosic/attention-mechanism-tutorial-from-simple-to-advanced-1260",
  "publish_date": "2025-07-06",
  "corpus_stage": "",
  "notes": "",
  "id": "55a36937fd83",
  "collected_at": "2026-10-02T14:06:39",
  "title": "Attention Mechanism Tutorial: From Simple to Advanced - DEV Community",
  "body_markdown": "Part 1: The Core Idea\nAttention is like a spotlight\n- it helps models focus on what's important.\nimport\ntorch\nimport\ntorch.nn.functional\nas\nF\n# Simple example: Which word is most important?\nsentence\n=\n[\n\"\nI\n\"\n,\n\"\nlove\n\"\n,\n\"\npizza\n\"\n]\nimportance\n=\ntorch\n.\ntensor\n([\n0.1\n,\n0.3\n,\n0.6\n])\n# pizza is most important\nEnter fullscreen mode\nExit fullscreen mode\nIntuition\n: Instead of treating all words equally, attention assigns different weights to focus on what matters most.\nPart 2: Basic Attention Weights\n# Raw attention scores (how much to focus on each word)\nscores\n=\ntorch\n.\ntensor\n([\n2.0\n,\n1.0\n,\n3.0\n])\n# [I, love, pizza]\n# Convert to probabilities (softmax)\nweights\n=\nF\n.\nsoftmax\n(\nscores\n,\ndim\n=\n0\n)\nprint\n(\nweights\n)\n# [0.24, 0.09, 0.67] - pizza gets most attention\nEnter fullscreen mode\nExit fullscreen mode\nWhat happened\n: Softmax converts raw scores to probabilities that sum to 1.\nPart 3: Weighted Combination\n# Word representations (simplified vectors)\nwords\n=\ntorch\n.\ntensor\n([[\n1.0\n,\n0.0\n],\n# \"I\"\n[\n0.0\n,\n1.0\n],\n# \"love\"\n[\n1.0\n,\n1.0\n]])\n# \"pizza\"\n# Apply attention weights\nattended\n=\ntorch\n.\nsum\n(\nweights\n.\nunsqueeze\n(\n1\n)\n*\nwords\n,\ndim\n=\n0\n)\nprint\n(\nattended\n)\n# Mostly \"pizza\" representation\nEnter fullscreen mode\nExit fullscreen mode\nIntuition\n: We combine all word vectors, but \"pizza\" contributes most because it has the highest attention weight.\nPart 4: Computing Attention Scores\n# How similar are words? (dot product)\nquery\n=\ntorch\n.\ntensor\n([\n1.0\n,\n1.0\n])\n# What we're looking for\nkey1\n=\ntorch\n.\ntensor\n([\n1.0\n,\n0.0\n])\n# \"I\"\nkey2\n=\ntorch\n.\ntensor\n([\n0.0\n,\n1.0\n])\n# \"love\"\nscore1\n=\ntorch\n.\ndot\n(\nquery\n,\nkey1\n)\n# 1.0\nscore2\n=\ntorch\n.\ndot\n(\nquery\n,\nkey2\n)\n# 1.0\nEnter fullscreen mode\nExit fullscreen mode\nTheory\n: Attention scores measure how well a query matches each key.\nPart 5: The Q, K, V Concept\n# Three roles for each word:\n# Q (Query): \"What am I looking for?\"\n# K (Key): \"What do I represent?\" \n# V (Value): \"What information do I carry?\"\nquery\n=\ntorch\n.\ntensor\n([\n1.0\n,\n0.0\n])\n# Looking for subject\nkeys\n=\ntorch\n.\ntensor\n([[\n1.0\n,\n0.0\n],\n# \"I\" - matches query well\n[\n0.0\n,\n1.0\n]])\n# \"love\" - doesn't match\nvalues\n=\ntorch\n.\ntensor\n([[\n2.0\n,\n3.0\n],\n# \"I\" carries this info\n[\n1.0\n,\n4.0\n]])\n# \"love\" carries this info\nEnter fullscreen mode\nExit fullscreen mode\nIntuition\n: Query asks \"what do I need?\", Keys answer \"what do I offer?\", Values provide the actual information.\nPart 6: One-Line Attention\n# Complete attention in one line\nattention_output\n=\ntorch\n.\nsum\n(\nF\n.\nsoftmax\n(\ntorch\n.\nmv\n(\nkeys\n,\nquery\n),\ndim\n=\n0\n).\nunsqueeze\n(\n1\n)\n*\nvalues\n,\ndim\n=\n0\n)\nEnter fullscreen mode\nExit fullscreen mode\nWhat it does\n: Computes scores (query·keys), applies softmax, weights the values.\nPart 7: Self-Attention Intuition\n# In self-attention, each word can attend to every other word\nsentence\n=\n[\n\"\nThe\n\"\n,\n\"\ncat\n\"\n,\n\"\nsat\n\"\n]\n# \"cat\" might attend to \"sat\" (what did the cat do?)\n# \"sat\" might attend to \"cat\" (who sat?)\nEnter fullscreen mode\nExit fullscreen mode\nKey insight\n: Words can look at each other to understand relationships and context.\nPart 8: Multi-Head Attention (Simple)\n# Multiple \"attention heads\" look for different things\nhead1_query\n=\ntorch\n.\ntensor\n([\n1.0\n,\n0.0\n])\n# Looking for subjects\nhead2_query\n=\ntorch\n.\ntensor\n([\n0.0\n,\n1.0\n])\n# Looking for actions\n# Each head focuses on different aspects\nEnter fullscreen mode\nExit fullscreen mode\nWhy multiple heads\n: Different heads can specialize in different types of relationships (subject-verb, adjective-noun, etc.).\nPart 9: Scaling Up\n# Real sentences have many words\nseq_len\n=\n10\n# 10 words in sentence\nd_model\n=\n64\n# Each word is 64-dimensional vector\n# Q, K, V matrices transform word vectors\nQ\n=\ntorch\n.\nrandn\n(\nseq_len\n,\nd_model\n)\n# Queries for each word\nK\n=\ntorch\n.\nrandn\n(\nseq_len\n,\nd_model\n)\n# Keys for each word\nV\n=\ntorch\n.\nrandn\n(\nseq_len\n,\nd_model\n)\n# Values for each word\nEnter fullscreen mode\nExit fullscreen mode\nScale\n: Real models use hundreds of dimensions and thousands of words.\nPart 10: Attention Matrix\n# Attention scores between all word pairs\nattention_scores\n=\ntorch\n.\nmm\n(\nQ\n,\nK\n.\ntranspose\n(\n0\n,\n1\n))\n# [10, 10] matrix\nattention_weights\n=\nF\n.\nsoftmax\n(\nattention_scores\n,\ndim\n=\n1\n)\n# Each row sums to 1\n# Row i, column j = how much word i attends to word j\nEnter fullscreen mode\nExit fullscreen mode\nVisualization\n: Each row shows where one word \"looks\" in the sentence.\nPart 11: Why Attention Works\n# Traditional RNN: Information flows sequentially\n# Word 1 → Word 2 → Word 3 → Word 4\n# Attention: All words can interact directly\n# Word 1 ↔ Word 2 ↔ Word 3 ↔ Word 4\nEnter fullscreen mode\nExit fullscreen mode\nAdvantage\n: No information loss over long distances, parallel processing.\nPart 12: Putting It All Together\n# Complete self-attention step by step\ndef\nsimple_attention\n(\nX\n):\nQ\n=\nX\n# Queries (simplified)\nK\n=\nX\n# Keys\nV\n=\nX\n# Values\nscores\n=\ntorch\n.\nmm\n(\nQ\n,\nK\n.\ntranspose\n(\n0\n,\n1\n))\n# Compute similarities\nweights\n=\nF\n.\nsoftmax\n(\nscores\n,\ndim\n=\n1\n)\n# Convert to probabilities\noutput\n=\ntorch\n.\nmm\n(\nweights\n,\nV\n)\n# Weighted combination\nreturn\noutput\n# Usage\nword_vectors\n=\ntorch\n.\nrandn\n(\n5\n,\n8\n)\n# 5 words, 8 dimensions each\nattended_vectors\n=\nsimple_attention\n(\nword_vectors\n)\nEnter fullscreen mode\nExit fullscreen mode\nResult\n: Each word vector is now updated with information from all other words, weighted by attention.\nKey Takeaways\nAttention = Weighted Average\n: Focus more on important parts\nQ·K = Similarity\n: How well query matches key\nSoftmax = Probability\n: Convert scores to weights that sum to 1\nWeighted V = Output\n: Combine values using attention weights\nSelf-Attention = Words talking to each other\n: Every word can attend to every other word\nThis foundation prepares you for transformer models, which are built entirely on attention mechanisms!\nUnderstanding Attention: From Words to Vectors\n1. Word Embeddings - The Foundation\nimport\ntorch\nimport\ntorch.nn\nas\nnn\nimport\ntorch.nn.functional\nas\nF\n# Sample sentence: \"The cat sat on the mat\"\nvocab\n=\n{\n\"\n<pad>\n\"\n:\n0\n,\n\"\nthe\n\"\n:\n1\n,\n\"\ncat\n\"\n:\n2\n,\n\"\nsat\n\"\n:\n3\n,\n\"\non\n\"\n:\n4\n,\n\"\nmat\n\"\n:\n5\n}\nsentence\n=\n[\n1\n,\n2\n,\n3\n,\n4\n,\n1\n,\n5\n]\n# token IDs\n# Create embeddings\nvocab_size\n=\nlen\n(\nvocab\n)\nembed_dim\n=\n64\nembedding\n=\nnn\n.\nEmbedding\n(\nvocab_size\n,\nembed_dim\n)\n# Convert tokens to vectors\ntokens\n=\ntorch\n.\ntensor\n(\nsentence\n)\nembeddings\n=\nembedding\n(\ntokens\n)\nprint\n(\nf\n\"\nShape:\n{\nembeddings\n.\nshape\n}\n\"\n)\n# [6, 64]\nprint\n(\nf\n\"'\ncat\n'\nvector:\n{\nembeddings\n[\n1\n][\n:\n8\n]\n}\n...\n\"\n)\n# First 8 dimensions\nEnter fullscreen mode\nExit fullscreen mode\nEach word becomes a 64-dimensional vector that captures semantic meaning.\n2. The Q, K, V Matrices - Core of Attention\n# Attention dimensions\nd_model\n=\n64\nnum_heads\n=\n8\nd_k\n=\nd_model\n//\nnum_heads\n# 8\n# Linear transformations to create Q, K, V\nW_q\n=\nnn\n.\nLinear\n(\nd_model\n,\nd_model\n,\nbias\n=\nFalse\n)\nW_k\n=\nnn\n.\nLinear\n(\nd_model\n,\nd_model\n,\nbias\n=\nFalse\n)\nW_v\n=\nnn\n.\nLinear\n(\nd_model\n,\nd_model\n,\nbias\n=\nFalse\n)\n# Transform embeddings\nQ\n=\nW_q\n(\nembeddings\n)\n# Queries: \"What am I looking for?\"\nK\n=\nW_k\n(\nembeddings\n)\n# Keys: \"What do I represent?\"\nV\n=\nW_v\n(\nembeddings\n)\n# Values: \"What information do I carry?\"\nprint\n(\nf\n\"\nQ shape:\n{\nQ\n.\nshape\n}\n\"\n)\n# [6, 64]\nprint\n(\nf\n\"\nK shape:\n{\nK\n.\nshape\n}\n\"\n)\n# [6, 64]\nprint\n(\nf\n\"\nV shape:\n{\nV\n.\nshape\n}\n\"\n)\n# [6, 64]\nEnter fullscreen mode\nExit fullscreen mode\nIntuition:\nQ (Query)\n: \"What information does this word need?\"\nK (Key)\n: \"What kind of information does this word offer?\"\nV (Value)\n: \"What actual information does this word contain?\"\n3. Computing Attention Scores\n# Reshape for multi-head attention\nbatch_size\n,\nseq_len\n=\n1\n,\n6\nQ\n=\nQ\n.\nview\n(\nbatch_size\n,\nseq_len\n,\nnum_heads\n,\nd_k\n).\ntranspose\n(\n1\n,\n2\n)\n# [1, 8, 6, 8]\nK\n=\nK\n.\nview\n(\nbatch_size\n,\nseq_len\n,\nnum_heads\n,\nd_k\n).\ntranspose\n(\n1\n,\n2\n)\n# [1, 8, 6, 8]\nV\n=\nV\n.\nview\n(\nbatch_size\n,\nseq_len\n,\nnum_heads\n,\nd_k\n).\ntranspose\n(\n1\n,\n2\n)\n# [1, 8, 6, 8]\n# Attention scores: How much should each word pay attention to others?\nscores\n=\ntorch\n.\nmatmul\n(\nQ\n,\nK\n.\ntranspose\n(\n-\n2\n,\n-\n1\n))\n/\n(\nd_k\n**\n0.5\n)\nprint\n(\nf\n\"\nAttention scores shape:\n{\nscores\n.\nshape\n}\n\"\n)\n# [1, 8, 6, 6]\n# Example: How much does \"cat\" attend to each word?\ncat_attention\n=\nscores\n[\n0\n,\n0\n,\n1\n,\n:]\n# First head, \"cat\" position\nwords\n=\n[\n\"\nthe\n\"\n,\n\"\ncat\n\"\n,\n\"\nsat\n\"\n,\n\"\non\n\"\n,\n\"\nthe\n\"\n,\n\"\nmat\n\"\n]\nfor\ni\n,\nword\nin\nenumerate\n(\nwords\n):\nprint\n(\nf\n\"\ncat ->\n{\nword\n}\n:\n{\ncat_attention\n[\ni\n]\n:\n.\n3\nf\n}\n\"\n)\nEnter fullscreen mode\nExit fullscreen mode\n4. Softmax and Weighted Values\n# Convert scores to probabilities\nattention_weights\n=\nF\n.\nsoftmax\n(\nscores\n,\ndim\n=-\n1\n)\nprint\n(\nf\n\"\nAttention weights shape:\n{\nattention_weights\n.\nshape\n}\n\"\n)\n# [1, 8, 6, 6]\n# Apply attention to values\nattended_values\n=\ntorch\n.\nmatmul\n(\nattention_weights\n,\nV\n)\n# [1, 8, 6, 8]\n# Concatenate heads and project back\nattended_values\n=\nattended_values\n.\ntranspose\n(\n1\n,\n2\n).\ncontiguous\n().\nview\n(\nbatch_size\n,\nseq_len\n,\nd_model\n)\n# [1, 6, 64]\nprint\n(\nf\n\"\nFinal attended values shape:\n{\nattended_values\n.\nshape\n}\n\"\n)\n# Show attention pattern for \"cat\"\nprint\n(\n\"\n\\n\nAttention pattern for\n'\ncat\n'\n:\n\"\n)\ncat_weights\n=\nattention_weights\n[\n0\n,\n0\n,\n1\n,\n:]\n# First head\nfor\ni\n,\nword\nin\nenumerate\n(\nwords\n):\nprint\n(\nf\n\"\n{\nword\n}\n:\n{\ncat_weights\n[\ni\n]\n:\n.\n3\nf\n}\n\"\n)\nEnter fullscreen mode\nExit fullscreen mode\n5. Complete Self-Attention Implementation\nclass\nMultiHeadAttention\n(\nnn\n.\nModule\n):\ndef\n__init__\n(\nself\n,\nd_model\n,\nnum_heads\n):\nsuper\n().\n__init__\n()\nself\n.\nd_model\n=\nd_model\nself\n.\nnum_heads\n=\nnum_heads\nself\n.\nd_k\n=\nd_model\n//\nnum_heads\nself\n.\nW_q\n=\nnn\n.\nLinear\n(\nd_model\n,\nd_model\n)\nself\n.\nW_k\n=\nnn\n.\nLinear\n(\nd_model\n,\nd_model\n)\nself\n.\nW_v\n=\nnn\n.\nLinear\n(\nd_model\n,\nd_model\n)\nself\n.\nW_o\n=\nnn\n.\nLinear\n(\nd_model\n,\nd_model\n)\ndef\nforward\n(\nself\n,\nx\n):\nbatch_size\n,\nseq_len\n,\nd_model\n=\nx\n.\nsize\n()\n# Linear transformations\nQ\n=\nself\n.\nW_q\n(\nx\n).\nview\n(\nbatch_size\n,\nseq_len\n,\nself\n.\nnum_heads\n,\nself\n.\nd_k\n).\ntranspose\n(\n1\n,\n2\n)\nK\n=\nself\n.\nW_k\n(\nx\n).\nview\n(\nbatch_size\n,\nseq_len\n,\nself\n.\nnum_heads\n,\nself\n.\nd_k\n).\ntranspose\n(\n1\n,\n2\n)\nV\n=\nself\n.\nW_v\n(\nx\n).\nview\n(\nbatch_size\n,\nseq_len\n,\nself\n.\nnum_heads\n,\nself\n.\nd_k\n).\ntranspose\n(\n1\n,\n2\n)\n# Scaled dot-product attention\nscores\n=\ntorch\n.\nmatmul\n(\nQ\n,\nK\n.\ntranspose\n(\n-\n2\n,\n-\n1\n))\n/\n(\nself\n.\nd_k\n**\n0.5\n)\nattention_weights\n=\nF\n.\nsoftmax\n(\nscores\n,\ndim\n=-\n1\n)\nattended_values\n=\ntorch\n.\nmatmul\n(\nattention_weights\n,\nV\n)\n# Concatenate heads\nattended_values\n=\nattended_values\n.\ntranspose\n(\n1\n,\n2\n).\ncontiguous\n().\nview\n(\nbatch_size\n,\nseq_len\n,\nd_model\n)\n# Final projection\noutput\n=\nself\n.\nW_o\n(\nattended_values\n)\nreturn\noutput\n,\nattention_weights\n# Usage\nattention\n=\nMultiHeadAttention\n(\nd_model\n=\n64\n,\nnum_heads\n=\n8\n)\noutput\n,\nweights\n=\nattention\n(\nembeddings\n.\nunsqueeze\n(\n0\n))\nprint\n(\nf\n\"\nOutput shape:\n{\noutput\n.\nshape\n}\n\"\n)\n# [1, 6, 64]\nEnter fullscreen mode\nExit fullscreen mode\n6. Visualizing Attention Patterns\n# Extract attention weights for visualization\nattention_matrix\n=\nweights\n[\n0\n,\n0\n].\ndetach\n().\nnumpy\n()\n# First head\nwords\n=\n[\n\"\nthe\n\"\n,\n\"\ncat\n\"\n,\n\"\nsat\n\"\n,\n\"\non\n\"\n,\n\"\nthe\n\"\n,\n\"\nmat\n\"\n]\nprint\n(\n\"\nAttention Matrix (first head):\n\"\n)\nprint\n(\n\"\nFrom -> To:\n\"\n)\nfor\ni\n,\nfrom_word\nin\nenumerate\n(\nwords\n):\nprint\n(\nf\n\"\n{\nfrom_word\n:\n>\n4\n}\n:\n\"\n,\nend\n=\n\"\"\n)\nfor\nj\n,\nto_word\nin\nenumerate\n(\nwords\n):\nprint\n(\nf\n\"\n{\nattention_matrix\n[\ni\n,\nj\n]\n:\n.\n2\nf\n}\n\"\n,\nend\n=\n\"\"\n)\nprint\n()\nEnter fullscreen mode\nExit fullscreen mode\n7. Key Insights\nWhat happens in attention?\nEach word creates a\nquery\n(what it's looking for)\nEach word creates a\nkey\n(what it represents)\nWe compute similarity between queries and keys\nHigher similarity = more attention\nWe use attention weights to combine\nvalues\n(actual information)\nExample:\nWhen processing \"cat\", the model might:\nQuery: \"I need information about animals\"\nLook at all keys: \"the\" (determiner), \"sat\" (action), \"mat\" (object)\nPay most attention to \"sat\" because it's the relevant action\nCombine information weighted by attention scores\n8. Practical Example with Real Meaning\n# Sentence: \"The cat chased the mouse\"\nsentence\n=\n\"\nThe cat chased the mouse\n\"\nwords\n=\nsentence\n.\nlower\n().\nsplit\n()\n# Simulate what attention might learn\nprint\n(\n\"\nAttention patterns the model might learn:\n\"\n)\nprint\n(\n\"\n-\n'\ncat\n'\nattends to\n'\nchased\n'\n(subject-verb relationship)\n\"\n)\nprint\n(\n\"\n-\n'\nchased\n'\nattends to\n'\ncat\n'\nand\n'\nmouse\n'\n(verb-subject-object)\n\"\n)\nprint\n(\n\"\n-\n'\nmouse\n'\nattends to\n'\nchased\n'\n(object-verb relationship)\n\"\n)\nprint\n(\n\"\n-\n'\nthe\n'\nattends to following nouns (\n'\ncat\n'\n,\n'\nmouse\n'\n)\n\"\n)\n# This allows the model to understand:\n# - Who did what to whom\n# - Grammatical relationships\n# - Semantic dependencies\nEnter fullscreen mode\nExit fullscreen mode\nSummary\nAttention mechanism allows models to:\nFocus\non relevant parts of the input\nRelate\ndifferent words to each other\nCombine\ninformation based on relevance\nUnderstand\nlong-range dependencies\nThe magic is in the learned Q, K, V matrices that transform word embeddings into queries, keys, and values that can interact meaningfully.",
  "metadata": {
    "title": "Attention Mechanism Tutorial: From Simple to Advanced - DEV Community",
    "description": "Part 1: The Core Idea   Attention is like a spotlight - it helps models focus on what's...",
    "keywords": "software, coding, development, engineering, inclusive, community",
    "author": null,
    "og:type": "article",
    "og:url": "https://dev.to/vuk_rosic/attention-mechanism-tutorial-from-simple-to-advanced-1260",
    "og:title": "Attention Mechanism Tutorial: From Simple to Advanced",
    "og:description": "Part 1: The Core Idea   Attention is like a spotlight - it helps models focus on what's...",
    "og:site_name": "DEV Community",
    "og:image": "https://media2.dev.to/dynamic/image/width=1000,height=500,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnf1xxffktayvdjbxxxll.png",
    "twitter:site": "@thepracticaldev",
    "twitter:creator": "@VukRosic99",
    "twitter:title": "Attention Mechanism Tutorial: From Simple to Advanced",
    "twitter:description": "Part 1: The Core Idea   Attention is like a spotlight - it helps models focus on what's...",
    "twitter:card": "summary_large_image",
    "twitter:widgets:new-embed-design": "on",
    "twitter:image:src": "https://media2.dev.to/dynamic/image/width=1000,height=500,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnf1xxffktayvdjbxxxll.png"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/55a36937fd83/code/body-000.txt",
      "chars": 198,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-001.txt",
      "chars": 253,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-002.txt",
      "chars": 309,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-003.txt",
      "chars": 258,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-004.txt",
      "chars": 450,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-005.txt",
      "chars": 132,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-006.txt",
      "chars": 189,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-007.txt",
      "chars": 222,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-008.txt",
      "chars": 337,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-009.txt",
      "chars": 243,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-010.txt",
      "chars": 168,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-011.txt",
      "chars": 488,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-012.txt",
      "chars": 541,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-013.txt",
      "chars": 580,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-014.txt",
      "chars": 753,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-015.txt",
      "chars": 686,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-016.txt",
      "chars": 1448,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-017.txt",
      "chars": 406,
      "language": "text"
    },
    {
      "file": "attachments/55a36937fd83/code/body-018.txt",
      "chars": 584,
      "language": "text"
    }
  ],
  "images": [],
  "audio": [],
  "videos": [],
  "links": [],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:50:25Z",
  "source_url": "https://dev.to/vuk_rosic/attention-mechanism-tutorial-from-simple-to-advanced-1260",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 12929,
  "expected_body_images": 0,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/55a36937fd83/pages/source.html",
  "local_html": "attachments/55a36937fd83/pages/article.html",
  "body_base_path": "attachments/55a36937fd83/pages/",
  "body_markdown_path": "attachments/55a36937fd83/pages/article.md"
}