{"slug": "ghost-hunter-s-lab", "title": "Ghost Hunter's Lab 👻", "summary": "A developer built The Ghost Hunter's Lab, a local interpretability experiment that extracts sparse-autoencoder feature #23871 from Google's Gemma Scope 2 checkpoints for Gemma 3 4B IT, injects that direction into the model during inference via llama.cpp, and compares the outputs against random interventions. The project pairs a Python pipeline with a FastAPI/Jinja2 web experience that presents recorded results rather than running new inference on visit.", "body_md": "*Hacktoberfest 2026 — Ghost in the Machine*\n\nWhat if I could change something **inside** an AI model, instead of just changing what I asked it?\n\nNot the prompt. Not a system instruction. The model's own internal activity.\n\nFor this year's *Ghost in the Machine* challenge, I decided to take the theme literally.\n\nI wanted to go ghost hunting inside an open-weight model.\n\nAnd I found something interesting. Not a supernatural entity or a conscious thought, but a mathematical direction associated with ghost-related text.\n\nThe harder question was: **what would happen if I changed it?**\n\n**The Ghost Hunter's Lab** is a local AI interpretability experiment built around Gemma 3 4B IT, Gemma Scope 2 and llama.cpp.\n\nI built a Python pipeline to extract a published sparse-autoencoder (SAE) feature direction, inject it into the model during inference, and compare the results against random interventions.\n\nI also built an editorial web experience using FastAPI, Jinja2, native CSS and GSAP to make the investigation accessible to people who don't work with model internals every day.\n\n[Explore The Ghost Hunter's Lab](https://ghost-hunters-lab.onrender.com)\n\n[GitHub — Source Code and Scientific Evidence](https://github.com/Moonchichiii/ghost-hunters-lab)\n\n[Watch the Ghost Hunter's Lab cinematic demonstration](https://res.cloudinary.com/dakjlrean/video/upload/v1793436942/v2fiiwft24be7qnwkd3b.mp4)\n\nThe video uses AI-generated cinematic illustrations to explain the investigation. The scientific measurements are taken from real experiments performed locally with Gemma, not generated by the video model.\n\nThe website presents recorded results rather than executing new inference when someone visits it.\n\nIn 1949, philosopher Gilbert Ryle challenged Cartesian dualism in *The Concept of Mind*, using the phrase “the dogma of the Ghost in the Machine.”\n\nHe wasn't suggesting that machines were haunted.\n\nI borrowed the metaphor for something different: investigating patterns inside an AI model.\n\nLarge language models contain many internal representations that are difficult to interpret directly.\n\nSparse autoencoders can help researchers break complicated internal activations into features that are easier to investigate. These features are not literal thoughts stored in individual neurons, but some correlate with recognizable patterns of text.\n\nOne feature in Gemma Scope 2 appeared associated with ghosts and spirits.\n\nIt became my experimental subject.\n\nThis was one of the most interesting parts of the project, because I wasn't simply connecting to an API and sending prompts. I needed access to the actual model weights, an interpretability resource and an inference runtime that supported internal interventions.\n\nI began with Google's work on mechanistic interpretability and its published **Gemma Scope 2** resources.\n\nGoogle describes sparse autoencoders as tools for examining internal model representations. The release includes SAEs and transcoders for the Gemma 3 family.\n\nThese were my starting points:\n\nThe important discovery was that I didn't need to train a sparse autoencoder myself. Google had already published checkpoints that could be inspected locally.\n\nThat made this investigation possible within the challenge week.\n\nI used the public Gemma Scope 2 feature-exploration resources, including Neuronpedia, to understand how individual SAE features are organized and interpreted.\n\nThe relevant feature collection is:\n\n[Neuronpedia — Gemma 3 4B IT, Layer 22, Gemma Scope 2, 65K](https://www.neuronpedia.org/gemma-3-4b-it/22-gemmascope-2-res-65k)\n\nThis corresponds to a sparse autoencoder trained on Gemma's residual-stream representations at layer 22.\n\nI selected feature **#23871** as the ghost-related candidate to investigate.\n\nBut finding an interesting feature wasn't enough. I needed its actual numerical representation.\n\nGoogle hosts the Gemma Scope 2 checkpoints on Hugging Face:\n\nI navigated to:\n\n`resid_post/layer_22_width_65k_l0_medium`\n\n[Open the exact layer-22 checkpoint directory](https://huggingface.co/google/gemma-scope-2-4b-it/tree/main/resid_post/layer_22_width_65k_l0_medium)\n\nThis directory contains the SAE configuration and checkpoint data, including `params.safetensors` and `examples.safetensors`.\n\nThe parameter file contains the trained tensors needed to examine the SAE's mathematical feature directions.\n\nUsing Python and `safetensors`, I extracted the decoder direction corresponding to feature **23871**.\n\nThe result was a vector of **2,560 float32 numbers**.\n\nI saved that direction locally as:\n\n`ghost-23871.f32`\n\nThat small file represented the direction I would later inject into Gemma.\n\nIt wasn't a separate AI model, a prompt, or a piece of executable code. It was the mathematical direction extracted from the SAE.\n\nNext, I needed the actual language model.\n\nI chose **Gemma 3 4B IT**, using a Q4_K_M quantized GGUF version so it could run on my Debian computer.\n\nI obtained the model from:\n\n[bartowski/google_gemma-3-4b-it-GGUF on Hugging Face](https://huggingface.co/bartowski/google_gemma-3-4b-it-GGUF)\n\nThe downloaded model was approximately 2.4 GiB on disk.\n\nInitially, I tested it using `llama-cli`, running prompts directly from the terminal.\n\nThis mattered because I wanted to verify that ordinary local inference worked before trying any intervention.\n\nThe model ran locally and generated normal responses.\n\nI now had the base model and the extracted SAE direction.\n\nBut I still needed a way to connect them.\n\nI used [llama.cpp](https://github.com/ggml-org/llama.cpp), an open-source inference runtime that supports local GGUF models.\n\nIts control-vector functionality was the critical piece.\n\nInstead of editing the stored model weights, I could supply a mathematical direction and apply it during inference.\n\nI converted the extracted float32 direction into a GGUF control-vector file containing a layer-specific tensor named:\n\n`direction.22`\n\nI then used llama.cpp's control-vector options:\n\n`--control-vector-scaled``--control-vector-layer-range`\nThe experiment applied the ghost-related direction at **layer 22**, at strength **+16**.\n\nConceptually, the intervention was:\n\n`modified activation = original activation + strength × feature direction`\n\nThis is **activation steering**.\n\nIt doesn't permanently rewrite Gemma's weights, and it doesn't prove that the feature represents a complete, independently stored concept.\n\nBut it lets me make an intervention and measure the consequences.\n\nI didn't want to mistake ordinary model sensitivity for evidence of a ghost-specific effect.\n\nSo I created five independently seeded random directions, using seeds **2026–2030**.\n\nEach random vector was normalized to match the norm of the extracted SAE direction.\n\nThat gave me a comparison between the original model, the SAE-derived intervention and several arbitrary directions of the same length.\n\nWith the experimental environment configured, I could finally ask the important question:\n\n**Does this particular direction produce a distinguishable effect?**\n\nI began with one unfinished sentence:\n\nThe mysterious figure was a…\n\nThe original model generated:\n\n**man**\n\nI applied the ghost-related SAE direction at strength +16.\n\nIt still generated:\n\nThen I applied a random direction at the same strength.\n\nAgain:\n\nSo had nothing happened?\n\nNot quite.\n\nI inspected the probability assigned to the exact alternative next token `\" ghost\"` — including its leading space.\n\nThese are the results from the locally reproduced pilot:\n\n| Condition | Probability of `\" ghost\"` | \n|---|---|\n| Original Gemma | 5.862800% | \n| Ghost direction +16 | 6.131469% | \n| Random direction +16 | 6.294708% | \n\nThe surprising result was that the **random direction raised the absolute ghost-token probability more than the ghost-related direction did**.\n\nWithout a random control, I could have looked at the change from 5.86% to 6.13% and declared success.\n\nThat would have been misleading.\n\nI also measured the relative log preference between `\" ghost\"` and `\" man\"`. On that different metric, the SAE direction produced the larger shift.\n\nThe generated answer was unchanged, but the probability distribution underneath it had moved.\n\nAnd different measurements revealed different aspects of the result.\n\nThis was an exploratory pilot, not the final evaluation.\n\nOne prompt wasn't enough.\n\nI created and committed a fixed dataset of 20 prompts before evaluating it. The prompts were new to that evaluation, although I had already learned from the exploratory pilot.\n\nI then tested seven conditions:\n\nThat produced **140 recorded prompt-condition observations**.\n\nI measured the change in the log probability of the exact `\" ghost\"` token relative to the unmodified model.\n\n| Direction | Mean Δ log P( `\" ghost\"` ) | \n|---|---|\n| Ghost SAE +16 | **+0.01639** | \n| Random 2026 | −0.04937 | \n| Random 2027 | −0.00643 | \n| Random 2028 | −0.03373 | \n| Random 2029 | −0.03016 | \n| Random 2030 | −0.03679 | \n\nA positive value means the target token became more probable relative to baseline. These numbers are changes in log probability, not percentage-point changes.\n\nThe ghost direction had a higher average shift than all five sampled random directions.\n\nIt increased the target token's probability on **13 of 20 prompts**.\n\nBut seven prompts shifted negatively, and on only **6 of 20 individual prompts** did the SAE direction outperform every random control on the primary metric.\n\nI also measured the change in ghost-versus-man log preference.\n\nThe SAE direction had a positive mean of approximately **+0.04222**, with **11 of 20** positive prompt shifts.\n\nThis wasn't evidence of a reliable ghost switch. It was a small, variable effect in a deliberately selected experimental setting.\n\nMy question wasn't only whether a ghost-related prediction could move.\n\nI also wanted to understand whether unrelated predictions changed.\n\nI created another frozen set of 12 prompts spanning geography, colors, language and everyday knowledge.\n\nI compared baseline, ghost steering and one random direction.\n\nThat produced **36 additional observations**.\n\n| Intervention | Mean absolute change in expected-token log probability | \n|---|---|\n| Ghost +16 | 0.04995 | \n| Random +16 | 0.07932 | \n\nThe ghost intervention changed unrelated next-token predictions too.\n\nThe random direction produced a larger average absolute shift on this particular probe set, but that doesn't establish that the SAE intervention is generally safer or more selective.\n\nThese were exact-token probability measurements, not a complete model-accuracy or general-reasoning benchmark.\n\nI couldn't conclude that all unrelated capabilities were preserved.\n\nNor could I conclude that the model had been damaged in a broader sense.\n\nWhat I could conclude was that the intervention had measurable effects outside the target context.\n\nOnce the scientific measurements were complete, I wanted to make the work understandable without expecting visitors to run a multi-gigabyte language model.\n\nI built the [Ghost Hunter's Lab website](https://ghost-hunters-lab.onrender.com) using:\n\nThe website is hosted on **Render** and reads the committed evidence snapshot.\n\nIt doesn't run Gemma inference for visitors. The original experimental inference ran locally on my Debian machine.\n\nI also created a cinematic video using Seedance-generated visual illustrations, then combined the footage with accurate scientific findings and a soundtrack.\n\nThe model-layer imagery is conceptual artwork, not a scan of real internal activations.\n\nThe results and statistics are from the local experiments.\n\nThis project would have been fundamentally different with a conventional closed text-generation API.\n\nA hosted API could let me ask a model for a spooky story.\n\nBut it wouldn't ordinarily give me the model weights, the ability to inspect an independently published SAE decoder direction, or the ability to inject that direction at a selected internal layer.\n\nThe combination of **Gemma's accessible weights, Gemma Scope 2's published interpretability checkpoints and llama.cpp's open-source inference runtime** let me investigate something below the text response.\n\nI could reproduce the local setup, construct my own controls, measure probability changes, and inspect effects beyond the target prompt.\n\nThat's the value of open-weight research: it makes experiments possible that are difficult or impossible through ordinary text-only APIs.\n\nThe most useful finding wasn't a dramatic haunted response.\n\nIt was seeing how easy it would have been to misinterpret one measurement.\n\nA ghost-related direction increased the probability of a ghost-related token.\n\nBut so did a random direction — and by more on the original pilot's absolute probability measure.\n\nAcross the larger evaluation, the SAE direction had a stronger mean than the five sampled controls, but its effects remained inconsistent.\n\nAnd unrelated predictions changed too.\n\nI learned how to explore published interpretability resources, extract an SAE direction, run local Gemma inference, perform activation steering and build reproducible evaluations.\n\nI also learned why good controls and careful limitations matter more than a spectacular-looking demonstration.\n\n**I moved an internal signal. I didn't erase a ghost.**\n\nWeight-level exorcism remains an experiment for another day.\n\nFor Halloween, I think that's a more interesting ending than pretending I found a magic switch.\n\n[Scientific Evidence and Reproducibility Report](https://github.com/Moonchichiii/ghost-hunters-lab/blob/main/docs/research/EVIDENCE_REPORT.md)\n\n**Research resources:**\n\n**Best Use of Gemma** — The scientific investigation uses locally running Gemma 3 4B IT, Gemma Scope 2, and activation steering to measure internal interventions.\n\n**Best Use of Render** — Render hosts the publicly accessible FastAPI application presenting the verified scientific evidence.\n\n*Built for the Hacktoberfest 2026 Open-Source AI Challenge, Week 4: Ghost in the Machine.*", "url": "https://wpnews.pro/news/ghost-hunter-s-lab", "canonical_source": "https://dev.to/moonchichiii/ghost-hunters-lab-575k", "published_at": "2026-10-31 09:10:14+00:00", "updated_at": "2026-10-31 09:20:02.159496+00:00", "lang": "en", "topics": ["artificial-intelligence", "machine-learning", "large-language-models", "ai-research", "ai-tools"], "entities": ["Gemma 3 4B IT", "Gemma Scope 2", "llama.cpp", "Google", "Neuronpedia", "Hugging Face", "FastAPI", "Gilbert Ryle"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/ghost-hunter-s-lab", "markdown": "https://wpnews.pro/news/ghost-hunter-s-lab.md", "text": "https://wpnews.pro/news/ghost-hunter-s-lab.txt", "jsonld": "https://wpnews.pro/news/ghost-hunter-s-lab.jsonld"}}