CoolFace
Apppublic

sobhandutta/agentic-personal-assistant

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
rag_visualization.ipynb6875 linesDownload Raw Back to root
1{2 "cells": [3  {4   "cell_type": "markdown",5   "id": "c33b282d",6   "metadata": {},7   "source": [8    "# ๐Ÿง  RAG Vector Store โ€” Deep Dive & Visualisation\n",9    "\n",10    "**How Sobhan's personal knowledge base goes from Markdown files to a searchable vector database.**\n",11    "\n",12    "---\n",13    "\n",14    "## What you will explore in this notebook\n",15    "\n",16    "We have 8 Markdown files about Sobhan Dutta โ€” his career history, UX/AI expertise, and education.\n",17    "By the end of this notebook you will have:\n",18    "\n",19    "1. Loaded and measured the raw documents (characters, tokens, files)\n",20    "2. Split them into overlapping **chunks** suitable for retrieval\n",21    "3. Converted every chunk into a high-dimensional **embedding vector** using OpenAI\n",22    "4. Stored those vectors in a persistent **ChromaDB** vector store\n",23    "5. **Visualised** the vector space in 2-D and 3-D using t-SNE\n",24    "6. Run live **queries** and watched where they land in vector space\n",25    "\n",26    "---\n",27    "\n",28    "## The three parts\n",29    "\n",30    "| Part | Topic | Key concept |\n",31    "|---|---|---|\n",32    "| **A** | Documents โ†’ Chunks | Why we split and how overlap prevents information loss |\n",33    "| **B** | Chunks โ†’ Vectors | What an embedding is and why dimensions matter |\n",34    "| **C** | Visualise the space | t-SNE, cluster structure, query placement, live retrieval |\n",35    "\n",36    "> **Prerequisites:** `OPENAI_API_KEY` in a `.env` file โ€” needed for embeddings.\n",37    "> Run `python data/ingest_kb.py` first to build the vector store on disk.\n",38    "> jupyter notebook rag_visualization.ipynb to open notebook"39   ]40  },41  {42   "cell_type": "code",43   "execution_count": 1,44   "id": "35b1f20e",45   "metadata": {},46   "outputs": [47    {48     "name": "stdout",49     "output_type": "stream",50     "text": [51      "OpenAI API Key found โ€” starts with sk-proj-...\n",52      "\n",53      "Knowledge base : /Users/sobhandutta/projects/full-llm-assistant/knowledge_base\n",54      "Vector store   : vector_store\n"55     ]56    }57   ],58   "source": [59    "import os, glob\n",60    "import numpy as np\n",61    "from pathlib import Path\n",62    "from collections import Counter\n",63    "from dotenv import load_dotenv\n",64    "\n",65    "from openai import OpenAI\n",66    "from chromadb import PersistentClient\n",67    "\n",68    "from sklearn.manifold import TSNE\n",69    "import plotly.graph_objects as go\n",70    "\n",71    "import tiktoken\n",72    "\n",73    "load_dotenv(override=True)\n",74    "\n",75    "openai = OpenAI()\n",76    "api_key = os.getenv(\"OPENAI_API_KEY\", \"\")\n",77    "print(f\"OpenAI API Key found โ€” starts with {api_key[:8]}...\" if api_key else \"โŒ OPENAI_API_KEY not set\")\n",78    "\n",79    "# Paths โ€” relative to this notebook (which lives in the agentic/ root)\n",80    "KB_PATH          = Path(\"knowledge_base\")\n",81    "VECTOR_STORE_PATH = str(Path(\"vector_store\"))\n",82    "COLLECTION_NAME  = \"sobhan_knowledge_base\"\n",83    "EMBEDDING_MODEL  = \"text-embedding-3-small\"   # must match data/ingest_kb.py\n",84    "\n",85    "print(f\"\\nKnowledge base : {KB_PATH.resolve()}\")\n",86    "print(f\"Vector store   : {VECTOR_STORE_PATH}\")"87   ]88  },89  {90   "cell_type": "markdown",91   "id": "f7236d44",92   "metadata": {},93   "source": [94    "---\n",95    "## Part A โ€” Documents โ†’ Chunks\n",96    "\n",97    "### Step 1: Measure the knowledge base\n",98    "\n",99    "Before touching any LLM, let's measure the raw data:\n",100    "- **Files** โ€” how many documents we have and how they're organised\n",101    "- **Characters** โ€” raw size on disk\n",102    "- **Tokens** โ€” what the LLM *actually* processes (roughly `chars / 4` for English)\n",103    "\n",104    "This tells us: could we just dump everything into one prompt?\n",105    "Spoiler: technically yes for 8 files โ€” but RAG is still the right pattern for accuracy, cost, and scalability."106   ]107  },108  {109   "cell_type": "code",110   "execution_count": 2,111   "id": "388fbfc6",112   "metadata": {},113   "outputs": [114    {115     "name": "stdout",116     "output_type": "stream",117     "text": [118      "==================================================\n",119      "  Knowledge Base: 9 documents\n",120      "==================================================\n",121      "\n",122      "  ๐Ÿ“ career/  (4 files)\n",123      "     โ””โ”€ ataya.md\n",124      "     โ””โ”€ early_career.md\n",125      "     โ””โ”€ elisity.md\n",126      "     โ””โ”€ nuance.md\n",127      "\n",128      "  ๐Ÿ“ education/  (1 files)\n",129      "     โ””โ”€ background.md\n",130      "\n",131      "  ๐Ÿ“ expertise/  (3 files)\n",132      "     โ””โ”€ frontend_engineering.md\n",133      "     โ””โ”€ leadership.md\n",134      "     โ””โ”€ ux_design_philosophy.md\n",135      "\n",136      "  ๐Ÿ“ youtube/  (1 files)\n",137      "     โ””โ”€ youtube.md\n",138      "\n",139      "==================================================\n",140      "  Total characters :   25,400\n",141      "  Average per file :    2,822 chars\n"142     ]143    }144   ],145   "source": [146    "# Load every .md file and gather stats\n",147    "documents = []\n",148    "for md_file in sorted(KB_PATH.rglob(\"*.md\")):\n",149    "    category = md_file.parent.name   # \"career\", \"expertise\", or \"education\"\n",150    "    text     = md_file.read_text(encoding=\"utf-8\")\n",151    "    documents.append({\"path\": md_file, \"category\": category,\n",152    "                       \"filename\": md_file.stem, \"text\": text})\n",153    "\n",154    "# Print a summary tree\n",155    "print(f\"{'='*50}\")\n",156    "print(f\"  Knowledge Base: {len(documents)} documents\")\n",157    "print(f\"{'='*50}\")\n",158    "category_counts = Counter(d[\"category\"] for d in documents)\n",159    "for cat, count in sorted(category_counts.items()):\n",160    "    cat_docs = [d[\"filename\"] for d in documents if d[\"category\"] == cat]\n",161    "    print(f\"\\n  ๐Ÿ“ {cat}/  ({count} files)\")\n",162    "    for name in cat_docs:\n",163    "        print(f\"     โ””โ”€ {name}.md\")\n",164    "\n",165    "# Measure total size\n",166    "all_text = \"\\n\\n\".join(d[\"text\"] for d in documents)\n",167    "print(f\"\\n{'='*50}\")\n",168    "print(f\"  Total characters : {len(all_text):>8,}\")\n",169    "print(f\"  Average per file : {len(all_text)/len(documents):>8,.0f} chars\")"170   ]171  },172  {173   "cell_type": "code",174   "execution_count": 3,175   "id": "57f9405b",176   "metadata": {},177   "outputs": [178    {179     "name": "stdout",180     "output_type": "stream",181     "text": [182      "Total tokens in knowledge base : 5,230\n",183      "Chars-per-token ratio          : 4.86  (English โ‰ˆ 4)\n",184      "\n",185      "Fits in Claude context (200,000 tokens)?  โœ… YES\n",186      "Fits in GPT-4o context (128,000 tokens)?   โœ… YES\n",187      "\n",188      "Cost to send ALL docs every query : ~$0.0000 (haiku input pricing)\n",189      "Cost with RAG (top-5 chunks)      : ~$0.000002  (7ร— cheaper)\n"190     ]191    }192   ],193   "source": [194    "# Token count using the tokeniser claude-sonnet-4-6 / gpt-4o share (cl100k_base)\n",195    "encoding    = tiktoken.get_encoding(\"cl100k_base\")\n",196    "token_count = len(encoding.encode(all_text))\n",197    "\n",198    "print(f\"Total tokens in knowledge base : {token_count:,}\")\n",199    "print(f\"Chars-per-token ratio          : {len(all_text)/token_count:.2f}  (English โ‰ˆ 4)\")\n",200    "\n",201    "# Cost and context comparison\n",202    "claude_context = 200_000\n",203    "gpt4_context   = 128_000\n",204    "cost_full      = token_count / 1_000_000 * 0.003   # claude-haiku input price\n",205    "\n",206    "print(f\"\\nFits in Claude context ({claude_context:,} tokens)?  \"\n",207    "      + (\"โœ… YES\" if token_count < claude_context else \"โŒ NO\"))\n",208    "print(f\"Fits in GPT-4o context ({gpt4_context:,} tokens)?   \"\n",209    "      + (\"โœ… YES\" if token_count < gpt4_context else \"โŒ NO\"))\n",210    "print(f\"\\nCost to send ALL docs every query : ~${cost_full:.4f} (haiku input pricing)\")\n",211    "\n",212    "rag_tokens = 5 * 150  # top-5 chunks ร— ~150 tokens each\n",213    "cost_rag   = rag_tokens / 1_000_000 * 0.003\n",214    "print(f\"Cost with RAG (top-5 chunks)      : ~${cost_rag:.6f}  ({cost_full/cost_rag:.0f}ร— cheaper)\")"215   ]216  },217  {218   "cell_type": "markdown",219   "id": "a874e332",220   "metadata": {},221   "source": [222    "### Step 2: Split documents into chunks\n",223    "\n",224    "**Why chunk at all?**\n",225    "\n",226    "Each document becomes a single vector if stored whole. A long document about Sobhan's career\n",227    "would produce one vector that \"averages\" all its content โ€” making it hard to match a specific\n",228    "question like \"What did Sobhan achieve at Elisity?\".\n",229    "\n",230    "Smaller, focused chunks = more precise retrieval.\n",231    "\n",232    "**Why overlap?**\n",233    "\n",234    "```\n",235    "Doc text: |โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€|\n",236    "\n",237    "Chunk 1:  |โ”€โ”€โ”€โ”€โ”€โ”€ 600 โ”€โ”€โ”€โ”€โ”€โ”€|\n",238    "Chunk 2:              |โ”€โ”€ 100 overlap โ”€โ”€|โ”€โ”€โ”€โ”€โ”€โ”€ 600 โ”€โ”€โ”€โ”€โ”€โ”€|\n",239    "Chunk 3:                                        |โ”€โ”€ 100 โ”€โ”€|โ”€โ”€ 600 โ”€โ”€|\n",240    "```\n",241    "\n",242    "A sentence near a chunk boundary appears in **two** chunks. Without overlap, it might be\n",243    "split and never fully retrieved. Overlap trades a little storage for significantly better retrieval."244   ]245  },246  {247   "cell_type": "code",248   "execution_count": 4,249   "id": "8b97f3e9",250   "metadata": {},251   "outputs": [252    {253     "name": "stdout",254     "output_type": "stream",255     "text": [256      "Documents   : 9\n",257      "Chunks      : 53\n",258      "Avg per doc : 5.9\n",259      "\n",260      "Chunk 0 preview (600 chars):\n",261      "  Source   : ataya (career)\n",262      "  Content  : # Director of Engineering (UX & UI) โ€” Atayalan Inc\n",263      "\n",264      "## Role Overview\n",265      "Sobhan Dutta joined Atayalan Inc in January 2022 as the founding U.S. hire and Director of Engineering (UX & UI), based in San Jose...\n"266     ]267    }268   ],269   "source": [270    "CHUNK_SIZE    = 600   # characters per chunk (matches data/ingest_kb.py)\n",271    "CHUNK_OVERLAP = 100   # overlap between adjacent chunks\n",272    "\n",273    "def chunk_text(text, chunk_size, overlap):\n",274    "    chunks, start = [], 0\n",275    "    while start < len(text):\n",276    "        chunks.append(text[start : start + chunk_size])\n",277    "        start += chunk_size - overlap\n",278    "    return chunks\n",279    "\n",280    "# Chunk every document and attach metadata\n",281    "all_chunks = []\n",282    "for doc in documents:\n",283    "    for i, chunk_str in enumerate(chunk_text(doc[\"text\"], CHUNK_SIZE, CHUNK_OVERLAP)):\n",284    "        if len(chunk_str.strip()) >= 50:   # skip tiny trailing fragments\n",285    "            all_chunks.append({\n",286    "                \"text\":     chunk_str,\n",287    "                \"source\":   doc[\"filename\"],\n",288    "                \"category\": doc[\"category\"],\n",289    "                \"chunk_index\": i,\n",290    "            })\n",291    "\n",292    "print(f\"Documents   : {len(documents)}\")\n",293    "print(f\"Chunks      : {len(all_chunks)}\")\n",294    "print(f\"Avg per doc : {len(all_chunks)/len(documents):.1f}\")\n",295    "print(f\"\\nChunk 0 preview ({len(all_chunks[0]['text'])} chars):\")\n",296    "print(f\"  Source   : {all_chunks[0]['source']} ({all_chunks[0]['category']})\")\n",297    "print(f\"  Content  : {all_chunks[0]['text'][:200].strip()}...\")"298   ]299  },300  {301   "cell_type": "code",302   "execution_count": 5,303   "id": "3e975c16",304   "metadata": {},305   "outputs": [306    {307     "data": {308      "application/vnd.plotly.v1+json": {309       "config": {310        "plotlyServerURL": "https://plot.ly"311       },312       "data": [313        {314         "marker": {315          "color": "#6366f1"316         },317         "name": "Chunk size",318         "nbinsx": 30,319         "opacity": 0.85,320         "type": "histogram",321         "x": [322          600,323          600,324          600,325          600,326          389,327          600,328          600,329          600,330          550,331          600,332          600,333          600,334          600,335          320,336          600,337          600,338          600,339          600,340          600,341          423,342          600,343          600,344          600,345          600,346          431,347          600,348          600,349          600,350          600,351          600,352          128,353          600,354          600,355          600,356          600,357          600,358          384,359          600,360          600,361          600,362          600,363          600,364          257,365          600,366          600,367          600,368          600,369          600,370          600,371          600,372          600,373          600,374          502375         ]376        }377       ],378       "layout": {379        "annotations": [380         {381          "showarrow": false,382          "text": " Mean: 562 chars",383          "x": 561.9622641509434,384          "xanchor": "left",385          "xref": "x",386          "y": 1,387          "yanchor": "top",388          "yref": "y domain"389         }390        ],391        "height": 400,392        "shapes": [393         {394          "line": {395           "color": "orange",396           "dash": "dash"397          },398          "type": "line",399          "x0": 561.9622641509434,400          "x1": 561.9622641509434,401          "xref": "x",402          "y0": 0,403          "y1": 1,404          "yref": "y domain"405         }406        ],407        "template": {408         "data": {409          "bar": [410           {411            "error_x": {412             "color": "#f2f5fa"413            },414            "error_y": {415             "color": "#f2f5fa"416            },417            "marker": {418             "line": {419              "color": "rgb(17,17,17)",420              "width": 0.5421             },422             "pattern": {423              "fillmode": "overlay",424              "size": 10,425              "solidity": 0.2426             }427            },428            "type": "bar"429           }430          ],431          "barpolar": [432           {433            "marker": {434             "line": {435              "color": "rgb(17,17,17)",436              "width": 0.5437             },438             "pattern": {439              "fillmode": "overlay",440              "size": 10,441              "solidity": 0.2442             }443            },444            "type": "barpolar"445           }446          ],447          "carpet": [448           {449            "aaxis": {450             "endlinecolor": "#A2B1C6",451             "gridcolor": "#506784",452             "linecolor": "#506784",453             "minorgridcolor": "#506784",454             "startlinecolor": "#A2B1C6"455            },456            "baxis": {457             "endlinecolor": "#A2B1C6",458             "gridcolor": "#506784",459             "linecolor": "#506784",460             "minorgridcolor": "#506784",461             "startlinecolor": "#A2B1C6"462            },463            "type": "carpet"464           }465          ],466          "choropleth": [467           {468            "colorbar": {469             "outlinewidth": 0,470             "ticks": ""471            },472            "type": "choropleth"473           }474          ],475          "contour": [476           {477            "colorbar": {478             "outlinewidth": 0,479             "ticks": ""480            },481            "colorscale": [482             [483              0,484              "#0d0887"485             ],486             [487              0.1111111111111111,488              "#46039f"489             ],490             [491              0.2222222222222222,492              "#7201a8"493             ],494             [495              0.3333333333333333,496              "#9c179e"497             ],498             [499              0.4444444444444444,500              "#bd3786"501             ],502             [503              0.5555555555555556,504              "#d8576b"505             ],506             [507              0.6666666666666666,508              "#ed7953"509             ],510             [511              0.7777777777777778,512              "#fb9f3a"513             ],514             [515              0.8888888888888888,516              "#fdca26"517             ],518             [519              1,520              "#f0f921"521             ]522            ],523            "type": "contour"524           }525          ],526          "contourcarpet": [527           {528            "colorbar": {529             "outlinewidth": 0,530             "ticks": ""531            },532            "type": "contourcarpet"533           }534          ],535          "heatmap": [536           {537            "colorbar": {538             "outlinewidth": 0,539             "ticks": ""540            },541            "colorscale": [542             [543              0,544              "#0d0887"545             ],546             [547              0.1111111111111111,548              "#46039f"549             ],550             [551              0.2222222222222222,552              "#7201a8"553             ],554             [555              0.3333333333333333,556              "#9c179e"557             ],558             [559              0.4444444444444444,560              "#bd3786"561             ],562             [563              0.5555555555555556,564              "#d8576b"565             ],566             [567              0.6666666666666666,568              "#ed7953"569             ],570             [571              0.7777777777777778,572              "#fb9f3a"573             ],574             [575              0.8888888888888888,576              "#fdca26"577             ],578             [579              1,580              "#f0f921"581             ]582            ],583            "type": "heatmap"584           }585          ],586          "histogram": [587           {588            "marker": {589             "pattern": {590              "fillmode": "overlay",591              "size": 10,592              "solidity": 0.2593             }594            },595            "type": "histogram"596           }597          ],598          "histogram2d": [599           {600            "colorbar": {601             "outlinewidth": 0,602             "ticks": ""603            },604            "colorscale": [605             [606              0,607              "#0d0887"608             ],609             [610              0.1111111111111111,611              "#46039f"612             ],613             [614              0.2222222222222222,615              "#7201a8"616             ],617             [618              0.3333333333333333,619              "#9c179e"620             ],621             [622              0.4444444444444444,623              "#bd3786"624             ],625             [626              0.5555555555555556,627              "#d8576b"628             ],629             [630              0.6666666666666666,631              "#ed7953"632             ],633             [634              0.7777777777777778,635              "#fb9f3a"636             ],637             [638              0.8888888888888888,639              "#fdca26"640             ],641             [642              1,643              "#f0f921"644             ]645            ],646            "type": "histogram2d"647           }648          ],649          "histogram2dcontour": [650           {651            "colorbar": {652             "outlinewidth": 0,653             "ticks": ""654            },655            "colorscale": [656             [657              0,658              "#0d0887"659             ],660             [661              0.1111111111111111,662              "#46039f"663             ],664             [665              0.2222222222222222,666              "#7201a8"667             ],668             [669              0.3333333333333333,670              "#9c179e"671             ],672             [673              0.4444444444444444,674              "#bd3786"675             ],676             [677              0.5555555555555556,678              "#d8576b"679             ],680             [681              0.6666666666666666,682              "#ed7953"683             ],684             [685              0.7777777777777778,686              "#fb9f3a"687             ],688             [689              0.8888888888888888,690              "#fdca26"691             ],692             [693              1,694              "#f0f921"695             ]696            ],697            "type": "histogram2dcontour"698           }699          ],700          "mesh3d": [701           {702            "colorbar": {703             "outlinewidth": 0,704             "ticks": ""705            },706            "type": "mesh3d"707           }708          ],709          "parcoords": [710           {711            "line": {712             "colorbar": {713              "outlinewidth": 0,714              "ticks": ""715             }716            },717            "type": "parcoords"718           }719          ],720          "pie": [721           {722            "automargin": true,723            "type": "pie"724           }725          ],726          "scatter": [727           {728            "marker": {729             "line": {730              "color": "#283442"731             }732            },733            "type": "scatter"734           }735          ],736          "scatter3d": [737           {738            "line": {739             "colorbar": {740              "outlinewidth": 0,741              "ticks": ""742             }743            },744            "marker": {745             "colorbar": {746              "outlinewidth": 0,747              "ticks": ""748             }749            },750            "type": "scatter3d"751           }752          ],753          "scattercarpet": [754           {755            "marker": {756             "colorbar": {757              "outlinewidth": 0,758              "ticks": ""759             }760            },761            "type": "scattercarpet"762           }763          ],764          "scattergeo": [765           {766            "marker": {767             "colorbar": {768              "outlinewidth": 0,769              "ticks": ""770             }771            },772            "type": "scattergeo"773           }774          ],775          "scattergl": [776           {777            "marker": {778             "line": {779              "color": "#283442"780             }781            },782            "type": "scattergl"783           }784          ],785          "scattermap": [786           {787            "marker": {788             "colorbar": {789              "outlinewidth": 0,790              "ticks": ""791             }792            },793            "type": "scattermap"794           }795          ],796          "scattermapbox": [797           {798            "marker": {799             "colorbar": {800              "outlinewidth": 0,801              "ticks": ""802             }803            },804            "type": "scattermapbox"805           }806          ],807          "scatterpolar": [808           {809            "marker": {810             "colorbar": {811              "outlinewidth": 0,812              "ticks": ""813             }814            },815            "type": "scatterpolar"816           }817          ],818          "scatterpolargl": [819           {820            "marker": {821             "colorbar": {822              "outlinewidth": 0,823              "ticks": ""824             }825            },826            "type": "scatterpolargl"827           }828          ],829          "scatterternary": [830           {831            "marker": {832             "colorbar": {833              "outlinewidth": 0,834              "ticks": ""835             }836            },837            "type": "scatterternary"838           }839          ],840          "surface": [841           {842            "colorbar": {843             "outlinewidth": 0,844             "ticks": ""845            },846            "colorscale": [847             [848              0,849              "#0d0887"850             ],851             [852              0.1111111111111111,853              "#46039f"854             ],855             [856              0.2222222222222222,857              "#7201a8"858             ],859             [860              0.3333333333333333,861              "#9c179e"862             ],863             [864              0.4444444444444444,865              "#bd3786"866             ],867             [868              0.5555555555555556,869              "#d8576b"870             ],871             [872              0.6666666666666666,873              "#ed7953"874             ],875             [876              0.7777777777777778,877              "#fb9f3a"878             ],879             [880              0.8888888888888888,881              "#fdca26"882             ],883             [884              1,885              "#f0f921"886             ]887            ],888            "type": "surface"889           }890          ],891          "table": [892           {893            "cells": {894             "fill": {895              "color": "#506784"896             },897             "line": {898              "color": "rgb(17,17,17)"899             }900            },901            "header": {902             "fill": {903              "color": "#2a3f5f"904             },905             "line": {906              "color": "rgb(17,17,17)"907             }908            },909            "type": "table"910           }911          ]912         },913         "layout": {914          "annotationdefaults": {915           "arrowcolor": "#f2f5fa",916           "arrowhead": 0,917           "arrowwidth": 1918          },919          "autotypenumbers": "strict",920          "coloraxis": {921           "colorbar": {922            "outlinewidth": 0,923            "ticks": ""924           }925          },926          "colorscale": {927           "diverging": [928            [929             0,930             "#8e0152"931            ],932            [933             0.1,934             "#c51b7d"935            ],936            [937             0.2,938             "#de77ae"939            ],940            [941             0.3,942             "#f1b6da"943            ],944            [945             0.4,946             "#fde0ef"947            ],948            [949             0.5,950             "#f7f7f7"951            ],952            [953             0.6,954             "#e6f5d0"955            ],956            [957             0.7,958             "#b8e186"959            ],960            [961             0.8,962             "#7fbc41"963            ],964            [965             0.9,966             "#4d9221"967            ],968            [969             1,970             "#276419"971            ]972           ],973           "sequential": [974            [975             0,976             "#0d0887"977            ],978            [979             0.1111111111111111,980             "#46039f"981            ],982            [983             0.2222222222222222,984             "#7201a8"985            ],986            [987             0.3333333333333333,988             "#9c179e"989            ],990            [991             0.4444444444444444,992             "#bd3786"993            ],994            [995             0.5555555555555556,996             "#d8576b"997            ],998            [999             0.6666666666666666,1000             "#ed7953"1001            ],1002            [1003             0.7777777777777778,1004             "#fb9f3a"1005            ],1006            [1007             0.8888888888888888,1008             "#fdca26"1009            ],1010            [1011             1,1012             "#f0f921"1013            ]1014           ],1015           "sequentialminus": [1016            [1017             0,1018             "#0d0887"1019            ],1020            [1021             0.1111111111111111,1022             "#46039f"1023            ],1024            [1025             0.2222222222222222,1026             "#7201a8"1027            ],1028            [1029             0.3333333333333333,1030             "#9c179e"1031            ],1032            [1033             0.4444444444444444,1034             "#bd3786"1035            ],1036            [1037             0.5555555555555556,1038             "#d8576b"1039            ],1040            [1041             0.6666666666666666,1042             "#ed7953"1043            ],1044            [1045             0.7777777777777778,1046             "#fb9f3a"1047            ],1048            [1049             0.8888888888888888,1050             "#fdca26"1051            ],1052            [1053             1,1054             "#f0f921"1055            ]1056           ]1057          },1058          "colorway": [1059           "#636efa",1060           "#EF553B",1061           "#00cc96",1062           "#ab63fa",1063           "#FFA15A",1064           "#19d3f3",1065           "#FF6692",1066           "#B6E880",1067           "#FF97FF",1068           "#FECB52"1069          ],1070          "font": {1071           "color": "#f2f5fa"1072          },1073          "geo": {1074           "bgcolor": "rgb(17,17,17)",1075           "lakecolor": "rgb(17,17,17)",1076           "landcolor": "rgb(17,17,17)",1077           "showlakes": true,1078           "showland": true,1079           "subunitcolor": "#506784"1080          },1081          "hoverlabel": {1082           "align": "left"1083          },1084          "hovermode": "closest",1085          "mapbox": {1086           "style": "dark"1087          },1088          "paper_bgcolor": "rgb(17,17,17)",1089          "plot_bgcolor": "rgb(17,17,17)",1090          "polar": {1091           "angularaxis": {1092            "gridcolor": "#506784",1093            "linecolor": "#506784",1094            "ticks": ""1095           },1096           "bgcolor": "rgb(17,17,17)",1097           "radialaxis": {1098            "gridcolor": "#506784",1099            "linecolor": "#506784",1100            "ticks": ""1101           }1102          },1103          "scene": {1104           "xaxis": {1105            "backgroundcolor": "rgb(17,17,17)",1106            "gridcolor": "#506784",1107            "gridwidth": 2,1108            "linecolor": "#506784",1109            "showbackground": true,1110            "ticks": "",1111            "zerolinecolor": "#C8D4E3"1112           },1113           "yaxis": {1114            "backgroundcolor": "rgb(17,17,17)",1115            "gridcolor": "#506784",1116            "gridwidth": 2,1117            "linecolor": "#506784",1118            "showbackground": true,1119            "ticks": "",1120            "zerolinecolor": "#C8D4E3"1121           },1122           "zaxis": {1123            "backgroundcolor": "rgb(17,17,17)",1124            "gridcolor": "#506784",1125            "gridwidth": 2,1126            "linecolor": "#506784",1127            "showbackground": true,1128            "ticks": "",1129            "zerolinecolor": "#C8D4E3"1130           }1131          },1132          "shapedefaults": {1133           "line": {1134            "color": "#f2f5fa"1135           }1136          },1137          "sliderdefaults": {1138           "bgcolor": "#C8D4E3",1139           "bordercolor": "rgb(17,17,17)",1140           "borderwidth": 1,1141           "tickwidth": 01142          },1143          "ternary": {1144           "aaxis": {1145            "gridcolor": "#506784",1146            "linecolor": "#506784",1147            "ticks": ""1148           },1149           "baxis": {1150            "gridcolor": "#506784",1151            "linecolor": "#506784",1152            "ticks": ""1153           },1154           "bgcolor": "rgb(17,17,17)",1155           "caxis": {1156            "gridcolor": "#506784",1157            "linecolor": "#506784",1158            "ticks": ""1159           }1160          },1161          "title": {1162           "x": 0.051163          },1164          "updatemenudefaults": {1165           "bgcolor": "#506784",1166           "borderwidth": 01167          },1168          "xaxis": {1169           "automargin": true,1170           "gridcolor": "#283442",1171           "linecolor": "#506784",1172           "ticks": "",1173           "title": {1174            "standoff": 151175           },1176           "zerolinecolor": "#283442",1177           "zerolinewidth": 21178          },1179          "yaxis": {1180           "automargin": true,1181           "gridcolor": "#283442",1182           "linecolor": "#506784",1183           "ticks": "",1184           "title": {1185            "standoff": 151186           },1187           "zerolinecolor": "#283442",1188           "zerolinewidth": 21189          }1190         }1191        },1192        "title": {1193         "text": "Distribution of Chunk Sizes (characters)"1194        },1195        "width": 750,1196        "xaxis": {1197         "title": {1198          "text": "Characters per chunk"1199         }1200        },

Showing the first 1,200 of 6875 lines. Download the file for the rest.