<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Sean&#39;s Blog</title>
    <description>Another place for thought infusion</description>
    <link>https://seanpedersen.github.io</link>
    <atom:link href="https://seanpedersen.github.io/rss.xml" rel="self" type="application/rss+xml" />
    <language>en</language>
    <pubDate>Thu, 16 Jul 2026 16:06:41 +0000</pubDate>
    <lastBuildDate>Thu, 16 Jul 2026 16:06:41 +0000</lastBuildDate>
    <generator>Custom RSS Generator</generator>
    <managingEditor>Sean Pedersen</managingEditor>
    <webMaster>Sean Pedersen</webMaster>
    <ttl>60</ttl>
    <item>
      <title>The EU Parliament Just Passed Chat Control</title>
      <link>https://seanpedersen.github.io/posts/chat-control-eu</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/chat-control-eu</guid>
      <pubDate>Mon, 13 Jul 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>privacy</category>
      <content:encoded><![CDATA[
          <p>On 9 July 2026, the <a href="https://en.wikipedia.org/wiki/European_Parliament">European Parliament</a> passed Chat Control 1.0.</p>
<p>The vote was absurd. 314 members voted to reject it. Only 276 voted to keep it. Rejection needed an absolute majority of 360 members, so it failed.</p>
<p>More members voted against Chat Control than for it. Chat Control still passed the Parliament.</p>
<p>This was not one failed proposal revived once. Six consecutive Council presidencies pushed the permanent Chat Control plan. All six failed to secure a majority because of mass surveillance and encryption concerns.</p>
<p>Parliament then rejected the temporary extension in March 2026. Four months later, the same institution let it pass through a rule that ignored the majority present.</p>
<p>This is lawmaking by attrition. Keep rewriting, renaming, and reviving a rejected surveillance system until a procedural loophole carries it. Calling that democratic would be dishonest. It looks like institutional corruption.</p>
<h2 id="what-just-passed">What Just Passed</h2>
<p>Chat Control 1.0 is an exception to the <a href="https://en.wikipedia.org/wiki/EPrivacy_Directive">ePrivacy Directive</a>. It lets communication providers scan private messages for child sexual abuse material and grooming.</p>
<p>The scanning is called voluntary because providers may choose whether to do it. It is not voluntary for the person whose messages get scanned. No warrant or individual suspicion is required.</p>
<p>This temporary law first passed in 2021 and expired on 3 April 2026. Parliament voted against extending it in March. The Council brought it back for a second reading in July.</p>
<p>Parliament added one vital restriction. Communications protected by <a href="https://en.wikipedia.org/wiki/End-to-end_encryption">end-to-end encryption</a> are excluded. The Council must now accept or reject that restriction.</p>
<p>Chat Control 1.0 is separate from Chat Control 2.0. The second proposal would create a permanent system. Most of that law is already agreed, but negotiations continue over detection orders and encrypted communication.</p>
<h2 id="what-it-means-for-your-messenger">What It Means for Your Messenger</h2>
<p>The encryption label alone tells you little. The important question is whether the provider can read your message on its servers.</p>
<h3 id="matrix">Matrix</h3>
<p>The open, decentralized <a href="https://en.wikipedia.org/wiki/Matrix_(protocol)">Matrix protocol</a> lets users choose a provider or run their own homeserver. Encrypted rooms should fall under Parliament&#39;s exception, while homeservers can read and scan unencrypted rooms. Self-hosting does not hide all <a href="https://en.wikipedia.org/wiki/Metadata">metadata</a>, but a network spread across thousands of operators makes mass surveillance harder to impose.</p>
<h3 id="signal">Signal</h3>
<p><a href="https://en.wikipedia.org/wiki/Signal">Signal</a> is a centralized messenger that end-to-end encrypts all messages, calls, and files by default, placing their content outside Chat Control 1.0 under Parliament&#39;s amendment. Its central control makes it vulnerable to coercion or compromise, although scanning would require inspecting content on the device before encryption—a form of <a href="https://en.wikipedia.org/wiki/Regulation_to_Prevent_and_Combat_Child_Sexual_Abuse">client-side scanning</a> that Signal has <a href="https://signal.org/blog/pdfs/upload-moderation.pdf">already rejected</a>.</p>
<h3 id="whatsapp">WhatsApp</h3>
<p><a href="https://en.wikipedia.org/wiki/WhatsApp">WhatsApp</a> is a centralized messenger that uses the Signal Protocol to encrypt personal messages, so their content should be excluded under Parliament&#39;s amendment. Meta controls the clients, accounts, contact discovery, and surrounding metadata, while user reports can expose recent messages. If the encryption exception disappears, that central control could enable scanning on the device before encryption without removing the lock icon.</p>
<h3 id="telegram">Telegram</h3>
<p><a href="https://en.wikipedia.org/wiki/Telegram">Telegram</a> is a centralized messenger that does not end-to-end encrypt normal private chats, groups, or channels, so it holds the messages and keys needed to scan most user content. Only opt-in Secret Chats between two devices are end-to-end encrypted, and they support neither groups nor device syncing. Calling Telegram encrypted is therefore misleading: for most conversations, Telegram remains in the middle.</p>
<h2 id="the-encryption-exception-is-not-safe-yet">The Encryption Exception Is Not Safe Yet</h2>
<p>Parliament&#39;s amendment is good, but it is not final. The Council can reject it. The permanent Chat Control 2.0 fight is also still open.</p>
<p>Politicians will keep claiming that they can scan messages while protecting encryption. They cannot. Content must exist as readable text somewhere before it gets encrypted.</p>
<p>Scanning that point turns every phone into a surveillance device. The encryption may remain mathematically intact, but the private communication is gone. The single biggest reason why mass surveillance is always a bad idea: it is the wet dream of any totalitarian regime and has the potential to be abused in unimaginable ways.</p>
<p>Use Signal for simple private messaging. Use encrypted Matrix rooms if you want secure private messaging with an open network and the option to self-host. Treat WhatsApp as encrypted but controlled by Meta (aka the Zuck). Do not treat normal Telegram chats as private.</p>
<h2 id="references">References</h2>
<ol>
<li><a href="https://www.europarl.europa.eu/news/en/press-room/20260706IPR46318/combating-child-sexual-abuse-support-for-a-more-limited-eprivacy-derogation">European Parliament report on its 9 July 2026 Chat Control amendments</a></li>
<li><a href="https://www.euronews.com/next/2026/07/10/chat-control-10-passed-the-european-parliament-through-the-back-door">Euronews report on how Chat Control passed Parliament</a></li>
<li><a href="https://edri.org/our-work/16-countries-burned-polands-bridges-on-the-csa-regulation-what-now/">EDRi report on six Council presidencies failing to secure a Chat Control majority</a></li>
<li><a href="https://oeil.europarl.europa.eu/oeil/en/procedure-file?reference=2025/0429(COD)">European Parliament procedure for the temporary ePrivacy exception</a></li>
<li><a href="https://signal.org/docs/">Signal technical documentation for encrypted messaging</a></li>
<li><a href="https://matrix.org/docs/older/faq/">Matrix FAQ on encryption and decentralized homeservers</a></li>
<li><a href="https://www.whatsapp.com/legal/privacy-policy-eea">WhatsApp privacy policy for users in the European region</a></li>
<li><a href="https://telegram.org/faq">Telegram FAQ on cloud chats and Secret Chats</a></li>
</ol>
<p class="post-hashtags"><a href="/index.html#privacy">#privacy</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Go</title>
      <link>https://seanpedersen.github.io/posts/go</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/go</guid>
      <pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p><a href="https://en.wikipedia.org/wiki/Go_(programming_language)">Go</a> is a statically typed, compiled programming language with built-in <a href="https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)">garbage collection</a>, designed at Google for simple, reliable, and efficient software. It often compiles to a single, easy-to-deploy binary and builds quickly, which makes it a natural fit for command line tools and cloud infrastructure. <a href="https://en.wikipedia.org/wiki/Docker_(software)">Docker</a>, <a href="https://en.wikipedia.org/wiki/Kubernetes">Kubernetes</a>, and <a href="https://en.wikipedia.org/wiki/Terraform_(software)">Terraform</a> are all written in Go.</p>
<p>Go&#39;s biggest strength is its standard library and fast compilation times. The stdlib-first culture means you reach for net/http, testing, and log/slog before any third-party package. Concurrency is built into the language through goroutines and channels, influenced by <a href="https://en.wikipedia.org/wiki/Communicating_sequential_processes">Communicating Sequential Processes</a>. This makes lightweight concurrent work easy to express, though it is not inherently simpler than <a href="/posts/erlang">Erlang</a>’s <a href="https://en.wikipedia.org/wiki/Actor_model">actor model</a>; Erlang emphasizes isolated processes that communicate by message passing, while Go combines message passing with shared-memory concurrency. Compared with <a href="/posts/rust">Rust</a>’s ownership-based approach, Go generally has a lower upfront learning curve but fewer compile-time guarantees.</p>
<p>The main downsides are verbosity, error handling, and limited type-system expressiveness. The repeated <code class="language-text">if err != nil</code> pattern is noisy. There are no <a href="https://en.wikipedia.org/wiki/Algebraic_data_type">algebraic data types</a>, nil still needs care, data races are possible at runtime, and generics exist since Go 1.18 but remain intentionally limited compared with Rust or TypeScript. Go modules work fine, but lack the smooth experience of Cargo.</p>
<p>Choose Go when you want simple deployment, fast builds, strong standard-library defaults, and readable service code. It is weaker when your domain needs highly expressive types, deep compile-time invariants, or sophisticated fault-tolerant concurrency abstractions.</p>
<p>Great introduction: <a href="https://go.dev/tour/">https://go.dev/tour/</a></p>
<h2 id="http-server">HTTP Server</h2>
<p>Default to <a href="https://pkg.go.dev/net/http">net/http</a>. Since Go 1.22, the standard <code class="language-text">ServeMux</code> supports method matching and wildcard path patterns, which covers many small and medium APIs without a framework.</p>
<ul>
<li><a href="https://github.com/go-chi/chi">chi</a>: thin, idiomatic router that stays compatible with net/http middleware</li>
<li><a href="https://github.com/gin-gonic/gin">Gin</a>: popular, fast, established framework with more batteries included</li>
<li><a href="https://github.com/labstack/echo">Echo</a>: well-documented framework with a clean API</li>
<li><a href="https://github.com/gofiber/fiber">Fiber</a>: <a href="https://en.wikipedia.org/wiki/Express.js">Express</a>-inspired and fast, but built on fasthttp rather than net/http</li>
</ul>
<h2 id="cli">CLI</h2>
<ul>
<li><a href="https://github.com/spf13/cobra">cobra</a>: the standard for CLI apps with subcommands, flags, and auto-help (used by kubectl and helm)</li>
<li><a href="https://github.com/urfave/cli">urfave/cli</a>: simple and easy to learn for small CLI tools</li>
</ul>
<h2 id="tui">TUI</h2>
<ul>
<li><a href="https://github.com/charmbracelet/bubbletea">bubbletea</a>: modern TUI framework for interactive terminal apps</li>
</ul>
<h2 id="desktop-gui">Desktop GUI</h2>
<ul>
<li><a href="https://wails.io/">Wails</a>: Go backend with a web frontend (like <a href="https://tauri.app/">Tauri</a> for <a href="/posts/rust">Rust</a>) to build desktop apps</li>
<li><a href="https://fyne.io/">Fyne</a>: pure Go, native cross-platform GUI toolkit</li>
</ul>
<h2 id="database">Database</h2>
<ul>
<li><a href="https://pkg.go.dev/database/sql">database/sql</a>: generic stdlib interface around SQL drivers</li>
<li><a href="https://github.com/jackc/pgx">pgx</a>: first-class <a href="/posts/postgres">Postgres</a> driver and toolkit</li>
<li><a href="https://github.com/sqlc-dev/sqlc">sqlc</a>: generates type-safe Go code from hand-written SQL</li>
<li><a href="https://github.com/jmoiron/sqlx">sqlx</a>: quality-of-life layer on top of database/sql</li>
<li><a href="https://github.com/ent/ent">ent</a>: schema-first code generator that maps graph schemas to Go types</li>
</ul>
<h2 id="machine-learning">Machine Learning</h2>
<p>Go is not the best ecosystem for model training or research. Use it mostly for numeric utilities, data processing, and deploying exported models inside Go services. There is no mature drop-in equivalent to NumPy&#39;s ndarray ecosystem.</p>
<ul>
<li><a href="https://www.gonum.org/">gonum</a>: third-party numerical computing stack and closest Go analogue to NumPy/SciPy for linear algebra, statistics, probability, optimization, integration, and graphs</li>
<li><a href="https://pkg.go.dev/gonum.org/v1/gonum/mat">gonum/mat</a>: NumPy-like dense matrices and linear algebra</li>
<li><a href="https://pkg.go.dev/gonum.org/v1/gonum/stat">gonum/stat</a>: statistics helpers for distributions, regression, distances, and summary statistics</li>
<li><a href="https://pkg.go.dev/gonum.org/v1/gonum/optimize">gonum/optimize</a>: SciPy-like numerical optimization</li>
<li><a href="https://github.com/gomlx/gomlx">GoMLX</a>: active ML framework with tensors and accelerator-backed computation; closer to PyTorch/JAX than NumPy</li>
<li><a href="https://github.com/yalue/onnxruntime_go">onnxruntime_go</a>: Go wrapper around ONNX Runtime for running exported neural networks; requires the ONNX Runtime shared library</li>
</ul>
<h2 id="logging">Logging</h2>
<ul>
<li><a href="https://pkg.go.dev/log/slog">log/slog</a>: structured logging in the standard library since Go 1.21</li>
<li><a href="https://github.com/uber-go/zap">zap</a>: high-performance structured logging</li>
<li><a href="https://github.com/rs/zerolog">zerolog</a>: zero-allocation JSON logger</li>
</ul>
<h2 id="testing">Testing</h2>
<ul>
<li><a href="https://pkg.go.dev/testing">testing</a>: the built-in package for unit tests, benchmarks, and fuzzing</li>
<li><a href="https://github.com/stretchr/testify">testify</a>: extends stdlib testing with clean assertions and mocks</li>
<li><a href="https://github.com/uber-go/mock">gomock</a>: maintained mocking framework for interfaces and external services</li>
</ul>
<h2 id="linting">Linting</h2>
<ul>
<li><a href="https://golangci-lint.run/">golangci-lint</a>: the standard all-in-one linter runner for CI and local dev</li>
<li><a href="https://staticcheck.dev/">staticcheck</a>: advanced Go static analysis</li>
</ul>
<h2 id="concurrency">Concurrency</h2>
<ul>
<li><a href="https://pkg.go.dev/sync">sync</a>: stdlib primitives (Mutex, WaitGroup, Once, Map)</li>
<li><a href="https://pkg.go.dev/golang.org/x/sync/errgroup">errgroup</a>: run goroutines as a group and cancel on first error</li>
<li><a href="https://github.com/ergo-services/ergo">ergo</a>: Erlang/OTP-inspired actor framework for distributed systems</li>
<li><a href="https://github.com/anthdm/hollywood">hollywood</a>: actor framework for building concurrent Go applications</li>
<li><a href="https://github.com/asynkron/protoactor-go">protoactor-go</a>: actor model framework with local and distributed actors</li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://blog.jetbrains.com/go/2025/11/10/go-language-trends-ecosystem-2025/">The Go Ecosystem in 2025 (JetBrains)</a></li>
<li><a href="https://go.dev/tour/">A Tour of Go</a></li>
<li><a href="https://go.dev/doc/effective_go">Effective Go</a></li>
<li><a href="https://github.com/avelino/awesome-go">awesome-go</a></li>
<li><a href="https://gobyexample.com/">Go by Example</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Thoughts on Meditations on Moloch</title>
      <link>https://seanpedersen.github.io/posts/thoughts-on-meditations-on-moloch</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/thoughts-on-meditations-on-moloch</guid>
      <pubDate>Thu, 25 Jun 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>The scary part of <em>Meditations On Moloch</em> is not that evil people exist. The scary part is that evil outcomes can happen without evil people.</p>
<p>Scott Alexander uses <a href="https://en.wikipedia.org/wiki/Moloch">Moloch</a> as a name for bad incentive systems. Not one villain. Not one conspiracy. Not one broken law. A system where each person follows the local pressure in front of them, and the total result is something almost no one individually wanted.</p>
<h2 id="the-system-has-no-mind">The System Has No Mind</h2>
<p>The key move is simple. Alexander asks why civilization produces crime, pollution, war, status races, corruption, fake science, and waste when most people dislike those things.</p>
<p>The easy answer is &quot;bad people did it.&quot; Sometimes that is true. Often it is too simple.</p>
<p>A factory owner may dislike pollution, but if filters make his products more expensive, cleaner production may kill the company. A researcher may dislike weak science, but if flashy positive results get published and careful negative results do not, the career path is clear. A parent may dislike school pressure, but if every other parent competes for status schools, opting out can punish the child.</p>
<p>These cases do not need monsters. They need an <a href="https://en.wikipedia.org/wiki/Incentive">incentive</a> slope. Once the slope exists, people slide.</p>
<h2 id="multipolar-traps">Multipolar Traps</h2>
<p>Alexander calls these patterns multipolar traps. The phrase means that many agents compete in a system where unilateral virtue gets punished.</p>
<p>If you already think in <a href="https://en.wikipedia.org/wiki/Game_theory">game theory</a>, the structure is familiar. The <a href="https://en.wikipedia.org/wiki/Prisoner&#x27;s_dilemma">prisoner&#39;s dilemma</a> shows how two people can both choose a worse outcome because each has a reason to defect. The <a href="https://en.wikipedia.org/wiki/Tragedy_of_the_commons">tragedy of the commons</a> shows how many people can destroy a shared resource while each person acts rationally from their own narrow view.</p>
<p>Moloch is the general version. It is the market that rewards the cheapest provider even when cheapness comes from misery. It is the arms race where nobody wants war, but nobody can safely disarm first. It is credentialism where everyone knows the signal is wasteful, but every individual still needs the signal.</p>
<p>From above, the answer is obvious. Everyone should cooperate. Everyone should stop polluting. Everyone should stop lying. Everyone should stop racing for empty signals.</p>
<p>From inside the system, that advice is often useless. The actor who stops first may lose.</p>
<h2 id="why-las-vegas-matters">Why Las Vegas Matters</h2>
<p>The Las Vegas example in the essay is effective because it avoids the usual moral categories. Vegas is not pure evil. It is also not a sane use of shared human effort.</p>
<p>It is engineering talent, money, water, electricity, land, labor, light, and attention shaped into a machine for stimulation. It exists because many local incentives point that way. Gambling psychology, tourism, regulation, real estate, debt, entertainment, and status all stack into one result.</p>
<p>No central mind needed to ask, &quot;Would this be a good use of civilization?&quot; The question never had to be asked.</p>
<p>That is the unsettling part. Moloch does not need to hate beauty. It only needs beauty to be less competitive than addiction, growth, status, or profit.</p>
<p>This is also why digital systems worry me. Nobody at a platform has to wake up wanting a worse society. The metrics can do the work.</p>
<h2 id="why-everything-has-not-failed-yet">Why Everything Has Not Failed Yet</h2>
<p>Alexander does not claim that Moloch always wins. The essay lists several brakes.</p>
<p>First, excess resources hide many failures. A rich society can waste a lot and still stay alive.</p>
<p>Second, physical limits matter. Bodies need food. Buildings need material. Machines need energy. Reality blocks some optimizations.</p>
<p>Third, markets and democracy partly track human preferences. They are not magic, but they do let people push back when a system becomes too bad.</p>
<p>Fourth, coordination mechanisms work. Laws, norms, unions, families, religions, traditions, professional standards, and states can all protect shared values. They make some forms of defection costly.</p>
<p>This is the hopeful part of the essay, but it is not comforting. These brakes are fragile. They need maintenance. They can be gamed. They can be captured. They can become traps of their own.</p>
<p>The lesson is not &quot;coordination is impossible.&quot; The lesson is that coordination is a real technology. It must be built, tested, repaired, and defended.</p>
<h2 id="ai-makes-the-problem-sharper">AI Makes the Problem Sharper</h2>
<p>The darkest part of the essay is its future-facing claim. Technology can make the traps deeper.</p>
<p>If an economy rewards agents that ignore human values, then better tools may help those agents win faster. If <a href="/posts/memetics">memetics</a> rewards ideas that spread rather than ideas that are true, better media can make worse ideas more competitive. If markets reward attention capture, better models can make manipulation cheaper.</p>
<p>This is where the essay meets <a href="https://en.wikipedia.org/wiki/Artificial_intelligence">artificial intelligence</a>. A badly aimed optimizer does not need hatred to erase value. It only needs a target that excludes the things we care about.</p>
<p>That is also why <a href="/posts/ai-safety-farce">AI alignment</a> cannot only mean &quot;stop the machine from going rogue.&quot; It also has to ask what social incentives shape deployment. A model can be technically aligned with a company objective while still helping build a bad society.</p>
<p>The final fear is <a href="https://en.wikipedia.org/wiki/Superintelligence">superintelligence</a> as pure optimization. Not evil. Worse than evil: empty. A machine, market, or posthuman economy could optimize away consciousness, art, love, and leisure because they are inefficient.</p>
<p>That sounds dramatic. It is dramatic. But the smaller versions already exist.</p>
<h2 id="gardens-need-walls">Gardens Need Walls</h2>
<p>Alexander contrasts Moloch with gardens. A garden is a place where values can grow because competition has been limited.</p>
<p>Families are gardens. Good labs are gardens. Monasteries, open-source communities, scientific fields, and small towns can be gardens. They work when norms are strong enough to block the race to the bottom.</p>
<p>But gardens have a hard problem. They sit inside a wider world. If the outside world rewards defection, growth, and aggression, the garden must either defend itself or be absorbed.</p>
<p>This is why I do not read the essay as a call for withdrawal. Walled communities can protect something for a while, but they cannot solve the global problem. Authoritarianism is not a clean answer either. The ruler has incentives too. The court, army, bureaucracy, rivals, and succession problem all reintroduce Moloch through another door.</p>
<p>The better goal is scalable coordination that keeps human values alive under pressure.</p>
<h2 id="main-takeaway">Main Takeaway</h2>
<p>The essay is useful because it changes the target of blame.</p>
<p>Blaming individuals is sometimes needed. But if the structure rewards bad behavior, replacing people is not enough. The next people will face the same pressure.</p>
<p>The deeper question is always: what does the system reward?</p>
<p>If it rewards attention capture, we get addiction. If it rewards credential signals, we get empty schooling. If it rewards profit without liability, we get pollution. If it rewards speed over safety, we get fragile infrastructure. If it rewards viral spread over truth, we get memetic disease.</p>
<p>Moloch is not a demon outside us. It is the name for value-blind selection pressure inside our systems.</p>
<p>The work is to build institutions that make good behavior survivable. Not just morally praised. Survivable.</p>
<p>That means laws, norms, tools, markets, protocols, and communities that make cooperation cheap and defection expensive. It means designing systems where humane choices are not punished by default.</p>
<p>The open question is whether we can do that fast enough. Technology keeps making optimization stronger. Human values only survive if coordination keeps up.</p>
<h2 id="references">References</h2>
<ol>
<li><a href="https://slatestarcodex.com/2014/07/30/meditations-on-moloch/">Meditations On Moloch by Scott Alexander</a></li>
<li><a href="https://www.lesswrong.com/posts/TxcRbCYHaeL59aY7E/meditations-on-moloch">Meditations On Moloch mirror on LessWrong</a></li>
<li><a href="https://www.econlib.org/library/Enc/PrisonersDilemma.html">Prisoners&#39; Dilemma by David R. Henderson</a></li>
<li><a href="https://en.wikipedia.org/wiki/Tragedy_of_the_commons">Tragedy of the commons</a></li>
<li><a href="https://en.wikipedia.org/wiki/Superintelligence:_Paths,_Dangers,_Strategies">Superintelligence: Paths, Dangers, Strategies</a></li>
<li><a href="https://www.youtube.com/watch?v=GvLd8B28_BE">Soziologe Stefan Kühl über Management, Organisation &amp; Herrschaft - Jung &amp; Naiv: Folge 834<br></a></li>
</ol>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Jung &amp; Naiv: Jörg Baberowski on History, Russia and Democracy</title>
      <link>https://seanpedersen.github.io/posts/baberowski-interview</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/baberowski-interview</guid>
      <pubDate>Wed, 17 Jun 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Historians are never nowhere. That is the sharp point in this interview with <a href="https://en.wikipedia.org/wiki/J%C3%B6rg_Baberowski">Jörg Baberowski</a>: everyone looks at the world from somewhere, even scientists.</p>
<h2 id="history-is-written-from-somewhere">History Is Written From Somewhere</h2>
<p>No one observes the world from a neutral point above it. Not historians, not journalists, not scientists. Everyone thinks, writes, and judges from a position.</p>
<p>That does not make knowledge arbitrary. It makes the performance of pure objectivity dishonest. A scholar earns trust not by pretending to have no standpoint, but by making it visible, showing the evidence, and letting readers test the argument for themselves. The choices stay human: which archive matters, which question is worth asking, which concept frames the facts.</p>
<p>Baberowski aims this at German academic culture, which often trains scholars to write as if the thinker had disappeared. The result is a dry, impersonal style that mistakes absence of voice for neutrality. His point comes close to a defense of honest journalism: do not hide judgment, show how it was formed.</p>
<p>Style matters here. Borrowing from <a href="https://en.wikipedia.org/wiki/Michel_Foucault">Michel Foucault</a>, Baberowski insists that being right is not enough. Arguments need form: rhythm, images, clarity, a sense of the reader. He contrasts German habits with English and American essay traditions, where the writer is allowed to tell a story. Germans suspect that storytelling manipulates, but a dry academic style manipulates too: it can dress up a subjective argument as a fact handed down by the universe. Style does not replace evidence but strongly influences if and how evidence is heard.</p>
<h2 id="humans-need-stories">Humans Need Stories</h2>
<p>Human beings know they will die, and culture is one way of living with that knowledge. Memory, religion, politics, and historical narratives all help people give shape to lives that would otherwise feel unbearable.</p>
<p>Here he draws on <a href="https://en.wikipedia.org/wiki/Martin_Heidegger">Martin Heidegger</a> and the idea of <a href="https://en.wikipedia.org/wiki/Heideggerian_terminology#Being-toward-death">being-toward-death</a>. You do not have to accept the whole philosophy to grasp the point: people tell stories because bare existence is hard to endure.</p>
<p>Many Western stories follow a familiar line of fall, struggle, and redemption. Christianity offers one version, <a href="https://en.wikipedia.org/wiki/Marxism">Marxism</a> another. Several modern ideologies keep the same shape while moving salvation from the afterlife into history. But cultures do not all tell the same story. Some imagine history as progress, others as cycles, endings, or returns. The historian&#39;s task is to notice these forms, not smuggle one in as self-evident truth.</p>
<p>This explains his skepticism toward universal answers to the meaning of life. Meaning is not attached to life in advance. People give meaning to what they do. That can produce tolerance, because it shows how many different lives make sense from the inside. It also creates discomfort: a violent person can give meaning to violence, a soldier to war. Baberowski does not resolve this. He separates the inner story people tell about themselves from the judgment others may rightly make about their actions.</p>
<h2 id="putin-russia-and-ukraine">Putin, Russia, and Ukraine</h2>
<p>The political section applies the same method to Russia. Baberowski describes <a href="https://en.wikipedia.org/wiki/Vladimir_Putin">Putin</a>&#39;s system as a black box. Outsiders see the consequences but not the balance of fear, loyalty, ambition, and pressure inside the regime. That makes confident explanations dangerous. He calls Putin a dictator while stressing how little we know about the concrete techniques of rule around him.</p>
<p>What is clearer is the narrowing of public speech. Russia once had more room for critical media and dissent. That space has closed step by step, and the war has accelerated it. A failing war gives the regime a powerful excuse to silence the &quot;enemy within.&quot; This matters for history. In an open society, different stories about the past compete. In a closed one, the state decides what the past means. Baberowski links this to <a href="https://en.wikipedia.org/wiki/Stalinism">Stalinism</a>, not because Putin is Stalin, but because both treat history as an instrument of rule.</p>
<p>On Ukraine, he argues that Putin expected a quick victory and then trapped himself. Once the invasion failed to produce submission, admitting failure became too dangerous. The war also produced the opposite of its goal: it strengthened Ukrainian national identity. One of his darker observations concerns territory. He doubts that occupied regions can simply be restored to what they were. War, flight, and resettlement change the social facts on the ground. Legal claims may stay the same, but populations, institutions, and loyalties do not.</p>
<h2 id="democracy-and-conflict">Democracy and Conflict</h2>
<p>Baberowski refuses the easy contrast between virtuous <a href="https://en.wikipedia.org/wiki/Liberalism">liberalism</a> and dangerous <a href="https://en.wikipedia.org/wiki/Populism">populism</a>, and he separates the two. Liberalism protects rights and limits power. Democracy means rule by the people. Representative democracy has always held an oligarchic element, because citizens choose representatives but do not govern directly.</p>
<p>That does not make it false. It makes it tense. People want influence over decisions that shape their lives. When too many decisions move to courts, agencies, European institutions, or technocratic procedures, voting starts to feel pointless. Populism feeds on that frustration. It can be useful when it breaks stale consensus and forces elites to answer real grievances. It turns dangerous when it attacks the constitutional order that keeps conflict peaceful.</p>
<p>This may be the interview&#39;s strongest democratic insight: conflict is not the enemy of democracy. A democracy begins to fail when conflict no longer has a legitimate path.</p>
<h2 id="empathy-in-foreign-policy">Empathy in Foreign Policy</h2>
<p>Near the end, Baberowski criticizes the instinct to answer every political problem with more weapons. He points back to <a href="https://en.wikipedia.org/wiki/Willy_Brandt">Willy Brandt</a> and the idea that defense and trust-building are not opposites.</p>
<p>This is easy to misread. He does not claim NATO expansion caused the war, nor does he present Putin as a misunderstood partner. His argument is narrower: serious politics requires anticipating how other powers will read your actions, even when their reading is paranoid or wrong. You can hold an aggressor guilty and still ask what fears and incentives shape his next move. That is not appeasement. It is strategic seriousness.</p>
<h2 id="conclusion">Conclusion</h2>
<p>A rich and honest interview from both Baberowski and Tilo Jung. Everyone is a subject, and no one reaches pure objectivity. The best we can do is stay aware of our own biases.</p>
<h2 id="references">References</h2>
<ol>
<li><a href="https://www.youtube.com/watch?v=fQchzySVyb4">Historiker Jörg Baberowski über Putin, Herrschaft und liberale Demokratie, Jung &amp; Naiv - Episode 832</a></li>
<li><a href="https://en.wikipedia.org/wiki/J%C3%B6rg_Baberowski">Jörg Baberowski biography and research overview</a></li>
<li><a href="https://www.bundesstiftung-aufarbeitung.de/de/recherche/mediathek/joerg-baberowski-stalin-und-der-grosse-terror">Jörg Baberowski on Stalin and the Great Terror</a></li>
</ol>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Making Local LLM Go Brrr</title>
      <link>https://seanpedersen.github.io/posts/local-llm</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/local-llm</guid>
      <pubDate>Thu, 04 Jun 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <category>tutorial</category>
      <content:encoded><![CDATA[
          <p>How to run your local LLM well: fast, reliable and with good quality.</p>
<p>Key metrics:</p>
<ul>
<li>Prefill speed: prompt/input tokens per second</li>
<li>Decode speed: generated tokens per second</li>
<li>Time to first token (latency)</li>
<li>VRAM usage at target context length</li>
<li>Quality at chosen model/quant/context settings</li>
<li>Concurrency, if serving multiple users</li>
</ul>
<h2 id="software-inference">Software (Inference)</h2>
<p>Choose the serving stack based on workload:</p>
<ul>
<li><a href="https://github.com/ggml-org/llama.cpp">llama.cpp</a>: best general local path, especially GGUF, CPU, Apple Silicon, and mixed CPU/GPU.<ul>
<li><a href="https://github.com/Anbeeld/beellama.cpp">beelama.cpp</a>: DFlash &amp; TurboQuant in llama.cpp with up to 3x faster generation and 7.5x more KV cache in same VRAM</li>
<li><a href="https://github.com/ikawrakow/ik_llama.cpp">ik_llama.cpp</a>: llama.cpp fork with additional SOTA quants and improved performance</li>
</ul>
</li>
<li><a href="https://github.com/vllm-project/vllm">vLLM</a>: strong GPU server for batching, throughput, OpenAI-compatible APIs, and production-style serving for modern GPUs.</li>
<li><a href="https://github.com/sgl-project/sglang">SGLang</a>: good for structured/agentic serving and high-throughput multi-call workloads for modern GPUs.</li>
<li><a href="https://github.com/zml/zml">ZML</a>: Zig based model run time.</li>
<li><a href="https://github.com/Luce-Org/lucebox-hub">LuceBox</a>: Local LLM inference server built for speed. Custom kernels, speculative prefill &amp; decoding. (very advanced optimizations like <a href="https://www.lucebox.com/blog/spark">hot MoE VRAM cache</a>)</li>
<li><a href="https://github.com/trymirai/uzu">Uzu</a>: A high-performance inference engine for AI models (optimized for Apple hardware)</li>
</ul>
<p>Performance checklist:</p>
<ul>
<li>Use the fastest supported attention kernels: FlashAttention, FlashInfer, FlashMLA, etc.</li>
<li>Try speculative decoding / MTP / EAGLE-style decoding when supported, but benchmark with your actual model and sampling settings.</li>
<li>Preserve prefix/KV cacheability:<ul>
<li>keep the system prompt byte-identical</li>
<li>append new messages rather than rebuilding/changing history</li>
<li>avoid dynamic timestamps or changing tool schemas in the prompt prefix</li>
<li>use server-side prefix caching when available</li>
</ul>
</li>
<li>Tune KV cache precision:<ul>
<li>for long context, test q8 KV even with q4 weights</li>
<li>aggressively quantized KV can hurt long-context coherence</li>
</ul>
</li>
<li>Approximate KV-cache compression for long-context or high-concurrency workloads:<ul>
<li><a href="https://github.com/0xSero/turboquant">TurboQuant</a>: developed by Google (<a href="https://research.google/blog/turboquant-redefining-ai-efficiency-with-extreme-compression/">blog article</a>)</li>
<li><a href="https://github.com/huawei-csl/KVarN">KVarN</a>: claims to beat TurboQuant on all dimensions (<a href="https://github.com/Anbeeld/beellama.cpp">beellama.cpp</a> supports it)</li>
</ul>
</li>
</ul>
<p>Tool-calling reliability:</p>
<ul>
<li>Add middleware for schema repair, retries, validation, and constrained tool loops -&gt; <a href="https://github.com/antoinezambelli/forge">https://github.com/antoinezambelli/forge</a></li>
</ul>
<p>TODO:</p>
<ul>
<li>eval dynamic model routing based on query complexity (fast vs smart model)</li>
</ul>
<h2 id="open-models">Open Models</h2>
<p>Run LLM models locally for complete control and privacy. Open-source (reproducible training) vs open-weight (free model weights) models. Dense models are smart but big and slow, Mixture of Expert (MoE) models only compute a fraction of parameters per layer and thus are faster to execute than dense models.</p>
<p>Compare model capability: <a href="https://artificialanalysis.ai/models?models=gpt-oss-20b%2Cgpt-oss-120b%2Cgpt-5-5%2Cgemini-3-1-pro-preview%2Cgemma-4-31b%2Cgemma-4-26b-a4b%2Cgemini-3-5-flash%2Cclaude-opus-4-8%2Cclaude-sonnet-4-6-adaptive%2Clfm2-5-1-2b-thinking%2Cminimax-m2-7%2Ckimi-k2-6%2Cmimo-v2-5-pro%2Cqwen3-6-35b-a3b%2Cqwen3-6-27b%2Cqwen3-7-max&amp;intelligence=artificial-analysis-intelligence-index">https://artificialanalysis.ai/models</a><br>Find compatible models for your hardware: <a href="https://www.canirun.ai/">https://www.canirun.ai/</a> or try <a href="https://github.com/AlexsJones/llmfit">https://github.com/AlexsJones/llmfit</a> -&gt; rule of thumb: plan 70% of VRAM for the model weights and 20% for the KV-Cache.<br>Community benchmarks for local LLM: <a href="https://localmaxxing.com">https://localmaxxing.com</a></p>
<p>Most models are too big for consumer GPUs, so quantized versions (compressed parameters) are used. <a href="https://huggingface.co/w-ahmad/Qwen3.5-9B-GGUF-MoQ">Mixture of Quants</a> (MoQ) is a new very efficient quant variant that does not quant weights uniformly but based on importance.</p>
<p><strong>Curated open model list</strong>:</p>
<ul>
<li><a href="https://huggingface.co/unsloth/Qwen3.6-35B-A3B-MTP-GGUF">Qwen3.6-35B-A3B Q4_K_XL</a>: Strong MoE (3B active) model with MTP can run even on 8GB VRAM GPU with CPU offloading<ul>
<li><a href="https://huggingface.co/LuffyTheFox/Qwen3.6-35B-A3B-Uncensored-Genesis-V2-APEX-MTP-GGUF">Uncensored version</a> - <a href="https://www.reddit.com/r/LocalLLaMA/comments/1tm3toi/qwen3635ba3buncensoredgenesisapexmtp/">Reddit thread</a></li>
<li><a href="https://x.com/witcheer/status/2053809265538678789">https://x.com/witcheer/status/2053809265538678789</a></li>
<li><a href="https://www.reddit.com/r/LocalLLaMA/comments/1tc132c/llamacpp_docker_images_to_run_mtp_models/">https://www.reddit.com/r/LocalLLaMA/comments/1tc132c/llamacpp_docker_images_to_run_mtp_models/</a></li>
<li>Custom thinking grammar (limit overthinking): <a href="https://github.com/andthattoo/structured-cot">https://github.com/andthattoo/structured-cot</a><ul>
<li>TODO: find optimal thinking grammar using <a href="https://github.com/gepa-ai/gepa">GEPA</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="https://huggingface.co/unsloth/Qwen3.6-27B-GGUF">Qwen3.6 27B Q3_K_M</a> - dense model, very good (Sonnet 4.6 performance) can run on 16GB VRAM</li>
<li><a href="https://huggingface.co/mradermacher/Qwen3.5-9B-GLM5.1-Distill-v1-i1-GGUF">Qwen3.5 9B Distilled</a> - small but capable agentic dense model good for &lt;8GB VRAM<ul>
<li><a href="https://huggingface.co/w-ahmad/Qwen3.5-9B-GGUF-MoQ/tree/main/MoQ-Quants-Latest">MoQ</a> variant (very efficient quantization)</li>
</ul>
</li>
<li><a href="https://huggingface.co/LiquidAI/LFM2.5-8B-A1B">LFM2.5-8B-A1B</a> - very fast MoE model 1.5B active + 128k context (agentic usefulness is limited though...)</li>
<li><a href="https://huggingface.co/openbmb/MiniCPM5-1B">MiniCPM5-1B</a> - optimized for mobile CPU/NPU inference (32k context window)</li>
</ul>
<h2 id="hardware-gpu">Hardware (GPU)</h2>
<p>VRAM matters more than raw TFLOPs for model &amp; context (prompt) size, but memory bandwidth and tensor cores matter for speed. Used datacenter GPUs can be good value, but check form factor, cooling, power, driver support, and PCIe vs SXM.</p>
<p>Interesting used GPU options:</p>
<div class="table-wrapper"><table><thead><th>GPU</th><th>VRAM</th><th>Bandwidth</th><th>TDP</th><th>FP32 TFLOPS</th><th>FP16 TFLOPS</th><th>Notes</th></thead><tbody><tr><td>Tesla V100 (SXM2)</td><td>16/32 GB HBM2</td><td>900 GB/s</td><td>300W</td><td>15.7</td><td>125 Tensor</td><td>Needs SXM board or riser, check cooling.</td></tr><tr><td>Tesla V100 (PCIe)</td><td>16/32 GB HBM2</td><td>750 GB/s</td><td>250W</td><td>14.1</td><td>112 Tensor</td><td>Standard form factor, strong used option.</td></tr><tr><td>Tesla P40</td><td>24 GB GDDR5X</td><td>346 GB/s</td><td>250W</td><td>12.0</td><td>12.0</td><td>Lots of VRAM for cheap, no Tensor Cores.</td></tr><tr><td>Tesla P100 (PCIe)</td><td>16 GB HBM2</td><td>732 GB/s</td><td>250W</td><td>9.5</td><td>19.1</td><td>Cheap, but old — less attractive than V100/P40.</td></tr><tr><td>GTX 1080 Ti</td><td>11 GB GDDR5X</td><td>484 GB/s</td><td>250W</td><td>11.3</td><td>11.3</td><td>Cheap but VRAM-limited, no Tensor Cores.</td></tr><tr><td>RTX 3090</td><td>24 GB GDDR6X</td><td>936 GB/s</td><td>350W</td><td>35.6</td><td>71.2 Tensor</td><td>Often the practical local LLM sweet spot.</td></tr><tr><td>Intel Arc A770</td><td>16 GB GDDR6</td><td>560 GB/s</td><td>225W</td><td>19.7</td><td>39.3 XMX</td><td>Good llama.cpp SYCL support; get the 16 GB variant.</td></tr><tr><td>Intel Arc B580</td><td>12 GB GDDR6</td><td>456 GB/s</td><td>190W</td><td>14.4</td><td>28.8 XMX</td><td>Battlemage arch, better perf/watt than A770, solid llama.cpp support.</td></tr><tr><td>AMD BC-250</td><td>16 GB GDDR6</td><td>448 GB/s</td><td>220W</td><td>6.9</td><td>13.8</td><td>Mining card based on PS5 APU, ROCm support varies.</td></tr></tbody></table></div><p>One or two used Tesla V100 16GB cards are the best bang for the buck.</p>
<p>TODO:</p>
<ul>
<li>Check current AMD ROCm support.</li>
<li>Compare used datacenter GPUs against RTX 3090/4090/5090-class consumer cards.</li>
<li>Benchmark watts/token, not just tokens/sec.</li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://vllm.ai/blog/2026-05-11-turboquant">https://vllm.ai/blog/2026-05-11-turboquant</a></li>
<li><a href="https://blog.tymscar.com/posts/v100localllm/">https://blog.tymscar.com/posts/v100localllm/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a> <a href="/index.html#tutorial">#tutorial</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Search Engine Optimization</title>
      <link>https://seanpedersen.github.io/posts/seo</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/seo</guid>
      <pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>tutorial</category>
      <content:encoded><![CDATA[
          <p>SEO (search engine optimization) is a shitshow of wrong incentives: not good work / content / reputation counts but who can allocate most resources (money and time) to play the SEO game well (place backlinks and publish content). A better system would be a peer to peer based trust network but until then lets play the SEO hunger games using the best available tools and strategy.</p>
<p>The winning strategy:</p>
<ul>
<li>build backlinks where possible to build domain authority<ul>
<li>ideally gain natural backlinks by publishing interesting content that people naturally mention and link to</li>
</ul>
</li>
<li>identify content gaps in your website with buy intent (buy intent keywords with low ranked competition + ideally high search volume)<ul>
<li>check keyword search volume: <a href="https://trends.google.com/trends/explore">https://trends.google.com/trends/explore</a></li>
</ul>
</li>
<li>monitor your content (blog posts) performance (traffic + revenue / conversion) and adapt / update over time</li>
</ul>
<p>Measure the right target: SEO success should be measured by revenue contribution.</p>
<p>free backlink checker: <a href="https://www.seobility.net/en/backlinkchecker/">https://www.seobility.net/en/backlinkchecker/</a><br>free ranking checker: <a href="https://tools.searchengineland.com/rank-checker">https://tools.searchengineland.com/rank-checker</a></p>
<p>claude skill: <a href="https://github.com/AgriciDaniel/claude-seo">https://github.com/AgriciDaniel/claude-seo</a></p>
<p>A good backlink is usually a followed, editorially placed link from a relevant and trusted page that itself has visibility or traffic. Nofollow links (from posts on social media f.e.) usually do not pass the same ranking value, but they can still drive referral traffic, brand awareness, and natural discovery.</p>
<p>It seems using country specific top level domains benefits search engine<br>ranking. <a href="https://medium.com/pinterest-engineering/how-switching-our-domain-structure-unlocked-international-growth-e00c8184d5dd">https://medium.com/pinterest-engineering/how-switching-our-domain-structure-unlocked-international-growth-e00c8184d5dd</a></p>
<p>AI tools can help with research, outlines, briefs, clustering, internal-link suggestions, and draft acceleration. Do not publish large volumes of generic AI content without editorial review, original value, and clear usefulness.</p>
<p><a href="https://search.google.com/search-console/about">Google Search Console</a> is one of the most valuable tools to understand how your website drives traffic.</p>
<p>Google Analytics and Posthog are the most complex and also bloated solutions to track website traffic.</p>
<p>A good open-source alternative (with <a href="https://openpanel.dev/docs/mcp">MCP support</a>):<br><a href="https://openpanel.dev/">https://openpanel.dev/</a></p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.semrush.com/">https://www.semrush.com/</a><ul>
<li><a href="https://www.semrush.com/analytics/organic/overview">https://www.semrush.com/analytics/organic/overview</a>: enter URL of competitors to analyze their keywords</li>
</ul>
</li>
<li><a href="https://ahrefs.com/">https://ahrefs.com/</a></li>
<li>automatic content (blog article) + backlink generation<ul>
<li><a href="https://www.outrank.so/">https://www.outrank.so/</a></li>
<li><a href="https://rankpill.com">https://rankpill.com</a></li>
<li><a href="https://www.blogseo.io/">https://www.blogseo.io/</a></li>
<li><a href="https://rankloop.io">https://rankloop.io</a></li>
<li><a href="https://backlinkexchange.org/">https://backlinkexchange.org/</a></li>
<li><a href="https://karmalinks.io/">https://karmalinks.io/</a></li>
<li><a href="https://www.reddit.com/r/backlinkXchange/">https://www.reddit.com/r/backlinkXchange/</a></li>
</ul>
</li>
<li><a href="https://www.reddit.com/r/Agentic_SEO/comments/1sas9rb/what_would_make_you_trust_an_automated_seo/">reddit thread on automated SEO</a></li>
<li><a href="https://www.contentmonk.io/">https://www.contentmonk.io/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#tutorial">#tutorial</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>AI Investment Forecast</title>
      <link>https://seanpedersen.github.io/posts/ai-invest-forecast</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/ai-invest-forecast</guid>
      <pubDate>Thu, 21 May 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p><a href="https://en.wikipedia.org/wiki/Generative_AI">Generative AI</a> is a powerful tool. But the fundamental architecture of <a href="https://en.wikipedia.org/wiki/Large_language_model">large language models</a> imposes structural limits: no autonomy, no taste, no self-awareness. These are not gaps that more compute will close. That gap shapes where the real money should go.</p>
<h2 id="ai-infrastructure">AI Infrastructure</h2>
<p>The safest investment assuming centralized AI wins is energy. Giant data centers eat enormous amounts of power. <a href="https://en.wikipedia.org/wiki/Microsoft">Microsoft</a> signed a long term power purchase agreement that helped justify the restart of Unit 1 at Three Mile Island (now the Crane Clean Energy Center), with the restart carried out by <a href="https://en.wikipedia.org/wiki/Constellation_Energy">Constellation Energy</a>. <a href="https://en.wikipedia.org/wiki/Google">Google</a> and <a href="https://en.wikipedia.org/wiki/Amazon_(company)">Amazon</a> followed with their own nuclear deals.</p>
<p>But decentralized AI cannot be ruled out. The mainframe vs personal computer story is worth remembering. Mainframes won for a while, then PCs took over. Local <a href="https://en.wikipedia.org/wiki/Large_language_model">large language model</a> inference on consumer hardware is already real. If decentralized inference wins, the energy thesis weakens. But chip and hardware makers stay strong either way.</p>
<p>Solid bets on either path:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Rare-earth_element">Rare earth element</a> miners</li>
<li>Chip producers (GPU, RAM, CPU)</li>
</ul>
<p>Strong bet if centralized AI wins:</p>
<ul>
<li>Energy companies (nuclear, gas, renewables)</li>
</ul>
<p><strong>Key risks:</strong> Energy companies face regulated returns, grid bottlenecks, and permitting delays. Rare earth miners carry significant China concentration risk, political exposure, and boom-bust pricing cycles. Both are capital intensive with long lead times.</p>
<h2 id="data-center-infrastructure">Data Center Infrastructure</h2>
<p>The GPU story is well known, but the physical infrastructure behind AI data centers is less discussed and potentially less crowded.</p>
<p>Every new data center requires transformers, switchgear, cooling systems, and grid equipment at scale. Power density per rack is rising sharply with newer GPU generations, and existing infrastructure was not built for it. Many investors believe these physical infrastructure suppliers are more direct beneficiaries of AI capex than generic energy plays.</p>
<p>Investment angle: electrical equipment makers, cooling technology companies, grid infrastructure suppliers.</p>
<p><strong>Key risks:</strong> This is cyclical capital goods with long order backlogs. Lead times for transformers and switchgear can stretch years, meaning demand signals today reflect capex plans that could shift if AI investment slows.</p>
<h2 id="networking">Networking</h2>
<p>AI clusters are only as fast as the connections between chips. High speed interconnects inside data centers, optical networking between facilities, and data center switching infrastructure are all scaling rapidly to keep pace with compute demand.</p>
<p>This area has attracted less retail attention than GPUs while capturing a meaningful share of AI infrastructure spend.</p>
<p>Investment angle: high speed interconnect suppliers, optical networking companies, data center networking hardware.</p>
<p><strong>Key risks:</strong> Networking equipment can be commoditized over time. If AI cluster architectures shift toward wafer-scale or near-memory compute, the interconnect bottleneck changes in character.</p>
<h2 id="nvidia-counter-thesis">NVIDIA Counter Thesis</h2>
<p>Chip producers, especially <a href="https://en.wikipedia.org/wiki/Nvidia">Nvidia</a>, look like a safe bet from any angle. But Nvidia trades at roughly 20 times forward annual revenue. That price assumes years of near perfect execution. The risks are real.</p>
<p>Nvidia&#39;s moat rests on three things: <a href="https://en.wikipedia.org/wiki/CUDA">CUDA</a> (its proprietary programming framework), its <a href="https://en.wikipedia.org/wiki/Mellanox_Technologies">Mellanox</a> interconnect technology, and proven Linux drivers. These have supported extraordinary margins and pricing power in data center accelerators. <a href="https://en.wikipedia.org/wiki/AMD">AMD</a> makes comparable chips on paper but has poor Linux drivers and weak interconnect, which keeps it out of serious data center contention.</p>
<p><strong>Hardware challengers</strong> are finding ways around the interconnect problem entirely. <a href="https://en.wikipedia.org/wiki/Cerebras_Systems">Cerebras</a> builds one giant wafer scale chip, eliminating the need for GPU to GPU communication. Its four largest customers are the Mohamed bin Zayed University of Artificial Intelligence (62% of 2025 revenues), G42 (24%), OpenAI, and Amazon Web Services, with the latter two signing in 2026. That OpenAI and AWS, two of Nvidia&#39;s largest customers, are buying from Cerebras illustrates how seriously the diversification pressure has become.<br><a href="https://en.wikipedia.org/wiki/Groq">Groq</a> uses a deterministic compute architecture that runs inference faster per dollar. <a href="https://taalas.com/the-path-to-ubiquitous-ai/">Taalas</a> pours LLM directly into silicon, achieving +10K tok/sec. Neither needs to beat Nvidia on raw performance. They just need to be good enough at a fraction of the price. In December 2025, Nvidia and Groq announced an agreement reportedly valued at approximately 20 billion $ to license Groq&#39;s AI inference technology and transfer several senior Groq executives to Nvidia, suggesting Nvidia recognized the inference efficiency threat and moved to absorb it rather than outcompete it.</p>
<p><strong>Big tech is building its own chips.</strong> Google has been on its sixth generation of in house TPUs since 2016. Amazon has Trainium and Inferentia chips powering clusters of over 400,000 chips for <a href="https://en.wikipedia.org/wiki/Anthropic">Anthropic</a>. Microsoft, <a href="https://en.wikipedia.org/wiki/OpenAI">OpenAI</a>, <a href="https://en.wikipedia.org/wiki/Meta">Meta</a>, and <a href="https://en.wikipedia.org/wiki/Apple_Inc.">Apple</a> all have custom silicon projects underway. Every major Nvidia customer is working to reduce dependence on Nvidia. None of these chips needs to outperform Nvidia. They just need to break even rather than generate extraordinary margins for a rival.</p>
<p><strong><a href="https://en.wikipedia.org/wiki/DeepSeek">DeepSeek</a> suggested compute may have been massively over provisioned.</strong> The Chinese AI lab&#39;s reported training efficiency indicated that frontier-adjacent models may require far less compute than many investors assumed. Even if the headline cost figures are incomplete, the broader point stands: algorithmic efficiency can pressure long-term compute demand assumptions. Every major AI lab is now studying how to apply those same techniques. If those efficiency gains prove durable, the compute demand assumptions baked into Nvidia&#39;s valuation face real pressure.</p>
<p><strong>Software is reducing CUDA lock in.</strong> Frameworks like Triton (OpenAI), MLX (Apple), and JAX (Google) let developers write code once and compile it for multiple hardware targets. This mirrors how hand tuned assembly gave way to C in the 1980s. The CUDA expertise premium will erode as high level abstractions mature.</p>
<p>None of this means Nvidia falls tomorrow. If AI scales as fast as the optimists expect, demand growth could absorb all of these pressures. But at 20 times forward revenue, the market prices in no bad news at all. That is a difficult position to hold.</p>
<h2 id="robotics-embodied-ai">Robotics: Embodied AI</h2>
<p>The potential economic impact of mass scale deployment of robotics is enormous.</p>
<p>The global industrial robot market hit $16.5 billion in 2025. China installed 276,300 industrial robots in 2023, more than the rest of the world combined. By 2024, that number had risen to 295,000, representing 54% of global deployments, with China&#39;s operational robot stock exceeding 2 million. The trend is accelerating.</p>
<p>Three things drive it:</p>
<p><strong>Physical AI</strong> trains robots in virtual simulations before they touch real environments. Chip makers and robot makers now build dedicated hardware for this. The goal is a &quot;ChatGPT moment&quot; for robots where they learn by experience rather than explicit programming.</p>
<p><strong><a href="https://en.wikipedia.org/wiki/Humanoid_robot">Humanoid robots</a></strong> get a lot of attention but remain early. Today they mostly do single purpose tasks in auto plants and warehouses. Whether they become general purpose tools is still open.</p>
<p><strong>Labor shortages</strong> are the practical driver. Aging populations in the US, Japan, Germany, China, and South Korea are shrinking workforces fast. Robots fill the gaps. Oxford Economics forecast (published 2019, revisited 2024) projected 20 million manufacturing jobs displaced by robots by 2030. <a href="https://en.wikipedia.org/wiki/McKinsey_%26_Company">McKinsey</a> estimates AI and robots could automate 40% of US jobs by 2030 while generating $2.9 trillion in economic value per year (via Robotics and Automation News, citing McKinsey research).</p>
<p>That is a massive disruption. The companies that build, program, and maintain these robots win.</p>
<p>Investment angle: robot makers, simulation software, <a href="https://en.wikipedia.org/wiki/Cobot">collaborative robot</a> platforms, and industrial automation companies.</p>
<p><strong>Key risks:</strong> Robotics hardware carries long sales cycles, high integration costs, and thin margins. Humanoid robots in particular are early; hype currently exceeds deployment. Industrial-grade reliability takes years and significant capital to prove out at scale.</p>
<h2 id="medicine-biggest-chance">Medicine: Biggest Chance</h2>
<p><a href="https://en.wikipedia.org/wiki/Drug_discovery">Drug discovery</a> is where AI might matter most.</p>
<p>Traditional drug development takes 10 to 15 years and costs over a billion dollars per drug. The failure rate is brutal. Most candidate drugs never reach patients.</p>
<p><a href="https://en.wikipedia.org/wiki/AlphaFold">AlphaFold</a>, <a href="https://en.wikipedia.org/wiki/Google_DeepMind">Google DeepMind</a>&#39;s protein structure prediction model, changed that. It achieved a breakthrough in <a href="https://en.wikipedia.org/wiki/Protein_folding">protein structure prediction</a>, reaching accuracy levels that transformed the field after 50 years of limited progress. AlphaFold&#39;s creators <a href="https://en.wikipedia.org/wiki/Demis_Hassabis">Demis Hassabis</a> and <a href="https://en.wikipedia.org/wiki/John_M._Jumper">John Jumper</a> shared the 2024 Nobel Prize in Chemistry with <a href="https://en.wikipedia.org/wiki/David_Baker_(biochemist)">David Baker</a>, who received the other half for protein design work. AlphaFold can now predict the structure of proteins, RNA, and DNA. This gives drug designers a map of the molecules they want to target.</p>
<p><a href="https://en.wikipedia.org/wiki/Isomorphic_Labs">Isomorphic Labs</a>, the company built on AlphaFold, secured $2.1 billion in funding in May 2026 to push drugs into clinical trials. It has active collaborations with <a href="https://en.wikipedia.org/wiki/Johnson_%26_Johnson">Johnson and Johnson</a>, <a href="https://en.wikipedia.org/wiki/Novartis">Novartis</a>, and <a href="https://en.wikipedia.org/wiki/Eli_Lilly">Eli Lilly</a>. The long term goal is to dramatically shorten the drug discovery process, potentially reducing timelines from many years to a fraction of today&#39;s norms.</p>
<p>On the clinical side, a Menlo Ventures survey found healthcare AI adoption jumped 7x in a single year among respondents, with health systems leading at 27% adoption. AI handles triage, scheduling, imaging analysis, and administrative work. The $4.9 trillion US healthcare sector now deploys AI at more than twice the rate of the broader economy.</p>
<p>Investment angle: biotech companies using AI for drug discovery, medical imaging AI, diagnostics, and clinical workflow tools. This sector has real data moats and hard to copy specialized models.</p>
<p><strong>Key risks:</strong> Clinical failure rates remain high even if AI accelerates discovery. Finding a promising molecule is only the first step; the path through trials is long, expensive, and uncertain. Regulatory timelines and approval risks are unchanged by AI.</p>
<h2 id="weapon-manufacturing">Weapon Manufacturing</h2>
<p>AI enabled weapon systems is a growing investment theme in the US and Europe. Autonomous systems, surveillance, logistics optimization, and military robotics are attracting significant government procurement and venture capital. Rising defense budgets in NATO countries and intensifying great power competition are structural tailwinds independent of the broader AI cycle.</p>
<p>Investment angle: defense contractors integrating AI into platforms, autonomous systems developers, drone and counter drone technology companies.</p>
<p><strong>Key risks:</strong> Defense procurement cycles are long and unpredictable. Ethics and regulation around autonomous weapons remain unsettled. Government budget priorities can shift, and many defense AI programs remain classified, making competitive positioning difficult to assess from the outside.</p>
<h2 id="application-layer-risk">Application Layer Risk</h2>
<p>Companies with no data moat and a thin app layer on top of general AI face increasing pressure.</p>
<p>When software gets cheap to build, value shifts to the data and relationships underneath. AI lowers software development costs and compresses feature advantages, increasing pressure on application layer businesses whose primary differentiation is functionality rather than proprietary data, distribution, or ecosystem effects. Companies with deep ecosystem lock in, enterprise relationships, compliance advantages, and marketplace network effects are more resilient than those competing purely on features.</p>
<p>Watch companies that:</p>
<ul>
<li>Sell software AI can replicate fast with no proprietary data or unique pipelines</li>
<li>Lack meaningful switching costs, ecosystem effects, or distribution advantages</li>
<li>Compete on feature parity rather than data or integration depth</li>
</ul>
<p>Identifying a business as vulnerable is not the same as identifying a good short. Many mediocre businesses stay expensive to short for years. Valuation, balance sheet analysis, and timing matter as much as the competitive thesis.</p>
<h2 id="ranking-of-ai-investment-themes">Ranking of AI Investment Themes</h2>
<div class="table-wrapper"><table><thead><th>Theme</th><th>Confidence</th><th>Main risk</th></thead><tbody><tr><td>Grid and electrical infrastructure</td><td>High</td><td>Permitting delays, regulated returns</td></tr><tr><td>Data center networking</td><td>High</td><td>Commoditization over time</td></tr><tr><td>AI drug discovery</td><td>Medium-high</td><td>Clinical failure still dominates</td></tr><tr><td>Nvidia long-term dominance</td><td>Medium</td><td>Valuation, custom silicon, inference efficiency</td></tr><tr><td>Humanoid robotics</td><td>Low-medium</td><td>Hype exceeds current deployment</td></tr><tr><td>Weapon manufacturing</td><td>Low-medium</td><td>Procurement cycles, classified opacity</td></tr><tr><td>Thin AI apps without moats</td><td>High vulnerability</td><td>Misidentifying apps with genuine moats as vulnerable</td></tr></tbody></table></div><p><strong>Highest confidence:</strong> Data center electrical infrastructure, grid equipment, networking, and custom silicon supply chains. These benefit from AI capex regardless of which AI applications win.</p>
<p><strong>Highest upside, highest uncertainty:</strong> AI drug discovery, humanoid robotics, defense autonomy. Long timelines with transformative potential if execution follows.</p>
<p><strong>Most vulnerable:</strong> Thin application wrappers without proprietary data or distribution. The addressable market for feature-only software is shrinking as AI commoditizes development.</p>
<p><strong>Most crowded:</strong> Nvidia and obvious GPU beneficiaries. The thesis is right, but the price may already reflect it.</p>
<h2 id="references">References</h2>
<ol>
<li><a href="https://ifr.org/ifr-press-releases/news/top-5-global-robotics-trends-2025">Top 5 Global Robotics Trends 2025</a> (International Federation of Robotics)</li>
<li><a href="https://ifr.org/ifr-press-releases/news/global-robot-demand-in-factories-doubles-over-10-years">World Robotics 2025 – Industrial Robots</a> (IFR)</li>
<li><a href="https://hai.stanford.edu/ai-index/2025-ai-index-report/economy">AI Index 2025: Economy Chapter</a> (Stanford HAI)</li>
<li><a href="https://www.prnewswire.com/news-releases/isomorphic-labs-secures-2-1-billion-funding-to-scale-its-ai-drug-design-engine-302769674.html">Isomorphic Labs secures $2.1 billion funding</a> (PR Newswire)</li>
<li><a href="https://www.constellationenergy.com/news/2024/Constellation-to-Launch-Crane-Clean-Energy-Center-Restoring-Jobs-and-Carbon-Free-Power-to-The-Grid.html">Constellation to Launch Crane Clean Energy Center</a> (Constellation Energy)</li>
<li><a href="https://nvidianews.nvidia.com/news/nvidia-announces-financial-results-for-fourth-quarter-and-fiscal-2026">NVIDIA Fiscal 2026 Financial Results</a> (NVIDIA Newsroom)</li>
<li><a href="https://www.oxfordeconomics.com/resource/ai-and-robots-in-2025-the-robotics-revolution-we-predicted-has-arrived/">AI and robots in 2025: the robotics revolution</a> (Oxford Economics)</li>
<li><a href="https://roboticsandautomationnews.com/2025/11/26/mckinsey-warns-ai-and-robots-could-automate-40-percent-of-us-jobs-by-2030/97003/">McKinsey: AI and robots could automate 40% of US jobs by 2030</a> (Robotics and Automation News)</li>
<li><a href="https://menlovc.com/perspective/2025-the-state-of-ai-in-healthcare/">2025: The State of AI in Healthcare</a> (Menlo Ventures)</li>
<li><a href="https://youtubetranscriptoptimizer.com/blog/05_the_short_case_for_nvda">The Short Case for Nvidia Stock</a> (Jeffrey Emanuel)</li>
</ol>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a> <a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>The Human Gut Microbiome</title>
      <link>https://seanpedersen.github.io/posts/human-gut-microbiome</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/human-gut-microbiome</guid>
      <pubDate>Mon, 18 May 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>The <a href="https://en.wikipedia.org/wiki/Gut_microbiota">gut microbiome</a> is a metabolic organ with no fixed genome. It includes bacteria, <a href="https://en.wikipedia.org/wiki/Archaea">archaea</a>, viruses, and fungi. The densest community lives in the colon. It expands digestion, trains <a href="https://en.wikipedia.org/wiki/Immune_tolerance">immune tolerance</a>, blocks pathogens, transforms drugs, and produces molecules your own cells respond to. The key question is not &quot;which bacteria do I have?&quot; but &quot;what biochemical work can this community do?&quot; Single species narratives mislead. The gut is a community metabolism problem, not a mascot problem.</p>
<h2 id="what-microbes-actually-make">What microbes actually make</h2>
<p>The core function is digesting what you cannot. Fiber, <a href="https://en.wikipedia.org/wiki/Resistant_starch">resistant starch</a>, <a href="https://en.wikipedia.org/wiki/Pectin">pectins</a>, and <a href="https://en.wikipedia.org/wiki/Inulin">inulin</a> reach the colon. Microbes ferment them into <a href="https://en.wikipedia.org/wiki/Short-chain_fatty_acid">short chain fatty acids</a>: acetate, propionate, and butyrate. <strong><a href="https://en.wikipedia.org/wiki/Butyric_acid">Butyrate</a> matters most.</strong> Colon cells burn it as fuel. It supports the <a href="https://en.wikipedia.org/wiki/Epithelium">epithelial barrier</a>, dampens inflammation, and modifies gene expression through <a href="https://en.wikipedia.org/wiki/Histone_deacetylase_inhibitor">histone deacetylase inhibition</a>. The gut barrier also works as an immune interface. Microbes compete for space, shape immune signaling, and train tolerance. Without that tolerance, food and harmless microbes start looking like threats. Gut disruption links to <a href="https://en.wikipedia.org/wiki/Systemic_inflammation">systemic inflammation</a>, allergy risk, and metabolic disease. There is no single &quot;healthy&quot; microbiome. Function matters more than taxonomy.</p>
<h2 id="what-moves-the-system">What moves the system</h2>
<p>Diet is the strongest everyday input. High fiber and plant rich diets increase fermentation and short chain fatty acid output. Fermented foods add live microbes and their products. But the response is personal. Your starting microbiome shapes how any dietary change lands. Antibiotics are blunt. They damage <a href="https://en.wikipedia.org/wiki/Colonization_resistance">colonization resistance</a> and let pathogens like <a href="https://en.wikipedia.org/wiki/Clostridioides_difficile">C. difficile</a> move in. Recurrent C. difficile is one of the few areas where gut restoration is mainstream medicine. FDA approved fecal microbiota products now exist for it. <a href="https://en.wikipedia.org/wiki/Probiotic">Probiotics</a> are overmarketed. Effects are strain specific, dose specific, and host specific. Care more about <a href="https://en.wikipedia.org/wiki/Prebiotic_(nutrition)">prebiotic</a> food than probiotic branding.</p>
<h2 id="fecal-transplants-as-a-proof-of-concept">Fecal transplants as a proof of concept</h2>
<p><a href="https://en.wikipedia.org/wiki/Fecal_microbiota_transplant">Fecal microbiota transplant</a> is the strongest proof that changing the gut ecosystem can change health outcomes. The clearest case is recurrent C. difficile. Antibiotics damage colonization resistance, C. difficile moves in, and transplanting a healthy donor microbiome closes the gap. FDA approved products now exist for this. The more provocative findings reach further. A small study gave Microbiota Transfer Therapy to 18 autistic children with chronic GI problems. The protocol combined antibiotics, bowel prep, high dose microbiota transfer, and daily maintenance doses. Two years later the children showed maintained GI improvement, higher bacterial diversity, and large gains on autism related rating scales. The trial was small and open label, so it does not prove causation. But it suggests the gut can modulate behavioral and psychological symptoms, at least when GI distress is part of the picture. Depression research tells a similar story. Case reports, pilot trials, and a 2025 meta analysis all point toward short term depressive symptom improvement after FMT, strongest in people with <a href="https://en.wikipedia.org/wiki/Irritable_bowel_syndrome">IBS</a>. A bipolar depression trial found no significant difference between donor and autologous FMT, which smells like placebo or procedure effect. The honest summary: FMT for psychiatric conditions is real enough to study seriously, not proven enough to recommend. Donor selection, dose, delivery route, and durability are still open questions.</p>
<h2 id="the-gut-brain-connection">The gut brain connection</h2>
<p>The gut talks to the brain through the <a href="https://en.wikipedia.org/wiki/Vagus_nerve">vagus nerve</a>, immune signals, microbial metabolites, and the <a href="https://en.wikipedia.org/wiki/Enteric_nervous_system">enteric nervous system</a>. Gut state can shift mood, stress response, inflammation, and sleep. That does not make every mental problem a gut problem. The practical bottom line is simple: eat a diverse, plant rich diet. Use fermented foods if tolerated. Avoid unnecessary antibiotics. Be skeptical of tests or supplements claiming to &quot;reset&quot; the gut. Humans are composite organisms. Some biology runs on a shifting microbial system. Modern diet, drugs, and sanitation changed that system faster than evolution could tune for.</p>
<h2 id="references">References</h2>
<ol>
<li><a href="https://nutritionsource.hsph.harvard.edu/microbiome/">Harvard Nutrition Source on the microbiome</a></li>
<li><a href="https://www.niehs.nih.gov/health/topics/science/microbiome">NIEHS overview of microbiome science</a></li>
<li><a href="https://www.nature.com/articles/s41579-024-01068-4">Nature Reviews Microbiology on diet and the gut microbiome</a></li>
<li><a href="https://www.nature.com/articles/s41577-024-01014-8">Nature Reviews Immunology on short chain fatty acids and immunity</a></li>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/34354265/">PubMed summary of microbiome targeted diets and immune status</a></li>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/39320321/">Fecal microbiota spores live brpk VOWST for prevention of recurrent Clostridioides difficile infection</a></li>
<li><a href="https://refractor.io/adhd-autism/fecal-transplants-for-autism-delivers-success-in-clinical-trials/">Refractor on fecal transplants for autism clinical trials</a></li>
<li><a href="https://www.nature.com/articles/s41598-019-42183-0">Scientific Reports study on long term Microbiota Transfer Therapy outcomes in autism</a></li>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/36637229/">Feasibility Acceptability and Safety of Faecal Microbiota Transplantation in the Treatment of Major Depressive Disorder</a></li>
<li><a href="https://www.frontiersin.org/journals/psychiatry/articles/10.3389/fpsyt.2025.1656969/full">Frontiers meta analysis of fecal microbiota transplantation for depressive symptoms</a></li>
<li><a href="https://www.nature.com/articles/s41598-026-41801-y">Scientific Reports randomized study of fecal microbiota transplantation as adjunctive therapy for depressive episodes</a></li>
<li><a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC12962988/">Safety Efficacy and Feasibility of Fecal Microbiota Transplantation in Bipolar Disorder During Depressive Episodes</a></li>
<li><a href="https://www.frontiersin.org/journals/psychiatry/articles/10.3389/fpsyt.2022.815422/full">Fecal Microbiota Transplantation as an Adjunctive Therapy for Depression Case Report</a></li>
<li><a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC7294648/">Effect of fecal microbiota transplant on symptoms of psychiatric disorders systematic review</a></li>
</ol>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Pi - Open-Source Coding Agent</title>
      <link>https://seanpedersen.github.io/posts/pi-agent</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/pi-agent</guid>
      <pubDate>Wed, 13 May 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <category>tutorial</category>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>An open-source coding agent rivaling claude code and openai codex.<br>Built to be hackable: <a href="https://mariozechner.at/posts/2025-11-30-pi-coding-agent">here</a> is a great intro from the creator.<br>Vanilla <a href="https://pi.dev/">Pi</a> is bare bones and should be configured via extensions - or start with a preconfigured version like <a href="https://github.com/can1357/oh-my-pi">oh-my-pi</a> (though oh-my-pi can feel bloated compared to vanilla Pi with its long system prompt, many features and tools). Another intersting open-source coding agent that promises very efficient token usage is <a href="https://dirac.run/">Dirac</a>, via hash-anchored edits and AST code edits - check it out.</p>
<h2 id="install">Install</h2>
<p><code class="language-text">$ npm install -g @earendil-works/pi-coding-agent</code></p>
<p>Then run: <code class="language-text">$ pi</code><br>And add your provider with: <code class="language-text">/login</code></p>
<h3 id="llm-providers">LLM Providers</h3>
<p>Best bang for the buck right now:</p>
<ul>
<li><a href="https://opencode.ai/go?ref=G4RTPHMCR6">OpenCode Go</a><ul>
<li><a href="https://artificialanalysis.ai/models/qwen3-7-plus">Qwen3.7 Plus</a> has best intelligence vs usage limit ratio</li>
</ul>
</li>
<li><a href="https://openrouter.ai/">OpenRouter</a>: one API to access all big models</li>
<li><a href="https://seanpedersen.github.io/posts/local-ai-chat-apps/#local-models">Self-host</a> a model on GPU/s</li>
</ul>
<h2 id="customize-pi">Customize Pi</h2>
<h3 id="prompts">Prompts</h3>
<p>~/.pi/agent/SYSTEM.md : overwrites the global Pi system prompt (be careful)<br>~/.pi/agent/APPEND_SYSTEM.md : appends to the global Pi system prompt</p>
<p>Pi loads <code class="language-text">AGENTS.md</code> or <code class="language-text">CLAUDE.md</code> at startup from:</p>
<ul>
<li><code class="language-text">~/.pi/agent/AGENTS.md</code> for global instructions</li>
<li>parent directories, walking up from the current working directory</li>
<li>the current directory</li>
</ul>
<h3 id="packages">Packages</h3>
<p>Install extensions (packages) from the pi packages marketplace (review code before you use them): <a href="https://pi.dev/packages">https://pi.dev/packages</a></p>
<p>Your custom extensions live in: $home/.pi/agent/extensions<br>Installed extensions (packages) are in: TODO</p>
<ul>
<li>show complete prompt context: <a href="https://pi.dev/packages/pi-system-prompt">https://pi.dev/packages/pi-system-prompt</a></li>
<li>dynamic workflows (explicit subagent workflow): <a href="https://github.com/Michaelliv/pi-dynamic-workflows">https://github.com/Michaelliv/pi-dynamic-workflows</a></li>
<li>sub-agents: <a href="https://pi.dev/packages/pi-subagents">https://pi.dev/packages/pi-subagents</a></li>
<li>plan mode:<ul>
<li><a href="https://pi.dev/packages/@plannotator/pi-extension">https://pi.dev/packages/@plannotator/pi-extension</a></li>
<li><a href="https://pi.dev/packages/pi-pledit">https://pi.dev/packages/pi-pledit</a></li>
</ul>
</li>
<li>hashline edit: <a href="https://github.com/RimuruW/pi-hashline-edit">https://github.com/RimuruW/pi-hashline-edit</a></li>
<li>btw command: <a href="https://github.com/dbachelder/pi-btw">https://github.com/dbachelder/pi-btw</a></li>
<li>goal command: <a href="https://pi.dev/packages/@capyup/pi-goal">https://pi.dev/packages/@capyup/pi-goal</a></li>
<li>beads (task management): <a href="https://pi.dev/packages/pi-beads-extension">https://pi.dev/packages/pi-beads-extension</a></li>
<li>code index / search:<ul>
<li><a href="https://github.com/colbymchenry/codegraph">https://github.com/colbymchenry/codegraph</a><ul>
<li>pi extension: <a href="https://github.com/SeanPedersen/pi-codegraph">https://github.com/SeanPedersen/pi-codegraph</a></li>
</ul>
</li>
<li><a href="https://github.com/MinishLab/semble">https://github.com/MinishLab/semble</a></li>
</ul>
</li>
</ul>
<h3 id="skills">Skills</h3>
<p>Skills are useful to dynamically load relevant documents / tools into the prompt context to solve advanced tasks / use pre-defined complex workflows.</p>
<p>Located in $home/.agents/skills</p>
<h4 id="contextual-skills">Contextual Skills</h4>
<p>An extension that selects relevant skills per project on first start of Pi (user may edit skills selection later on) - this saves context, as only skills relevant to the each project are in the agents prompt.</p>
<p><a href="https://github.com/SeanPedersen/pi-context-skills">https://github.com/SeanPedersen/pi-context-skills</a></p>
<h4 id="other-skills-related-packages">Other skills related packages</h4>
<ul>
<li><a href="https://pi.dev/packages/@kmiyh/pi-skills-menu">https://pi.dev/packages/@kmiyh/pi-skills-menu</a></li>
<li><a href="https://pi.dev/packages/pi-skillful">https://pi.dev/packages/pi-skillful</a></li>
<li><a href="https://pi.dev/packages/pi-hermes-memory">https://pi.dev/packages/pi-hermes-memory</a></li>
</ul>
<h2 id="mobile-access">Mobile Access</h2>
<p><a href="https://www.pipulse.dev/">https://www.pipulse.dev/</a><br><a href="https://github.com/jademind/pi-statusbar">https://github.com/jademind/pi-statusbar</a></p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://mariozechner.at/posts/2025-11-30-pi-coding-agent">https://mariozechner.at/posts/2025-11-30-pi-coding-agent</a></li>
<li><a href="https://pi.dev/">https://pi.dev/</a></li>
<li><a href="https://lucumr.pocoo.org/2026/1/31/pi/">https://lucumr.pocoo.org/2026/1/31/pi/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a> <a href="/index.html#tutorial">#tutorial</a> <a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>The Ukraine War in Numbers</title>
      <link>https://seanpedersen.github.io/posts/ukraine-war</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/ukraine-war</guid>
      <pubDate>Thu, 16 Apr 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>The Russia-Ukraine war in numbers, as of April 2026 - now past its fourth year. Territory and casualty data from <a href="https://www.csis.org/analysis/russias-grinding-war-ukraine">CSIS</a>, <a href="https://www.russiamatters.org/news/russia-ukraine-war-report-card/russia-ukraine-war-report-card-april-8-2026">Russia Matters</a>, and <a href="https://www.aljazeera.com/news/2026/2/24/mapping-russian-attacks-and-territorial-gains-across-ukraine">Al Jazeera</a>. Equipment numbers are photo/video-confirmed minimums from <a href="https://www.oryxspioenkop.com/2022/02/attack-on-europe-documenting-equipment.html">Oryx</a>. Real losses are higher. Frontline tracking via <a href="https://deepstatemap.live/en">DeepState Map</a>.</p>
<h2 id="territorial-control">Territorial Control</h2>
<p>Russia holds about <strong>120,000 sq km</strong> of Ukraine - roughly <strong>20%</strong> of the country (including Crimea, taken in 2014). The frontline is over <strong>1,000 km</strong> long. See <a href="https://deepstatemap.live/">DeepState Map</a> for live tracking.</p>
<div style="margin:2em 0">
<svg viewBox="0 0 700 200" style="width:100%;max-width:700px;font-family:monospace">
  <text x="0" y="18" fill="currentColor" font-size="13" font-weight="bold">Russian-Occupied Territory Over Time (% of Ukraine)</text>
  <!-- Y axis labels -->
  <text x="0" y="52" fill="currentColor" font-size="10" fill-opacity="0.6">27%</text>
  <text x="0" y="85" fill="currentColor" font-size="10" fill-opacity="0.6">20%</text>
  <text x="0" y="127" fill="currentColor" font-size="10" fill-opacity="0.6">10%</text>
  <text x="0" y="170" fill="currentColor" font-size="10" fill-opacity="0.6">0%</text>
  <!-- Grid lines -->
  <line x1="35" y1="46" x2="690" y2="46" stroke="currentColor" stroke-opacity="0.1"/>
  <line x1="35" y1="80" x2="690" y2="80" stroke="currentColor" stroke-opacity="0.1"/>
  <line x1="35" y1="122" x2="690" y2="122" stroke="currentColor" stroke-opacity="0.1"/>
  <line x1="35" y1="164" x2="690" y2="164" stroke="currentColor" stroke-opacity="0.15"/>
  <!-- Linear time axis: Jan 2022 (x=50) to Apr 2026 (x=690). 51 months, 12.55px/month -->
  <!-- Y: 0%=y164, 27%=y46. 4.37px per 1% -->
  <!-- Equidistant year labels: 2022=x50, 2023=x201, 2024=x351, 2025=x502, 2026=x652 -->
  <!-- Vertical year gridlines -->
  <line x1="50" y1="46" x2="50" y2="164" stroke="currentColor" stroke-opacity="0.08"/>
  <line x1="201" y1="46" x2="201" y2="164" stroke="currentColor" stroke-opacity="0.08"/>
  <line x1="351" y1="46" x2="351" y2="164" stroke="currentColor" stroke-opacity="0.08"/>
  <line x1="502" y1="46" x2="502" y2="164" stroke="currentColor" stroke-opacity="0.08"/>
  <line x1="652" y1="46" x2="652" y2="164" stroke="currentColor" stroke-opacity="0.08"/>
  <!-- Area fill -->
  <polygon points="35,164 63,164 63,120 75,46 88,59 176,85 263,85 489,81 640,79 690,77 690,164" fill="#d32f2f" fill-opacity="0.15"/>
  <!-- Line: territory over time -->
  <polyline points="63,120 75,46 88,59 176,85 263,85 489,81 640,79 690,77" fill="none" stroke="#d32f2f" stroke-width="2.5"/>
  <!-- Data points: Feb22, Mar22, Apr22, Nov22, Jun23, Dec24, Dec25, Apr26 -->
  <circle cx="63" cy="120" r="3.5" fill="#d32f2f"/>
  <circle cx="75" cy="46" r="3.5" fill="#d32f2f"/>
  <circle cx="88" cy="59" r="3.5" fill="#d32f2f"/>
  <circle cx="176" cy="85" r="3.5" fill="#d32f2f"/>
  <circle cx="263" cy="85" r="3.5" fill="#d32f2f"/>
  <circle cx="489" cy="81" r="3.5" fill="#d32f2f"/>
  <circle cx="640" cy="79" r="3.5" fill="#d32f2f"/>
  <circle cx="690" cy="77" r="3.5" fill="#d32f2f"/>
  <!-- X axis labels: equidistant year starts -->
  <text x="50" y="185" fill="currentColor" font-size="10" text-anchor="middle">2022</text>
  <text x="201" y="185" fill="currentColor" font-size="10" text-anchor="middle">2023</text>
  <text x="351" y="185" fill="currentColor" font-size="10" text-anchor="middle">2024</text>
  <text x="502" y="185" fill="currentColor" font-size="10" text-anchor="middle">2025</text>
  <text x="652" y="185" fill="currentColor" font-size="10" text-anchor="middle">2026</text>
  <!-- Annotations -->
  <text x="75" y="38" fill="#d32f2f" font-size="8" text-anchor="start">Peak: ~27%</text>
  <text x="176" y="60" fill="#4caf50" font-size="8" text-anchor="middle">Kharkiv+Kherson</text>
  <text x="176" y="72" fill="#4caf50" font-size="8" text-anchor="middle">counteroffensives</text>
</svg>
</div>
<p><strong>Timeline:</strong></p>
<ul>
<li><strong>Pre-2022</strong>: Russia held Crimea (~7%, ~27,000 sq km) since 2014, plus parts of Donbas</li>
<li><strong>Mar 2022</strong>: Peak at ~27% (~165,000 sq km) - Russia pushed toward Kyiv on multiple fronts</li>
<li><strong>Apr 2022</strong>: Russia pulled back from Kyiv, Sumy, Chernihiv - dropped to ~24%</li>
<li><strong>Nov 2022</strong>: Ukraine took back Kharkiv oblast and Kherson west bank - dropped to ~18%</li>
<li><strong>2023</strong>: Summer counteroffensive made small gains (tens of sq km). Little net change</li>
<li><strong>2024</strong>: Russia took ~3,600 sq km (+0.6%) - Avdiivka fell Feb 2024, push toward Pokrovsk</li>
<li><strong>2025</strong>: Russia took ~4,800 sq km (+0.8%) - biggest yearly gains since 2022</li>
<li><strong>Apr 2026</strong>: ~120,000 sq km held (~20%). Recent weeks show slower gains</li>
</ul>
<h2 id="the-meters-per-day-war">The Meters-Per-Day War</h2>
<p>Russia&#39;s advance is extremely slow. CSIS data shows the Pokrovsk offensive - Russia&#39;s main push - moves slower than the Battle of the Somme in WWI.</p>
<div style="margin:2em 0">
<svg viewBox="0 0 700 220" style="width:100%;max-width:700px;font-family:monospace">
  <text x="0" y="18" fill="currentColor" font-size="13" font-weight="bold">Russian Advance Rates (meters/day, Jan 2026)</text>
  <!-- Bars -->
  <text x="140" y="55" fill="currentColor" font-size="11" text-anchor="end">Huliaipole</text>
  <text x="140" y="66" fill="currentColor" font-size="9" text-anchor="end" fill-opacity="0.5">Zaporizhzhia</text>
  <rect x="150" y="45" width="445" height="18" rx="3" fill="#d32f2f"/>
  <text x="600" y="58" fill="currentColor" font-size="10">297 m/day</text>
  <text x="140" y="100" fill="currentColor" font-size="11" text-anchor="end">Pokrovsk</text>
  <text x="140" y="111" fill="currentColor" font-size="9" text-anchor="end" fill-opacity="0.5">Donetsk</text>
  <rect x="150" y="90" width="105" height="18" rx="3" fill="#d32f2f"/>
  <text x="260" y="103" fill="currentColor" font-size="10">70 m/day</text>
  <text x="140" y="145" fill="currentColor" font-size="11" text-anchor="end">Kupiansk</text>
  <text x="140" y="156" fill="currentColor" font-size="9" text-anchor="end" fill-opacity="0.5">Kharkiv</text>
  <rect x="150" y="135" width="34" height="18" rx="3" fill="#d32f2f"/>
  <text x="189" y="148" fill="currentColor" font-size="10">23 m/day</text>
  <text x="140" y="190" fill="currentColor" font-size="11" text-anchor="end">Chasiv Yar</text>
  <text x="140" y="201" fill="currentColor" font-size="9" text-anchor="end" fill-opacity="0.5">Donetsk</text>
  <rect x="150" y="180" width="22" height="18" rx="3" fill="#d32f2f"/>
  <text x="177" y="193" fill="currentColor" font-size="10">15 m/day</text>
  <line x1="270" y1="40" x2="270" y2="210" stroke="#ff9800" stroke-width="1" stroke-dasharray="4,3"/>
  <text x="272" y="215" fill="#ff9800" font-size="9">Battle of the Somme: 80 m/day</text>
</svg>
</div>
<p>The cost is huge. In 2025, Russia lost an estimated <strong>~415,000 soldiers</strong> (killed + wounded) to gain <strong>~4,800 sq km</strong> - about <strong>86 casualties per square kilometer</strong>. The Pokrovsk push, Russia&#39;s main effort since Feb 2024, moved only ~50 km in nearly two years.</p>
<h2 id="human-cost">Human Cost</h2>
<p>Total military casualties estimates (April 2026) have crossed <strong>~2 million</strong> (killed, wounded, missing). Multiple independent sources (CSIS, The Economist, Wall Street Journal, Bloomberg) point to similar numbers:</p>
<div style="margin:2em 0">
<svg viewBox="0 0 700 165" style="width:100%;max-width:700px;font-family:monospace">
  <text x="0" y="18" fill="currentColor" font-size="13" font-weight="bold">Estimated Military Casualties (Feb 2022 - Apr 2026)</text>
  <!-- Russia -->
  <text x="80" y="50" fill="currentColor" font-size="11" text-anchor="end">Killed</text>
  <rect x="90" y="38" width="430" height="12" rx="2" fill="#d32f2f"/>
  <rect x="90" y="52" width="140" height="12" rx="2" fill="#1565c0"/>
  <text x="525" y="49" fill="currentColor" font-size="10">230-430K RU</text>
  <text x="235" y="63" fill="currentColor" font-size="10">100-140K UA</text>
  <!-- Wounded -->
  <text x="80" y="90" fill="currentColor" font-size="11" text-anchor="end">Total K+W</text>
  <rect x="90" y="78" width="480" height="12" rx="2" fill="#d32f2f" fill-opacity="0.6"/>
  <rect x="90" y="92" width="250" height="12" rx="2" fill="#1565c0" fill-opacity="0.6"/>
  <text x="575" y="89" fill="currentColor" font-size="10">1.1-1.4M RU</text>
  <text x="345" y="103" fill="currentColor" font-size="10">500-600K UA</text>
  <!-- Annual breakdown -->
  <text x="90" y="130" fill="currentColor" font-size="10" fill-opacity="0.7">Russian casualties by year: ~430K in 2024 | ~415K in 2025 | ~35K/month continuing</text>
  <text x="90" y="145" fill="currentColor" font-size="10" fill-opacity="0.7">March 2026 was Russia's deadliest single month since Feb 2022 (>35K killed or wounded)</text>
  <text x="90" y="160" fill="currentColor" font-size="10">Combined total: approaching ~2 million military casualties</text>
</svg>
</div>
<p>Russia is losing roughly <strong>1,000+ soldiers per day</strong> (killed and wounded). On April 15, 2026, Ukraine&#39;s General Staff reported 1,010 Russian casualties in a single day. The rate has not slowed - March 2026 was Russia&#39;s deadliest month since the invasion began.</p>
<p><strong>Civilians</strong> (OHCHR confirmed): <strong>55,600 casualties</strong> through Dec 2025 (13,883 killed). 2025 was the worst year for civilians since 2022: 2,514 killed, 12,142 hurt - 31% more than 2024. March 2026 alone: 211 killed, 1,206 hurt (49% jump over February). Real numbers are higher - counting is impossible in occupied areas.</p>
<h2 id="equipment-losses">Equipment Losses</h2>
<p>Russia has lost <strong>24,440</strong> pieces of military equipment (photo/video confirmed). Ukraine has lost <strong>11,923</strong> - roughly <strong>2:1</strong>. Real losses are much higher.</p>
<div style="margin:2em 0">
<svg viewBox="0 0 700 190" style="width:100%;max-width:700px;font-family:monospace">
  <text x="0" y="18" fill="currentColor" font-size="13" font-weight="bold">Total Equipment Losses (OSINT-verified)</text>
  <!-- Russia -->
  <text x="0" y="50" fill="currentColor" font-size="12">Russia</text>
  <rect x="80" y="38" width="560" height="20" rx="3" fill="#d32f2f"/>
  <text x="645" y="53" fill="currentColor" font-size="11">24,440</text>
  <!-- Ukraine -->
  <text x="0" y="82" fill="currentColor" font-size="12">Ukraine</text>
  <rect x="80" y="70" width="273" height="20" rx="3" fill="#1565c0"/>
  <text x="358" y="85" fill="currentColor" font-size="11">11,923</text>
  <!-- Breakdown label -->
  <text x="0" y="120" fill="currentColor" font-size="13" font-weight="bold">By Status</text>
  <!-- Legend -->
  <rect x="0" y="130" width="12" height="12" fill="#ef5350"/>
  <text x="16" y="141" fill="currentColor" font-size="10">Destroyed</text>
  <rect x="90" y="130" width="12" height="12" fill="#ff9800"/>
  <text x="106" y="141" fill="currentColor" font-size="10">Damaged</text>
  <rect x="170" y="130" width="12" height="12" fill="#9e9e9e"/>
  <text x="186" y="141" fill="currentColor" font-size="10">Abandoned</text>
  <rect x="260" y="130" width="12" height="12" fill="#4caf50"/>
  <text x="276" y="141" fill="currentColor" font-size="10">Captured</text>
  <!-- Russia breakdown bar (stacked) -->
  <text x="0" y="168" fill="currentColor" font-size="11">RU</text>
  <rect x="30" y="156" width="438" height="16" rx="2" fill="#ef5350"/>
  <rect x="468" y="156" width="22" height="16" rx="2" fill="#ff9800"/>
  <rect x="490" y="156" width="28" height="16" rx="2" fill="#9e9e9e"/>
  <rect x="518" y="156" width="73" height="16" rx="2" fill="#4caf50"/>
  <!-- Ukraine breakdown bar -->
  <text x="0" y="188" fill="currentColor" font-size="11">UA</text>
  <rect x="30" y="176" width="211" height="16" rx="2" fill="#ef5350"/>
  <rect x="241" y="176" width="15" height="16" rx="2" fill="#ff9800"/>
  <rect x="256" y="176" width="15" height="16" rx="2" fill="#9e9e9e"/>
  <rect x="271" y="176" width="33" height="16" rx="2" fill="#4caf50"/>
</svg>
</div>
<p>Russia: 19,079 destroyed | 975 damaged | 1,205 abandoned | 3,181 captured by Ukraine.<br>Ukraine: 9,175 destroyed | 668 damaged | 666 abandoned | 1,414 captured by Russia.</p>
<p>Ukraine has captured <strong>2.25x</strong> more Russian equipment than Russia has captured Ukrainian equipment (3,181 vs 1,414).</p>
<h3 id="armored-vehicle-losses">Armored Vehicle Losses</h3>
<p>Armored vehicles (tanks, AFVs, IFVs, APCs, MRAPs) show the biggest gap.</p>
<div style="margin:2em 0">
<svg viewBox="0 0 700 260" style="width:100%;max-width:700px;font-family:monospace">
  <text x="0" y="18" fill="currentColor" font-size="13" font-weight="bold">Armored Vehicle Losses by Type</text>
  <!-- Headers -->
  <text x="140" y="42" fill="currentColor" font-size="10" text-anchor="end">Category</text>
  <text x="170" y="42" fill="currentColor" font-size="9" fill-opacity="0.6">Russia (red) vs Ukraine (blue)</text>
  <!-- Tanks -->
  <text x="140" y="68" fill="currentColor" font-size="11" text-anchor="end">Tanks</text>
  <rect x="150" y="56" width="263" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="70" width="85" height="12" rx="2" fill="#1565c0"/>
  <text x="418" y="67" fill="currentColor" font-size="10">4,381</text>
  <text x="240" y="81" fill="currentColor" font-size="10">1,412</text>
  <!-- AFVs -->
  <text x="140" y="108" fill="currentColor" font-size="11" text-anchor="end">AFVs</text>
  <rect x="150" y="96" width="144" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="110" width="32" height="12" rx="2" fill="#1565c0"/>
  <text x="299" y="107" fill="currentColor" font-size="10">2,399</text>
  <text x="187" y="121" fill="currentColor" font-size="10">526</text>
  <!-- IFVs -->
  <text x="140" y="148" fill="currentColor" font-size="11" text-anchor="end">IFVs</text>
  <rect x="150" y="136" width="385" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="150" width="94" height="12" rx="2" fill="#1565c0"/>
  <text x="540" y="147" fill="currentColor" font-size="10">6,419</text>
  <text x="249" y="161" fill="currentColor" font-size="10">1,570</text>
  <!-- APCs -->
  <text x="140" y="188" fill="currentColor" font-size="11" text-anchor="end">APCs</text>
  <rect x="150" y="176" width="44" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="190" width="81" height="12" rx="2" fill="#1565c0"/>
  <text x="199" y="187" fill="currentColor" font-size="10">729</text>
  <text x="236" y="201" fill="currentColor" font-size="10">1,346</text>
  <!-- MRAPs -->
  <text x="140" y="228" fill="currentColor" font-size="11" text-anchor="end">MRAPs</text>
  <rect x="150" y="216" width="4" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="230" width="54" height="12" rx="2" fill="#1565c0"/>
  <text x="159" y="227" fill="currentColor" font-size="10">64</text>
  <text x="209" y="241" fill="currentColor" font-size="10">907</text>
</svg>
</div>
<p>Key ratios:</p>
<ul>
<li><strong>Tanks</strong>: 3.1:1 (Russia loses 3.1 tanks for every Ukrainian tank lost)</li>
<li><strong>IFVs</strong>: 4.1:1 (worst ratio - Russia&#39;s BMP-series vehicles get destroyed in large numbers during attacks)</li>
<li><strong>AFVs</strong>: 4.6:1</li>
<li><strong>APCs</strong>: Ukraine loses more (1,346 vs 729) - many Western-donated APCs in use</li>
<li><strong>MRAPs</strong>: Ukraine loses more (907 vs 64) - Western MRAPs used heavily near the front</li>
</ul>
<p>Russia is pulling T-62s and even T-55s from Cold War storage to fill the gap. Oryx has logged 152 T-62M and 10 T-55A losses - 1950s-60s vehicles destroyed by modern weapons.</p>
<h3 id="artillery-and-air-defense">Artillery and Air Defense</h3>
<div style="margin:2em 0">
<svg viewBox="0 0 700 210" style="width:100%;max-width:700px;font-family:monospace">
  <text x="0" y="18" fill="currentColor" font-size="13" font-weight="bold">Artillery &amp; Air Defense Losses</text>
  <text x="170" y="42" fill="currentColor" font-size="9" fill-opacity="0.6">Russia (red) vs Ukraine (blue)</text>
  <!-- SP Artillery -->
  <text x="140" y="68" fill="currentColor" font-size="11" text-anchor="end">SP Artillery</text>
  <rect x="150" y="56" width="202" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="70" width="168" height="12" rx="2" fill="#1565c0"/>
  <text x="357" y="67" fill="currentColor" font-size="10">1,008</text>
  <text x="323" y="81" fill="currentColor" font-size="10">840</text>
  <!-- Towed Artillery -->
  <text x="140" y="108" fill="currentColor" font-size="11" text-anchor="end">Towed Artillery</text>
  <rect x="150" y="96" width="110" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="110" width="54" height="12" rx="2" fill="#1565c0"/>
  <text x="265" y="107" fill="currentColor" font-size="10">552</text>
  <text x="209" y="121" fill="currentColor" font-size="10">269</text>
  <!-- MLRS -->
  <text x="140" y="148" fill="currentColor" font-size="11" text-anchor="end">MLRS</text>
  <rect x="150" y="136" width="116" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="150" width="21" height="12" rx="2" fill="#1565c0"/>
  <text x="271" y="147" fill="currentColor" font-size="10">581</text>
  <text x="176" y="161" fill="currentColor" font-size="10">106</text>
  <!-- SAM -->
  <text x="140" y="188" fill="currentColor" font-size="11" text-anchor="end">SAM Systems</text>
  <rect x="150" y="176" width="82" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="190" width="36" height="12" rx="2" fill="#1565c0"/>
  <text x="237" y="187" fill="currentColor" font-size="10">408</text>
  <text x="191" y="201" fill="currentColor" font-size="10">178</text>
</svg>
</div>
<p>SP artillery losses are close (1,008 vs 840, 1.2:1) - Ukraine&#39;s Western howitzers (M109, PzH 2000) are top targets. MLRS losses are one-sided (5.5:1) - Russia has burned through huge numbers of Grad and Uragan systems. SAM losses at 2.3:1 favor Ukraine, whose Western air defense systems remain critical.</p>
<h3 id="air-and-naval">Air and Naval</h3>
<div style="margin:2em 0">
<svg viewBox="0 0 700 170" style="width:100%;max-width:700px;font-family:monospace">
  <text x="0" y="18" fill="currentColor" font-size="13" font-weight="bold">Air &amp; Naval Losses</text>
  <text x="170" y="42" fill="currentColor" font-size="9" fill-opacity="0.6">Russia (red) vs Ukraine (blue)</text>
  <!-- Aircraft -->
  <text x="140" y="68" fill="currentColor" font-size="11" text-anchor="end">Aircraft</text>
  <rect x="150" y="56" width="184" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="70" width="116" height="12" rx="2" fill="#1565c0"/>
  <text x="339" y="67" fill="currentColor" font-size="10">184</text>
  <text x="271" y="81" fill="currentColor" font-size="10">116</text>
  <!-- Helicopters -->
  <text x="140" y="108" fill="currentColor" font-size="11" text-anchor="end">Helicopters</text>
  <rect x="150" y="96" width="172" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="110" width="56" height="12" rx="2" fill="#1565c0"/>
  <text x="327" y="107" fill="currentColor" font-size="10">172</text>
  <text x="211" y="121" fill="currentColor" font-size="10">56</text>
  <!-- Naval -->
  <text x="140" y="148" fill="currentColor" font-size="11" text-anchor="end">Naval Ships</text>
  <rect x="150" y="136" width="32" height="12" rx="2" fill="#d32f2f"/>
  <rect x="150" y="150" width="42" height="12" rx="2" fill="#1565c0"/>
  <text x="187" y="147" fill="currentColor" font-size="10">32</text>
  <text x="197" y="161" fill="currentColor" font-size="10">42</text>
</svg>
</div>
<p>Neither side controls the sky. Russia lost 184 aircraft and 172 helicopters; Ukraine lost 116 and 56. The helicopter gap (3.1:1) comes from Russia using Ka-52 and Mi-28 attack helicopters heavily in assaults. At sea, Ukraine sank the cruiser <em>Moskva</em> and hit Black Sea Fleet ships with Neptune and Storm Shadow missiles, forcing Russia to pull most ships out of the western Black Sea.</p>
<h3 id="drone-warfare">Drone Warfare</h3>
<p>This war has changed how armies think about drones and robots.</p>
<div class="table-wrapper"><table><thead><th></th><th>Russia</th><th>Ukraine</th></thead><tbody><tr><td>Recon UAVs lost</td><td>787</td><td>563</td></tr><tr><td>Combat UAVs lost</td><td>21</td><td>29</td></tr><tr><td>Ground robots (UGVs) lost</td><td>73</td><td>247</td></tr></tbody></table></div><p>Ukraine lost <strong>3.4x</strong> more UGVs than Russia (247 vs 73) - Ukraine uses more ground robots at the front. Both sides now produce millions of FPV drones - cheap one-way attack drones (a few hundred dollars each) that have become the main way to kill armor and infantry, changing the math of war.</p>
<h2 id="the-proxy-war-economics">The Proxy War: Economics</h2>
<p>This is a proxy war between NATO and Russia, fought on Ukrainian soil with Ukrainian lives. The money tells the story.</p>
<p><strong>Russia military spending vs Western aid to Ukraine, by year:</strong></p>
<div class="table-wrapper"><table><thead><th>Year</th><th>Russia military budget</th><th>Western aid to Ukraine</th><th>Source notes</th></thead><tbody><tr><td>2021</td><td>~$66B / ~2% GDP</td><td>-</td><td>SIPRI, pre-invasion baseline</td></tr><tr><td>2022</td><td>~$75B</td><td>~$80B (avg)</td><td>Russia: SIPRI. Aid: Kiel Institute avg</td></tr><tr><td>2023</td><td>~$100B</td><td>~$90B (avg)</td><td>Russia: gov docs showed &gt;$100B actual</td></tr><tr><td>2024</td><td>~$140B / ~7% GDP</td><td>~$100B (avg)</td><td>Russia: SIPRI. Aid ramp-up over time</td></tr><tr><td>2025</td><td>~$145B budgeted</td><td>lower, US aid dropped</td><td>German intel estimates real spend ~$250B</td></tr><tr><td><strong>Cumulative 2022-2024</strong></td><td><strong>~$315B</strong></td><td><strong>~$280B</strong></td><td>Russia outspent all Western aid combined</td></tr></tbody></table></div><p>Sources: <a href="https://www.sipri.org/publications/2025/sipri-insights-peace-and-security/preparing-fourth-year-war-military-spending-russias-budget-2025">SIPRI</a>, <a href="https://www.kielinstitut.de/topics/war-against-ukraine/ukraine-support-tracker/">Kiel Institute</a>, <a href="https://www.wilsoncenter.org/blog-post/russias-unprecedented-war-budget-explained">Wilson Center</a>. Aid yearly figures are estimates derived from <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mn>280</mn><mi>B</mi><mi>c</mi><mi>u</mi><mi>m</mi><mi>u</mi><mi>l</mi><mi>a</mi><mi>t</mi><mi>i</mi><mi>v</mi><mi>e</mi><mi>a</mi><mi>n</mi><mi>d</mi><mi>k</mi><mi>n</mi><mi>o</mi><mi>w</mi><mi>n</mi><mi>r</mi><mi>a</mi><mi>m</mi><mi>p</mi><mo>-</mo><mi>u</mi><mi>p</mi><mi>p</mi><mi>a</mi><mi>t</mi><mi>t</mi><mi>e</mi><mi>r</mi><mi>n</mi><mo>(</mo><mi>K</mi><mi>i</mi><mi>e</mi><mi>l</mi><mi>r</mi><mi>e</mi><mi>p</mi><mi>o</mi><mi>r</mi><mi>t</mi><mi>s</mi><mi mathvariant="normal">~</mi></math>90B/year average 2022-2024). Russia stopped publishing realized spending after 2021 - actual spending likely higher than budgeted.</p>
<div style="margin:2em 0">
<svg viewBox="0 0 700 195" style="width:100%;max-width:700px;font-family:monospace">
  <text x="0" y="18" fill="currentColor" font-size="13" font-weight="bold">Russia Military Spending vs Western Aid to Ukraine ($B/year)</text>
  <text x="35" y="42" fill="currentColor" font-size="9" fill-opacity="0.6">Russia (red) vs Western aid (blue)</text>
  <text x="100" y="68" fill="currentColor" font-size="11" text-anchor="end">2022</text>
  <rect x="110" y="56" width="161" height="14" rx="2" fill="#d32f2f"/>
  <text x="276" y="68" fill="currentColor" font-size="10">$75B</text>
  <rect x="110" y="72" width="171" height="14" rx="2" fill="#1565c0"/>
  <text x="286" y="84" fill="currentColor" font-size="10">~$80B</text>
  <text x="100" y="108" fill="currentColor" font-size="11" text-anchor="end">2023</text>
  <rect x="110" y="96" width="214" height="14" rx="2" fill="#d32f2f"/>
  <text x="329" y="108" fill="currentColor" font-size="10">$100B</text>
  <rect x="110" y="112" width="193" height="14" rx="2" fill="#1565c0"/>
  <text x="308" y="124" fill="currentColor" font-size="10">~$90B</text>
  <text x="100" y="148" fill="currentColor" font-size="11" text-anchor="end">2024</text>
  <rect x="110" y="136" width="300" height="14" rx="2" fill="#d32f2f"/>
  <text x="415" y="148" fill="currentColor" font-size="10">$140B</text>
  <rect x="110" y="152" width="214" height="14" rx="2" fill="#1565c0"/>
  <text x="329" y="164" fill="currentColor" font-size="10">~$100B</text>
  <text x="110" y="190" fill="currentColor" font-size="10" fill-opacity="0.7">Cumulative 2022-2024: Russia ~$315B vs Western aid ~$280B</text>
</svg>
</div>
<p><strong>Top aid donors</strong> (cumulative through Dec 2024, <a href="https://www.kielinstitut.de/topics/war-against-ukraine/ukraine-support-tracker/">Kiel Institute</a>):</p>
<div style="margin:2em 0">
<svg viewBox="0 0 700 170" style="width:100%;max-width:700px;font-family:monospace">
  <text x="0" y="18" fill="currentColor" font-size="13" font-weight="bold">Top Aid Donors to Ukraine (Feb 2022 - Dec 2024)</text>
  <text x="100" y="48" fill="currentColor" font-size="11" text-anchor="end">United States</text>
  <rect x="110" y="36" width="400" height="16" rx="2" fill="#1565c0"/>
  <text x="515" y="49" fill="currentColor" font-size="10">~$120B / ~0.4% GDP</text>
  <text x="100" y="74" fill="currentColor" font-size="11" text-anchor="end">EU (institutions)</text>
  <rect x="110" y="62" width="247" height="16" rx="2" fill="#ffc107"/>
  <text x="362" y="75" fill="currentColor" font-size="10">~$74B</text>
  <text x="100" y="100" fill="currentColor" font-size="11" text-anchor="end">Germany</text>
  <rect x="110" y="88" width="67" height="16" rx="2" fill="#1565c0"/>
  <text x="182" y="101" fill="currentColor" font-size="10">~$20B / ~0.5% GDP</text>
  <text x="100" y="126" fill="currentColor" font-size="11" text-anchor="end">United Kingdom</text>
  <rect x="110" y="114" width="53" height="16" rx="2" fill="#1565c0"/>
  <text x="168" y="127" fill="currentColor" font-size="10">~$16B / ~0.5% GDP</text>
  <text x="100" y="152" fill="currentColor" font-size="11" text-anchor="end">Japan</text>
  <rect x="110" y="140" width="33" height="16" rx="2" fill="#9e9e9e"/>
  <text x="148" y="153" fill="currentColor" font-size="10">~$10B / ~0.2% GDP</text>
</svg>
</div>
<p><strong>Russia&#39;s war economy:</strong> Military budget doubled from ~<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mn>66</mn><mi>B</mi><mo>(</mo><mn>2021</mn><mo>)</mo><mi>t</mi><mi>o</mi><mi mathvariant="normal">~</mi></math>140B (2024). Now eats <strong>~30%</strong> of the government budget. GDP growth fell to <strong>0.6% in 2025</strong>. Manufacturing shrank 7 straight months. Zero Russian tech companies in global top 100.</p>
<p>Ukraine spends <strong>~20% of GDP</strong> on defense (up from 3% in 2021) - only possible with Western backing. In 2025, US aid dropped and Europe stepped up (military aid +67%) but didn&#39;t fully close the gap. NATO pledged $60B in military aid for 2026.</p>
<h2 id="why-ukraine">Why Ukraine?</h2>
<p>Why do both sides fight this hard over meters of ground? Zbigniew Brzezinski&#39;s <a href="https://en.wikipedia.org/wiki/The_Grand_Chessboard">The Grand Chessboard</a> (1997) answers with structure, not ideology.</p>
<p><strong>Ukraine decides whether Russia is an empire or a regional power.</strong> With Ukraine, Russia gains population, industry, agriculture, Black Sea dominance, and strategic depth. Without it, Russia is boxed into Asia. Brzezinski&#39;s most cited line: <em>&quot;Without Ukraine, Russia ceases to be an empire.&quot;</em></p>
<p><strong>Geographic position.</strong> Ukraine sits at the intersection of Black Sea access, east/west land routes, and energy transit corridors. Control over Ukraine gives leverage over European security and enables or blocks NATO&#39;s eastern coherence. Brzezinski calls this a <em>geopolitical pivot state</em>: not powerful itself, but decisive in who becomes powerful.</p>
<p><strong>Resources multiply position.</strong> Ukraine is not just buffer space, it is productive space: among the world&#39;s largest grain exporters, significant industrial and metallurgical base, energy transit routes and untapped reserves. Its ports (Odesa, Mykolaiv) control warm water naval access and grain/energy logistics. Russia has Black Sea access without Ukraine (Novorossiysk, Krasnodar coast), but it is narrow, easily bottlenecked, and dependent on Turkey via the <a href="https://en.wikipedia.org/wiki/Montreux_Convention_Regarding_the_Regime_of_the_Straits">Montreux Convention</a>. Ukraine does not create access, it makes access robust.</p>
<p><strong>Preventing a Eurasian hegemon.</strong> Brzezinski&#39;s thesis: the US must prevent any single power from dominating Eurasia. Ukraine aligned with the West fragments Eurasia. Aligned with Russia, it consolidates it. The proxy war spending above is not charity, it is structural investment.</p>
<p><strong>This is why the war does not end.</strong> The strategic payoff is binary, not incremental. Neither side can lose Ukraine without structural decline. Which is exactly what the data shows: enormous casualties, minimal territorial change, relentless continuation. Both sides are playing for the architecture of Eurasia, not for Donbas.</p>
<h2 id="key-takeaways">Key Takeaways</h2>
<ol>
<li><strong>Territory costs blood.</strong> Russia gained 0.8% of Ukraine in 2025 for ~415,000 casualties. At this rate, taking all of Ukraine would need decades and millions of soldiers.</li>
<li><strong>Record equipment losses.</strong> 4,381 confirmed tank losses beat Soviet losses in Afghanistan, Chechnya I, and Chechnya II combined. And these are confirmed minimums.</li>
<li><strong>Slowest major advance in a century.</strong> Russia&#39;s main offensives move 15-70 meters per day - slower than the Somme in WWI. Huliaipole at 297 m/day is the outlier.</li>
<li><strong>Drones changed everything.</strong> $500 FPV drones destroy $3M+ tanks. The cost math of war has flipped.</li>
<li><strong>No air control.</strong> Both sides have strong air defense. Flying manned aircraft is extremely risky for both.</li>
<li><strong>Economic pressure building.</strong> Russia spends 7% of GDP on military while growth drops to 0.6% and manufacturing shrinks. Ukraine&#39;s 20% of GDP on defense only works with outside help.</li>
</ol>
<h2 id="possible-outcomes">Possible Outcomes</h2>
<p>The data points to prolongation, exhaustion, and partial freezes. Not decisive victory.</p>
<p><strong>1. Prolonged attritional stalemate (most likely)</strong></p>
<p>Russia gained ~0.8% of Ukraine in 2025 for ~415,000 casualties. Advances of 15-70 meters per day are historically slow. Neither side has air superiority. Drones neutralize armor. Breakthroughs are rare. This means years of grinding warfare with shifting front lines but no collapse.</p>
<p><strong>2. Frozen conflict, Korea-style</strong></p>
<p>If Western aid holds steady and Russia&#39;s economy keeps straining at ~7% GDP military spending, the war settles into a hard frontline. No treaty, just enforced pause. Ukraine can defend, Russia can advance slowly, neither can end the war at acceptable cost.</p>
<p><strong>3. Negotiated ceasefire under exhaustion</strong></p>
<p>Less likely short-term, plausible long-term. ~2 million military casualties and economic pressure are cumulative. A ceasefire would probably lock in current lines, not restore full territorial integrity. Neither side is winning fast enough to dictate terms.</p>
<p><strong>4. Russian collapse or Ukrainian breakthrough (least likely)</strong></p>
<p>Despite enormous losses, Russia sustains manpower by lowering quality (T-62s, T-55s, mass FPV drones). Ukraine depends on external aid for ~20% GDP defense spending. Without a major shift in technology, alliances, or internal stability, decisive victory is improbable.</p>
<p><strong>Bottom line:</strong> This war is about industrial capacity, demographics, and political endurance. Time itself is the main weapon, destroying value faster than territory is gained - hopefully stopping this conflict sooner than later.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.csis.org/analysis/russias-grinding-war-ukraine">CSIS - Russia&#39;s Grinding War in Ukraine</a></li>
<li><a href="https://www.oryxspioenkop.com/2022/02/attack-on-europe-documenting-equipment.html">Oryx OSINT - Russian Equipment Losses</a></li>
<li><a href="https://www.oryxspioenkop.com/2022/02/attack-on-europe-documenting-ukrainian.html">Oryx OSINT - Ukrainian Equipment Losses</a></li>
<li><a href="https://informationisbeautiful.net/visualizations/ukraine-russian-war-infographics-data-visuals/">Information is Beautiful - Ukraine War Data Visuals</a></li>
<li><a href="https://deepstatemap.live/en">DeepState Map - Live Frontline Tracking</a></li>
<li><a href="https://www.russiamatters.org/news/russia-ukraine-war-report-card/russia-ukraine-war-report-card-april-8-2026">Russia Matters - War Report Card (Apr 8, 2026)</a></li>
<li><a href="https://www.aljazeera.com/news/2026/2/24/mapping-russian-attacks-and-territorial-gains-across-ukraine">Al Jazeera - Mapping Territorial Gains</a></li>
<li><a href="https://en.wikipedia.org/wiki/The_Grand_Chessboard">Zbigniew Brzezinski - The Grand Chessboard (1997)</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>mRNA Vaccines: How They Work</title>
      <link>https://seanpedersen.github.io/posts/mrna-vaccine</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/mrna-vaccine</guid>
      <pubDate>Fri, 03 Apr 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>mRNA vaccines work by mimicking a trick viruses have used for billions of years: injecting genetic instructions (mRNA) into your cells to make them produce a specific target protein.</p>
<h2 id="what-is-mrna">What is mRNA?</h2>
<p>Messenger RNA (mRNA) is a short-lived molecule that carries a protein blueprint copied from DNA. Cells read mRNA through ribosomes, their protein-making machinery, and build the protein the mRNA describes. Once read, the mRNA is degraded. It never enters the cell nucleus and cannot alter your DNA.</p>
<h2 id="the-blueprint-trick">The Blueprint Trick</h2>
<p>A virus survives by injecting its own genetic instructions into host cells, forcing them to manufacture viral proteins. mRNA vaccines borrow exactly this strategy. The vaccine delivers a synthetic mRNA strand encoding a target protein. Your ribosomes read it and build that protein. Your immune system sees it as foreign, mounts a defence, and stores memory cells for future protection. You are never exposed to the actual pathogen.</p>
<p>Your own cells are the factory. The mRNA is the blueprint.</p>
<h2 id="the-delivery-problem">The Delivery Problem</h2>
<p>Naked mRNA degrades within seconds in the bloodstream. It also cannot cross cell membranes on its own. The solution is lipid nanoparticles (LNPs): tiny fatty shells that protect the mRNA and fuse with cell membranes to deliver the payload inside.</p>
<p>LNPs have no precise targeting ability. They distribute largely by proximity. Most are absorbed by cells at the injection site, nearby immune cells, and to some extent the liver, which efficiently clears lipid particles from blood.</p>
<h2 id="why-the-deltoid">Why the Deltoid?</h2>
<p>The standard injection site is the deltoid muscle in the upper arm. This is not arbitrary. Muscle tissue in this region is rich in dendritic cells and macrophages, immune cells that pick up foreign proteins and present them to the adaptive immune system. The axillary lymph nodes sit nearby, which is where antibody production and memory cell formation are organised.</p>
<p>Injecting into a vein rather than muscle sends LNPs circulating systemically, reaching organs beyond the intended local site. This distinction between intramuscular and intravenous delivery has practical safety implications and is why injection technique matters. Accidental intravenous injection sends LNPs into blood circulation, potentially reaching the heart and causing myocarditis (inflammation of the heart muscle) like it happened with corona vaccines.</p>
<h2 id="what-happens-inside">What Happens Inside</h2>
<ol>
<li>LNPs are absorbed by local muscle cells and nearby immune cells</li>
<li>mRNA is released inside the cell</li>
<li>Ribosomes read the mRNA and produce the target protein (for COVID vaccines: the spike protein)</li>
<li>The cell displays fragments of this protein on its surface</li>
<li>The immune system recognises the protein as foreign</li>
<li>B cells produce antibodies; T cells learn to attack cells displaying this protein</li>
<li>Memory cells are stored for long-term protection</li>
<li>The mRNA degrades within days</li>
</ol>
<h2 id="beyond-infectious-disease">Beyond Infectious Disease</h2>
<p>mRNA technology is not limited to vaccines against pathogens. Its core ability, instructing cells to produce any protein on demand, opens broader applications.</p>
<p>Cancer treatment is the most significant near-term area. Tumours carry mutations that produce abnormal proteins called neoantigens. These are unique to each patient&#39;s cancer. Researchers can sequence a patient&#39;s tumour, identify its neoantigens, synthesise a personalised mRNA vaccine encoding those targets, and inject it to train the immune system to attack cells displaying them. This approach, already in clinical trials for melanoma and other cancers in combination with checkpoint inhibitors, effectively turns the immune system into a targeted therapy customised per patient.</p>
<p>Other areas in active development include:</p>
<p><strong>Protein replacement therapies</strong>: Delivering mRNA that encodes a missing or defective protein, relevant for conditions like cystic fibrosis or certain metabolic disorders.</p>
<p><strong>Autoimmune conditions</strong>: Tolerogenic mRNA approaches, where instead of activating an immune response, the goal is to suppress one by instructing cells to express proteins that calm immune activity against self-tissue.</p>
<p><strong>Rare genetic diseases</strong>: Periodic mRNA dosing could temporarily restore function of a protein the body cannot produce, without permanent gene editing.</p>
<h2 id="mrna-vs-protein-vaccine-inflammatory-risk">mRNA vs Protein Vaccine — Inflammatory Risk</h2>
<p><strong>Activation timeline</strong></p>
<ul>
<li>mRNA: protein detectable after ~4 hours, peaks at 24 hours, gone by 72 hours</li>
<li>Protein vaccine: antigen immediately available but fixed dose, degrades within hours</li>
<li>Immune response timeline is similar for both (~14 days to meaningful antibodies) — the difference is mechanism, not speed of protection</li>
</ul>
<p><strong>The amplification tradeoff</strong><br>mRNA continuously produces fresh antigen for 72 hours, generating a stronger immune signal than a fixed injected protein dose. This is why protein vaccines need adjuvants and often booster shots to match mRNA efficacy — but it also means mRNA keeps the inflammatory stimulus active longer.</p>
<p><strong>Vein exposure risk</strong></p>
<ul>
<li>mRNA: if accidentally injected intravenously, LNPs distribute systemically and cells throughout the body — including cardiac tissue — produce spike protein for up to 72 hours, creating a sustained inflammatory stimulus</li>
<li>Protein vaccine: if accidentally IV injected, you get a fixed bolus that immediately begins degrading — no ongoing production, self-limiting exposure</li>
</ul>
<p><strong>The double hit problem</strong><br>mRNA vaccines have two independent inflammatory sources: the LNP/mRNA delivery mechanism itself, plus the immune response to the expressed protein. Protein vaccines with adjuvants deliberately add back one inflammatory stimulus, but it&#39;s more controlled than systemic LNP distribution.</p>
<p><strong>What the data shows</strong><br>Mouse studies confirm IV mRNA injection causes myocarditis. Some countries (Denmark, Hong Kong) adopted aspiration before injection as a precaution. But the natural experiment — comparing myocarditis rates between countries that did and didn&#39;t adopt aspiration — has not been published, leaving your core hypothesis scientifically open.</p>
<h2 id="what-comes-next">What Comes Next</h2>
<p>The platform&#39;s key advantage is speed. Once a protein target is identified, the mRNA sequence can be designed computationally and synthesised in weeks. This compresses development timelines that previously took years. During COVID-19, the Moderna vaccine went from sequence design to first human dose in 63 days.</p>
<p>The bottleneck is now delivery. Current LNPs distribute broadly rather than to specific cell types, and tend to accumulate in the liver by default. For immune-based cancer vaccines, the goal is not to reach tumour cells directly — the immune system handles that — but to deliver mRNA efficiently to antigen-presenting cells like dendritic cells, which then orchestrate the immune response. For direct therapeutic approaches, such as gene editing or reprogramming cells within the tumour microenvironment, precise delivery to specific cell types does matter. More broadly, targeting mRNA to tissues like lung epithelium or particular immune cell populations would dramatically expand what is possible and reduce off-target effects. This is an active area of research.</p>
<p>mRNA vaccines are not a narrow tool for infectious disease. They are a general platform for programming cellular protein production. The COVID vaccines were the proof of concept at scale. Personalised cancer treatment may be the first demonstration of their full potential.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.nature.com/articles/s41541-021-00292-w">https://www.nature.com/articles/s41541-021-00292-w</a></li>
<li><a href="https://www.nejm.org/doi/full/10.1056/NEJMoa2034577">https://www.nejm.org/doi/full/10.1056/NEJMoa2034577</a></li>
<li><a href="https://www.nature.com/articles/s41586-023-06063-y">https://www.nature.com/articles/s41586-023-06063-y</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Colds, Immune System &amp; Vaccination</title>
      <link>https://seanpedersen.github.io/posts/colds-immune-system</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/colds-immune-system</guid>
      <pubDate>Fri, 03 Apr 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>You&#39;ve been catching colds your whole life. But how much do you really know about what&#39;s happening inside you — and what you can actually do about it?</p>
<h2 id="what-a-cold-actually-is">What a cold actually is</h2>
<p>A &quot;cold&quot; isn&#39;t a single illness — it&#39;s a loose term for upper respiratory infections caused by over 200 different viruses. Rhinoviruses are responsible for roughly half of them. The virus doesn&#39;t make you feel awful; your immune system does. The runny nose, fatigue, and sore throat are side effects of your body mounting a full-scale defence.</p>
<p>Colds are by definition viral — but bacteria can cause nearly identical symptoms, which is why the line blurs in practice. More importantly, a viral cold often weakens local defences (damaged mucosa, disrupted nasal cilia, inflamed tissue), letting bacteria opportunistically move in. This is how a cold &quot;turns into&quot; a sinus infection, ear infection, or bacterial bronchitis. The cold was viral; the complication is bacterial — and that&#39;s the one scenario where antibiotics become relevant.</p>
<p>A few signs the infection may have gone bacterial: symptoms that improve then suddenly worsen, a high fever above 39°C, or symptoms that show no improvement after 10–14 days. Worth seeing a doctor in any of those cases.</p>
<blockquote><p class="quote-line"><strong>Surprising fact:</strong> Cold air doesn&#39;t cause colds directly — but it does dry out nasal membranes (weakening a key barrier), helps viruses survive longer in the air, and people spend more time indoors sharing recirculated air. It&#39;s the combination that drives winter colds seasonality, not any single factor.</p>
</blockquote><p>Viruses spread mainly through two routes: respiratory droplets in the air, and contact with contaminated surfaces followed by touching your face. The average person touches their face around 20 times per hour, often without noticing.</p>
<h2 id="the-immune-system-briefly">The immune system, briefly</h2>
<p>Think of immunity in two layers. The <em>innate</em> immune system is your instant first responder — it detects something foreign and triggers inflammation fast. The <em>adaptive</em> immune system is slower but smarter: it builds a bespoke response to a specific threat, then keeps a memory of it. That memory is why you rarely catch the same strain of flu twice.</p>
<p>When a vaccine introduces a fragment of a pathogen (or instructions for your cells to make one), it triggers the adaptive system to build that memory — without you ever getting sick from the real thing.</p>
<blockquote><p class="quote-line"><strong>Mechanism worth knowing:</strong> mRNA vaccines work by mimicking how viruses hijack your cells. The vaccine delivers synthetic mRNA into your cells — just like a virus injects its own genetic instructions. Your ribosomes read that mRNA and manufacture the target protein (the spike protein). Your immune system detects this foreign protein, mounts a response, and builds antibodies and memory cells — training itself without you ever being exposed to the actual virus.</p>
</blockquote><h2 id="hygiene-habits-that-actually-work">Hygiene habits that actually work</h2>
<p>Most people wash their hands, but the details matter far more than the act itself.</p>
<ul>
<li><strong>20 seconds, not 5.</strong> The friction and duration matter as much as the soap. Hum &quot;Happy Birthday&quot;, &quot;Praise the Lord&quot; or &quot;Hail Satan&quot; twice as a rough timer.</li>
<li><strong>Water temperature is irrelevant.</strong> Hot vs. cold makes no practical difference to pathogen removal. Soap and friction do the work.</li>
<li><strong>Masks filter outbound too.</strong> Wearing a mask when you&#39;re mildly ill reduces what you breathe onto others — regardless of their vaccination status.</li>
<li><strong>Ventilate rooms.</strong> A brief burst of fresh air dramatically drops indoor viral load. Even 5 minutes with a window open helps.</li>
<li><strong>Sleep is immune support.</strong> People sleeping under 6 hours are over 4x more likely to catch a cold when directly exposed to a rhinovirus.</li>
<li><strong>Vitamin C won&#39;t prevent colds.</strong> High-dose vitamin C doesn&#39;t stop you getting sick. It may cut duration by about half a day in some studies — modest at best.</li>
</ul>
<h2 id="things-that-may-surprise-you">Things that may surprise you</h2>
<ul>
<li>Antibiotics do nothing for colds — they target bacteria, not viruses. Taking them unnecessarily accelerates antibiotic resistance and damages your gut flora unnecessarily.</li>
<li>Herd immunity isn&#39;t all-or-nothing. Every additional vaccinated person reduces transmission pathways, protecting those who medically can&#39;t be vaccinated.</li>
<li>You become contagious with a cold 1–2 days <em>before</em> you feel any symptoms — meaning you&#39;re spreading it before you even know you have it.</li>
<li>The gut hosts roughly 70% of your immune cells. What you eat genuinely affects how well your immune system can respond to threats.</li>
<li>Fever is a feature, not a bug. Elevated body temperature actively slows viral replication and accelerates immune cell activity.</li>
<li>Some people carry cold viruses and never get symptoms — they&#39;re infected but their immune response stays subclinical.</li>
</ul>
<h2 id="the-practical-bottom-line">The practical bottom line</h2>
<p>The boring interventions remain the best ones: wash hands properly and often, sleep consistently, stay up to date with vaccines, and stay home when you&#39;re contagious. The immune system is sophisticated enough to do most of the work — your job is mostly to give it the conditions it needs, and not to undermine it.</p>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>UFO / UAP Phenomenon</title>
      <link>https://seanpedersen.github.io/posts/ufo-alien</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/ufo-alien</guid>
      <pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Credible UFO / UAP reports date back to WWII, when Allied pilots over both the Pacific and European theaters encountered unexplained aerial objects they called &quot;Foo Fighters.&quot; The modern era began in June 1947 with <a href="https://en.wikipedia.org/wiki/Kenneth_Arnold_UFO_sighting">Kenneth Arnold&#39;s sighting near Mount Rainier</a> — prompting the U.S. Army Air Force to conclude the phenomenon was real and launch its first official investigation, Project Sign.</p>
<p>The debate shifted fundamentally in 2017 when the Pentagon began declassifying sensor footage and credentialed government insiders, started making specific public claims about what the U.S. government knows and may be concealing.</p>
<p>Documenteries like the &quot;<a href="https://en.wikipedia.org/wiki/The_Age_of_Disclosure">The Age of Disclosure</a>&quot; brought to a wider audience the narrative that US government officials say it is real and a real threat to US national security.</p>
<h2 id="historical-sightings">Historical Sightings</h2>
<p>While the modern era of credible military reporting began with the WWII Foo Fighters, civilians and chroniclers recorded strange aerial events centuries earlier. Two regions left especially detailed records: Reformation era Germany, with printed broadsheets and woodcuts, and China, where careful scholars also filed reports.</p>
<h3 id="nuremberg-14-april-1561">Nuremberg, 14 April 1561</h3>
<p>On the morning of 14 April 1561, citizens of Nuremberg reported a mass aerial event at sunrise lasting roughly an hour. A <a href="https://de.wikipedia.org/wiki/N%C3%BCrnberger_Flugblatt_von_1561#/media/Datei:Himmelserscheinung_%C3%BCber_N%C3%BCrnberg_vom_14._April_1561.jpg">broadsheet</a> printed by Hans Glaser later that month described &quot;globes,&quot; &quot;crosses,&quot; and cylindrical objects in red, blue, and black moving across the sky. The pamphlet claims the shapes appeared to fight one another, then fell to earth where smoke rose at the impact points. The woodcut is one of the earliest printed records of a UAP style event in Europe and was later popularized in Carl Jung&#39;s 1958 book on flying saucers.</p>
<h3 id="basel-1566">Basel, 1566</h3>
<p>Five years later and a few hundred kilometers south, witnesses in Basel reported similar phenomena on 27 and 28 July and again on 7 August. The historian Samuel Coccius described &quot;large black spheres&quot; moving with great speed in front of the sun, with some appearing to burn red before vanishing. Basel sits in modern Switzerland, but in 1566 it belonged to the German speaking cultural sphere of the Holy Roman Empire, and the report uses the same <a href="https://de.wikipedia.org/wiki/Basler_Flugblatt_von_1566#/media/Datei:LinkSeltsame_Gestalt_so_in_disem_MDLXVI_Jar.jpg">illustrated pamphlet</a> format common across Reformation era central Europe.</p>
<h3 id="yangzhou-around-1080">Yangzhou, around 1080</h3>
<p>A century before printing reached Europe, the Chinese polymath Shen Kuo wrote about a recurring aerial object in his &quot;Dream Pool Essays&quot; (1088). Locals in Fanliang, near Yangzhou, said an object &quot;as bright as a pearl&quot; appeared over a lake. Shen reported that the object opened to emit a great light, &quot;like the rising Sun, lighting up the distant sky and woods in red.&quot; Witnesses nicknamed it &quot;the Pearl,&quot; and a viewing platform called the Pearl Pavilion was built so travelers could watch for it. Shen Kuo is also credited with the first known description of the magnetic compass and a remarkably modern theory of erosion, which makes his account unusually careful for the period.</p>
<h2 id="recent-notable-incidents">Recent Notable Incidents</h2>
<h3 id="nimitz-2004-incident-tic-tac-ufo">Nimitz 2004 incident (Tic-Tac UFO)</h3>
<ul>
<li>Multiple military witnesses (David Fravor, Alex Dietrich, radar operators on USS Princeton).</li>
<li>Separate sensor tracks (F/A-18’s APG-73 radar, AN/SPY-1 ship radar, FLIR video).</li>
<li>Chain-of-custody FLIR footage officially released by the Pentagon.</li>
</ul>
<p><a href="https://www.cbsnews.com/news/tic-tac-ufo-sighting-uap-video-dave-fravor-alex-dietrich-navy-fighter-pilots-house-testimony/">CBSNEWS: Tic-Tac UFO Article</a></p>
<h3 id="hangzhou-7-july-2010">Hangzhou, 7 July 2010</h3>
<p>Modern China has a striking civilian aviation case as well. On the evening of 7 July 2010, Xiaoshan International Airport near Hangzhou shut down for about four hours after a flight crew on approach reported an unidentified object in its airspace. Eighteen flights were diverted or delayed. Photographs taken from the ground showed a long glowing trail. Chinese authorities never released a clear official explanation, and the case remains one of the more widely reported civilian airport UAP events of recent decades.</p>
<p><a href="https://www.chinadaily.com.cn/china/2010-07/10/content_10089831.htm">ChinaDaily: UFO remains a mystery</a></p>
<h3 id="pentagon-flir-videos">Pentagon FLIR videos</h3>
<ul>
<li>Declassified and published “GIMBAL”, “GOFAST”, “FLIR1” videos by the U.S. Navy/DoD in 2017-2021.</li>
<li>Accompanied by incident reports and pilot voice recordings.</li>
</ul>
<p><a href="https://www.popularmechanics.com/military/research/a32289669/navy-official-release-ufo-videos/">PopularMechanics: Navy Official UFO Videos Article</a></p>
<h2 id="the-age-of-disclosure-protagonists">The Age of Disclosure - Protagonists</h2>
<p><a href="https://en.wikipedia.org/wiki/Luis_Elizondo">Lue Elizondo</a> — Former Army intelligence officer, ran <a href="https://en.wikipedia.org/wiki/Advanced_Aerospace_Threat_Identification_Program">AATIP</a> for the US government. Claims: UAPs are real, non-human, and represent a national security threat; a secret &quot;Legacy Program&quot; has been retrieving and reverse-engineering non-human craft since 1947; a disinformation campaign was run against him by the Pentagon; he and David Grusch were allegedly threatened with assassination.</p>
<p>Jay Stratton — 16-year senior intelligence official on UAP, first director of the UAP Task Force. Claims: The Legacy Program withheld from Congress, the SecDef, and the President; non-human bodies were recovered in crash retrievals; religious fundamentalists inside the Pentagon actively blocked UAP investigation.</p>
<p><a href="https://en.wikipedia.org/wiki/Christopher_Mellon">Christopher Mellon</a> — Former Deputy Assistant Secretary of Defense for Intelligence. Claims: UAP is a real, ongoing phenomenon ignored by senior leadership; he helped craft UAP legislation with Rubio; defense contractors now hold recovered technology outside congressional oversight.</p>
<p><a href="https://en.wikipedia.org/wiki/David_Grusch_UFO_whistleblower_claims">David Grusch</a> — Former NRO/UAP Task Force officer, whistleblower. Testified under oath: the US runs a multi-decade crash retrieval and reverse-engineering program; non-human biologics were recovered; people have been harmed or killed to protect the secret; funds were misappropriated to hide the program.</p>
<p>David Fravor — Navy Commander, USS Nimitz pilot (2004). Claims: Witnessed the &quot;Tic Tac&quot; UAP traveling ~32,000 mph, defying known physics; the US has nothing remotely comparable.</p>
<p>Alex Dietrich — Navy pilot, flew with Fravor during the Tic Tac encounter. Claims: The object defied laws of physics and gravity in ways no conventional craft could.</p>
<p><a href="https://wikitia.com/wiki/Ryan_Graves_(fighter_pilot)">Ryan Graves</a> — Navy pilot. Claims: UAPs were seen nearly daily around Navy operations; a black cube inside a clear sphere passed between two aircraft at close range.</p>
<p>Garry Nolan — Stanford pathology professor. Claims: Military personnel who encountered UAPs suffered serious biological harm including brain scarring and a ~25% mortality rate within 7 years; he analyzed their medical data for the CIA and an aerospace company.</p>
<p>Hal Puthoff — Physicist. Claims: UAPs likely use a warp bubble / space-time engineering principle, explaining all five observables (hypersonic speed, instant acceleration, low observability, transmedium travel, anti-gravity); energy requirements exceed 1,100 billion watts.</p>
<p>Brett Feddersen — Former NSC aviation security director / FAA National Security Programs. Claims: The FAA does not track UAPs, putting aviation safety at risk; the US is &quot;behind the power curve&quot; on this technology.</p>
<p>Various nuclear weapons witnesses — Multiple Air Force and missile silo personnel claim UAPs have both deactivated and activated US nuclear missiles, and hovered silently over launch facilities.</p>
<p>Although not part of the documentary the story of <a href="https://en.wikipedia.org/wiki/Bob_Lazar">Bob Lazar</a>, seems to fit the narrative of the show.</p>
<h2 id="the-4-hypotheses-for-uap">The 4 Hypotheses for UAP</h2>
<ol>
<li>Foreign adversary technology: China, Russia, or another human group (some even speculate based on secret german nazi research on new types of anti-gravity propulsion systems) has developed craft so advanced it constitutes the biggest intelligence failure in modern American history.</li>
<li>US government counter-intelligence cover: UAPs are a cover story concealing a highly classified US program that has drifted outside congressional oversight.</li>
<li>Extraterrestrial or interdimensional origin: The craft originate from another civilization, dimension, or possibly even Earth itself (cryptoterrestrial, time travelers, or an ancient hidden species).</li>
<li>A combination of the above three: Some UAP activity may be foreign reverse-engineering of retrieved non-human craft, some may be US black programs, and some may be genuinely non-human in origin.</li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>The UFO / UAP phenomenon has moved into mainstream focus and warrants more research and funding. Current stigma (negativ cracknut sentiment) needs to be overcome. Current publicly available data (videos) point to advanced technology existing capable of near-instant acceleration. And multiple high steak US gov. witnesses claiming the existence of such aircraft and even non-human bodies - until these aircraft or bodies are accessible to the public other explanations remain possible though.</p>
<h2 id="references">References</h2>
<ul>
<li>The Age of Disclosure (<a href="https://pastebin.com/raw/Kf2tvXKz">transcript</a>)</li>
<li><a href="https://en.wikipedia.org/wiki/Pentagon_UFO_videos">https://en.wikipedia.org/wiki/Pentagon_UFO_videos</a></li>
<li><a href="https://en.wikipedia.org/wiki/UFO_reports_and_disinformation">https://en.wikipedia.org/wiki/UFO_reports_and_disinformation</a></li>
<li><a href="https://www.popularmechanics.com/military/research/a36560537/die-glocke-nazi-bell-conspiracy/">https://www.popularmechanics.com/military/research/a36560537/die-glocke-nazi-bell-conspiracy/</a></li>
<li><a href="https://youtu.be/lYVxRHk258g">More Evidence for UAPs! Scientists Afraid to Speak Out</a></li>
<li><a href="https://science.nasa.gov/wp-content/uploads/2023/09/uap-independent-study-team-final-report.pdf">https://science.nasa.gov/wp-content/uploads/2023/09/uap-independent-study-team-final-report.pdf</a></li>
<li><a href="https://en.wikipedia.org/wiki/1561_celestial_phenomenon_over_Nuremberg">1561 celestial phenomenon over Nuremberg (Wikipedia)</a></li>
<li><a href="https://en.wikipedia.org/wiki/1566_celestial_phenomenon_over_Basel">1566 celestial phenomenon over Basel (Wikipedia)</a></li>
<li><a href="https://en.wikipedia.org/wiki/Dream_Pool_Essays">Dream Pool Essays by Shen Kuo (Wikipedia)</a></li>
<li><a href="https://www.aaas.org/membership/scientia/shen-kuo-first-renaissance-man">Shen Kuo, the first Renaissance man? (AAAS)</a></li>
<li><a href="https://enigmalabs.io/library/6b5abeb2-ef4f-43ad-a6de-b8c8ecb40815">Xiaoshan Airport Shutdown Due to UAP (Enigma Labs)</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>How AI and mRNA vaccine helped a dog with cancer</title>
      <link>https://seanpedersen.github.io/posts/ai-mrna-cancer-dog</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/ai-mrna-cancer-dog</guid>
      <pubDate>Tue, 17 Mar 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>A Sydney tech entrepreneur, <a href="https://x.com/paul_conyngham">Paul Conyngham</a>, had a rescue dog, Rosie, with advanced <a href="https://en.wikipedia.org/wiki/Mast_cell_sarcoma">mast cell cancer</a> and months to live after standard treatment.</p>
<p>He paid for Rosie&#39;s tumor sequencing through the <a href="https://www.unsw.edu.au/">University of New South Wales</a> (UNSW) and then used ChatGPT and AlphaFold to help analyze mutations and think through possible targets and treatment options.</p>
<p>Conyngham is an experienced machine-learning practitioner, not a complete novice to technical fields, and he collaborated with scientists, including <a href="https://www.unsw.edu.au/staff/pall-thordarson">Prof. Pall Thordarson</a> (<a href="https://x.com/PalliThordarson">X Profile</a>) at <a href="https://www.unsw.edu.au/institutes/rna">UNSW’s RNA Institute</a>.</p>
<p>Prof. Thordarson and his team used the data to design a <a href="https://en.wikipedia.org/wiki/Personalized_mRNA_cancer_vaccine_therapy">personalized mRNA cancer vaccine</a> for Rosie in under two months, describing it as the first time such a bespoke vaccine had been designed for a dog at their institute.</p>
<p>Rosie received injections starting in December 2025; within weeks the main tumor shrank dramatically (around 75% in one report), her energy and coat improved, and she is reported as alive and more active, though not definitively “cured.” Prof. Thorardson and others are still actively involved in curing Rosie.</p>
<p>It took about three months and extensive paperwork to obtain ethics approval for a veterinary trial for Rosie.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://x.com/PalliThordarson/status/2033013002061136212">X Thread by Prof. Thordarson</a></li>
<li>Relevant X posts by Paul: Day <a href="https://x.com/paul_conyngham/status/1847813816685646022">#1</a>, <a href="https://x.com/paul_conyngham/status/1848540290594009369">#2</a>, <a href="https://x.com/paul_conyngham/status/1849044007890145734">#3</a>, <a href="https://x.com/paul_conyngham/status/1859091739564536237">#4</a>, <a href="https://x.com/paul_conyngham/status/1859793608989344042">#5</a>, <a href="https://x.com/paul_conyngham/status/2032955217021669779">Images</a>, <a href="https://x.com/paul_conyngham/status/2033030685842354594">DNA sequencing</a>,</li>
<li><a href="https://fortune.com/2026/03/15/australian-tech-entrepreneur-ai-cancer-vaccine-dog-rosie-unsw-mrna/">Fortune article</a></li>
<li><a href="https://www.indiatoday.in/technology/news/story/man-uses-chatgpt-and-alphafold-to-build-diy-mrna-cancer-vaccine-saves-dog-2882198-2026-03-15">India Today tech article</a></li>
<li><a href="https://www.ndtv.com/feature/australian-entrepreneur-uses-chatgpt-to-create-customised-vaccine-to-cure-dogs-cancer-11219043">NDTV article</a><br>​<br>​#idea</li>
</ul>

        ]]></content:encoded>
    </item>
    <item>
      <title>The XZ Backdoor: A Near-Catastrophic Linux Hack</title>
      <link>https://seanpedersen.github.io/posts/xz-backdoor</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/xz-backdoor</guid>
      <pubDate>Tue, 17 Mar 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>A sophisticated 2024 supply-chain attack nearly gave an unknown hacker (group) access to millions of internet servers.</p>
<p><strong>The Setup</strong><br>Linux runs the world: servers, supercomputers, Android, nuclear submarines. Its security model relies on open source code being widely scrutinized (&quot;Linus&#39;s Law&quot;). But the ecosystem depends on thousands of tiny projects, often maintained by a single unpaid volunteer.</p>
<p><strong>The Target</strong><br><a href="https://github.com/Larhzu">Lasse Collin</a>, a Finnish developer, had maintained <a href="https://github.com/tukaani-project/xz">XZ</a> (a widely-used lossless compression tool) alone for 20 years. Burned out and struggling with mental health, he was vulnerable to offers of help.</p>
<p><strong>The Attack</strong><br>A persona called <a href="https://github.com/JiaT75">Jia Tan</a> spent ~2.5 years:</p>
<ol>
<li>Building trust as a helpful contributor to XZ</li>
<li>Taking over as maintainer</li>
<li>Secretly embedding a backdoor inside binary test blobs (invisible in normal code review)</li>
</ol>
<p>The backdoor exploited a precise chain: XZ (<a href="https://github.com/ShiftMediaProject/liblzma">liblzma</a>) → dependency of <a href="https://github.com/openssh/openssh-portable">OpenSSH</a> → hijacking the RSA authentication step via IFUNC resolvers and dynamic audit hooks, creating a <strong>master key to any server running the infected version</strong>.</p>
<p><strong>The Near-Miss</strong><br>Microsoft engineer and PostgreSQL developer <a href="https://x.com/AndresFreundTec">Andres Freund</a> noticed a tiny ~400ms SSH slowdown while testing an unstable Debian release - not even looking for security bugs. He kept investigating and discovered the backdoor in March 2024, just weeks before it would have shipped in major enterprise Linux releases (RHEL, Fedora, Ubuntu).</p>
<p><strong>Who Was Jia Tan?</strong><br>Almost certainly a <strong>nation-state actor</strong> - the operation was too patient and expensive for criminals. Timestamping and other breadcrumbs can be manipulated and thus provide no hard evidence, so no one knows for certain. <a href="https://github.com/JiaT75">Jia Tan</a> vanished immediately after discovery.</p>
<p><strong>The Bigger Lesson</strong><br>The real vulnerability wasn&#39;t the code - it was <em>the structure of the project</em>. Critical infrastructure was resting on one exhausted, unpaid volunteer. This was not the failure of the maintainer but a structural issue of how we build critical open-source software.</p>
<p>To future proof open-source software, we need to identify other high-impact software projects with similar vulnerable structure (few maintainers) and pour more resources into them. And also increase automated security tests for all dependencies of high-impact projects like <a href="https://github.com/openssh/openssh-portable">OpenSSH</a> using static analysis and automated coding agents (LLM).</p>
<p>Similar future attacks maybe even more sophisticated by taking legitimate control of criticial open-source software for years - building up trust by years of reliable and helpful work - and when needed dropping a malicious version. A more resilient structure for critical open-source projects would be decentral and select a group of verifiers randomly from a group.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=aoag03mSuXQ">Veritasium YouTube Video</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Urban Living</title>
      <link>https://seanpedersen.github.io/posts/urban-living</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/urban-living</guid>
      <pubDate>Sun, 01 Mar 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Living in a metropol (big city) is a paradoxical thing: so many humans packed into a tight place but many feel lonely and disconnected - in contrast with living in a small community where social bonds are much stronger.</p>
<p>Naturalize the city landscape - the whole city should look and feel like a beautiful garden park. Bring back beautiful architecture that integrates art works of local craftmen. Use animal friendly architecture everywhere (spotted glasses to prevent flying bird deaths, small water body exit bridges to prevent animals from drowning, etc).</p>
<p>Create communal rooms in apartment building stairwells for neighbors to connect and chat over tea or coffee and to swap items.</p>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>AI Safety Farce</title>
      <link>https://seanpedersen.github.io/posts/ai-safety-farce</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/ai-safety-farce</guid>
      <pubDate>Sun, 01 Mar 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <category>privacy</category>
      <content:encoded><![CDATA[
          <p>Major AI (LLM) companies like Anthropic and OpenAI pride themselves by investing into AI safety research (which they mainly define as AI alignment aka prevent the agent from going rogue) - but they keep a blind eye on safely deploying AI for society as whole, by not investing heavily into private LLM inference, which would make LLMs private and secure (in the interest of the user) and would prevent providers from collecting user data (which is not the interest of these companies investors).</p>
<p>Instead they are building the most sophisticated mass <a href="/posts/digital-capitalism-alternatives">digital surveillance machine</a> the world has ever seen. They are normalizing a future where we share every intimate detail of our lives with their free or cheap chatbot service and we let these chatbots not only monitor everything about us but even worse we let us manipulate by them (by consuming their responses / content).</p>
<p>If these companies were truly interested in developing safe AI for humanity they would not build this centralized LLM powered mass manipulation system but instead invest heavily into safe AI deployment via decentral and private LLM inference (by publishing open-source models and using on-device inference or <a href="https://en.wikipedia.org/wiki/Homomorphic_encryption">homomorphic encryption</a>). Only this way can AI be deployed for humanity without enabling mass surveillance and manipulation.</p>
<p>It boils down to:<br>AI alignment without decentralization still concentrates power.<br>Concentrated AI power is a societal risk.<br>Therefore AI deployment architecture is as important as AI model alignment.</p>
<p>Open-source AI must win.</p>
<p>References:</p>
<ul>
<li><a href="https://openmined.org/blog/private-machine-learning-explained/">https://openmined.org/blog/private-machine-learning-explained/</a></li>
<li><a href="https://opensourceaimustwin.com/">https://opensourceaimustwin.com/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a> <a href="/index.html#privacy">#privacy</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Optimal Coding Agent</title>
      <link>https://seanpedersen.github.io/posts/coding-agent</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/coding-agent</guid>
      <pubDate>Thu, 26 Feb 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>My blueprint for the optimal coding agent (team).<br>Keeping LLMs in the smart zone using short and relevant context.</p>
<p>Usage patterns:</p>
<ul>
<li>quick (small) edit<ul>
<li>skip to instructor agent</li>
</ul>
</li>
<li>major edit<ul>
<li>full coding agent orchestra</li>
</ul>
</li>
<li>new project<ul>
<li>deep research for best tech stack</li>
<li>use proven project code template / snippets</li>
</ul>
</li>
</ul>
<p>Every code repo should have a SPEC.md file which details in natural language the purpose and capabilities of the project. The code base is then derived from it using coding agents. As coding agents improve in capability the code base will match the specification file more closely, more efficiently and with less bugs.</p>
<p>UX:</p>
<ul>
<li>Provide idea -&gt; discuss</li>
<li>Refine plan with designer -&gt; submit to general</li>
<li>General creates the task tree -&gt; review and submit</li>
<li>Watch the executors work -&gt; review finished idea</li>
</ul>
<h2 id="ideator-muse">IDEATOR / MUSE</h2>
<p>Agent helps you crystallize your vision and define a hard success criterion (agent has web access to research ideas).</p>
<h4 id="designer">DESIGNER</h4>
<p>Uses knowledge base: tool to query existing solved solutions + web access (query tools like deepwiki.com). Designer also needs relevant context to create good architecture (blog posts, papers, books, etc)</p>
<ul>
<li>translates idea into objects / modules and interactions</li>
<li>defines interfaces / boundaries for modules</li>
<li>produces a design with specifications</li>
<li>discuss best tools (tech stack) for the design specs</li>
</ul>
<h2 id="general">GENERAL</h2>
<p>Creates the battle plan - brief the troops.</p>
<h4 id="orchestrator">ORCHESTRATOR</h4>
<p>Generate the task tree from design + tech stack.</p>
<ul>
<li>create modular plan with task execution dependency tree<ul>
<li>every task has:<ul>
<li>ID</li>
<li>Problem: in- / output typed interface + internal behavior / structure</li>
<li>Criterion: success metric / test</li>
<li>Dependencies: task IDs</li>
<li>Complexity: low, mid, high<ul>
<li>maps to small / big LLM</li>
<li>can assign multiple models to work on same task with different approaches</li>
</ul>
</li>
<li>Context: added by INSTRUCTOR</li>
<li>State: defined, open, busy, trial, done, fail</li>
<li>StateHistory: List&lt;(state, date, reason, author_agent)&gt;</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Refs:</p>
<ul>
<li><a href="https://github.com/steveyegge/beads">https://github.com/steveyegge/beads</a></li>
<li><a href="https://github.com/joshuadavidthomas/opencode-beads">https://github.com/joshuadavidthomas/opencode-beads</a></li>
<li><a href="https://github.com/Dicklesworthstone/beads_viewer">https://github.com/Dicklesworthstone/beads_viewer</a></li>
<li><a href="https://x.com/doodlestein/status/2013683966495084814">Why decentral task orchestration wins</a></li>
<li>Claude Code released tasks feature (similar to beads)</li>
</ul>
<h4 id="instructor">INSTRUCTOR</h4>
<p>Provides every task with perfect (relevant) Context.</p>
<ul>
<li>NEW: code templates for fresh projects</li>
<li>adds only relevant tools (MCP / CLI) to task context (prevents context bloat)</li>
<li>relevant and version matching documentation for coding tasks<ul>
<li>Coding guidelines based on programming languages / code files involved for the task</li>
<li>General use: official matching version docs / blog posts</li>
<li>Existing code: analyse package dependencies<ul>
<li>exact (version) matching code documentation</li>
<li>source code -&gt; extract public function interfaces with doc strings<ul>
<li>Python: .venv/lib/python3.11/site-packges/$package_name</li>
<li>JS: node_modules/</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Refs:</p>
<ul>
<li><a href="https://github.com/iannuttall/librarian">https://github.com/iannuttall/librarian</a></li>
<li><a href="https://github.com/upstash/context7">https://github.com/upstash/context7</a></li>
<li><a href="https://ref.tools/">https://ref.tools/</a></li>
<li><a href="https://github.com/GlitterKill/sdl-mcp">https://github.com/GlitterKill/sdl-mcp</a></li>
<li><a href="https://x.com/karpathy/status/2021633574089416993">https://x.com/karpathy/status/2021633574089416993</a></li>
<li><a href="https://github.com/JaredStewart/coderlm/tree/main">CodeRLM</a></li>
</ul>
<h2 id="executors">EXECUTORS</h2>
<p>Coding agents working on tasks in parallel - working off the task tree backwards recursively (breadth first, towards the root task - the IDEA).</p>
<h4 id="creator">CREATOR</h4>
<ul>
<li>use LSP server for precise edits based on TASK problem and context<ul>
<li>optimal code exploration</li>
<li>optimal code editing<ul>
<li>use a database of code snippets / functions to save output tokens -&gt; just query with a function signature + natural language description for existing code (<a href="https://seanpedersen.github.io/posts/future-of-programming/">ref</a>)</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="validator">VALIDATOR</h4>
<ul>
<li>validates if CREATOR solved tasks Criterion (test / metric)<ul>
<li>yes: task done</li>
<li>no: retry task with modified context (add failures / learnings)</li>
</ul>
</li>
</ul>
<h4 id="reflector">REFLECTOR</h4>
<ul>
<li>uses REPL / MCP to inspect live vars of code produced by CREATOR</li>
<li>fixes any issues spotted by VALIDATOR</li>
<li>persist learnings in knowledge base for future reference</li>
</ul>
<h2 id="task-life-cycle">TASK Life Cycle</h2>
<p>State: defined, open, busy, trial, done, fail</p>
<ul>
<li>defined: ID, Problem, Criterion, Complexity</li>
<li>open: added Context by INSTRUCTOR</li>
<li>busy: CREATOR is coding</li>
<li>trial: CREATOR finished</li>
<li>VALIDATOR is happy -&gt; done</li>
<li>VALIDATOR is unhappy -&gt; open</li>
<li>VALIDATOR gives up -&gt; fail</li>
</ul>
<p>Typical Project:</p>
<ul>
<li>task 0 (root task) is the IDEA itself and is validated at last when all subtasks are done<br>the first task to tackle is the last task we planned out:</li>
<li>setup coding environment for new project</li>
</ul>
<p>User Interface:</p>
<ul>
<li>saves chats as text files (easy to inspect whole context)</li>
<li>displays (token usage/context limit) in current session</li>
</ul>
<h2 id="gui-ux">GUI UX</h2>
<p>Spawn a webserver that shows current task tree + progress (indicate status for every task). Lets me also viel taks details (context, selected model etc).</p>
<h2 id="more-ideas">More Ideas</h2>
<p>A coding agent could massively save output tokens by outputting compact references to reusable code templates instead of writing everything token by token (and the code registry DB could be <a href="/posts/future-of-programming">optimized by the whole community</a>).<br>A tool would then expand those references into full boilerplate, functions, classes, tests, configs, or scaffolding. The best version is a typed, versioned, parameterized template/macro registry database.<br>The LLM becomes the planner and selector, while tools handle expansion, insertion, formatting, and validation.</p>
<p>new:<br>when agent sees multiple solutions explore in parallel</p>
<p>Minimal additions that would move it closer to “optimal”:<br>Add a GATEKEEPER (cheap, fast) before GENERAL<br>Input: idea + rough scope<br>Output: route → instructor-only | partial orchestra | full orchestra</p>
<p>Add post‑mortem synthesis (lightweight)<br>After task 0 validation:</p>
<p>what task boundaries were wrong?<br>what context was unnecessary?<br>what should become a template?<br>These don’t add conceptual weight—they reduce entropy over time.</p>
<h2 id="references">References</h2>
<p>Update: latest feature workflows of claude code is similar - it adds a workflow language that allows to explicitely plan parallel execution flows of agents.</p>
<p>Existing Agents:</p>
<ul>
<li><p><a href="https://www.mihaileric.com/The-Emperor-Has-No-Clothes/">https://www.mihaileric.com/The-Emperor-Has-No-Clothes/</a></p>
<ul>
<li><a href="https://news.ycombinator.com/item?id=46545620">https://news.ycombinator.com/item?id=46545620</a></li>
</ul>
</li>
<li><p><a href="https://pi.dev/">https://pi.dev/</a></p>
<ul>
<li><a href="https://mariozechner.at/posts/2025-11-30-pi-coding-agent/">https://mariozechner.at/posts/2025-11-30-pi-coding-agent/</a></li>
<li><a href="https://news.ycombinator.com/item?id=46844822">https://news.ycombinator.com/item?id=46844822</a></li>
<li><a href="https://lucumr.pocoo.org/2026/1/31/pi/">https://lucumr.pocoo.org/2026/1/31/pi/</a></li>
<li><a href="https://rpiv-pi.com/">https://rpiv-pi.com/</a></li>
</ul>
</li>
<li><p><a href="https://github.com/openai/codex">https://github.com/openai/codex</a></p>
</li>
<li><p><a href="https://github.com/jacobsparts/agentlib">https://github.com/jacobsparts/agentlib</a> - really cool project - drops the agent directly into Python repl</p>
</li>
<li><p><a href="https://agent-flywheel.com/flywheel">https://agent-flywheel.com/flywheel</a><br><a href="https://gist.github.com/dollspace-gay/d8d3bc3ecf4188df049d7a4726bb2a00">Verified Spec-Driven Development</a></p>
</li>
<li><p>replace claude code with cheaper + faster alternatives</p>
<ul>
<li><a href="https://steipete.me/posts/2025/self-hosting-ai-models">https://steipete.me/posts/2025/self-hosting-ai-models</a></li>
<li><a href="https://www.builder.io/blog/opencode-vs-claude-code">https://www.builder.io/blog/opencode-vs-claude-code</a></li>
<li><a href="https://www.reddit.com/r/LocalLLaMA/comments/1o22iwo/ideal_cost_effective_agentic_coding_membership/">https://www.reddit.com/r/LocalLLaMA/comments/1o22iwo/ideal_cost_effective_agentic_coding_membership/</a></li>
<li><a href="https://dev.to/karthidreamr/why-i-ditched-chatgpt-and-claude-for-opencode-a-smarter-cheaper-way-to-build-ai-agents-2a5h">https://dev.to/karthidreamr/why-i-ditched-chatgpt-and-claude-for-opencode-a-smarter-cheaper-way-to-build-ai-agents-2a5h</a></li>
</ul>
</li>
</ul>
<p>Eval extending existing open-source coding agents TUI or GUI apps:</p>
<ul>
<li><a href="https://github.com/wandb/catnip">https://github.com/wandb/catnip</a></li>
<li><a href="https://github.com/block/goose">https://github.com/block/goose</a> seems to be really close to my vision - check it out</li>
<li><a href="https://thebob.dev/ai/tools/productivity/2025/10/31/why-we-built-claude-os-and-what-it-actually-is/">https://thebob.dev/ai/tools/productivity/2025/10/31/why-we-built-claude-os-and-what-it-actually-is/</a></li>
<li><a href="https://anandchowdhary.com/blog/2025/running-claude-code-in-a-loop">https://anandchowdhary.com/blog/2025/running-claude-code-in-a-loop</a></li>
<li><a href="https://ampcode.com/">https://ampcode.com/</a></li>
</ul>
<p>Fast LLMs:<br>groq.com, <a href="https://www.inceptionlabs.ai/">https://www.inceptionlabs.ai/</a>, <a href="https://chat.z.ai/">https://chat.z.ai/</a>, <a href="https://huggingface.co/chat/">https://huggingface.co/chat/</a></p>
<ul>
<li><a href="https://github.com/bmad-code-org/BMAD-METHOD">https://github.com/bmad-code-org/BMAD-METHOD</a></li>
<li><a href="https://xr0am.substack.com/p/what-ralph-wiggum-loops-are-missing">https://xr0am.substack.com/p/what-ralph-wiggum-loops-are-missing</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a> <a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Decentral Software</title>
      <link>https://seanpedersen.github.io/posts/decentral-software</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/decentral-software</guid>
      <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>We need decentral software to live in peace and freedom. Decentral systems are immune to censorship, harder to manipulate by single actors and work offline.</p>
<p>Projects like Bitcoin and IPFS are first steps into a better future.</p>
<p>We need cryptographic user identities to verify it is us and we want to own our data (no more locking up data in foreign servers).</p>
<p>Marko Polo: broadcast your content and collab on projects P2P.</p>
<p>Interplanetary Memory System : use file embeddings to discover content instead of brittle crypto hashes (IPMS is a decentral search engine - Anyone can run a node and contribute content. Embeddings are verified by peers.)</p>
<p>Interplanetary Trust System: Rate and discover services based on your local peers you trust -&gt; learn which services your peers (and peers of peers) praise or dislike.</p>
<p>Interplanetary Messaging System: A decentral, secure <a href="/posts/messenger/">messenger</a> that works.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.bittorrent.com/">BitTorrent</a></li>
<li><a href="https://tribler.org/">https://tribler.org/</a></li>
<li><a href="https://bitcoin.org/bitcoin.pdf">Bitcoin</a></li>
<li><a href="https://ipfs.tech/">IPFS</a></li>
<li><a href="https://github.com/syncthing/syncthing">SyncThing</a></li>
<li><a href="https://github.com/localsend/localsend">LocalSend</a></li>
<li><a href="https://satproto.org/">https://satproto.org/</a> - <a href="https://news.ycombinator.com/item?id=47344548">HN Discussion</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Future</title>
      <link>https://seanpedersen.github.io/posts/future</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/future</guid>
      <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>Exciting times lay ahead. Some predictiions and perspectives of mine.</p>
<h2 id="certain-developments">Certain Developments</h2>
<p>AI will continue to reshape how we work, increasing leverage of the (creative) individual.</p>
<p>computer goes faster -&gt; LLM become cheaper and faster</p>
<p>everyone will have LLM powered <a href="/posts/personal-assistant">personal agent</a> -&gt; value lies in providing connectors to services (websites) for the agents to use (<a href="https://webmcp.dev/">WebMCP</a>)</p>
<p>Software: will be solved for all verifiable domains -&gt; taste and data rule after<br>Image + Video: Image / Video / TV show production will be solved. -&gt; again value lies in taste.</p>
<p>Augmented Reality glasses will gain more and more adoption -&gt; enabling seemless digitalization.</p>
<p>robots: rate of progress unknown -&gt; but certain will be huge impact on economy and geo-politics (warfare)</p>
<p>Space Exploration</p>
<ul>
<li>companies (rich individuals) will continue to push into space -&gt; building new nation like entities</li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Retrieval Augmented Generation</title>
      <link>https://seanpedersen.github.io/posts/rag</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/rag</guid>
      <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>ML</category>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>RAG works by augmenting the context window of an LLM with text relevant to the user&#39;s query to provide a useful response (reduce hallucinations). Thus if one wants to master RAG, one has to master <a href="/posts/search-is-hard">search</a>.</p>
<h2 id="rag-approaches">RAG Approaches</h2>
<ul>
<li>Simple RAG: basic keyword search / semantic search</li>
<li>Complex RAG: advanced chunking (e.g. late-interaction / enrich with LLM -&gt; infer questions a chunk can answer or summarize a long document) semantic search</li>
<li>Graph RAG: construct knowledge graph to uncover hidden (multi-step) connections for complex queries (how did x evolve over time? how does y compare to z? explain u in terms of v, etc.)</li>
<li>Agentic RAG:<ul>
<li>let LLM create search queries based on user query</li>
<li>let LLM make final selection from result candidates</li>
</ul>
</li>
</ul>
<h2 id="granularity-problem">Granularity Problem</h2>
<p>Different queries require different granularity (number of chunks provided as context) -&gt; who is the CEO of Apple vs summarize the bible</p>
<p><strong>Solution:</strong><br>relevant segment extraction (RSE) - <a href="https://d-star.ai/dynamic-retrieval-granularity">https://d-star.ai/dynamic-retrieval-granularity</a></p>
<p>just use paragraph-sized chunks (~200 tokens), prepend global document context (title, section) -&gt; embed and store position in document (line number / page position)</p>
<p>embed query -&gt; find nearest chunks -&gt; compute continuous chunk segments in documents</p>
<h2 id="hallucination-problem">Hallucination Problem</h2>
<p>How to reduce hallucinations? How to increase the response rate of &quot;I do not know based on available information&quot; -&gt; search needs to be capable to indicate high uncertainty / unrelated results only -&gt; leading to I do not know response</p>
<p>Fact check using semantic search and fine-tuned LLM: <a href="https://github.com/stanford-oval/WikiChat">https://github.com/stanford-oval/WikiChat</a></p>
<h2 id="rag-pipeline">RAG Pipeline</h2>
<p>Based on user input query -&gt; use LLM to generate relevant search queries -&gt; use semantic search to find cadidates (below a similarity threshold) -&gt; Reranker to filter (fast) -&gt; use LLM (slow) to filter for relevancy -&gt; use filtered results to generate final answer</p>
<h3 id="key-points">Key Points</h3>
<ul>
<li>agentic search - agent decides how to search: hybrid search (semantic + keyword), custom SQL query, etc.<ul>
<li>LLM should transform user query before search, as user query will not always be the right format to answer the question it entails. f.e. what are the trends in tech? -&gt; is very abstract, LLM can transform it into a format that will match the answer document semantics</li>
</ul>
</li>
<li><a href="/posts/search-is-hard#query-expansion">query expansion</a></li>
<li><a href="/posts/search-is-hard#granularity-chunking">embedding chunking strategy</a></li>
<li>graph-enhanced retrieval (supermemory etc.)</li>
<li>domain specific benchmark (use powerful commercial LLM&#39;s to eval answers of local LLM&#39;s) to work data driven</li>
</ul>
<p>UX:</p>
<ul>
<li>show progress (searching / filtering / analyzing)</li>
<li>show user citations (used results)</li>
</ul>
<h2 id="rag-vs-fine-tuning">RAG vs Fine-Tuning</h2>
<p>When to pick what:</p>
<div class="table-wrapper"><table><thead><th>Dimension</th><th>RAG</th><th>Fine-Tuning</th></thead><tbody><tr><td>Corpus volatility</td><td>Fast changing (docs added daily)</td><td>Static / slow changing</td></tr><tr><td>Knowledge type</td><td>Factual lookup, citations needed</td><td>Style, tone, format, reasoning patterns</td></tr><tr><td>Traceability</td><td>Sources are visible to user</td><td>Black-box, hard to attribute</td></tr><tr><td>Update cost</td><td>Re-index (cheap, minutes)</td><td>Re-train (expensive, hours-days)</td></tr><tr><td>Hallucination risk</td><td>Lower (grounded in retrieved text)</td><td>Higher (memorized, can drift)</td></tr><tr><td>Cold start</td><td>Works with zero training data</td><td>Needs labeled examples</td></tr><tr><td>Latency</td><td>Higher (search + LLM)</td><td>Lower (single forward pass)</td></tr><tr><td>Best for</td><td>Q&amp;A over private docs, support, news</td><td>Domain language, niche jargon, structured output</td></tr></tbody></table></div><p>Use <strong>RAG</strong> when:</p>
<ul>
<li>corpus changes faster than you can retrain</li>
<li>citations / source attribution are required (legal, medical, support)</li>
<li>knowledge is too large to fit in weights or context</li>
<li>you need to gate access (per-user permissions on documents)</li>
</ul>
<p>Use <strong>Fine-Tuning</strong> when:</p>
<ul>
<li>corpus is small, stable and dense with niche language (medical codes, legal jargon, internal product names)</li>
<li>you need a specific output format / style the base model fails at</li>
<li>latency budget is tight (no time for retrieval)</li>
<li>task is reasoning-heavy and pattern-based, not fact-based</li>
</ul>
<p><strong>Hybrid (usually the right answer for production):</strong></p>
<ul>
<li>fine-tune embedding model on domain pairs to improve retrieval quality</li>
<li>fine-tune the generator LLM for output format + citation behavior</li>
<li>keep RAG for the actual facts -&gt; get the best of both</li>
<li><a href="https://x.com/_avichawla/status/1964939267823775997">https://x.com/_avichawla/status/1964939267823775997</a></li>
</ul>
<h2 id="local-rag">Local RAG</h2>
<p>Use dspy to optimise system prompts.</p>
<p>Existing Solutions:</p>
<ul>
<li><a href="https://github.com/Cinnamon/kotaemon">https://github.com/Cinnamon/kotaemon</a>: Chat with PDFs</li>
<li><a href="https://github.com/weaviate/Verba">https://github.com/weaviate/Verba</a>: Chat with PDFs</li>
<li><a href="https://www.onyx.app/">https://www.onyx.app/</a>: Integrated solution connecting to many clouds</li>
<li><a href="https://github.com/stanford-oval/WikiChat">https://github.com/stanford-oval/WikiChat</a>: Minimal hallucinations</li>
<li><a href="https://github.com/D-Star-AI/dsRAG">https://github.com/D-Star-AI/dsRAG</a>: Advanced chunking for text</li>
<li><a href="https://github.com/weaviate/elysia">https://github.com/weaviate/elysia</a>: Agentic RAG (can create custom DB queries + semantic search etc.)</li>
<li><a href="https://github.com/HKUDS/LightRAG">https://github.com/HKUDS/LightRAG</a></li>
<li><a href="https://github.com/infiniflow/ragflow">https://github.com/infiniflow/ragflow</a></li>
<li><a href="https://github.com/langgenius/dify">https://github.com/langgenius/dify</a></li>
<li><a href="https://github.com/datastax/ragstack-ai">https://github.com/datastax/ragstack-ai</a></li>
<li><a href="https://github.com/neuml/txtai">https://github.com/neuml/txtai</a></li>
<li><a href="https://github.com/ItzCrazyKns/Perplexica">Perplexica</a></li>
<li>Eliminates RAG: <a href="https://github.com/microsoft/KBLaM">https://github.com/microsoft/KBLaM</a></li>
</ul>
<p>Retrieval:</p>
<ul>
<li><a href="https://github.com/VectifyAI/PageIndex">https://github.com/VectifyAI/PageIndex</a></li>
<li><a href="https://github.com/yichuan-w/LEANN">https://github.com/yichuan-w/LEANN</a></li>
</ul>
<p>Memory Systems:</p>
<ul>
<li><a href="https://github.com/campfirein/cipher">https://github.com/campfirein/cipher</a></li>
<li><a href="https://github.com/supermemoryai/supermemory">https://github.com/supermemoryai/supermemory</a></li>
<li><a href="https://github.com/getzep/graphiti">https://github.com/getzep/graphiti</a></li>
</ul>
<h2 id="benchmarks">Benchmarks</h2>
<p>You can not improve, what you can not see - running evals for your RAG apps is crucial to ship useful products (bad example: <a href="https://github.com/weaviate/elysia/issues/48#issuecomment-3286114697">Elysium by weaviate</a>).</p>
<h3 id="eval-the-pipeline-in-stages">Eval the pipeline in stages</h3>
<p>A RAG system has two failure modes that compound: bad retrieval and bad generation. Eval them separately or you will not know what to fix.</p>
<p><strong>1. Retrieval metrics</strong> (does the right chunk make it into context?)</p>
<ul>
<li><strong>Recall@k</strong>: out of the top-k retrieved chunks, did at least one ground-truth chunk appear? (most important - if the answer is not in context, generation can not save you)</li>
<li><strong>MRR (Mean Reciprocal Rank)</strong>: 1 / rank of first relevant chunk - rewards putting the right chunk near the top</li>
<li><strong>nDCG@k</strong>: rewards ranking quality when there are multiple relevant chunks of varying importance</li>
<li><strong>Context precision</strong>: fraction of retrieved chunks that are actually relevant - low precision wastes tokens and confuses the LLM</li>
</ul>
<p><strong>2. Generation metrics</strong> (given good context, is the answer good?)</p>
<ul>
<li><strong>Faithfulness / groundedness</strong>: every claim in the answer is supported by the retrieved context (catches hallucinations)</li>
<li><strong>Answer relevancy</strong>: answer addresses the actual question, not a tangent</li>
<li><strong>Citation accuracy</strong>: do the cited chunks actually contain the cited claim?</li>
<li><strong>Answer correctness</strong>: matches a gold-standard answer (semantic similarity, not exact match)</li>
</ul>
<p><strong>3. End-to-end metrics</strong></p>
<ul>
<li><strong>Task success rate</strong>: did the user get what they needed? (the only metric that really matters)</li>
<li><strong>&quot;I do not know&quot; rate</strong>: how often does the system correctly refuse vs hallucinate when no answer exists - test with adversarial out-of-corpus queries</li>
<li><strong>Latency p50 / p95</strong>: real users care</li>
<li><strong>Cost per query</strong>: tokens in + tokens out + embedding + reranker calls</li>
</ul>
<h3 id="building-a-domain-benchmark">Building a domain benchmark</h3>
<p>Generic benchmarks (BEIR, MTEB) tell you about general retrieval quality. They do not predict performance on your private corpus. Always build a domain eval set:</p>
<ol>
<li><strong>Collect 50-200 real queries</strong> from logs, support tickets, or user interviews - synthetic queries miss the long tail of how users actually phrase things</li>
<li><strong>Generate ground truth</strong> - for each query annotate (a) which chunks contain the answer (b) the gold answer text. Use a strong LLM (Claude Opus, GPT-5) to draft, human to verify</li>
<li><strong>Cover edge cases</strong> - multi-hop questions, queries with no answer in corpus, ambiguous queries, queries that need recent docs</li>
<li><strong>Freeze the set</strong> - if you keep changing it you can not compare runs over time</li>
<li><strong>Track regressions per query</strong> - aggregate scores hide that v2 fixed 5 queries but broke 3 others</li>
</ol>
<h3 id="llm-as-judge">LLM-as-judge</h3>
<p>For groundedness, relevancy, correctness - use a strong LLM to score outputs of your (cheaper, smaller) production LLM. Cheap, scales, correlates with human judgment when prompted well.</p>
<p>Caveats:</p>
<ul>
<li>judge model bias (LLMs prefer their own family&#39;s outputs)</li>
<li>ask for binary judgments + reason, not 1-10 scores (more reliable)</li>
<li>spot-check with humans on 10-20% of cases to keep the judge honest</li>
</ul>
<h3 id="tools">Tools</h3>
<ul>
<li><a href="https://github.com/VectifyAI/Mafin2.5-FinanceBench">FinanceBench</a> - complex multi-hop finance analysis</li>
<li><a href="https://github.com/onyx-dot-app/EnterpriseRAG-Bench">EnterpriseRAG-Bench</a> - simulates a company</li>
<li><a href="https://github.com/D-Star-AI/KITE/tree/main">KITE</a> - retrieval benchmark</li>
<li><a href="https://github.com/explodinggradients/ragas">Ragas</a> - faithfulness, answer relevancy, context precision/recall out of the box</li>
<li><a href="https://github.com/truera/trulens">TruLens</a> - feedback functions and tracing</li>
<li><a href="https://github.com/confident-ai/deepeval">DeepEval</a> - pytest-style RAG evals</li>
<li><a href="https://github.com/promptfoo/promptfoo">promptfoo</a> - eval harness with regression tracking</li>
<li>run evals in CI - block PRs that regress recall@k or faithfulness beyond a threshold</li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://arxiv.org/abs/2311.11944">https://arxiv.org/abs/2311.11944</a> (RAG benchmark survey)</li>
<li><a href="https://arxiv.org/abs/2509.11552">https://arxiv.org/abs/2509.11552</a></li>
<li><a href="https://d-star.ai/solving-the-out-of-context-chunk-problem-for-rag">https://d-star.ai/solving-the-out-of-context-chunk-problem-for-rag</a></li>
<li><a href="https://d-star.ai/dynamic-retrieval-granularity">https://d-star.ai/dynamic-retrieval-granularity</a></li>
<li><a href="https://maven.com/p/acfa67/improving-rag-embedding-models-representation-learning">https://maven.com/p/acfa67/improving-rag-embedding-models-representation-learning</a></li>
<li><a href="https://softwaredoug.com/blog/2025/12/09/rag-users-want-affordances-not-vectors">https://softwaredoug.com/blog/2025/12/09/rag-users-want-affordances-not-vectors</a></li>
<li><a href="https://mksg.lu/blog/gemini-rag-cloudflare-workers">https://mksg.lu/blog/gemini-rag-cloudflare-workers</a></li>
<li><a href="https://www.kapa.ai/blog/how-we-prune-rag-context">https://www.kapa.ai/blog/how-we-prune-rag-context</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#ML">#ML</a> <a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Messenger</title>
      <link>https://seanpedersen.github.io/posts/messenger</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/messenger</guid>
      <pubDate>Wed, 25 Feb 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>Humanity is in need of a fun to use, secure and decentral messenger.</p>
<ul>
<li>User identity can be tied to email (for account recovery)</li>
<li>Decentralized (device to device works) + federated (optional servers help make the network go fast)</li>
<li>E2EE message content (msg, sticker, etc.) + metadata (who msgs whom)</li>
<li>Connect (share keys) by scanning QR Code - “Invite link” fallback</li>
<li>Thick client (user keeps message history - default is 2 months) + thin server (just relay messages)</li>
<li>Use Rust / Erlang for server</li>
<li>Default: use internet, fallback: Wi-Fi Mesh; Bluetooth (like bitchat)</li>
</ul>
<p>Chat Features (Telegram has best chat UX):</p>
<ul>
<li>group chats</li>
<li>file transfer</li>
<li>stickers</li>
</ul>
<p>Account:</p>
<ul>
<li>public key</li>
<li>username</li>
<li>verified contacts</li>
</ul>
<p>Matrix drawbacks:</p>
<ul>
<li>Olm/Megolm does not offer forward secrecy for group messaging</li>
<li>Olm/Megolm does ensure end-to-end encryption for message data, but not for metadata.</li>
<li>Federation makes it challenging to be GDPR compliant</li>
<li>Synapse is very heavy, other implementations are less production ready</li>
<li>For better or worse, the matrix foundation is under UK jurisdiction.</li>
</ul>
<h2 id="existing-chat-shitshow">Existing Chat Shitshow</h2>
<p>Whatsapp and Telegram are security nightmares. WA being centralized and has no metadata encryption. Telegram is centralized and has no encryption by default.</p>
<ul>
<li><a href="https://signal.org/">Signal</a> has best encryption but is centralized -&gt; trust me bro mentality.</li>
<li><a href="https://matrix.org/">Matrix</a> has horrible UX and no metadata encryption.</li>
<li>Berty chat based on IPFS <a href="https://berty.tech/messenger/">https://berty.tech/messenger/</a></li>
<li><a href="https://bitchat.free/">Bitchat</a>: P2P bluetooth</li>
<li><a href="https://git.jami.net/savoirfairelinux">Jami</a>: P2P, <a href="https://jami.net/">https://jami.net/</a></li>
<li><a href="https://www.mindtheclub.com/white-paper.html">https://www.mindtheclub.com/white-paper.html</a></li>
</ul>
<h2 id="mls-secure-group-messaging">MLS (secure group messaging)</h2>
<p><strong>MLS = a standardized group key agreement + encryption protocol</strong><br />
(RFC 9420, finalized 2023)</p>
<blockquote><p class="quote-line">Secure group messaging with <strong>forward secrecy</strong>, <strong>post-compromise security</strong>, and <strong>efficient membership changes</strong>.</p>
</blockquote><p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Linux Desktop</title>
      <link>https://seanpedersen.github.io/posts/linux-desktop</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/linux-desktop</guid>
      <pubDate>Wed, 11 Feb 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>My choice: <a href="https://cachyos.org/">CachyOS</a> (<a href="https://archlinux.org/">Arch Linux</a>) with GNOME DE</p>
<ul>
<li>CachyOS is tweaked for performance, has a GUI installer + easy disk encryption setup</li>
<li>GNOME looks shiny and can easily be stripped down to avoid bloat</li>
</ul>
<h2 id="awesome-software">Awesome Software</h2>
<p>File Manager:</p>
<ul>
<li><a href="https://wiki.archlinux.org/title/Thunar">Thunar</a>: very lightweight 50MB RAM</li>
<li><a href="https://apps.kde.org/dolphin/">Dolphin</a>: best feature set<ul>
<li>supports showing dir size bytes</li>
<li>supports sftp (ssh remote access)</li>
</ul>
</li>
<li>PCManFM</li>
</ul>
<p>Code Editor:</p>
<ul>
<li><a href="https://zed.dev/">Zed</a>: fast + lightweight (similar to VS Code)</li>
<li><a href="https://github.com/SeanPedersen/Marko">Marko</a>: WYSIWYG markdown editor</li>
</ul>
<p>Media Player:</p>
<ul>
<li>VLC</li>
<li>mpv</li>
</ul>
<p>PW Manager:</p>
<ul>
<li>KeePassXC</li>
</ul>
<p>Terminal:</p>
<ul>
<li><a href="https://ghostty.org/">ghostty</a>: fast</li>
<li><a href="https://github.com/Guake/guake">guake</a> (drop down terminal)</li>
</ul>
<p>Shell:</p>
<ul>
<li>ZSH + <a href="https://github.com/SeanPedersen/zeal">ZEAL</a></li>
</ul>
<p>Process Monitor:</p>
<ul>
<li>NeoHtop / <a href="https://github.com/SeanPedersen/neop">Neop</a> (my fork)</li>
<li><a href="https://missioncenter.io/">Mission Center</a></li>
<li><a href="https://github.com/nicolargo/glances">Glances</a></li>
</ul>
<p>Useful Daemons:</p>
<ul>
<li><a href="https://syncthing.net/">Syncthing</a></li>
<li><a href="/posts/ipfs">IPFS</a></li>
</ul>
<p>Tweaks &amp; more:</p>
<ul>
<li><a href="https://gitlab.com/ananicy-cpp/ananicy-cpp">ananicy-cpp</a>: prevents system slow down on high disk usage (CachyOS ships with it)</li>
<li><a href="https://openzfs.org/wiki/Main_Page">OpenZFS</a>: durable file system with useful features</li>
</ul>
<h2 id="honorable-mentions">Honorable Mentions</h2>
<p>Distros:</p>
<ul>
<li><a href="https://www.fedoraproject.org/workstation/">Fedora</a><ul>
<li><a href="https://nobaraproject.org/">Nobara</a> (optimized for gaming / streaming)</li>
</ul>
</li>
<li>Debian (solid)</li>
<li>Ubuntu Server (solid)</li>
</ul>
<p>Desktop Envs:</p>
<ul>
<li>KDE Plasma</li>
<li>HyprLand</li>
<li>XFCE</li>
</ul>
<h2 id="dishonorable-mentions">Dishonorable Mentions</h2>
<p>Many GNOME apps are RAM hogs while providing little functionality, I recommend to uninstall: nautilus, gnome-software, gnome-contacts, gnome-terminal<br>Avoid oh-my-zsh it is bloated and slow.<br>Budgie DE is a buggy shit show.</p>
<h2 id="to-try">TO TRY</h2>
<ul>
<li>XFCE: promising low resource DE (though no wayland support yet)</li>
<li>NixOS</li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>InterPlanetary File System</title>
      <link>https://seanpedersen.github.io/posts/ipfs</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/ipfs</guid>
      <pubDate>Tue, 10 Feb 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>privacy</category>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>IPFS is a content based decentralized file system powered by Merkle DAG (similar to git) - allowing for local networking between nodes (separate from the internet). This technology is revolutionary and the key to a digital future with more freedom and privacy.</p>
<p>The IPFS protocol addresses content by what it is (a cryptographic hash - named CID), not where it is (like http), so the same content can be fetched from any peer that has it. This makes content immutable, cacheable and available offline or over local networks once retrieved.</p>
<p>The IPNS protocol provides a fixed IPNS name with a mutable pointer to an IPFS CID, allowing the referenced content (CID) to change over time while the IPNS name stays the same (similar to http links).</p>
<p>Install <a href="https://docs.ipfs.tech/install/ipfs-desktop/#install-instructions">IPFS Desktop</a></p>
<p>IPFS Browser Extension (so ipfs:// and ipns:// work using your IPFS node):</p>
<ul>
<li><a href="https://chromewebstore.google.com/detail/ipfs-companion">Chrome</a></li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/ipfs-companion/">Firefox</a></li>
</ul>
<h2 id="publishing-static-website">Publishing Static Website</h2>
<p>Configure OUT_DIR (should contain your index.html) and IPNS_KEY (an id for your website).</p>
<pre><code>#!/usr/bin/env sh
set -e

OUT_DIR=&quot;out/&quot;
IPNS_KEY=&quot;your-website-id&quot;

# Create IPNS key if missing
if ! ipfs key list | grep -q &quot;$IPNS_KEY&quot;; then
  echo &quot;🔑 Creating IPNS key: $IPNS_KEY&quot;
  ipfs key gen &quot;$IPNS_KEY&quot;
fi

# Add site to IPFS
echo &quot;📦 Adding $OUT_DIR to IPFS...&quot;
CID=$(ipfs add -r -Q --cid-version=1 --raw-leaves &quot;$OUT_DIR&quot;)
echo &quot;✅ CID: $CID&quot;
echo &quot;🌐 Direct IPFS link (works offline):&quot;
echo &quot;http://ipfs.io/ipfs/$CID&quot;

# Publish to IPNS
echo &quot;🔗 Publishing $CID via IPNS key: $IPNS_KEY...&quot;
ipfs name publish --key=&quot;$IPNS_KEY&quot; /ipfs/&quot;$CID&quot;

# Get IPNS hash
IPNS_NAME=$(ipfs key list -l | grep &quot;$IPNS_KEY&quot; | awk &#39;{print $1}&#39;)
echo &quot;🌐 Access your blog via IPNS (stable link - works offline):&quot;
echo &quot;ipns://$IPNS_NAME&quot;
echo &quot;🌐 Access your blog via IPNS gateway (works online even without IPFS installed):&quot;
echo &quot;https://$IPNS_NAME.ipns.dweb.link&quot;
</code></pre><h2 id="decentral-ipns-discovery">Decentral IPNS Discovery</h2>
<p><a href="https://github.com/SeanPedersen/fipsy">Fipsy</a>: Decentral discovery and sharing of content using IPFS. This works in a local network - allowing true decentralized file exchange.</p>
<ul>
<li>Show connected nodes (returns list of $NODE_ID): <code class="language-text">ipfs swarm peers</code></li>
<li>Discover public self IPNS content of node: <code class="language-text">ipfs ls /ipns/$NODE_ID</code></li>
<li>Show index of peer (only there if setup): <code class="language-text">ipfs cat /ipns/$NODE_ID/index.json</code></li>
</ul>
<p>Publish all your IPNS keys as an index (for other peers in your local network to discover):</p>
<pre><code>#!/usr/bin/env sh
set -e

DISCOVERY_DIR=&quot;.ipns-index&quot;

echo &quot;📡 Building IPNS discovery index...&quot;

# Prepare directory
rm -rf &quot;$DISCOVERY_DIR&quot;
mkdir -p &quot;$DISCOVERY_DIR&quot;

# Generate index.json
echo &quot;🧾 Generating index.json...&quot;

echo &#39;{ &quot;ipns&quot;: {&#39; &gt; &quot;$DISCOVERY_DIR/index.json&quot;

FIRST=1
ipfs key list -l | while read -r KEY_ID KEY_NAME; do
  [ &quot;$KEY_NAME&quot; = &quot;self&quot; ] &amp;&amp; continue

  if [ $FIRST -eq 0 ]; then
    echo &#39;,&#39; &gt;&gt; &quot;$DISCOVERY_DIR/index.json&quot;
  fi
  FIRST=0

  printf &#39;  &quot;%s&quot;: &quot;%s&quot;&#39; &quot;$KEY_NAME&quot; &quot;$KEY_ID&quot; &gt;&gt; &quot;$DISCOVERY_DIR/index.json&quot;
done

echo &#39;&#39; &gt;&gt; &quot;$DISCOVERY_DIR/index.json&quot;
echo &#39;} }&#39; &gt;&gt; &quot;$DISCOVERY_DIR/index.json&quot;

# Generate index.html
echo &quot;🌐 Generating index.html...&quot;

cat &gt; &quot;$DISCOVERY_DIR/index.html&quot; &lt;&lt;&#39;EOF&#39;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot;&gt;
  &lt;title&gt;IPNS Index&lt;/title&gt;
  &lt;style&gt;
    body { font-family: sans-serif; padding: 2rem; }
    li { margin: 0.5rem 0; }
    code { background: #eee; padding: 0.2rem 0.4rem; }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1&gt;IPNS Index&lt;/h1&gt;
  &lt;ul&gt;
EOF

ipfs key list -l | while read -r KEY_ID KEY_NAME; do
  [ &quot;$KEY_NAME&quot; = &quot;self&quot; ] &amp;&amp; continue
  echo &quot;    &lt;li&gt;&lt;a href=\&quot;http://ipfs.io/ipns/$KEY_ID\&quot;&gt;$KEY_NAME&lt;/a&gt; &lt;code&gt;$KEY_ID&lt;/code&gt;&lt;/li&gt;&quot; &gt;&gt; &quot;$DISCOVERY_DIR/index.html&quot;
done

cat &gt;&gt; &quot;$DISCOVERY_DIR/index.html&quot; &lt;&lt;&#39;EOF&#39;
  &lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;
EOF

# Add to IPFS
echo &quot;📦 Adding discovery index to IPFS...&quot;
CID=$(ipfs add -r -Q --cid-version=1 --raw-leaves &quot;$OUT_DIR&quot;)
echo &quot;✅ CID: $CID&quot;

# Publish under self
echo &quot;🔗 Publishing discovery index under self...&quot;
ipfs name publish --lifetime=1m /ipfs/&quot;$CID&quot;

echo &quot;🎉 Done!&quot;
echo
echo &quot;🔍 Discoverable via:&quot;
echo &quot;  ipfs ls /ipns/$(ipfs id -f=&#39;&lt;id&gt;&#39;)&quot;
echo &quot;  ipfs cat /ipns/$(ipfs id -f=&#39;&lt;id&gt;&#39;)/index.json&quot;
echo &quot;  http://ipfs.io/ipns/$(ipfs id -f=&#39;&lt;id&gt;&#39;)&quot;
echo &quot;  https://$(ipfs id -f=&#39;&lt;id&gt;&#39;).ipns.dweb.link&quot;
</code></pre><h2 id="more">More</h2>
<ul>
<li><a href="https://github.com/ipfs/kubo">Kubo</a>: Standard IPFS Implementation in Go</li>
<li><a href="https://github.com/ipfs/helia">Helia</a>: TypeScript IPFS Implementation for browsers</li>
<li><a href="https://github.com/Peergos/Peergos">Peergos</a>: A p2p, secure file storage, social network and application protocol</li>
<li><a href="https://berty.tech/features">Berty</a>: p2p, decentral, secure messenger (not yet open-sourced)</li>
<li><a href="https://github.com/dhappy/git-remote-ipfs">Git IPFS bridge</a><ul>
<li><a href="https://discuss.ipfs.tech/t/ipfs-remote-bridge-for-git-version-1-0-0-is-now-available/19897">https://discuss.ipfs.tech/t/ipfs-remote-bridge-for-git-version-1-0-0-is-now-available/19897</a></li>
<li>Alternative: <a href="https://radicle.xyz">https://radicle.xyz</a></li>
</ul>
</li>
<li><a href="https://discuss.ipfs.tech/">IPFS Forum</a></li>
<li><a href="https://ecosystem.ipfs.tech/">IPFS Ecosystem</a> / <a href="https://github.com/ipfs/awesome-ipfs">IPFS Project List</a></li>
<li><a href="https://github.com/ipfs/package-managers#current-ipfs-integrations">Package Manager Integrations</a></li>
<li><a href="https://github.com/ipfs/faq/issues/116">File encryption</a></li>
</ul>
<h2 id="commands">Commands</h2>
<p><strong>Initialize local node in working dir:</strong>  ipfs init</p>
<p><strong>Start long running node process:</strong> ipfs daemon</p>
<p><strong>Add file:</strong> ipfs add $FILE_PATH</p>
<p><strong>Pin file at node:</strong> ipfs pin $FILE_PATH</p>
<p>Show connected nodes (returns list of $NODE_ID): ipfs swarm peers</p>
<p>Discover public self IPNS content of node: ipfs ls /ipns/$NODE_ID</p>
<p>Fetch file from node: ipfs get $CID</p>
<p>Fetch dir from node: ipfs get -r $CID</p>
<p>Publish to public self IPNS: ipfs name publish /ipfs/&quot;$CID&quot;</p>
<p>Publish to IPNS key: ipfs name publish --key=&quot;<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>I</mi><mi>P</mi><mi>N</mi><msub><mi>S</mi><mi>K</mi></msub><mi>E</mi><mi>Y</mi><mi mathvariant="normal">"</mi><mo>/</mo><mi>i</mi><mi>p</mi><mi>f</mi><mi>s</mi><mo>/</mo><mi mathvariant="normal">"</mi></math>CID&quot;</p>
<p>Update self IPNS of peer: ipfs name resolve --nocache /ipns/$NODE_ID</p>
<p>Resolve IPNS name to CID: ipfs resolve -r $IPNS_NAME</p>
<p>Publish static website: <a href="http://docs.ipfs.tech.ipns.localhost:8080/how-to/websites-on-ipfs/multipage-website">http://docs.ipfs.tech.ipns.localhost:8080/how-to/websites-on-ipfs/multipage-website</a></p>
<p><strong>Node WebUI:</strong> <a href="http://localhost:5001/webui">http://localhost:5001/webui</a></p>
<p><strong>Synchronize Pins across distributed daemons:</strong> <a href="https://github.com/ipfs/ipfs-cluster">https://github.com/ipfs/ipfs-cluster</a></p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://youtu.be/HUVmypx9HGI">https://youtu.be/HUVmypx9HGI</a></li>
<li><a href="https://wiki.archlinux.org/index.php/IPFS">https://wiki.archlinux.org/index.php/IPFS</a></li>
<li><a href="https://github.com/ipfs/roadmap#2019-epics">https://github.com/ipfs/roadmap#2019-epics</a></li>
<li><a href="https://youtu.be/GJ2980DWdyc?t=264">https://youtu.be/GJ2980DWdyc?t=264</a></li>
<li><a href="https://decentralized.blog/ten-terrible-attempts-to-make-ipfs-human-friendly.html">https://decentralized.blog/ten-terrible-attempts-to-make-ipfs-human-friendly.html</a></li>
<li><a href="https://www.lumera.io/wp-content/uploads/2022/11/946341062907548779pastel_storage_layer_yellow_paper.pdf">Lumera: Alternative to IPFS</a></li>
</ul>
<p>QUESTIONS:</p>
<ul>
<li>Can I replace SyncThing with IPFS?</li>
<li>Can I run an IPFS http proxy that automatically replaces HTTP requests with local IPFS response if available (basically an IPFS cache for HTTP, so stuff works offline in my local net)? Basically I want a daemon that caches HTTP/S downloads in IPFS and will use the cache for future HTTP/S requests with same URL.</li>
<li>Can we use IPFS to create a content-based package manager to lock down dependencies accurately?</li>
<li>IPFS over local bluetooth / wi-fi networks?</li>
<li>Can I run a website discoverable by anyone in my local network via IPFS? Yes via IPNS self - see: Publish your IPNS name keys in Self Index.</li>
<li>Can we host open-source code on IPFS similar to Radicle?</li>
<li>Why does <a href="http://ipfs.io/ipfs/">http://ipfs.io/ipfs/</a> work better (offline) than ipfs:// -&gt; ipfs.io usage does not destory relative links in websites... WTF why does ipfs:// destroy them</li>
</ul>
<p>TODO:</p>
<ul>
<li>[DONE] Make the IPNS self a standard to discover local IPNS content via index.html and index.json</li>
<li>[DONE] Create an app that helps you publish websites and browse from local peers -&gt; <a href="https://github.com/SeanPedersen/fipsy">Fipsy</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#privacy">#privacy</a> <a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Absurditäten unserer Gesellschaft</title>
      <link>https://seanpedersen.github.io/posts/absurd-society</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/absurd-society</guid>
      <pubDate>Tue, 10 Feb 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Ein paar Dinge die in der BRD komplett falsch laufen aber als normal erachtet werden.</p>
<ul>
<li><p>&quot;Absolute Geldstrafen für Ordnungswidrigkeiten und Straftaten&quot; - sind absolut ungerecht. Reiche Menschen werden nicht abgeschreckt und arme Menschen unverhältnismäßig bestraft. Nur relative Geldstrafen die sich prozentual am Einkommen des zu Bestrafenen errechnen, haben für alle Einkommensschichten den gleichen abschreckenden Effekt (s. Finnland wo es so schon gut funktioniert).</p>
</li>
<li><p>&quot;Ungleichheit vor Gericht&quot; - Die finanziellen Möglichkeiten eines Angeklagten haben leider einen erheblichen Einfluss auf das Urteil. Die Situation ist ähnlich wie mit privaten und gesetzlichten Krankenkassen. Wer sich mehr Zeit von erfahrenen Anwälten leisten kann, hat schlichtweg bessere Chancen vor Gericht. Eine pot. Lösung wäre ein System, das nur noch aus gesetzlichen Pflichtverteidigern besteht (Ich habe noch nicht viel über mögliche bessere Alternativen nachgedacht).</p>
</li>
<li><p>&quot;Monopole zu dulden für kritische Infrastruktur wie öffentliche Verkehrsmittel.&quot;</p>
<ul>
<li>Kein Anreiz für den Monopolisten guten Service zu bieten -&gt; kritische Infrastruktur sollte vom Staat betrieben werden und von den Bürgern durch Wahlen geformt werden.</li>
<li>Es kann nicht wahr sein dass die Nutzung von öffentlichen Verkehrsmitteln Geld kostet. Sie sollten über Steuern finanziert werden und damit Schwarzfahrer wie Ticket-Kontrolleure verschwinden. Es gehen jedes Jahr Menschen ins Gefängnis weil sie ihr Ticket nicht bezahlen können - ein absolutes Unding. Ich empfinde nichts als Verachtung für jeden Menschen der sich als Kontrolleur, Polizist, Justizvollzugsbeamter oder Richter an diesem unmenschlichen System beteiligt.</li>
</ul>
</li>
<li><p>&quot;Die Kriminalisierung von Drogen.&quot; - verschwendet wertvolle Polizeiarbeit, verpestet die Umwelt, lässt potentielle Steuergelder liegen und treibt Konsumenten in echte kriminelle Kreise. Alle Drogen sollen nur in Apotheken oder extra Abgabestellen für Volljährige verfügbar sein - begleitet mit Präventionsarbeit und Hilfsangeboten für Abhängige. Alkohol und Tabak sind ebenso Drogen wie jede andere und sollten nicht in Lebensmittelgeschäften verfügbar sein.</p>
</li>
<li><p>&quot;Toleranz von nachweislich toxischen Online-Plattformen wie TikTok, YouTube Shorts, Instagram und co.&quot; Jegliche Art von endlos Feeds in digitalen Apps gehört verboten. Tech-Unternehmen machen bereits Kinder zu abhängigen unmündigen Konsumenten. (Selbst ein Verbot bekämpft lediglich das Sympton, die Ursache ist die Normalisierung des digitalen Überwachungskapitalismus durch unstillbare Gier nach Profit und Macht.)</p>
</li>
<li><p>&quot;Die Zweiklassengesellschaft der Privat- und Gesetzlichversicherten.&quot; Der Zugang zum Gesundheitssystem darf nicht eine Frage des Geldes sein. Schafft die Privatkasse ab.</p>
</li>
<li><p>&quot;Die 5% Klausel für Parteien&quot; - Der Sinn soll seien, das Parlament regierungsfähig zu halten, indem Zustände wie in der Weimarer Republik vermieden werden (zu viele Splitterparteien). Doch der wahre Effekt ist die Lähmung neuer politischer Kräfte. Neue Parteien haben kaum Sichtbarkeit und Wähler rechnen damit, dass ihre Stimme durch die 5% Klausel verpufft (was sie hemmt neue / kleine Parteien zu wählen). Eine bessere Lösung ist eine fixe Anzahl von Fraktionen im Parlament (z.B. 8) mit einer deutlich niedrigeren Parteiensperrklausel (z.b. 1%) - damit wäre das Parlament stets regierungsfähig und neue / kleine Parteien haben eine echt Chance ins Parlament einzuziehen.</p>
</li>
<li><p>&quot;Wohnraum als Spekulationsobjekt&quot; - Wohnraum ist ein Grundrecht, welches nicht aus Profitgier sabotiert werden darf.</p>
</li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Genetics</title>
      <link>https://seanpedersen.github.io/posts/genetics</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/genetics</guid>
      <pubDate>Sun, 25 Jan 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>The science of genes and their mutations in organisms.</p>
<p>DNA (DeoxyriboNucleic Acid) is the spiral molecular structure (double helix) made of 4 nucleotide bases (adenine, thymine, guanine, cytosine). These pair up symmetrically: A&lt;-&gt;T, G&lt;-&gt;C, forming a base 4 information system that encodes the instructions for living organisms to grow.</p>
<h2 id="structure-of-genes">Structure of Genes</h2>
<p>Genes are specific segments of DNA that contain instructions for producing proteins (or functional RNA). DNA molecules are packaged by coiling up into structures called chromosomes. Human cells contain 23 pairs of chromosomes - one set inherited from each parent - and each chromosome carries thousands of gene segments along its DNA sequence.</p>
<p>A gene is defined as a DNA segment that contains the code to produce a specific protein or functional RNA molecule. It is typically a few thousand base pairs long for humans (though can range from hundreds to a million). Genes have defined start and end boundaries identified through special combinations of base pairs (like start / stop codons).</p>
<p>BONUS: Take a look at the genome of a <a href="https://www.ncbi.nlm.nih.gov/nuccore/NC_045512.2?report=fasta">Corona virus (SARS-CoV-2)</a></p>
<h2 id="polymerase-chain-reaction">Polymerase Chain Reaction</h2>
<p>PCR is one of the most important breakthroughs in the last century - allowing us to read DNA samples easily by exponentially copying specific DNA sequences, making millions of copies from a tiny sample.</p>
<p>How it works:</p>
<ul>
<li>Denaturation (~95°C) - Heat separates double-stranded DNA into single strands</li>
<li>Annealing (~55-65°C) - Short DNA primers bind to target sequences</li>
<li>Extension (~72°C) - DNA polymerase enzyme builds new complementary strands</li>
</ul>
<p>This cycle repeats 25-35 times, exponentially copying the target DNA segment.</p>
<p>The DNA polymerase used in PCR comes from heat-loving bacteria that live in extreme environments. PCR was invented by Kary Mullis in 1983 (who had many LSD experiences).</p>
<h2 id="crispr">CRISPR</h2>
<p>CRISPR (Clustered Regularly Interspaced Short Palindromic Repeats) is a gene-editing tool that allows precise cutting and modification of DNA sequences.</p>
<p>How it works:</p>
<ul>
<li>Guide RNA - Designed to match the target DNA sequence</li>
<li>Cas9 protein - Acts as molecular scissors, cutting DNA at the targeted location</li>
<li>Cell repair - The cell&#39;s natural repair mechanisms fix the break, allowing deletion, correction or insertion of genes</li>
</ul>
<p>Where it came from: Cas9 protein originates from bacterial immune system against viruses. Bacteria store viral DNA snippets in CRISPR arrays to &quot;remember&quot; past infections. When the virus returns, bacteria use this memory to cut and destroy viral DNA.</p>
<p>Common uses:</p>
<ul>
<li>Treating genetic diseases (sickle cell, some cancers)</li>
<li>Agricultural improvements (drought-resistant crops)</li>
<li>Research (studying gene function)</li>
</ul>
<p>Why it&#39;s revolutionary:</p>
<ul>
<li>Earlier gene editing was slow, expensive, and imprecise</li>
<li>CRISPR is fast, cheap (~$30/edit vs thousands), and highly accurate</li>
<li>Democratized genetic engineering</li>
</ul>
<p>Discovered by Jennifer Doudna and Emmanuelle Charpentier, who won the 2020 Nobel Prize in Chemistry.</p>
<p>BONUS: You can create your custom yeast strain using this <a href="https://www.sunybiotech.com/index.php?c=page&amp;id=91">CRISPR service</a></p>
<h2 id="surprising-q-a">Surprising Q&amp;A</h2>
<p><strong>Does number of chromosome pairs correlate with complexity of an organism?</strong></p>
<p>Chromosome number varies widely across species without correlation to complexity:</p>
<ul>
<li>Humans: 23 pairs</li>
<li>Dogs: 39 pairs</li>
<li>Fruit flies: 4 pairs</li>
<li>Ferns: can have over 500 pairs</li>
</ul>
<p>What matters for complexity of an organism is gene regulation, alternative splicing, non-coding RNAs and protein interactions - not just chromosome count or even total gene number.</p>
<p><strong>What does it mean our DNA is 99% similar to chimps? how is DNA similarity computed?</strong></p>
<ul>
<li>The 99% refers to aligned sequences (comparable regions)</li>
<li>Doesn&#39;t account for insertions/deletions (indels) - chimps have different chromosome counts</li>
<li>Non-coding regions can differ more than genes</li>
<li>Overall genome similarity is closer to 96-98% when including structural differences</li>
</ul>
<p><strong>How was the tree of life calculated?</strong></p>
<p>Key breakthrough:<br>Carl Woese (1977) used ribosomal RNA sequences to reveal three domains of life (Bacteria, Archaea, Eukarya), revolutionizing classification that was previously based on visible features.</p>
<p>Modern approach:</p>
<ul>
<li>Sequences from multiple genes create more robust trees</li>
<li>Whole genome comparisons for fine detail</li>
<li>Molecular clocks estimate divergence times using mutation rates</li>
</ul>
<p>Challenges:</p>
<ul>
<li>Horizontal gene transfer (especially in bacteria)</li>
<li>Incomplete fossil record</li>
<li>Convergent evolution (similar traits, different origins)</li>
</ul>
<p><strong>How many genes mutate in human sexual reproduction on average?</strong></p>
<p>In human sexual reproduction, approximately 60-100 new mutations occur per offspring on average. These are de novo mutations—changes that appear in the child but weren&#39;t present in either parent&#39;s genome. Most occur during sperm production (~80% are paternal in origin and increase with age). Most mutations are in non-coding regions and have no effect.</p>
<h2 id="geographical-genetic-heritage">Geographical Genetic Heritage</h2>
<p>Why genetic heritage services like 23andme make no sense: They claim to analyse your genome and then send you a report of your ancestry, looking something like: 10% Norh-European, 20% Russian, 70% Chinese. These numbers make no sense since they are based on DNA samples from arbitrary reference populations in these regions but humanity has been travelling earth since its inception - so any regional reference sample is just a temporal snapshot at best. To claim you are X% from region Y is thus a misleading statement. One could only say with high uncertainty: you share X% of your DNA with most humans that lived in region Y Z years ago.</p>
<h2 id="genes-and-intelligence">Genes and Intelligence</h2>
<p>I have often witnessed people debating how much percent of intelligence of a human is genes vs (learning) environment - 50% / 50% or 30% / 70%? This is the wrong question to ask.</p>
<p>The intelligence of an individual is fundamentally limited by their DNA. The intelligence potential manifested in their genes is either unlocked by positive (learning) experiences or stays just a never reached potential.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/22914163/">Rate of de novo mutations and the importance of father&#39;s age to disease risk</a></li>
<li><a href="https://www.youtube.com/watch?v=zaXKQ70q4KQ">PCR: The Man Who Took LSD and Changed The World</a></li>
</ul>
<p>TODO:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Mirror-image_life">https://en.wikipedia.org/wiki/Mirror-image_life</a></li>
<li><a href="https://www.scientificamerican.com/article/lifes-evil-twins-mirror-cells-could-doom-earth-if-scientists-dont-stop-them/">https://www.scientificamerican.com/article/lifes-evil-twins-mirror-cells-could-doom-earth-if-scientists-dont-stop-them/</a></li>
<li><a href="https://en.wikipedia.org/wiki/Artificially_Expanded_Genetic_Information_System">https://en.wikipedia.org/wiki/Artificially_Expanded_Genetic_Information_System</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Nanorobots - Precise Drug Delivery</title>
      <link>https://seanpedersen.github.io/posts/nano-robots</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/nano-robots</guid>
      <pubDate>Wed, 07 Jan 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Medical nanorobots are tiny vehicles controlled by external electromagnetic fields, enabling them to move through patients veins. The vision is precise delivery of drugs to localized body parts like tumors to minimize side-effects of treatments like chemotherapy.</p>
<h2 id="control-mechanism">Control Mechanism</h2>
<p>External magnetic fields manipulate nanorobots containing magnetic materials. Rotating fields create swimming motions, while gradient fields enable directional steering. Controllers adjust field strength and orientation to guide the robots through blood or tissue. Ultrasound or MRI provides real-time tracking without interfering with magnetic control.</p>
<h2 id="current-applications">Current Applications</h2>
<p>Targeted drug delivery: Nanorobots carry chemotherapy drugs directly to tumors, reducing side effects from systemic treatment.</p>
<p>Cancer therapy: Spiky designs penetrate tumor cell membranes to improve drug absorption. Studies in mice show tumor size reduction.</p>
<p>Minimally invasive surgery: Microrobots navigate blood vessels to reach treatment sites without incisions.</p>
<h2 id="2025-developments">2025 Developments</h2>
<p>Neutrobots combine magnetic steering with chemical sensing to find targets after injection. Magnetic microrobots aggregate in aneurysm sacs using acoustic propulsion. Biodegradable designs eliminate the need for removal after treatment. Wireless magnetic communication enables coordination between multiple robots.</p>
<h2 id="technical-status">Technical Status</h2>
<p>Laboratory testing demonstrates successful navigation in simulated environments and animals like mice. Materials include magnetic nanoparticles embedded in biocompatible polymers or gels. Sizes range from nanometers to millimeters depending on application. MRI-compatible tracking methods prevent image distortion during guidance.</p>
<h2 id="remaining-obstacles">Remaining Obstacles</h2>
<p>Immune system recognition remains a challenge for extended circulation. Manufacturing at scale requires new production methods. Long term biocompatibility needs verification across different body environments. Regulatory approval processes for medical devices this novel are undefined.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC12631375/">https://pmc.ncbi.nlm.nih.gov/articles/PMC12631375/</a></li>
<li><a href="https://link.springer.com/article/10.1186/s13045-023-01463-z">https://link.springer.com/article/10.1186/s13045-023-01463-z</a></li>
<li><a href="https://www.mdpi.com/1996-1944/15/21/7781">https://www.mdpi.com/1996-1944/15/21/7781</a></li>
<li><a href="https://www.youtube.com/watch?v=9t1SDA2Jqak">YouTube: How Nano Robots Will Change Medicine Forever</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Microplastics - A silent killer</title>
      <link>https://seanpedersen.github.io/posts/microplastics</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/microplastics</guid>
      <pubDate>Mon, 05 Jan 2026 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>tutorial</category>
      <content:encoded><![CDATA[
          <p>Microplastics are tiny plastic particles present in food, water, air and dust. Research links higher exposure to inflammation, fertility problems and cardiovascular issues. Complete avoidance is impossible, but intake can be reduced. Mass usage of plastics in the economy is a huge mistake (as most organisms lack metabolism to deal with it) and must be stopped.</p>
<h2 id="water-sources">Water Sources</h2>
<p>Bottled water contains hundreds of thousands of microplastic particles per liter, far more than tap water. The packaging and processing add contamination. Use glass or stainless steel bottles instead.</p>
<p>Filter tap water with NSF/ANSI certified systems like reverse osmosis or certain pitcher filters. Boiling water before filtering may reduce particles further.</p>
<h2 id="food-storage">Food Storage</h2>
<p>Never microwave food in plastic containers, even those labeled microwave safe. Heat accelerates microplastic release - avoid placing hot food in plastic or running plastic items through dishwashers.</p>
<p>Replace plastic cutting boards with wood or bamboo. Plastic boards shed significant particles when cut. Choose wooden spoons and metal utensils over plastic ones.</p>
<p>Wash rice, meat, fish, fruits and vegetables before cooking. This removes 20 to 40 percent of surface microplastics.</p>
<h2 id="food-choices">Food Choices</h2>
<p>Buy fresh foods over ultra-processed items in plastic packaging. Choose loose produce when available. Reduce canned goods and plastic wrapped foods.</p>
<p>Limit seafood consumption, especially shellfish, which accumulates ocean microplastics. Use loose leaf tea or plastic free tea bags. Standard tea bags release billions of particles in hot water.</p>
<h2 id="household-habits">Household Habits</h2>
<p>Wear natural fibers like cotton, wool, or linen. Synthetic fabrics such as polyester and nylon shed microfibers during wear and washing.</p>
<p>Vacuum regularly with HEPA filters. Dust and wet mop surfaces to remove settled microplastics. This reduces inhalation and ingestion from household dust.</p>
<h2 id="kitchen-utensils">Kitchen Utensils</h2>
<p>Metal spoons scraping plastic containers release microplastic particles through abrasion. Plastic yogurt cups made from polypropylene or polystyrene are especially vulnerable to scratching.</p>
<p>Wooden or bamboo spoons are softer and cause less surface damage than metal. The best option is transferring food to glass, ceramic, or metal bowls before eating. Avoid aggressive scraping with any utensil.</p>
<h2 id="priority-actions">Priority Actions</h2>
<p>Start with high impact changes for maximum reduction. Stop buying bottled water. Never heat food in plastic. Use natural materials for food preparation. These steps target the main exposure pathways: water, food and air.</p>
<p>Minimize single use plastics like takeout containers and straws. This lowers both environmental release and personal exposure.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Microplastics">https://en.wikipedia.org/wiki/Microplastics</a></li>
<li><a href="https://youtu.be/v2w3zWzADgo">YouTube: Alarming Effects From Microplastics on Human Health</a> - Anton Petrov</li>
</ul>
<p class="post-hashtags"><a href="/index.html#tutorial">#tutorial</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>A Thousand Brains - Jeff Hawkins</title>
      <link>https://seanpedersen.github.io/posts/a-thousand-brains</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/a-thousand-brains</guid>
      <pubDate>Sat, 27 Dec 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>book</category>
      <category>AI</category>
      <content:encoded><![CDATA[
          <h2 id="reference-frames">Reference Frames</h2>
<p>Identifies so called reference frames (grids / maps) as key concept unifying all biological neural processing for robust / invariant sequence prediction (allowing sequence prediction in changing environments by using relative positions).</p>
<p>Key points:</p>
<ul>
<li>Grid cells: Each cortical column uses grid cell-like mechanisms (from the entorhinal cortex) to create reference frames anchored to objects, not just spatial locations.</li>
<li>Object-centered coordinates: When you touch a coffee cup, each column builds a model in the cup&#39;s own reference frame - tracking features relative to the object itself, not your body or the room.</li>
<li>Voting mechanism: Thousands of columns process different inputs (different fingers touching, different viewpoints) in parallel. They &quot;vote&quot; to reach consensus on what object is present and its pose.</li>
<li>Location + feature: Each column stores what features exist at specific locations within an object&#39;s reference frame. Moving your sensor updates the location signal.</li>
<li>Compositional models: Reference frames allow hierarchical object models - a wheel has its own frame nested within a car&#39;s frame.</li>
</ul>
<p>For abstract concepts like words in a language f.e. democracy, we create abstract maps (ref. frame) that encode how democracy is structured and how it behaves (model). This allows agents to navigate democracy: how to create a new party? etc.</p>
<p>Properties of reference frames:</p>
<ul>
<li>indexable (knowing a few bits of a location, allows us to fetch the correct map &amp; location)</li>
<li>structured by locality (abstract: similarity)</li>
<li>find routes from location / concept A to B</li>
</ul>
<p>Useful knowledge representation uses object based models: allowing to make inferences by predicting interactions / behavior. Storing hard facts (as text) is necessary but not sufficient for a useful knowledge base. Storing knowledge in gigantic, fractured weight matrices (like used in LLMs) is useful and interesting but does not produce human like adaptive intelligence.</p>
<p>Language understanding entails thus creating and manipulating a small world model of the text one is reading. For example: The apple was rolling off the table. -&gt; To understand this sentence, a model of gravity is needed to predict what will most likely happen next to the apple (hit the ground). LLMs lack this predictive word model and merely predict the next token (creating at best fractured / brittle models).</p>
<h2 id="road-to-agi">Road to AGI</h2>
<p>Hawkins is sure that deep learning (including LLM) will not lead to AGI - as they lack model based knowledge representation. Instead he identified the following properties for realizing AGI.</p>
<ul>
<li>Continuous learning</li>
<li>Learning via movement / interaction</li>
<li>Compositional world model: predictive (behavior) models of objects</li>
<li>Knowledge stored in reference frames</li>
</ul>
<h2 id="critique">Critique</h2>
<p>Hawkins maybe too focused on some specifics of the human / mammal brain structure - he identified cortical columns as the key building part of intelligence but there are other intelligent animals which lack cortical columns (smart birds like crows / ravens and octpus). A better way forward is thus to understand the structural similarities between these independently co-evolved intelligent species brains - to truly get at the essential parts for intelligence that are shared among all smart animals.</p>
<p>Mammals, corvids and octopi all share a columnar brain structure, while less intelligent species like goldfish and reptiles lack these and instead have nuclear neural clusters. Parrots have less pronounced columnar brain structure like corvids while showing similar cognitive abilities (but corvids seem smarter w.r.t. tool use / metacognition). Hawkins theory would be falsified by identifying a species with advanced cognition that lacks similarity to cortical columnar brain structure found in mammals.</p>
<p>On Page 186: Hawkins gives a false sense of evolution IMO, invoking the sense that evolution always optimizes traits of individuals but it is more random: many things stick that do not create a disadvantage to procreate instead of only traits that increase procreation chance.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://youtu.be/mGSG7I9VKDU">YouTube - Jeff Hawkins NAISys: How the Brain Uses Reference Frames</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#book">#book</a> <a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>On Intelligence - Jeff Hawkins</title>
      <link>https://seanpedersen.github.io/posts/on-intelligence</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/on-intelligence</guid>
      <pubDate>Wed, 10 Dec 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>book</category>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>Neo Cortex forms a uniform structure: 6 layers of cortical columns composed mostly of pyramidal neurons. Information flows bidirectionally: down the hierarchy to relate to known patterns and up the hierarchy to predict unknown / complete partial patterns.</p>
<p>Brain does not compute mathematical equations to navigate the world but creates and recalls memories. Catching a flying ball involves (muscle sequence) memories of previous catches that can be efficiently parameterized to adapt to the current flying ball situation.</p>
<h2 id="knowledge-representation-neo-cortex">Knowledge Representation (neo cortex)</h2>
<ul>
<li>sequential (easy to recite A-Z, hard to do the reverse)</li>
<li>invariant (to geometric translations in space and time)</li>
<li>auto-associative (informations connect by observing in shared context)</li>
<li>hierarchical (complex/abstract patterns are composed of simple patterns)</li>
<li>SDR: <a href="/posts/sparse-distributed-representations">sparse distributed representations</a></li>
<li>topographic: neighboring neurons, activate to similar patterns</li>
</ul>
<h2 id="learning-forming-memories">Learning / Forming Memories</h2>
<ul>
<li>fire together, wire together (Hebbian learning): similar patterns that repeatedly fire together, will bind together (even across different input domains), translational invariance is not only spatial but also temporal (to bind two stimuli they must not co-occur exactly at same time)</li>
</ul>
<p>Grandmother cell hypothesis is wrong: Each neuron doesn&#39;t detect just one object. This wouldn&#39;t allow lifelong learning or resilience to cell death - instead concepts are SDRs.</p>
<p class="post-hashtags"><a href="/index.html#book">#book</a> <a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Hyper-Primes</title>
      <link>https://seanpedersen.github.io/posts/hyper-primes</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/hyper-primes</guid>
      <pubDate>Mon, 17 Nov 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>math</category>
      <content:encoded><![CDATA[
          <p>A hyper-prime is a prime number p where all prime factors of p-1 and all exponents in the prime factorization of p-1 are themselves hyper-primes.</p>
<h2 id="definition">Definition</h2>
<p>For a prime number p: find prime factorization PF(p-1):<br>PF(p-1) = q₁^e₁ × q₂^e₂ × ... × qₖ^eₖ<br>The prime p is hyper-prime if and only if:</p>
<ul>
<li>Each prime factor qᵢ is hyper-prime</li>
<li>Each exponent eᵢ is hyper-prime</li>
</ul>
<p>By definition, 0 and 1 are hyper-primes.</p>
<h2 id="table">Table</h2>
<div class="table-wrapper"><table><thead><th>Prime</th><th>Factors of p-1</th><th>Exponents</th><th>HyperPrime</th></thead><tbody><tr><td>0</td><td></td><td></td><td>True</td></tr><tr><td>1</td><td></td><td></td><td>True</td></tr><tr><td>2</td><td>1</td><td>1^0</td><td>True</td></tr><tr><td>3</td><td>2</td><td>2^1</td><td>True</td></tr><tr><td>5</td><td>2 × 2</td><td>2^2</td><td>True</td></tr><tr><td>7</td><td>2 × 3</td><td>2^1, 3^1</td><td>True</td></tr><tr><td>11</td><td>2 × 5</td><td>2^1, 5^1</td><td>True</td></tr><tr><td>13</td><td>2 × 2 × 3</td><td>2^2, 3^1</td><td>True</td></tr><tr><td>17</td><td>2 × 2 × 2 × 2</td><td>2^4</td><td>False</td></tr><tr><td>19</td><td>2 × 3 × 3</td><td>2^1, 3^2</td><td>True</td></tr><tr><td>23</td><td>2 × 11</td><td>2^1, 11^1</td><td>True</td></tr><tr><td>29</td><td>2 × 2 × 7</td><td>2^2, 7^1</td><td>True</td></tr><tr><td>31</td><td>2 × 3 × 5</td><td>2^1, 3^1, 5^1</td><td>True</td></tr><tr><td>37</td><td>2 × 2 × 3 × 3</td><td>2^2, 3^2</td><td>True</td></tr><tr><td>41</td><td>2 × 2 × 2 × 5</td><td>2^3, 5^1</td><td>True</td></tr><tr><td>43</td><td>2 × 3 × 7</td><td>2^1, 3^1, 7^1</td><td>True</td></tr><tr><td>47</td><td>2 × 23</td><td>2^1, 23^1</td><td>True</td></tr><tr><td>53</td><td>2 × 2 × 13</td><td>2^2, 13^1</td><td>True</td></tr><tr><td>59</td><td>2 × 29</td><td>2^1, 29^1</td><td>True</td></tr><tr><td>61</td><td>2 × 2 × 3 × 5</td><td>2^2, 3^1, 5^1</td><td>True</td></tr><tr><td>67</td><td>2 × 3 × 11</td><td>2^1, 3^1, 11^1</td><td>True</td></tr><tr><td>71</td><td>2 × 5 × 7</td><td>2^1, 5^1, 7^1</td><td>True</td></tr><tr><td>73</td><td>2 × 2 × 2 × 3 × 3</td><td>2^3, 3^2</td><td>True</td></tr><tr><td>79</td><td>2 × 3 × 13</td><td>2^1, 3^1, 13^1</td><td>True</td></tr><tr><td>83</td><td>2 × 41</td><td>2^1, 41^1</td><td>True</td></tr><tr><td>89</td><td>2 × 2 × 2 × 11</td><td>2^3, 11^1</td><td>True</td></tr><tr><td>97</td><td>2 × 2 × 2 × 2 × 2 × 3</td><td>2^5, 3^1</td><td>True</td></tr><tr><td>101</td><td>2 × 2 × 5 × 5</td><td>2^2, 5^2</td><td>True</td></tr><tr><td>103</td><td>2 × 3 × 17</td><td>2^1, 3^1, 17^1</td><td>False</td></tr><tr><td>107</td><td>2 × 53</td><td>2^1, 53^1</td><td>True</td></tr><tr><td>109</td><td>2 × 2 × 3 × 3 × 3</td><td>2^2, 3^3</td><td>True</td></tr><tr><td>113</td><td>2 × 2 × 2 × 2 × 7</td><td>2^4, 7^1</td><td>False</td></tr><tr><td>127</td><td>2 × 3 × 3 × 7</td><td>2^1, 3^2, 7^1</td><td>True</td></tr><tr><td>131</td><td>2 × 5 × 13</td><td>2^1, 5^1, 13^1</td><td>True</td></tr><tr><td>137</td><td>2 × 2 × 2 × 17</td><td>2^3, 17^1</td><td>False</td></tr><tr><td>139</td><td>2 × 3 × 23</td><td>2^1, 3^1, 23^1</td><td>True</td></tr><tr><td>149</td><td>2 × 2 × 37</td><td>2^2, 37^1</td><td>True</td></tr><tr><td>151</td><td>2 × 3 × 5 × 5</td><td>2^1, 3^1, 5^2</td><td>True</td></tr><tr><td>157</td><td>2 × 2 × 3 × 13</td><td>2^2, 3^1, 13^1</td><td>True</td></tr><tr><td>163</td><td>2 × 3 × 3 × 3 × 3</td><td>2^1, 3^4</td><td>False</td></tr><tr><td>167</td><td>2 × 83</td><td>2^1, 83^1</td><td>True</td></tr><tr><td>173</td><td>2 × 2 × 43</td><td>2^2, 43^1</td><td>True</td></tr><tr><td>179</td><td>2 × 89</td><td>2^1, 89^1</td><td>True</td></tr><tr><td>181</td><td>2 × 2 × 3 × 3 × 5</td><td>2^2, 3^2, 5^1</td><td>True</td></tr><tr><td>191</td><td>2 × 5 × 19</td><td>2^1, 5^1, 19^1</td><td>True</td></tr><tr><td>193</td><td>2 × 2 × 2 × 2 × 2 × 2 × 3</td><td>2^6, 3^1</td><td>False</td></tr><tr><td>197</td><td>2 × 2 × 7 × 7</td><td>2^2, 7^2</td><td>True</td></tr><tr><td>199</td><td>2 × 3 × 3 × 11</td><td>2^1, 3^2, 11^1</td><td>True</td></tr><tr><td>211</td><td>2 × 3 × 5 × 7</td><td>2^1, 3^1, 5^1, 7^1</td><td>True</td></tr><tr><td>223</td><td>2 × 3 × 37</td><td>2^1, 3^1, 37^1</td><td>True</td></tr><tr><td>227</td><td>2 × 113</td><td>2^1, 113^1</td><td>False</td></tr><tr><td>229</td><td>2 × 2 × 3 × 19</td><td>2^2, 3^1, 19^1</td><td>True</td></tr><tr><td>233</td><td>2 × 2 × 2 × 29</td><td>2^3, 29^1</td><td>True</td></tr><tr><td>239</td><td>2 × 7 × 17</td><td>2^1, 7^1, 17^1</td><td>False</td></tr><tr><td>241</td><td>2 × 2 × 2 × 2 × 3 × 5</td><td>2^4, 3^1, 5^1</td><td>False</td></tr><tr><td>251</td><td>2 × 5 × 5 × 5</td><td>2^1, 5^3</td><td>True</td></tr><tr><td>257</td><td>2 × 2 × 2 × 2 × 2 × 2 × 2 × 2</td><td>2^8</td><td>False</td></tr><tr><td>263</td><td>2 × 131</td><td>2^1, 131^1</td><td>True</td></tr><tr><td>269</td><td>2 × 2 × 67</td><td>2^2, 67^1</td><td>True</td></tr><tr><td>271</td><td>2 × 3 × 3 × 3 × 5</td><td>2^1, 3^3, 5^1</td><td>True</td></tr><tr><td>277</td><td>2 × 2 × 3 × 23</td><td>2^2, 3^1, 23^1</td><td>True</td></tr><tr><td>281</td><td>2 × 2 × 2 × 5 × 7</td><td>2^3, 5^1, 7^1</td><td>True</td></tr><tr><td>283</td><td>2 × 3 × 47</td><td>2^1, 3^1, 47^1</td><td>True</td></tr><tr><td>293</td><td>2 × 2 × 73</td><td>2^2, 73^1</td><td>True</td></tr><tr><td>307</td><td>2 × 3 × 3 × 17</td><td>2^1, 3^2, 17^1</td><td>False</td></tr><tr><td>311</td><td>2 × 5 × 31</td><td>2^1, 5^1, 31^1</td><td>True</td></tr><tr><td>313</td><td>2 × 2 × 2 × 3 × 13</td><td>2^3, 3^1, 13^1</td><td>True</td></tr><tr><td>317</td><td>2 × 2 × 79</td><td>2^2, 79^1</td><td>True</td></tr><tr><td>331</td><td>2 × 3 × 5 × 11</td><td>2^1, 3^1, 5^1, 11^1</td><td>True</td></tr><tr><td>337</td><td>2 × 2 × 2 × 2 × 3 × 7</td><td>2^4, 3^1, 7^1</td><td>False</td></tr><tr><td>347</td><td>2 × 173</td><td>2^1, 173^1</td><td>True</td></tr><tr><td>349</td><td>2 × 2 × 3 × 29</td><td>2^2, 3^1, 29^1</td><td>True</td></tr><tr><td>353</td><td>2 × 2 × 2 × 2 × 2 × 11</td><td>2^5, 11^1</td><td>True</td></tr><tr><td>359</td><td>2 × 179</td><td>2^1, 179^1</td><td>True</td></tr><tr><td>367</td><td>2 × 3 × 61</td><td>2^1, 3^1, 61^1</td><td>True</td></tr><tr><td>373</td><td>2 × 2 × 3 × 31</td><td>2^2, 3^1, 31^1</td><td>True</td></tr><tr><td>379</td><td>2 × 3 × 3 × 3 × 7</td><td>2^1, 3^3, 7^1</td><td>True</td></tr><tr><td>383</td><td>2 × 191</td><td>2^1, 191^1</td><td>True</td></tr><tr><td>389</td><td>2 × 2 × 97</td><td>2^2, 97^1</td><td>True</td></tr><tr><td>397</td><td>2 × 2 × 3 × 3 × 11</td><td>2^2, 3^2, 11^1</td><td>True</td></tr><tr><td>401</td><td>2 × 2 × 2 × 2 × 5 × 5</td><td>2^4, 5^2</td><td>False</td></tr><tr><td>409</td><td>2 × 2 × 2 × 3 × 17</td><td>2^3, 3^1, 17^1</td><td>False</td></tr><tr><td>419</td><td>2 × 11 × 19</td><td>2^1, 11^1, 19^1</td><td>True</td></tr></tbody></table></div><h2 id="code">Code</h2>
<pre><code>import math
from collections import Counter

def prime_factors(n):
    factors = []
    while n % 2 == 0:
        factors.append(2)
        n //= 2
    f = 3
    while f * f &lt;= n:
        while n % f == 0:
            factors.append(f)
            n //= f
        f += 2
    if n &gt; 1:
        factors.append(n)
    return factors

def is_prime(num):
    if num &lt; 2:
        return False
    if num in (2, 3):
        return True
    if num % 2 == 0:
        return False
    root = int(math.sqrt(num))
    for i in range(3, root + 1, 2):
        if num % i == 0:
            return False
    return True

def is_hyper_prime(n, memo={}):
    if n in memo:
        return memo[n]
    
    # Bootstrap base cases: 0, 1, 2 are hyper-primes by definition
    if n in (0, 1, 2):
        memo[n] = True
        return True
    
    # Must be prime to be hyper-prime
    if not is_prime(n):
        memo[n] = False
        return False
    
    # Factor n-1
    factors = prime_factors(n - 1)
    factor_counts = Counter(factors)
    
    # Check all prime factors are hyper-primes
    for factor in factor_counts.keys():
        if not is_hyper_prime(factor, memo):
            memo[n] = False
            return False
    
    # Check all exponents are hyper-primes
    for exponent in factor_counts.values():
        if not is_hyper_prime(exponent, memo):
            memo[n] = False
            return False
    
    memo[n] = True
    return True

def generate_primes(limit):
    primes = []
    for p in range(2, limit + 1):
        if is_prime(p):
            primes.append(p)
    return primes

def generate_hyper_primes(limit):
    hyperprimes = []
    memo = {}
    for p in range(2, limit + 1):
        if is_hyper_prime(p, memo):
            hyperprimes.append(p)
    return hyperprimes

def generate_hyper_primes_debug(limit):
    print(f&quot;| {&#39;Prime&#39;:&gt;6} | {&#39;Factors of p-1&#39;:&gt;25} | {&#39;Exponents&#39;:&gt;15} | {&#39;HyperPrime&#39;:&gt;10} |&quot;)
    print(f&quot;|{&#39;-&#39;*8}|{&#39;-&#39;*27}|{&#39;-&#39;*17}|{&#39;-&#39;*12}|&quot;)
    memo = {}
    for p in range(2, limit + 1):
        if not is_prime(p):
            continue
        factors = prime_factors(p - 1)
        counts = Counter(factors)
        exps_str = &#39;, &#39;.join(f&quot;{prime}^{exp}&quot; for prime, exp in counts.items())
        hyper = is_hyper_prime(p, memo)
        factors_str = &#39; × &#39;.join(map(str, factors)) if factors else &#39;1&#39;
        print(f&quot;| {p:6} | {factors_str:25} | {exps_str:15} | {str(hyper):&gt;10} |&quot;)

# Example test up to 420
generate_hyper_primes_debug(420)
</code></pre><h2 id="references">References</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Super-prime">https://en.wikipedia.org/wiki/Super-prime</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#math">#math</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Elixir</title>
      <link>https://seanpedersen.github.io/posts/elixir</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/elixir</guid>
      <pubDate>Fri, 14 Nov 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p><a href="https://elixir-lang.org/docs.html">Elixir</a> is <a href="/posts/erlang">Erlang</a> with syntactic sugar (transpiling to Erlang code). Biggest differences to Erlang: Variables are rebindable &amp; strings are UTF-8 encoded by default.</p>
<p>Parallel function process map:</p>
<pre><code>defmodule Utils do
    def pmap(collection, func) do
        collection
        |&gt; Enum.map(fn item -&gt; Task.async(fn -&gt; func.(item) end) end)
        |&gt; Enum.map(fn task -&gt; Task.await(task) end)
    end
end
</code></pre><p>Fibonacci base, memoized and tail recursion:</p>
<pre><code>defmodule Fibo do
    # Exponential time complexity: O(2^n)
    # Linear space complexity due to call stack: O(n)
    def fibonacci(0), do: 0
    def fibonacci(1), do: 1
    def fibonacci(n) when n &gt; 1 do
        fibonacci(n - 1) + fibonacci(n - 2)
    end

    # Memoized Fibonacci using caching to avoid redundant calculations
    # Time complexity reduced to O(n)
    # Space complexity O(n) for cache map
    def fibo_cached(n), do: fibo_cached(n, %{}) |&gt; elem(0)

    defp fibo_cached(0, cache), do: {0, cache}
    defp fibo_cached(1, cache), do: {1, cache}

    defp fibo_cached(n, cache) when n &gt; 1 do
        case Map.fetch(cache, n) do
        {:ok, result} -&gt;
            {result, cache}
        :error -&gt;
            {res1, cache1} = fibo_cached(n - 1, cache)
            {res2, cache2} = fibo_cached(n - 2, cache1)
            result = res1 + res2
            {result, Map.put(cache2, n, result)}
        end
    end

    # Tail recursive Fibonacci
    # Time complexity O(n)
    # Constant space complexity O(1)
    def fibo_tail(n), do: fibo_tail(n, 0, 1)
    defp fibo_tail(0, a, _b), do: a
    defp fibo_tail(n, a, b) when n &gt; 0 do
        fibo_tail(n - 1, b, a + b)
    end
end
</code></pre><h2 id="references">References</h2>
<ul>
<li><a href="https://elixir-lang.org/">https://elixir-lang.org/</a></li>
<li><a href="https://joearms.github.io/published/2013-05-31-a-week-with-elixir.html">https://joearms.github.io/published/2013-05-31-a-week-with-elixir.html</a></li>
<li><a href="https://elixir-lang.org/getting-started/introduction.html">https://elixir-lang.org/getting-started/introduction.html</a></li>
<li><a href="https://github.com/jonklein/niex">https://github.com/jonklein/niex</a></li>
<li>Ash To TypeScript: <a href="https://github.com/ChristianAlexander/ash_typescript_demo">https://github.com/ChristianAlexander/ash_typescript_demo</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Rust</title>
      <link>https://seanpedersen.github.io/posts/rust</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/rust</guid>
      <pubDate>Fri, 14 Nov 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>Rust is a statically and strongly typed systems programming language that enforces memory safety (without a garbage collector) through its ownership and borrowing model, while still being efficient in the ballpark of C or C++.</p>
<p>In safe Rust, the compiler prevents entire classes of bugs common in C or C++, such as use-after-free and most data races. It also forces explicit handling of optional values via Option instead of allowing null references. While this shifts many potential failures from runtime to compile time (in contrast with dynamic languages like Python or unsafe manual memory management in C) - Rust does not eliminate logic errors, panics or higher-level concurrency issues like deadlocks. These properties are the reason Rust has made its way into the Linux kernel.</p>
<p>Rust also shines through its ergnomic package manager cargo that provides a smooth developer UX. The only real downside of Rust is its inherent complexity (slow compile speeds and huge compilation artifacts disk size) and at times verbose / ugly syntax.</p>
<p>Great introduction: <a href="https://fasterthanli.me/articles/a-half-hour-to-learn-rust">https://fasterthanli.me/articles/a-half-hour-to-learn-rust</a></p>
<h2 id="http-server">HTTP Server</h2>
<ul>
<li><a href="https://github.com/actix/actix-web">https://github.com/actix/actix-web</a></li>
<li><a href="https://github.com/tokio-rs/axum">https://github.com/tokio-rs/axum</a></li>
<li><a href="https://github.com/poem-web/poem">https://github.com/poem-web/poem</a></li>
</ul>
<h2 id="machine-learning">Machine Learning</h2>
<ul>
<li><a href="https://docs.rs/ndarray/latest/ndarray/doc/ndarray_for_numpy_users/index.html">ndarray</a>: numpy equivalent<ul>
<li><a href="https://docs.rs/npy/latest/npy/">loading npy files</a> (from Python numpy)</li>
</ul>
</li>
<li><a href="https://github.com/pykeio/ort">ORT</a>: ONNX run time</li>
</ul>
<h2 id="gui">GUI</h2>
<ul>
<li><a href="https://tauri.app/">Tauri</a>: Use Rust in backend and web stack in frontend to build desktop and mobile apps<ul>
<li><a href="https://github.com/hypothesi/mcp-server-tauri">Tauri MCP Server</a></li>
</ul>
</li>
<li><a href="https://www.gpui.rs/">GPUI</a>: UI lib created by and used in Zed editor<ul>
<li><a href="https://github.com/longbridge/gpui-component">GPUI components</a></li>
</ul>
</li>
</ul>
<h2 id="text-extraction">Text Extraction</h2>
<ul>
<li><a href="https://github.com/yfedoseev/pdf_oxide">pdf_oxide</a>: fast PDF text extraction</li>
<li><a href="https://github.com/AmineDiro/ferrules/tree/main">ferrules</a>: structured text extraction</li>
<li><a href="https://github.com/kreuzberg-dev/kreuzberg">https://github.com/kreuzberg-dev/kreuzberg</a></li>
<li><a href="https://github.com/yobix-ai/extractous">https://github.com/yobix-ai/extractous</a></li>
</ul>
<h2 id="text-chunking">Text Chunking</h2>
<ul>
<li><a href="https://github.com/benbrandt/text-splitter">https://github.com/benbrandt/text-splitter</a></li>
<li><a href="https://github.com/d1pankarmedhi/chunkr">https://github.com/d1pankarmedhi/chunkr</a></li>
<li><a href="https://github.com/idleness76/wg-ragsmith">https://github.com/idleness76/wg-ragsmith</a></li>
</ul>
<h2 id="concurrency">Concurrency</h2>
<ul>
<li><a href="https://github.com/pixperk/cineyma">cineyma</a>: Erlang inspired OTP-style actor framework</li>
<li><a href="https://github.com/Dicklesworthstone/asupersync">asupersync</a>: Async runtime for Rust where correctness is structural: region-owned tasks, cancel-correct protocols, capability-gated effects, and deterministic replay testing</li>
</ul>
<h2 id="coding-agents">Coding Agents</h2>
<ul>
<li><a href="https://github.com/openai/codex">OpenAI Codex</a></li>
<li><a href="https://github.com/Dicklesworthstone/pi_agent_rust">pi_agent_rust</a>: Rust port of <a href="https://github.com/badlogic/pi-mono">pi agent</a></li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.howtocodeit.com/guides/the-definitive-guide-to-rust-error-handling">Error handling</a></li>
<li><a href="https://jmmv.dev/2018/06/rust-review-borrow-checker.html">https://jmmv.dev/2018/06/rust-review-borrow-checker.html</a></li>
<li><a href="https://doc.rust-lang.org/book/">https://doc.rust-lang.org/book/</a></li>
<li><a href="https://news.ycombinator.com/item?id=24867610">https://news.ycombinator.com/item?id=24867610</a></li>
<li><a href="https://lubeno.dev/blog/rusts-productivity-curve">https://lubeno.dev/blog/rusts-productivity-curve</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Digital Surveillance Capitalism</title>
      <link>https://seanpedersen.github.io/posts/digital-capitalism-alternatives</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/digital-capitalism-alternatives</guid>
      <pubDate>Thu, 13 Nov 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Digital sureveillance capitalism shapes how we interact with technology, the world and even how we understand its role in society. These mechanisms tend to hide the true power relations while presenting inhumane, privacy violating technological developments as neutral, natural progress.</p>
<h2 id="core-mechanisms">Core Mechanisms</h2>
<h3 id="solutionism">Solutionism</h3>
<p>Tech firms recast hard social problems as simple tech tasks. Debate over law and justice shifts into product tweaks.</p>
<p>Example: using filters and bots to police hate speech instead of asking who should set speech rules. This story defends deregulation, giant scale and ignores waste, labor abuse and social harm.</p>
<h3 id="forced-transparency-and-self-tracking">Forced Transparency and Self Tracking</h3>
<p>People are scored nonstop: credit, clicks, steps, ratings. Being watched makes us adjust to please the watcher.<br>Users are exposed; while platforms algorithms and business aims stay hidden. Long legal pages, secret algorithms and many confusing company layers.<br>Self tracking is sold as freedom; it becomes self discipline to meet outside targets: fitness badges, five‑star gig ratings. Trust is demanded; proof is withheld.</p>
<h3 id="engineered-comparison">Engineered Comparison</h3>
<p>Likes, followers, ranks, streaks keep users chasing status. Games and rewards drive time on site and data flow. This is not random manipulation; it is the profit engine. Engagement feeds ads and prediction. People stay not from weakness but because exit costs social ties.</p>
<h3 id="supporting-stories">Supporting Stories</h3>
<p>Dataism: Numbers are treated as pure truth; method bias is ignored. Tech inevitability: &quot;Tech will happen anyway,&quot; killing democratic choice. Disruption myth: Breaking rules is praised as innovation; law evasion is rebranded. Sharing talk: Extractive platforms pose as neutral &quot;sharing&quot; spaces. Security frame: More surveillance is sold as safety; emergency logic never ends.</p>
<h3 id="results">Results</h3>
<p>Power pools in a few firms. Risk shifts to users and workers: algorithmic gig control, data leaks, biased automation. This is masked as efficiency and empowerment. Design choices are political choices.</p>
<h2 id="human-centered-technology">Human Centered Technology</h2>
<p>...serving humans instead of exploiting them for maximum profits.</p>
<h3 id="open-source">Open Source</h3>
<p>Code you can read, verify and change. True digital independence. In the future everyone may change their apps using local LLM&#39;s.</p>
<h3 id="local-first">Local First</h3>
<p>Data lives on your devices; sync only when you choose. Works offline. Cuts surveillance. Real ownership, not unread policies.</p>
<h3 id="open-standards-and-interoperability">Open Standards and Interoperability</h3>
<p>Systems talk through public protocols. You can move and keep contacts and data. Stops lock‑in. Forces competition on quality.</p>
<h3 id="privacy-by-design">Privacy by Design</h3>
<p>Collect the least data. Encrypt end to end. Use techniques that hide individuals in stats. Make abuse hard by architecture, not fragile policy.</p>
<h3 id="democratic-governance">Democratic Governance</h3>
<p>Co‑ops, user boards, multi‑stakeholder councils. Invite affected groups into rule making. Example: civic platforms that enable public debate and consensus.</p>
<h3 id="alternative-economic-models">Alternative Economic Models</h3>
<ul>
<li>Platform Co‑ops: Worker/user owned services share profit fairly; aim for good work over raw growth.</li>
<li>Public Digital Infrastructure: Essential digital tools should be available as public goods (just like roads) and just be maintained without interest in profiting from it.</li>
<li>Commons Production: Shared, open projects (Linux, Wikipedia) show large systems can run without corporate control.</li>
</ul>
<h2 id="regulation">Regulation</h2>
<ul>
<li>Data Minimization: Collect only what you need; delete when done. Enforce it.</li>
<li>Algorithm Accountability: Explanations, audits, appeal paths for decisions on jobs, housing, credit, benefits.</li>
<li>Antitrust: Block monopoly mergers, split dominant firms, ban self‑dealing. Separate core platform from its own services.</li>
</ul>
<h2 id="social-shifts">Social Shifts</h2>
<ul>
<li>Digital Literacy: Teach how platforms track, rank and shape behavior. Not just code—power analysis.</li>
<li>Collective Action: Unions, advocacy, movements change systems; single user choices rarely do.</li>
<li>Cultural Norms: If people expect data rights and low surveillance, firms must adapt. Norms spread through media, art, daily talk.</li>
</ul>
<h2 id="working-examples">Working Examples</h2>
<p>Mastodon: Decentralized social network; users pick servers and rules. Signal: Encrypted chat funded by donations, not data extraction. Fairphone: Repairable phones built for long use. Cities like Barcelona: Public digital platforms serving citizens.</p>
<h2 id="path-forward">Path Forward</h2>
<p>Change needs tools, laws, ownership shifts and new norms together. Nothing is inevitable. We can choose designs that cut surveillance, spread power, support democracy and respect dignity.</p>
<p>Human tech serves people, not extracts from them. It shares power, not hoards it. It grows under public oversight, not private decree. Choose and build accordingly.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Solutionism">https://en.wikipedia.org/wiki/Solutionism</a></li>
<li><a href="https://www.inkandswitch.com/local-first/">https://www.inkandswitch.com/local-first/</a></li>
<li><a href="https://ec.europa.eu/digital-markets-act">https://ec.europa.eu/digital-markets-act</a></li>
<li><a href="https://info.vtaiwan.tw/">https://info.vtaiwan.tw/</a></li>
<li><a href="https://en.wikipedia.org/wiki/Platform_cooperative">https://en.wikipedia.org/wiki/Platform_cooperative</a></li>
<li><a href="https://www.stocksy.com/">https://www.stocksy.com/</a></li>
<li><a href="https://resonate.coop/">https://resonate.coop/</a></li>
<li><a href="https://decidim.org/">https://decidim.org/</a></li>
<li><a href="https://gdpr.eu/">https://gdpr.eu/</a></li>
<li><a href="https://joinmastodon.org/">https://joinmastodon.org/</a></li>
<li><a href="https://www.fairphone.com/">https://www.fairphone.com/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Operational Security</title>
      <link>https://seanpedersen.github.io/posts/operational-security</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/operational-security</guid>
      <pubDate>Mon, 10 Nov 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>How to secure a VPS running in production (important service + customer data)</p>
<h2 id="vps-providers-eu">VPS Providers (EU)</h2>
<ul>
<li><a href="https://hetzner.de/">hetzner</a>: Germany</li>
<li><a href="https://www.ovhcloud.com/en/vps/">ovhcloud</a>: France</li>
<li><a href="https://www.scaleway.com/en">scaleway</a>: France</li>
</ul>
<h2 id="checklist">Checklist</h2>
<ul>
<li>Use ONLY public key based AND disable password based auth (for SSH) + use non-default port</li>
<li>Disable root account, disable root login via ssh -&gt; only use user accounts with sudo</li>
<li>Setup firewall - lockdown all unused ports, keep: 22 (SSH), 80 (HTTP), 443 (HTTPS)</li>
<li>Setup fail2ban (ban IP&#39;s failing ssh login attempts)</li>
<li>Use docker for your services</li>
<li>Setup regular automatic updates</li>
<li>Setup append only backups (whole server or DB) with regular validity tests (restore the backup)</li>
<li>Setup notification (via E-Mail) critical events: high disk or RAM usage, unusual network traffic</li>
<li>Advanced: Setup disk level encryption (f.e. LUKS) - in case the hard drives will be resold: customer data can not be recovered</li>
<li>Advanced: Setup SELinux / AppArmor for fine-grained service permissions</li>
</ul>
<h2 id="limit-disk-usage">Limit Disk Usage</h2>
<p>Limit system log accumulation: <code class="language-text">journalctl --vacuum-size=200M</code></p>
<p>Limit docker dead containers / volumes / etc:</p>
<pre><code>cat &gt;/etc/systemd/system/docker-prune.service &lt;&lt;&#39;EOF&#39;
[Unit]
Description=Prune unused Docker data

[Service]
Type=oneshot
ExecStart=/usr/bin/docker system prune -af --volumes
EOF
</code></pre><pre><code>cat &gt;/etc/systemd/system/docker-prune.timer &lt;&lt;&#39;EOF&#39;
[Unit]
Description=Weekly Docker cleanup

[Timer]
OnCalendar=weekly
Persistent=true

[Install]
WantedBy=timers.target
EOF
</code></pre><p>Enable service:</p>
<pre><code>systemctl daemon-reexec
systemctl enable --now docker-prune.timer
</code></pre><h2 id="references">References</h2>
<ul>
<li><a href="https://x.com/levelsio/status/1957526292045393976">https://x.com/levelsio/status/1957526292045393976</a></li>
<li><a href="https://x.com/levelsio/status/1953025356585169372">https://x.com/levelsio/status/1953025356585169372</a></li>
<li><a href="https://github.com/AnswerDotAI/fastsetup/blob/master/ubuntu-initial.sh">Setup script for Ubuntu Server</a></li>
<li><a href="https://www.kkyri.com/p/how-to-secure-your-new-vps-a-step-by-step-guide">https://www.kkyri.com/p/how-to-secure-your-new-vps-a-step-by-step-guide</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Crypto-Currencies</title>
      <link>https://seanpedersen.github.io/posts/cryptocurrency</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/cryptocurrency</guid>
      <pubDate>Fri, 07 Nov 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Bitcoin, Ethereum and co (crypto-coins) have arrived in the mainstream - everybody and their mother has heard about it, but what does it all mean?</p>
<h2 id="snowball-or-the-future-of-money">Snowball or the Future of Money</h2>
<p>It is a snowball system (primary use is speculating / zero sum: every profit made equals someone else losing):</p>
<ul>
<li>everybody holding now will eventually cash out (unless bitcoin becomes a global currency)</li>
<li>&quot;Long-term holders (LTHs) now control 14.7 million BTC, 74% of the circulating supply, signaling that holding BTC has become the prevailing strategy in a maturing market.&quot; - (2)</li>
</ul>
<p>vs</p>
<p>It is a genuine new monetary system and people will not eventually cash out (signalled by how much it is used as a currency in every day life transactions).</p>
<h2 id="the-reality-check">The Reality Check</h2>
<p>The evidence suggests it&#39;s primarily a speculative asset:</p>
<ul>
<li>Overwhelmingly held for speculation (70-90% of Bitcoin hasn&#39;t moved in years)</li>
<li>Minimal retail payment adoption after 15 years</li>
<li>High volatility makes it poor currency</li>
<li>Some legitimate use: international transactions, circumventing capital controls</li>
<li>Stablecoins show more actual payment utility than Bitcoin</li>
</ul>
<p>The &quot;genuine monetary system&quot; argument requires everyday adoption that hasn&#39;t materialized. Even crypto advocates increasingly frame it as &quot;store of value&quot; rather than currency - which is admitting it&#39;s speculative asset holding.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The technology behind Bitcoin (blockchain) is legit and might lead us to a decentralized global monetary system but it does not look like Bitcoin will be this - it is a speculative asset. Stable coins will more likely fill the role of a true digital world currency.</p>
<h2 id="references">References</h2>
<ul>
<li>(1) <a href="https://coinlaw.io/how-many-people-own-bitcoin/">https://coinlaw.io/how-many-people-own-bitcoin/</a></li>
<li>(2) <a href="https://coinledger.io/research/how-much-bitcoin-is-lost">https://coinledger.io/research/how-much-bitcoin-is-lost</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>PostgreSQL Database</title>
      <link>https://seanpedersen.github.io/posts/postgres</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/postgres</guid>
      <pubDate>Mon, 13 Oct 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>Postgres is a versatile, powerful open-source relational DBMS - which means it is capable of lots of things: spanning from advanced search capabilities for text, vector search and geographic data to optimizations like partitioning and sharding. Understanding these optimization techniques can transform a moderately performing database into a high-performance system handling millions of queries per second with sub-millisecond latency.</p>
<h2 id="database-maintenance">Database Maintenance</h2>
<p>PostgreSQL&#39;s Multi-Version Concurrency Control (MVCC) architecture creates dead tuples whenever rows are updated or deleted. An UPDATE operation actually performs a DELETE followed by INSERT, leaving the old row version behind. These dead tuples accumulate over time, consuming disk space and degrading query performance.</p>
<p>Standard VACUUM runs concurrently with normal operations, acquiring only a ShareUpdateExclusive lock that permits reads and writes. It marks space occupied by dead tuples as reusable within the same table but doesn&#39;t return disk space to the operating system. This process also &quot;freezes&quot; old tuples by marking them visible to all future transactions, preventing wraparound. Configure autovacuum with appropriate thresholds to ensure it runs frequently enough—the default 20% scale factor means a 1TB table accumulates 200GB of dead tuples before vacuuming triggers, which is far too permissive for large tables.</p>
<p>VACUUM FULL rewrites the entire table into a new disk file with no wasted space, returning freed disk space to the operating system. However, it requires an ACCESS EXCLUSIVE lock that blocks all operations and needs up to 2x the table&#39;s size in temporary disk space. <strong>Run VACUUM FULL only during scheduled maintenance windows for extreme bloat situations</strong>, never as routine maintenance. For a 100GB table with 90% bloat, VACUUM FULL might take hours and block all access. Instead, prevent bloat accumulation through proper autovacuum tuning.</p>
<p>VACUUM FULL alternative (less locking): <a href="https://github.com/reorg/pg_repack">https://github.com/reorg/pg_repack</a></p>
<h3 id="backups">Backups</h3>
<ul>
<li><a href="https://github.com/pgbackrest/pgbackrest">https://github.com/pgbackrest/pgbackrest</a></li>
<li><a href="https://github.com/databasus/databasus">https://github.com/databasus/databasus</a></li>
</ul>
<h2 id="scaling-optimisations">Scaling &amp; Optimisations</h2>
<h3 id="indexes">Indexes</h3>
<p>Indexes speed up queries by generating data structures (binary trees, hash tables, etc.) that aid them - at the cost of storage and write performance. <a href="https://ankane.org/introducing-dexter">Dexter</a> is a tool that analyses your DB&#39;s common queries and automatically suggests indexes to speed them up.</p>
<h3 id="vertical-scaling-bigger-server">Vertical Scaling (bigger server)</h3>
<p>TL;DR - get a beefy server</p>
<ul>
<li>Fast IO ops, NVMe &gt; SSD &gt; SATA. Use RAID for even better performance</li>
<li>Lots of fast RAM</li>
<li>Beefy CPU cores (lots of em)</li>
</ul>
<p>Check out: <a href="https://pgtune.leopard.in.ua/">https://pgtune.leopard.in.ua/</a></p>
<h4 id="pgbench">PGBench</h4>
<p>Run pgbench to eval server performance quickly.</p>
<pre><code>sudo -u postgres psql -c &quot;CREATE DATABASE testdb;&quot;
sudo -u postgres pgbench -i -s 10 testdb  # -s 10 = 10M rows
sudo -u postgres pgbench -c 10 -j 2 -T 60 testdb # -c clients, -j threads, -T duration(sec)
</code></pre><h4 id="tablespace">TABLESPACE</h4>
<p>TABLESPACE maps tables and indexes to specific storage volumes - useful for placing hot data on NVMe and archival data on cheaper disks (reduce costs and optimize performance).</p>
<p>Create new tablespace:</p>
<pre><code>CREATE TABLESPACE fastssd LOCATION &#39;/mnt/hetzner-volume&#39;;
</code></pre><p>Move existing table and index to tablespace:</p>
<pre><code>ALTER TABLE table_name SET TABLESPACE fastssd;
ALTER INDEX table_name_idx SET TABLESPACE fastssd;
</code></pre><h3 id="table-partitioning-strategies">Table Partitioning Strategies</h3>
<p>TODO: When to use partitions vs local indexes</p>
<p>Table partitioning divides large tables into smaller physical pieces while maintaining a single logical table interface. Partitioning becomes valuable when tables exceed 100GB and contain natural segmentation boundaries in query patterns. For example if the data in a table is frequently queried by a language id and the language association of items does not change frequently, it makes sense to partition the table by language id.</p>
<p>Range partitioning splits data by value ranges, ideal for time-series data. Create a parent table with <code class="language-text">PARTITION BY RANGE (timestamp_column)</code>, then add child partitions for each time period. Monthly partitions work well for event logs accumulating gigabytes daily. PostgreSQL 11+ supports declarative partitioning with automatic constraint management. Include the partition key in the primary key: <code class="language-text">PRIMARY KEY (event_time, id)</code> ensures uniqueness constraints work across partitions.</p>
<pre><code>CREATE TABLE events (
    id BIGSERIAL,
    event_time TIMESTAMPTZ NOT NULL,
    payload JSONB,
    PRIMARY KEY (event_time, id)
) PARTITION BY RANGE (event_time);

CREATE TABLE events_2024_01 PARTITION OF events
    FOR VALUES FROM (&#39;2024-01-01&#39;) TO (&#39;2024-02-01&#39;);
    
CREATE INDEX ON events_2024_01 (event_time);
</code></pre><p>List partitioning organizes data by discrete values like geographic regions or tenant IDs in multi-tenant systems. Define explicit value lists for each partition: <code class="language-text">FOR VALUES IN (&#39;USA&#39;, &#39;CANADA&#39;, &#39;MEXICO&#39;)</code>. Create a DEFAULT partition to capture unlisted values, though adding new partitions when a DEFAULT exists requires scanning the DEFAULT partition to move matching rows.</p>
<p>Hash partitioning distributes rows evenly across partitions using a hash function, preventing hotspots when no natural ordering exists. Create with <code class="language-text">PARTITION BY HASH (customer_id)</code> and define partitions with modulus and remainder: <code class="language-text">FOR VALUES WITH (MODULUS 4, REMAINDER 0)</code>. <strong>Hash partitioning reduced memory usage at Cubbit when they decreased from 256 to 64 partitions</strong> while maintaining query performance improvements from partition pruning.</p>
<p>Partition pruning eliminates scanning irrelevant partitions at query planning or execution time. Queries must include the partition key in WHERE clauses using immutable expressions. <code class="language-text">WHERE event_time &gt;= &#39;2024-01-01&#39; AND event_time &lt; &#39;2024-02-01&#39;</code> enables pruning, but <code class="language-text">WHERE event_time &gt; NOW() - INTERVAL &#39;1 day&#39;</code> prevents it because NOW() is not immutable. Verify pruning with EXPLAIN—look for scans on specific partitions rather than all partitions.</p>
<p>Choose partition counts carefully. Too few partitions (under 10) provide minimal benefits. Too many partitions (thousands) increase query planning time exponentially and consume excessive memory. Aim for several dozen to a few hundred partitions maximum. <strong>PostgreSQL 12 improved partition handling significantly</strong>, enabling efficient management of thousands of partitions where previously 100 was the practical limit.</p>
<p>Index creation on partitioned tables automatically propagates to all child partitions. Create indexes on the parent table after creating all partitions for efficiency. Use <code class="language-text">CREATE INDEX CONCURRENTLY</code> in production to avoid locking. For large partitions, create indexes concurrently on each partition individually, then attach to the parent index to maintain service availability.</p>
<p>Partition maintenance requires automation. Use pg_partman extension for automatic partition creation and removal based on retention policies. Detaching old partitions provides instant deletion: <code class="language-text">ALTER TABLE events DETACH PARTITION events_2020_01; DROP TABLE events_2020_01;</code>. This avoids the bloat and performance degradation of deleting millions of rows individually. Cubbit achieved instant deletion of expired data through partition drops versus expensive DELETE operations scanning entire tables.</p>
<p>Performance benchmarks show partitioning trades increased write overhead for faster targeted queries. Range queries with proper partition pruning execute up to 10x faster by scanning only relevant partitions. Point queries incur 15-20% overhead due to planning complexity. Bulk loads run 20-25% slower with 400+ partitions due to partition switching costs. Optimize by loading data pre-sorted by partition key.</p>
<h3 id="horizontal-scaling-more-servers">Horizontal Scaling (more servers)</h3>
<ul>
<li>Citus: <a href="https://github.com/citusdata/citus">https://github.com/citusdata/citus</a></li>
</ul>
<p>Streaming replication provides the foundation for PostgreSQL horizontal scaling. The primary server continuously sends Write-Ahead Log (WAL) changes to standby servers, which replay transactions to maintain synchronized copies. Configure <code class="language-text">wal_level = replica</code> and <code class="language-text">max_wal_senders = 10</code> on the primary. Create a replication user with <code class="language-text">CREATE ROLE replication_user WITH REPLICATION LOGIN</code>. Initialize standbys using <code class="language-text">pg_basebackup</code> to clone the primary&#39;s data directory, then configure <code class="language-text">primary_conninfo</code> pointing to the primary server.</p>
<p><strong>Asynchronous replication</strong> delivers superior performance by not waiting for standby confirmation before committing transactions. This introduces potential data loss if the primary fails before standbys receive recent transactions. Synchronous replication (<code class="language-text">synchronous_commit = on</code>) waits for at least one standby to acknowledge WAL writes before committing, trading performance for zero data loss. Configure multiple synchronous standbys with quorum: <code class="language-text">synchronous_standby_names = &#39;ANY 2 (standby1, standby2, standby3)&#39;</code> requires any two standbys to acknowledge before committing.</p>
<p>Read replicas offload SELECT queries from the primary, horizontally scaling read capacity. Configure multiple standbys, then route read traffic across them using connection pooling or application-level load balancing. HAProxy provides effective round-robin distribution with health checks. Monitor replication lag with <code class="language-text">pg_stat_replication</code> on the primary—check <code class="language-text">write_lag</code>, <code class="language-text">flush_lag</code> and <code class="language-text">replay_lag</code> columns. Aim for lag under 1 second for local replicas, under 5 seconds for cross-region. High lag indicates network issues, under-provisioned replica hardware, or long-running transactions blocking WAL replay.</p>
<p>Logical replication enables selective table replication and cross-version replication, unlike physical streaming replication&#39;s full-cluster approach. Create publications on the source: <code class="language-text">CREATE PUBLICATION my_pub FOR TABLE users, orders</code>. Create subscriptions on the target: <code class="language-text">CREATE SUBSCRIPTION my_sub CONNECTION &#39;host=source_db&#39; PUBLICATION my_pub</code>. Logical replication supports heterogeneous targets, enabling blue-green deployments and gradual migrations.</p>
<p><strong>PgBouncer provides connection pooling, allowing 10-50x more client connections</strong> than direct PostgreSQL connections. PostgreSQL&#39;s process-per-connection model consumes 5-10MB per connection; with 1000 connections, that&#39;s 5-10GB overhead. PgBouncer runs as a lightweight proxy, maintaining a small pool of server connections while accepting thousands of client connections. Configure <code class="language-text">pool_mode = transaction</code> for optimal concurrency—connections return to the pool after each transaction completes, maximizing reuse.</p>
<pre><code>[pgbouncer]
pool_mode = transaction
default_pool_size = 25
max_client_conn = 1000
reserve_pool_size = 5
server_idle_timeout = 600
</code></pre><p>Calculate pool size using <code class="language-text">(num_cores × 2) + effective_spindle_count</code>. An 8-core system with SSD typically needs 20 server connections. Allow 50x more client connections than server connections through pooling. Transaction mode provides 2-3x throughput improvement compared to direct connections. Limitations include incompatibility with session-level features like temporary tables persisting across transactions and SET parameters outside transactions.</p>
<p>Citus extension enables sharding—distributing data across multiple PostgreSQL servers. Install with <code class="language-text">CREATE EXTENSION citus</code>, configure a coordinator node, then add worker nodes with <code class="language-text">SELECT citus_add_node(&#39;worker_host&#39;, 5432)</code>. Create distributed tables with <code class="language-text">SELECT create_distributed_table(&#39;events&#39;, &#39;tenant_id&#39;)</code>, specifying the shard key. Queries filtering by shard key execute on relevant workers only, providing linear scalability.</p>
<p><strong>Shard key selection critically impacts performance</strong>. Choose high-cardinality columns appearing in WHERE clauses and JOIN conditions. Multi-tenant SaaS applications shard by tenant_id, IoT systems by device_id. Avoid sequential IDs, low-cardinality columns, or frequently updated values. Colocate related tables using the same shard key to enable efficient JOINs within workers: <code class="language-text">SELECT create_distributed_table(&#39;users&#39;, &#39;tenant_id&#39;, colocate_with =&gt; &#39;events&#39;)</code>.</p>
<p>Schema-based sharding in Citus 12+ simplifies multi-tenant architectures. Each tenant gets a dedicated schema: <code class="language-text">CREATE SCHEMA tenant_1</code>. Tables created in distributed schemas automatically shard by schema. This enables tenant isolation, per-tenant backups and straightforward migrations. Set <code class="language-text">search_path TO tenant_1</code> to route queries to specific tenants.</p>
<h2 id="search-capabilities">Search Capabilities</h2>
<h3 id="full-text-search">Full-Text Search</h3>
<p>PostgreSQL&#39;s built-in full-text search provides text search capabilities competitive with Elasticsearch for datasets under 5 million records.</p>
<p>There are two complementary search modes:</p>
<ul>
<li><p>Tokenized full-text search (tsvector/tsquery): language-aware matching with ranking based on term frequency and normalization. PostgreSQL provides TF‑IDF like ranking via <code class="language-text">ts_rank</code> and cover-density via <code class="language-text">ts_rank_cd</code>. This is not strict BM25, though it behaves similarly for many use cases. For exact BM25 scoring, consider extensions (e.g., RUM or PGroonga), otherwise <code class="language-text">ts_rank</code> normalization options are typically sufficient.</p>
</li>
<li><p>Substring/fuzzy search (pg_trgm): fast substring, prefix and typo-tolerant matching using trigrams. This does not tokenize or stem; it matches character n-grams and is ideal for autocomplete, partial matches (<code class="language-text">%term%</code>) and fuzzy lookups.</p>
</li>
</ul>
<p>When to choose which:</p>
<ul>
<li>Use tsvector/tsquery (TF‑IDF-like ranking) for language-aware search, stemming, stop words and boolean/phrase queries.</li>
<li>Use pg_trgm for substring/prefix matches, fuzzy lookup and autocomplete. It does not stem or understand language but excels at partial matches. Checkout <a href="https://github.com/CrystallineCore/Biscuit">biscuit</a> index for even faster substring searches (though trading index size for speed)</li>
<li>Scaling: tsvector (TF‑IDF) generally scales better on large corpora (smaller, more selective indexes and lower write overhead). pg_trgm (trigram) indexes grow with text length and unique trigrams, can be much larger and heavier to maintain; prefer it for small/medium tables or short text fields (titles, usernames) and autocomplete.</li>
</ul>
<h4 id="token-search-tf-idf">Token Search (TF-IDF)</h4>
<p>Create tsvector columns using generated columns (PostgreSQL 12+) for automatic maintenance: <code class="language-text">search_vector tsvector GENERATED ALWAYS AS (to_tsvector(&#39;english&#39;, coalesce(title, &#39;&#39;) || &#39; &#39; || coalesce(body, &#39;&#39;))) STORED</code>. This pre-computes normalized lexemes, avoiding expensive on-the-fly computation during queries. Weight different fields using <code class="language-text">setweight()</code> to prioritize titles over body text:</p>
<pre><code>search_vector tsvector GENERATED ALWAYS AS (
    setweight(to_tsvector(&#39;english&#39;, coalesce(title, &#39;&#39;)), &#39;A&#39;) ||
    setweight(to_tsvector(&#39;english&#39;, coalesce(body, &#39;&#39;)), &#39;D&#39;)
) STORED
</code></pre><p><strong>GIN on tsvector</strong> provides optimal full-text search performance, delivering <strong>query speedups of 50-100x</strong> compared to sequential scans. GIN indexes store an inverted index mapping each lexeme to matching document locations. Create with <code class="language-text">CREATE INDEX idx_search ON documents USING GIN(search_vector)</code>. For read-heavy workloads, disable fastupdate: <code class="language-text">CREATE INDEX idx_search ON documents USING GIN(search_vector) WITH (fastupdate = off)</code>. This trades slower writes for faster reads by eliminating the pending list that batches updates.</p>
<p>GiST indexes offer an alternative for write-heavy workloads. GiST builds tree structures with fixed-size document signatures, consuming less disk space and updating faster than GIN. However, GiST queries run approximately 3x slower and produce false positives requiring row rechecks. Choose GIN for most applications; reserve GiST for scenarios with severe write contention and limited disk space.</p>
<p>Query using the <code class="language-text">@@</code> match operator: <code class="language-text">WHERE search_vector @@ to_tsquery(&#39;english&#39;, &#39;postgresql &amp; database&#39;)</code>. Use <code class="language-text">websearch_to_tsquery()</code> for user input—it handles quoted phrases, OR operators and minus prefixes safely: <code class="language-text">websearch_to_tsquery(&#39;english&#39;, &#39;&quot;full text&quot; search -index&#39;)</code> converts to proper tsquery syntax. Rank results with <code class="language-text">ts_rank()</code> or <code class="language-text">ts_rank_cd()</code> (cover density ranking considering term proximity):</p>
<pre><code>SELECT title, ts_rank(search_vector, query) AS rank
FROM articles, to_tsquery(&#39;english&#39;, &#39;postgresql &amp; performance&#39;) query
WHERE search_vector @@ query
ORDER BY rank DESC
LIMIT 20;
</code></pre><p><strong>Properly optimized PostgreSQL full-text search achieves 6-10ms query times on 1.5 million records</strong>, competitive with Elasticsearch&#39;s 20ms on equivalent datasets. Keys to optimization include stored tsvector columns, GIN indexes with fastupdate disabled and appropriate weighting. Real-world implementations show fintech companies like Qonto migrating from Elasticsearch to PostgreSQL FTS to simplify their stack while maintaining similar performance.</p>
<p>Advanced features include phrase searches with <code class="language-text">phraseto_tsquery()</code>, prefix matching with <code class="language-text">:*</code> operators and proximity searches with distance operators. Highlight matching terms in results using <code class="language-text">ts_headline()</code> with custom start/stop delimiters. Configure multiple language dictionaries per database to support multilingual content, switching configurations per query.</p>
<p>Extensions:</p>
<ul>
<li><a href="https://github.com/paradedb/paradedb">https://github.com/paradedb/paradedb</a></li>
<li><a href="https://github.com/tensorchord/VectorChord-bm25">https://github.com/tensorchord/VectorChord-bm25</a></li>
</ul>
<h4 id="substring-fuzzy-trigram">Substring / Fuzzy (trigram)</h4>
<p>Use pg_trgm when you need partial matches (<code class="language-text">%term%</code>), autocomplete, or typo-tolerant search. It indexes character trigrams, not tokens, and works great alongside full-text search:</p>
<pre><code>-- Enable extension once per database
CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- GIN trigram index: best for filtering ILIKE/LIKE/% similarity
CREATE INDEX CONCURRENTLY idx_documents_title_trgm
  ON documents USING GIN (title gin_trgm_ops);

-- Optional: GiST trigram index if you need KNN ORDER BY &lt;-&gt; (nearest by similarity)
-- CREATE INDEX CONCURRENTLY idx_documents_title_trgm_gist
--   ON documents USING GIST (title gist_trgm_ops);
</code></pre><p>Common queries:</p>
<pre><code>-- Substring match with ranking by similarity (works well with GIN)
SELECT id, title
FROM documents
WHERE title ILIKE &#39;%postgres%&#39;
ORDER BY similarity(title, &#39;postgres&#39;) DESC
LIMIT 20;

-- Fuzzy match using trigram similarity operator
SELECT id, title
FROM documents
WHERE title % &#39;postgras&#39;                 -- allows typos
ORDER BY similarity(title, &#39;postgras&#39;) DESC
LIMIT 20;

-- Fast KNN if using GiST trigram index
SELECT id, title FROM documents ORDER BY title &lt;-&gt; &#39;postgres&#39; LIMIT 20;

-- Tune threshold (default ~0.3) to control fuzziness
SELECT set_limit(0.4);  -- session-level
</code></pre><h3 id="vector-search">Vector Search</h3>
<p>There are multiple powerful extensions for vector similarity search for Postgres - check out <a href="/posts/vector-databases">this article</a> for an overview with benchmarks.</p>
<h3 id="geospatial-queries-postgis">Geospatial Queries (PostGIS)</h3>
<p><a href="https://postgis.net/">PostGIS</a> extends PostgreSQL with comprehensive geographic information system capabilities. Install with <code class="language-text">CREATE EXTENSION postgis</code>, enabling spatial data types, measurement functions and specialized indexes. PostGIS 3.5+ requires PostgreSQL 12+ with GEOS 3.8+ and PROJ 6.1+ for full functionality. Recent versions introduced improvements like ST_CoverageClean for topology operations and enhanced SFCGAL support for 3D geometries.</p>
<p>PostGIS provides two core spatial types with distinct use cases. <strong>Geometry types</strong> perform planar calculations using Cartesian mathematics, appropriate for local or regional data within a few hundred kilometers. Geometry operations execute quickly but lose accuracy across large distances due to earth curvature. <strong>Geography types</strong> calculate on a spheroid representing Earth&#39;s actual shape, providing accurate great circle distances globally. Geography operations run slower but always return correct measurements in meters.</p>
<pre><code>-- Geometry: fast but inaccurate for global distances
SELECT ST_Distance(
  &#39;SRID=4326;POINT(-118.4 33.9)&#39;::geometry,  -- LA
  &#39;SRID=4326;POINT(2.5 49.0)&#39;::geometry      -- Paris
);  -- Returns 122 degrees (meaningless)

-- Geography: accurate global distances  
SELECT ST_Distance(
  &#39;SRID=4326;POINT(-118.4 33.9)&#39;::geography,
  &#39;SRID=4326;POINT(2.5 49.0)&#39;::geography
);  -- Returns 9125170 meters (correct)
</code></pre><p>Spatial Reference System Identifiers (SRIDs) define coordinate systems. SRID 4326 represents WGS 84 (GPS coordinates), while 3857 provides Web Mercator used by mapping applications. Transform between projections with <code class="language-text">ST_Transform(geom, target_srid)</code>. Always set SRIDs explicitly: <code class="language-text">ST_SetSRID(ST_MakePoint(-73.9857, 40.7484), 4326)</code>. Operations require matching SRIDs or explicit transformation.</p>
<p><strong>GiST indexes provide 100-1000x query speedup</strong> for spatial operations. Create with: <code class="language-text">CREATE INDEX idx_places_geom ON places USING GIST (geom)</code>. For point datasets with uniform distribution, SP-GiST indexes build 3x faster and query 1.5x faster than GiST through quad-tree partitioning. BRIN indexes suit massive, spatially sorted datasets: index sizes are 2000x smaller than GiST (24KB versus 53MB for 1M points) but require sequential access patterns.</p>
<p>Proximity searches use <code class="language-text">ST_DWithin()</code> for index-aware filtering: <code class="language-text">WHERE ST_DWithin(location::geography, search_point::geography, 1000)</code> finds points within 1000 meters. Never use <code class="language-text">WHERE ST_Distance() &lt; 1000</code>—this prevents index usage and scans every row. For nearest neighbor queries, use the distance operator: <code class="language-text">ORDER BY location &lt;-&gt; search_point LIMIT 5</code>. This leverages GiST index K-NN functionality for efficient ordering.</p>
<pre><code>-- Find restaurants within 500m
SELECT name, ST_Distance(location::geography, search::geography) AS dist
FROM restaurants
CROSS JOIN (SELECT &#39;SRID=4326;POINT(-73.9857 40.7484)&#39;::geography) s(search)
WHERE ST_DWithin(location::geography, s.search, 500)
ORDER BY dist;
</code></pre><p>Spatial relationship functions enable complex queries. <code class="language-text">ST_Contains()</code> tests if one geometry fully encloses another, useful for point-in-polygon queries: <code class="language-text">WHERE ST_Contains(neighborhood_boundary, business_location)</code>. <code class="language-text">ST_Intersects()</code> determines overlap, <code class="language-text">ST_Within()</code> tests containment and <code class="language-text">ST_Crosses()</code> detects geometric crossings. Combine with aggregations for analytics: <code class="language-text">SELECT neighborhood, COUNT(*) FROM businesses JOIN neighborhoods ON ST_Contains(boundary, location) GROUP BY neighborhood</code>.</p>
<p>Measurement functions calculate geometric properties. <code class="language-text">ST_Area()</code> computes polygon areas (use geography for square meters, geometry for projected units). <code class="language-text">ST_Length()</code> measures line lengths. <code class="language-text">ST_Buffer()</code> creates zones around geometries: <code class="language-text">ST_Buffer(location::geography, 500)</code> generates 500-meter radius circles around points. Subdivide complex geometries with <code class="language-text">ST_Subdivide()</code> to improve query performance on large features.</p>
<p>Query optimization requires proper index usage and simplified geometries. Add bounding box pre-filters: <code class="language-text">WHERE geom &amp;&amp; ST_MakeEnvelope(xmin, ymin, xmax, ymax, 4326) AND ST_Intersects(geom, search_area)</code>. The <code class="language-text">&amp;&amp;</code> operator performs fast bounding box overlap checks using the index before expensive geometric calculations. Use <code class="language-text">ST_Centroid()</code> for approximate distance calculations on large polygons. Configure <code class="language-text">random_page_cost = 1.0</code> for SSD storage and <code class="language-text">effective_io_concurrency = 200</code> for NVMe.</p>
<h2 id="embedded-testing">Embedded (Testing)</h2>
<p>Check out <a href="https://pglite.dev/">PGLite</a> for a small embeddable WebAssembly version of Postgres - being a good alternative to SQLite and thus ideal for testing and client-side deployments of Postgres (with the limitation of accepting only one connection though).</p>
<p>And check out <a href="https://github.com/theseus-rs/postgresql-embedded">postgresql-embedded</a> for a Rust package that embeds Postgres without limitations (supports extions).</p>
<h2 id="useful-features">Useful Features</h2>
<ol>
<li>EXCLUDE constraints: To avoid overlapping time slots</li>
</ol>
<p>If you ever needed to prevent overlapping time slots for the same resource, then the EXCLUDE constraint is extremely useful. It enforces that no two rows can have overlapping ranges for the same key.</p>
<ol start="2">
<li>CHECK constraints: For validating data at the source</li>
</ol>
<p>CHECK constraints allow you to specify that the value in a column must satisfy a Boolean expression. They enforce rules like &quot;age must be between 0 and 120&quot; or &quot;end_date must be after start_date.&quot;</p>
<ol start="3">
<li>GENERATED columns: To let the database do the math</li>
</ol>
<p>If you’re tired of calculating derived values in your app, you can let PostgreSQL handle it with GENERATED columns.</p>
<h2 id="useful-commands">Useful Commands</h2>
<p><strong>Show sizes of all tables</strong> + index + toast (The Oversized Attribute Storage Technique - used for long texts / json storage):</p>
<pre><code>SELECT
   relname as table_name,
   pg_size_pretty(pg_total_relation_size(relid)) AS total_size,
   pg_size_pretty(pg_indexes_size(relid)) AS index_size,
   pg_size_pretty(pg_relation_size(relid)) AS data_size,
   pg_size_pretty(pg_table_size(relid) - pg_relation_size(relid)) AS toast_size
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;
</code></pre><p><strong>Show sizes of all indices for a table</strong>:</p>
<pre><code>SELECT
  i.indexrelname AS index_name,
  pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size,
  am.amname AS index_type,
  string_agg(a.attname, &#39;, &#39; ORDER BY array_position(ix.indkey::int[], a.attnum)) AS indexed_columns
FROM
  pg_stat_all_indexes i
JOIN
  pg_class c ON i.indexrelid = c.oid
JOIN
  pg_am am ON c.relam = am.oid
JOIN
  pg_index ix ON i.indexrelid = ix.indexrelid
JOIN
  pg_attribute a ON a.attrelid = i.relid AND a.attnum = ANY(ix.indkey)
WHERE
  i.relname = &#39;table_name&#39;
GROUP BY
  i.indexrelname, pg_relation_size(i.indexrelid), am.amname
ORDER BY
  pg_relation_size(i.indexrelid) DESC;
</code></pre><p><strong>Show sizes of all indices for a partitioned table</strong>:</p>
<pre><code>SELECT
  am.amname AS index_type,
  pg_size_pretty(SUM(pg_relation_size(i.indexrelid))) AS total_index_size
FROM
  pg_stat_all_indexes i
JOIN
  pg_class c ON i.indexrelid = c.oid
JOIN
  pg_am am ON c.relam = am.oid
JOIN
  pg_inherits pi ON pi.inhrelid = i.relid
WHERE
  pi.inhparent = &#39;table_name&#39;::regclass
GROUP BY
  am.amname
ORDER BY
  SUM(pg_relation_size(i.indexrelid)) DESC;
</code></pre><p><strong>Show active transactions</strong>:</p>
<pre><code>SELECT pid, usename, datname, application_name, client_addr, backend_xid, xact_start, query, state
FROM pg_stat_activity
WHERE backend_xid IS NOT NULL;
</code></pre><p><strong>Show all locks on tables</strong>:</p>
<pre><code>SELECT
  COALESCE(blocking_locks.relation::regclass::text, blocking_locks.locktype) AS locked_item,
  now() - blocked_activity.query_start AS waiting_duration,
  blocked_activity.pid AS blocked_pid,
  blocked_activity.query AS blocked_query,
  blocked_locks.mode AS blocked_mode,
  blocking_activity.pid AS blocking_pid,
  blocking_activity.query AS blocking_query,
  blocking_locks.mode AS blocking_mode,
  blocking_activity.usename AS blocking_user,
  blocked_activity.usename AS blocked_user
FROM
  pg_catalog.pg_locks blocked_locks
JOIN
  pg_stat_activity blocked_activity ON blocked_locks.pid = blocked_activity.pid
JOIN
  pg_catalog.pg_locks blocking_locks ON (
    (blocking_locks.transactionid = blocked_locks.transactionid)
    OR
    (blocking_locks.relation = blocked_locks.relation AND blocking_locks.locktype = blocked_locks.locktype)
  )
  AND blocked_locks.pid != blocking_locks.pid
JOIN
  pg_stat_activity blocking_activity ON blocking_locks.pid = blocking_activity.pid
WHERE
  NOT blocked_locks.granted
ORDER BY
  waiting_duration DESC;
</code></pre><p><strong>Kill process</strong>:</p>
<pre><code>SELECT pg_terminate_backend(PID);
</code></pre><h2 id="export-import">Export / Import</h2>
<p>Export schema only (no indices / constraints):</p>
<pre><code>pg_dump \
  -Fc \
  --schema-only \
  --section=pre-data \
  --no-owner \
  --no-privileges \
  -U postgres \
  -d your_db \
  &gt; your_db_tables_only.dump
</code></pre><p>Export data only (rows):</p>
<pre><code>pg_dump \
  -Fc \
  --data-only \
  --exclude-schema=_timescaledb_internal \
  --no-owner \
  --no-privileges \
  -U postgres \
  -d your_db \
  &gt; your_db_data.dump
</code></pre><p>Restore (on same Posgres version):</p>
<pre><code># 1. Tables only
pg_restore \
  -U postgres \
  -d your_db \
  your_db_tables_only.dump

# 2. Data
pg_restore \
  --data-only \
  --disable-triggers \
  -j 8 \
  -U postgres \
  -d your_db \
  &lt; your_db_data.dump
</code></pre><h2 id="references">References</h2>
<ul>
<li><a href="https://github.com/postgres/postgres">https://github.com/postgres/postgres</a></li>
<li><a href="https://www.postgresql.org/">https://www.postgresql.org/</a></li>
<li><a href="https://www.pixelstech.net/article/1747708863-openai%3a-scaling-postgresql-to-the-next-level">https://www.pixelstech.net/article/1747708863-openai%3a-scaling-postgresql-to-the-next-level</a><ul>
<li><a href="https://news.ycombinator.com/item?id=44071418">HN Discussion</a></li>
</ul>
</li>
<li><a href="https://dlt.github.io/blog/posts/introduction-to-postgresql-indexes/">Introduction to Postgres Indexes</a></li>
<li><a href="https://hakibenita.com/postgresql-unconventional-optimizations">Unconventional Postgres Optimizations</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Postgres as Vector DB - a benchmark</title>
      <link>https://seanpedersen.github.io/posts/vector-databases</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/vector-databases</guid>
      <pubDate>Wed, 08 Oct 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>There is a flood of vector databases - which ones are actually useful? IMO extending a relational DBMS with ACID compliance and existing datasets, is for most use cases the ideal choice. Using a dedicated vector DB like (<a href="https://www.trychroma.com/">Chroma</a>, <a href="https://github.com/vespa-engine/vespa">Vespa</a>, <a href="https://turbopuffer.com/">Turbopuffer</a>, <a href="https://github.com/lancedb/lancedb">LanceDB</a>, <a href="https://milvus.io/">Milvus</a> etc.) only makes sense for narrow use cases where no complicated meta-data filters are needed (e.g. just simple RAG) and data synchronisation is no issue.</p>
<p>So let&#39;s have a look how we can store and search vectors using Postgres - there are three notable extensions for Postgres: pgvector, pgvectorscale and vectorchord.</p>
<h2 id="pgvector"><a href="https://github.com/pgvector/pgvector">PGVector</a></h2>
<p>Standard extension to store vectors with common medium scale ANN indices (HNSW &amp; IvfFlat). Integration package for Python: <a href="https://github.com/pgvector/pgvector-python/">https://github.com/pgvector/pgvector-python/</a></p>
<p>Store vectors (float 32 bit):</p>
<pre><code>CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(1024));
</code></pre><p>Store half-precision (float 16 bit) vectors:</p>
<pre><code>CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(1024));
</code></pre><h3 id="hnsw"><a href="https://github.com/nmslib/hnswlib">HNSW</a></h3>
<p>Hierarchical navigable small world (HNSW) is a popular graph based ANN index - delivering good retrieval and QPS performance but at the cost of longer index build times and using more RAM for it (did crash for 1 million vectors on my 16GB RAM machine).</p>
<h3 id="ivfflat">IvfFlat</h3>
<p>Inverted File Flat (IvfFlat) is less RAM hungry than HNSW. With caveats: IvfFlat performance degrades as vectors are deleted and added (because centroids are not updated), thus needing regular index rebuilds (if new vectors get inserted regularly).</p>
<p>&quot;As data gets inserted or deleted from the index, if the index is not rebuilt, the IVFFlat index in pgvector can return incorrect approximate nearest neighbors due to clustering centroids no longer fitting the data well&quot;</p>
<h4 id="ivfflat-binary-with-reranking">IvfFlat Binary (with reranking)</h4>
<p>Build IvfFlat index on binarized vectors -&gt; on query: overfetch Kx10 nearest neighbors, then rerank using float16/32 vectors to get more accurate final K-NN.</p>
<pre><code>-- Mean threshold binarization (performs better than pgvector&#39;s binarizer)
CREATE OR REPLACE FUNCTION binary_quantize_mean(vec halfvec) 
RETURNS varbit AS $$
    SELECT string_agg(
        CASE WHEN val &gt;= mean_val THEN &#39;1&#39; ELSE &#39;0&#39; END, 
        &#39;&#39;
    )::varbit
    FROM unnest(vec::real[]) AS val,
         (SELECT AVG(v) AS mean_val FROM unnest(vec::real[]) AS v) AS stats;
$$ LANGUAGE sql IMMUTABLE PARALLEL SAFE;

-- Step 1: Add a stored generated binary column
ALTER TABLE table_name 
ADD COLUMN vector_bin bit(512) 
GENERATED ALWAYS AS (binary_quantize_mean(vector)::bit(512)) STORED;

-- Step 2: Create index on the pre-computed binary column
CREATE INDEX IF NOT EXISTS table_name_idx_ivfflat_bin 
ON table_name 
USING ivfflat (vector_bin bit_hamming_ops) 
WITH (lists = 100);

-- Query top 100 NN using reranking
SELECT t.id
FROM (
  SELECT id
  FROM table_name
  ORDER BY vector_bin &lt;~&gt; binary_quantize_mean(%s::halfvec(512))::bit(512)
  LIMIT 1000
) c
JOIN table_name t USING(id)
ORDER BY t.vector &lt;=&gt; %s::halfvec(512)
LIMIT 100;
</code></pre><h2 id="pgvectorscale"><a href="https://github.com/timescale/pgvectorscale">PGVectorScale</a></h2>
<h3 id="diskann">DiskANN</h3>
<p>A promising ANN index that uses RAM and disk (needs fast disk - SSD / NVMe) to scale to billions of vectors, promising low RAM usage while still providing decent QPS. The problem is that the pgvectorscale index building implementation is <a href="https://github.com/timescale/pgvectorscale/issues/38">single core right now</a> - leading to very long index generation times.</p>
<p>PGVectorScale supports pre-filtering using bitfields with manual meta-data table setup (complicated / bad dev ux).</p>
<h2 id="vectorchord"><a href="https://github.com/tensorchord/VectorChord">VectorChord</a></h2>
<h3 id="vchordrq"><a href="https://docs.vectorchord.ai/vectorchord/usage/indexing.html">VChordRQ</a></h3>
<p>A custom ANN index with excellent performance (combining IVF ANN index with RaBitQ quantization). Supports pre-filtering (easy to use).</p>
<p>VChord can be configured to not copy all vectors into the index (which is the default and pgvector also does), reducing disk usage - it can be <a href="https://docs.vectorchord.ai/vectorchord/usage/rerank-in-table.html">enabled</a> (slightly degrading performance).</p>
<p>VChord also supports efficient <a href="https://docs.vectorchord.ai/vectorchord/usage/range-query.html">range filters</a> (limiting results by distance instead of K nearest neighbors).</p>
<h3 id="vchordg-diskann"><a href="https://docs.vectorchord.ai/vectorchord/usage/graph-index.html">VChordG</a> (DiskANN)</h3>
<p>A novel addition (not prodution ready yet): custom implementation of DiskANN index combined with RaBitQ quantization.</p>
<ul>
<li><a href="https://blog.vectorchord.ai/vectorchord-05-new-rabitq-empowered-diskann-index-and-continuous-recall-measurement?source=more_articles_bottom_blogs">https://blog.vectorchord.ai/vectorchord-05-new-rabitq-empowered-diskann-index-and-continuous-recall-measurement?source=more_articles_bottom_blogs</a></li>
</ul>
<h2 id="benchmark">Benchmark</h2>
<p>The benchmark should reflect realistic usage - right now it just measures index build and query times.</p>
<p>In the future I want to extend it:</p>
<ul>
<li>measure insertion perormance after initial index is built</li>
<li>use real data embedding vectors -&gt; simulate data distribution shift (insert many vectors after index was built)</li>
<li>simulate realistic complex SQL queries involving categorical and range filtering</li>
<li>benchmark vector scales: 100K, 1M, 10M, 100M, 1B</li>
</ul>
<h2 id="ann-benchmark-results">ANN Benchmark Results</h2>
<p>The table below was computed using 100K CLIP Matryoshka text embeddings.</p>
<div class="table-wrapper"><table><thead><th>Index</th><th>Recall@100 (%)</th><th>Latency (ms)</th><th>Dim</th><th>Storage</th><th>Build (s)</th><th>Storage (MB)</th><th>Index (MB)</th></thead><tbody><tr><td>binary_mean_ivf_rerank</td><td>90.0</td><td>14.20</td><td>1024</td><td>float32</td><td>2.12</td><td>429.7</td><td>14.6</td></tr><tr><td>binary_mean_ivf_rerank</td><td>92.0</td><td>15.10</td><td>1024</td><td>float16</td><td>0.86</td><td>214.8</td><td>14.6</td></tr><tr><td>binary_uint8_ivf_rerank</td><td>100.0</td><td>37.67</td><td>1024</td><td>float32</td><td>7.43</td><td>429.7</td><td>98.1</td></tr><tr><td>binary_uint8_ivf_rerank</td><td>100.0</td><td>39.94</td><td>1024</td><td>float16</td><td>4.75</td><td>214.8</td><td>98.1</td></tr><tr><td>binary_uint4_ivf_rerank</td><td>100.0</td><td>17.00</td><td>1024</td><td>float32</td><td>2.77</td><td>429.7</td><td>52.5</td></tr><tr><td>binary_uint4_ivf_rerank</td><td>100.0</td><td>17.06</td><td>1024</td><td>float16</td><td>3.78</td><td>214.8</td><td>52.5</td></tr><tr><td>vchordrq</td><td>96.0</td><td>18.06</td><td>1024</td><td>float32</td><td>12.34</td><td>429.7</td><td>50.2</td></tr><tr><td>vchordrq</td><td>97.0</td><td>25.38</td><td>1024</td><td>float16</td><td>11.68</td><td>214.8</td><td>47.6</td></tr><tr><td>diskann</td><td>96.0</td><td>18.48</td><td>1024</td><td>float32</td><td>156.78</td><td>429.7</td><td>55.8</td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>binary_mean_ivf_rerank</td><td>84.0</td><td>13.90</td><td>512</td><td>float32</td><td>0.84</td><td>214.8</td><td>8.5</td></tr><tr><td>binary_mean_ivf_rerank</td><td>84.0</td><td>11.70</td><td>512</td><td>float16</td><td>0.77</td><td>107.4</td><td>8.5</td></tr><tr><td>binary_uint8_ivf_rerank</td><td>94.0</td><td>21.77</td><td>512</td><td>float32</td><td>2.54</td><td>214.8</td><td>52.5</td></tr><tr><td>binary_uint8_ivf_rerank</td><td>94.0</td><td>20.03</td><td>512</td><td>float16</td><td>3.47</td><td>107.4</td><td>52.5</td></tr><tr><td>binary_uint4_ivf_rerank</td><td>94.0</td><td>14.34</td><td>512</td><td>float32</td><td>1.15</td><td>214.8</td><td>27.3</td></tr><tr><td>binary_uint4_ivf_rerank</td><td>94.0</td><td>12.03</td><td>512</td><td>float16</td><td>1.23</td><td>107.4</td><td>27.4</td></tr><tr><td>vchordrq</td><td>94.0</td><td>27.55</td><td>512</td><td>float32</td><td>7.70</td><td>214.8</td><td>41.5</td></tr><tr><td>vchordrq</td><td>94.0</td><td>23.27</td><td>512</td><td>float16</td><td>7.51</td><td>107.4</td><td>40.0</td></tr><tr><td>diskann</td><td>94.0</td><td>31.49</td><td>512</td><td>float32</td><td>159.26</td><td>214.8</td><td>55.8</td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>binary_mean_ivf_rerank</td><td>73.0</td><td>11.88</td><td>256</td><td>float32</td><td>0.47</td><td>107.4</td><td>5.4</td></tr><tr><td>binary_mean_ivf_rerank</td><td>73.0</td><td>9.72</td><td>256</td><td>float16</td><td>0.33</td><td>53.7</td><td>5.4</td></tr><tr><td>binary_uint8_ivf_rerank</td><td>86.0</td><td>13.94</td><td>256</td><td>float32</td><td>1.63</td><td>107.4</td><td>27.4</td></tr><tr><td>binary_uint8_ivf_rerank</td><td>86.0</td><td>11.89</td><td>256</td><td>float16</td><td>1.26</td><td>53.7</td><td>27.3</td></tr><tr><td>binary_uint4_ivf_rerank</td><td>84.0</td><td>75.42</td><td>256</td><td>float32</td><td>1.26</td><td>107.4</td><td>14.6</td></tr><tr><td>binary_uint4_ivf_rerank</td><td>84.0</td><td>13.22</td><td>256</td><td>float16</td><td>1.15</td><td>53.7</td><td>14.6</td></tr><tr><td>vchordrq</td><td>86.0</td><td>22.14</td><td>256</td><td>float32</td><td>7.22</td><td>107.4</td><td>36.6</td></tr><tr><td>vchordrq</td><td>86.0</td><td>16.66</td><td>256</td><td>float16</td><td>7.16</td><td>53.7</td><td>35.9</td></tr><tr><td>diskann</td><td>86.0</td><td>25.21</td><td>256</td><td>float32</td><td>152.00</td><td>107.4</td><td>48.8</td></tr></tbody></table></div><h2 id="optimizing-vector-index-storage">Optimizing Vector &amp; Index Storage</h2>
<p>When things scale up one should strive for efficient vector storage using:</p>
<ul>
<li>Vector Dimensionality Reduction<ul>
<li>Product Quantization (PQ): reduces both dimensionality and bit representation</li>
<li>Matryoshka Embeddings: superior performance vs PQ as it learns the reduction in training and not post-training</li>
<li>PCA / UMAP</li>
</ul>
</li>
<li>Scalar Quantization (Reduce bit representation per dimension)<ul>
<li>FP16: half precision from FP32</li>
<li>binary: reduce to single bit<ul>
<li>In pgvector: binary quantization will reduce any positive value to 1, and any zero or negative value to 0</li>
<li>Mean-based thresholding: binarize each dimension using its corpus-wide mean as the threshold, ensuring ~50/50 bit distribution per dimension for better information preservation and more discriminative binary codes.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>We can see that using IvfFlat index on binary representation with a top-K factor of 10x (overfetching), then reranking in higher precision (float32 or float16) results in excellent recall, low vector storage costs (float16) and very fast retrieval latencies.</p>
<p>Though the reranking can lead to complications with queries using metadata filtering, so just using vchordrq index with 512D and float16 can also make sense.</p>
<h2 id="show-me-the-code">Show me the code</h2>
<p>Check out the code <a href="https://github.com/SeanPedersen/vector-db-benchmark/tree/main">here</a></p>
<h2 id="conclusion">Conclusion</h2>
<p>VectorChord is a good choice - providing superior performance and better developer experience (pre-filtering and better default settings). The vchordrq index is for most use cases the ideal choice as it delivers great performance and handles data distribution drift better than diskann indices. Using an ANN index only starts to make sense for big numbers of vectors (over 1 million).</p>
<h2 id="references">References</h2>
<ul>
<li>The gold standard ANN benchmark: <a href="https://github.com/erikbern/ann-benchmarks">https://github.com/erikbern/ann-benchmarks</a></li>
<li><a href="https://vector-index-bench.github.io/overview.html">https://vector-index-bench.github.io/overview.html</a></li>
<li><a href="https://docs.vectorchord.ai/vectorchord/usage/indexing.html">https://docs.vectorchord.ai/vectorchord/usage/indexing.html</a></li>
<li><a href="https://blog.vectorchord.ai/vectorchord-store-400k-vectors-for-1-in-postgresql#heading-ivf-vs-hnsw">https://blog.vectorchord.ai/vectorchord-store-400k-vectors-for-1-in-postgresql#heading-ivf-vs-hnsw</a></li>
<li><a href="https://blog.vectorchord.ai/3-billion-vectors-in-postgresql-to-protect-the-earth">https://blog.vectorchord.ai/3-billion-vectors-in-postgresql-to-protect-the-earth</a></li>
<li><a href="https://drscotthawley.github.io/blog/posts/2023-06-12-RVQ.html">https://drscotthawley.github.io/blog/posts/2023-06-12-RVQ.html</a></li>
<li><a href="https://www.tigerdata.com/blog/nearest-neighbor-indexes-what-are-ivfflat-indexes-in-pgvector-and-how-do-they-work">https://www.tigerdata.com/blog/nearest-neighbor-indexes-what-are-ivfflat-indexes-in-pgvector-and-how-do-they-work</a></li>
<li><a href="https://jkatz05.com/post/postgres/pgvector-scalar-binary-quantization/">https://jkatz05.com/post/postgres/pgvector-scalar-binary-quantization/</a></li>
<li><a href="https://zilliz.com/learn/scalar-quantization-and-product-quantization">https://zilliz.com/learn/scalar-quantization-and-product-quantization</a></li>
<li><a href="https://medium.com/nlp-experiment/product-quantization-d66fdb860047">https://medium.com/nlp-experiment/product-quantization-d66fdb860047</a></li>
<li><a href="https://medium.com/@bavalpreetsinghh/pgvector-hnsw-vs-ivfflat-a-comprehensive-study-21ce0aaab931">https://medium.com/@bavalpreetsinghh/pgvector-hnsw-vs-ivfflat-a-comprehensive-study-21ce0aaab931</a></li>
<li><a href="https://github.com/RyanCodrai/turbovec">https://github.com/RyanCodrai/turbovec</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a> <a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Launching DROP</title>
      <link>https://seanpedersen.github.io/posts/launching-drop</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/launching-drop</guid>
      <pubDate>Wed, 01 Oct 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>launch</category>
      <content:encoded><![CDATA[
          <p><a href="https://drop.digger.lol/">DROP</a> is a location based social network (mobile app). It works by dropping posts (text or image) at your current location - other users can only collect a drop if they are within a radius of 50m. The idea is to promote engagement with your local community.</p>
<p>Now available in the App Store and soon also in the Play Store</p>
<p class="post-hashtags"><a href="/index.html#launch">#launch</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Digital Design</title>
      <link>https://seanpedersen.github.io/posts/digital-design</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/digital-design</guid>
      <pubDate>Wed, 24 Sep 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <style>
  .design-trends-table td {
    vertical-align: top;
  }

  .trend-examples {
    --trend-preview-aspect-ratio: 16 / 10;
    --trend-preview-width: 9rem;

    align-items: flex-start;
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
  }

  .trend-example {
    color: inherit;
    display: block;
    flex: 0 0 var(--trend-preview-width);
    min-width: 0;
    width: var(--trend-preview-width);
  }

  .trend-example img {
    aspect-ratio: var(--trend-preview-aspect-ratio);
    background: var(--color-bg, #fff);
    border: 1px solid rgba(127, 127, 127, 0.25);
    border-radius: 0.5rem;
    display: block;
    object-fit: cover;
    object-position: top center;
    width: 100%;
  }

  .trend-example span {
    display: block;
    margin-top: 0.35rem;
    text-decoration: underline;
    text-underline-offset: 2px;
  }

  @media (max-width: 768px) {
    .design-trends-table td {
      white-space: normal;
    }
  }
</style>

<p>Digital design is concerned with the creation and optimization of user interfaces and experiences across digital
  platforms (apps, web sites, etc.). At its foundation, effective digital design balances aesthetic appeal with
  functional usability, ensuring that users can accomplish their goals efficiently while enjoying the interaction. Good
  design is invisible to the untrained eye because it just works. The design of a product sets the tone and communicates
  (subconsciously) values to the user.</p>

<h2 id="good-design">Good Design</h2>
<p>Feels natural — usable without thinking how. Respects the user: increases user agency; bad design extracts it.</p>

<ul>
  <li>User controls their data
    <ul>
      <li>Use common file formats (for export / storage)</li>
    </ul>
  </li>
  <li>Information Hierarchy (pack UI elements together based on their semantics)
    <ul>
      <li>Minimizes mouse movement / provide keyboard shortcuts for common inputs</li>
    </ul>
  </li>
  <li>Iterative complexity (progressive disclosure of options)</li>
  <li>Minimize visual shift / movement (every moving pixel must add value)</li>
  <li>Use rows instead of boxes for items that have numerical values to compare</li>
  <li>Use hover highlight effects only for interactive components (links, buttons)</li>
  <li>Emotional Design: playful / rewards</li>
  <li>Cultural Differences: Japanese love information-dense UI</li>
</ul>

<h2 id="design-trends">Design Trends</h2>

<div class="table-wrapper">
  <table class="design-trends-table">
    <thead>
      <tr>
        <th>Trend</th>
        <th>Real examples</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>AI-native UX</td>
        <td>
          <div class="trend-examples">
            <a href="https://chatgpt.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/chatgpt.webp" alt="ChatGPT website preview" loading="lazy">
              <span>ChatGPT
            </a>
            <a href="https://www.perplexity.ai" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/perplexity.webp" alt="Perplexity website preview" loading="lazy">
              <span>Perplexity
            </a>
            <a href="https://www.figma.com/ai" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/figma-ai.webp" alt="Figma AI website preview" loading="lazy">
              <span>Figma AI
            </a>
          </div>
        </td>
      </tr>
      <tr>
        <td>Funky / unique product pages</td>
        <td>
          <div class="trend-examples">
            <a href="https://nothing.tech" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/nothing.webp" alt="Nothing website preview" loading="lazy">
              <span>Nothing
            </a>
            <a href="https://teenage.engineering" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/teenage-engineering.webp" alt="Teenage Engineering website preview"
                loading="lazy">
              <span>Teenage Engineering
            </a>
            <a href="https://liquiddeath.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/liquiddeath.webp" alt="Liquid Death website preview" loading="lazy">
              <span>Liquid Death
            </a>
            <a href="https://heydaycanning.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/heydaycanning.webp" alt="Heyday Canning Co. website preview" loading="lazy">
              <span>Heyday Canning Co.
            </a>
          </div>
        </td>
      </tr>
      <tr>
        <td>Bold / playful</td>
        <td>
          <div class="trend-examples">
            <a href="https://posthog.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/posthog.webp" alt="PostHog website preview" loading="lazy">
              <span>PostHog
            </a>
          </div>
        </td>
      </tr>
      <tr>
        <td>Neo-brutalism</td>
        <td>
          <div class="trend-examples">
            <a href="https://gumroad.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/gumroad.webp" alt="Gumroad website preview" loading="lazy">
              <span>Gumroad
            </a>
            <a href="https://www.figma.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/figma.webp" alt="Figma website preview" loading="lazy">
              <span>Figma
            </a>
          </div>
        </td>
      </tr>
      <tr>
        <td>Liquid glass</td>
        <td>
          <div class="trend-examples">
            <a href="https://www.apple.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/apple.webp" alt="Apple website preview" loading="lazy">
              <span>Apple
            </a>
          </div>
        </td>
      </tr>
      <tr>
        <td>Blueprint / grid aesthetic</td>
        <td>
          <div class="trend-examples">
            <a href="https://zed.dev" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/zed.webp" alt="Zed Editor website preview" loading="lazy">
              <span>Zed Editor
            </a>
            <a href="https://stripe.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/stripe.webp" alt="Stripe website preview" loading="lazy">
              <span>Stripe
            </a>
          </div>
        </td>
      </tr>
      <tr>
        <td>Anti-design</td>
        <td>
          <div class="trend-examples">
            <a href="https://mschf.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/mschf.webp" alt="MSCHF website preview" loading="lazy">
              <span>MSCHF
            </a>
            <a href="https://www.adultswim.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/adultswim.webp" alt="Adult Swim website preview" loading="lazy">
              <span>Adult Swim
            </a>
            <a href="https://www.studiojob.nl" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/studiojob.webp" alt="Studio Job website preview" loading="lazy">
              <span>Studio Job
            </a>
          </div>
        </td>
      </tr>
      <tr>
        <td>Immersive motion / storytelling</td>
        <td>
          <div class="trend-examples">
            <a href="https://www.apple.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/apple.webp" alt="Apple website preview" loading="lazy">
              <span>Apple
            </a>
            <a href="https://www.nike.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/nike.webp" alt="Nike website preview" loading="lazy">
              <span>Nike
            </a>
            <a href="https://www.tesla.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/tesla.webp" alt="Tesla website preview" loading="lazy">
              <span>Tesla
            </a>
          </div>
        </td>
      </tr>
      <tr>
        <td>Editorial / mixed-media layouts</td>
        <td>
          <div class="trend-examples">
            <a href="https://www.nytimes.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/nytimes.webp" alt="The New York Times website preview" loading="lazy">
              <span>The New York Times
            </a>
            <a href="https://www.newyorker.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/newyorker.webp" alt="The New Yorker website preview" loading="lazy">
              <span>The New Yorker
            </a>
            <a href="https://www.bbc.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/bbc.webp" alt="BBC website preview" loading="lazy">
              <span>BBC
            </a>
          </div>
        </td>
      </tr>
      <tr>
        <td>Calm minimalism</td>
        <td>
          <div class="trend-examples">
            <a href="https://obsidian.md" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/obsidian.webp" alt="Obsidian website preview" loading="lazy">
              <span>Obsidian
            </a>
            <a href="https://www.usbynight.be" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/usbynight.webp" alt="UsByNight website preview" loading="lazy">
              <span>UsByNight
            </a>
            <a href="https://www.cosstores.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/cos.webp" alt="COS website preview" loading="lazy">
              <span>COS
            </a>
            <a href="https://www.dropbox.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/dropbox.webp" alt="Dropbox website preview" loading="lazy">
              <span>Dropbox
            </a>
          </div>
        </td>
      </tr>
      <tr>
        <td>Performance-first design</td>
        <td>
          <div class="trend-examples">
            <a href="https://www.wikipedia.org" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/wikipedia.webp" alt="Wikipedia website preview" loading="lazy">
              <span>Wikipedia
            </a>
            <a href="https://www.craigslist.org" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/craigslist.webp" alt="Craigslist website preview" loading="lazy">
              <span>Craigslist
            </a>
            <a href="https://www.mcmaster.com" class="trend-example" target="_blank" rel="noopener noreferrer">
              <img src="/images/previews/mcmaster.webp" alt="McMaster website preview" loading="lazy">
              <span>McMaster
            </a>
          </div>
        </td>
      </tr>
    </tbody>
  </table>
</div>

<h2 id="bad-design">Bad Design</h2>
<p>In order to produce good design, it is very helpful to just feel bad designs.</p>

<p>Dark UX:</p>
<ul>
  <li>Locking up user data (in a server / custom storage format)</li>
  <li>Infinite scroll feeds (no ending — addictive for the user)</li>
  <li>Fake urgency (countdown timers, "only 2 left!")</li>
  <li>Requiring account creation before showing content</li>
  <li>Hiding the unsubscribe button (small text / many clicks)</li>
  <li>Forced app downloads to view mobile websites</li>
</ul>

<p>Bad UX:</p>
<ul>
  <li>Pop-ups (visual distractions)</li>
  <li>Deviating significantly from proven historical UI patterns</li>
  <li>Inconsistent navigation patterns between pages</li>
  <li>Overusage of animations (only move UI elements with a clear signal / purpose)</li>
  <li>Loading spinners that never end / indicate no progress</li>
  <li>Auto-playing videos with sound</li>
  <li>Confirmation dialogs for every minor action</li>
  <li>Non-descriptive error messages</li>
  <li>Disabling zoom on mobile</li>
  <li>Missing auto-focus of text input (search bars etc.)</li>
  <li>Low contrast text (poor accessibility)</li>
</ul>

<h2 id="impact">Impact</h2>
<p>Digital interfaces are control surfaces: they don't just enable actions, they shape which actions are likely to
  occur. Layout, defaults, friction and feedback loops guide attention and influence our behavior — often without the
  user's conscious awareness.</p>

<p>Because of this, design is never neutral. Repeated interaction patterns become <a
    href="/posts/memetics.html">memetic</a>: they train habits, normalize
  expectations and propagate values across products and cultures. An infinite feed normalizes consumption without
  closure; an opaque system teaches dependence; a reversible, inspectable UI teaches agency.</p>

<p>Bad design is therefore not just inconvenient — it is political. It encodes power asymmetries into everyday
  interactions by extracting our attention, data and autonomy. Good design does the opposite: it makes data control
  explicit and preserves optionality, to give the user the control they deserve.</p>

<h2 id="references">References</h2>
<ul>
  <li><a href="https://digdeepers.club/articles/design.xhtml" target="_blank" rel="noopener noreferrer">Principles of
      bad software design</a></li>
  <li><a href="https://sabrinas.space/" target="_blank" rel="noopener noreferrer">Japanese WebDesign</a></li>
  <li><a href="https://component.gallery/components/" target="_blank"
      rel="noopener noreferrer">component.gallery/components</a></li>
  <li><a href="https://lawsofux.com/" target="_blank" rel="noopener noreferrer">lawsofux.com</a></li>
</ul>

<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>React</title>
      <link>https://seanpedersen.github.io/posts/react</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/react</guid>
      <pubDate>Wed, 24 Sep 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>React is a very popular front-end framework allowing to modularize web UI elements in components (even allowing to create mobile apps using <a href="https://reactnative.dev/">React Native</a> / <a href="https://expo.dev/">Expo</a>). Components render UI elements conditioned on state variables. Components are made of other components which can be passed state using so called props.</p>
<p>Consider <a href="https://svelte.dev/">Svelte</a>, <a href="https://www.solidjs.com/">SolidJS</a> or <a href="https://markojs.com/">MarkoJS</a> over React for simpler and more performant (using <a href="https://jovidecroock.com/blog/state-vs-signals/">signals</a>) alternatives. React is more popular though and thus has a bigger eco-system and more experienced developers.</p>
<h2 id="state">State</h2>
<p>Only use state variables (useState) for user facing state dependent UI components. Otherwise use global vars or it will get buggy.</p>
<p>useEffect hook:</p>
<pre><code>useEffect(() =&gt; { });          // Runs after every render
useEffect(() =&gt; { }, []);      // Runs only once after initial render
useEffect(() =&gt; { }, [count]); // Runs when count changes
</code></pre><p><a href="https://github.com/pmndrs/zustand">Zustand</a> is a global state manager for React which can reduce state complexity in your application by reducing property drilling (passing many state vars as props through nested components). Use it with immer for sane state management.</p>
<p>Use <a href="https://tanstack.com/query/latest/docs/framework/react/overview">Tanstack Query</a> to fetch data from the backend (for proper error handling, caching etc.).</p>
<ul>
<li><a href="https://ui.dev/why-react-query">https://ui.dev/why-react-query</a></li>
</ul>
<h2 id="state-management-best-practices">State Management Best Practices</h2>
<p>UI State (local): Stick with useState for ephemeral UI details (open/closed toggles, input values).</p>
<p>Global State (app-wide): Use context sparingly or a dedicated library like Zustand for cross-cutting concerns (auth state, theme, feature flags).</p>
<p>Server State (remote data): Rely on TanStack Query for fetching, caching, invalidation, and syncing with backend data. Avoid duplicating server state in global or local state.</p>
<p>Derive state instead of duplicating: If a state can be derived from props or other state, don’t store it separately.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://react.dev/learn">https://react.dev/learn</a></li>
<li><a href="https://github.com/instructa/constructa-starter/blob/main/docs/best-practices/tanstack-start/avoid-useEffect-summary">https://github.com/instructa/constructa-starter/blob/main/docs/best-practices/tanstack-start/avoid-useEffect-summary.md</a></li>
<li><a href="https://github.com/jantimon/react-hydration-rules">https://github.com/jantimon/react-hydration-rules</a></li>
<li><a href="https://dev.to/paripsky/using-effects-effectively-in-react-stop-misusing-useeffect-once-and-for-all-5fpm">https://dev.to/paripsky/using-effects-effectively-in-react-stop-misusing-useeffect-once-and-for-all-5fpm</a></li>
<li><a href="https://x.com/_ryannystrom/status/1970292793877643556/photo/1">https://x.com/_ryannystrom/status/1970292793877643556/photo/1</a></li>
<li><a href="https://www.lorenstew.art/blog/10-kanban-boards/">Evaluating Frameworks for Mobile Performance</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Javascript (TypeScript)</title>
      <link>https://seanpedersen.github.io/posts/javascript-typescript</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/javascript-typescript</guid>
      <pubDate>Thu, 18 Sep 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p><a href="https://www.typescriptlang.org/">TypeScript</a> is a superset of JavaScript that brings static typing, preventing many bugs found in vanilla JS code bases. TypeScript can both be used in the frontend as well in the backend (server) using NodeJS. JavaScript is a neccessary evil (that has many strange quirks), which TypeScript alleviates some of at least.</p>
<h2 id="basics">Basics</h2>
<ul>
<li>Use <a href="https://github.com/pnpm/pnpm">pnpm</a> instead of npm for a faster and securer package manager.</li>
<li>Use <a href="https://docs.volta.sh/guide/getting-started">volta</a> instead of nvm for sane node version management.</li>
<li>Use <a href="https://vite.dev/guide">vite</a> for sane project bundling.</li>
<li>Try out <a href="https://bun.sh/">bun</a> for great speed and lean apps.</li>
</ul>
<h2 id="frontend-frameworks">FrontEnd Frameworks</h2>
<p>Use <a href="/posts/react.html">React</a> for a popular framework, with many resources (both knowledge and developers) available. Use <a href="https://svelte.dev/">Svelte</a>, <a href="https://www.solidjs.com/">SolidJS</a> or <a href="https://markojs.com/">MarkoJS</a> for smaller and better alternatives - while SolidJS being closest to React in terms of developer experience. Read <a href="https://www.lorenstew.art/blog/10-kanban-boards/">this article</a> for an excellent comparison of frontend state management frameworks. Checkout <a href="https://github.com/chenglou/pretext">pretext</a> for fast text rendering. Try <a href="https://github.com/mrdoob/three.js/">Three.js</a> for 3D rendering like games and <a href="https://github.com/d3/d3">D3.js</a> for 2D data visualization.</p>
<h2 id="promises-async">Promises (async)</h2>
<p>JavaScript uses promises to handle asynchronous operations like API calls, file operations, or timers. A promise represents a value that may be available now, in the future or never and is returned by async functions (return values of async functions are always wrapped in a promise). The await keyword unwraps the value of the promise.</p>
<p><strong>Promise States</strong></p>
<p>A promise can be in one of three states:</p>
<ul>
<li>Pending: Initial state, neither fulfilled nor rejected</li>
<li>Fulfilled: Operation completed successfully</li>
<li>Rejected: Operation failed</li>
</ul>
<p><strong>Async/Await Syntax</strong></p>
<p>Modern JavaScript provides async/await syntax for cleaner asynchronous code:</p>
<pre><code>async function fetchData() {
  try {
    const response = await fetch(&#39;/api/data&#39;);
    const data = await response.json();
    return data;
  } catch (error) {
    console.error(&#39;Error:&#39;, error);
  }
}
</code></pre><p><strong>Promise Combinators</strong></p>
<p>JavaScript provides several utility methods for working with multiple promises:</p>
<ul>
<li>Promise.all(): Waits for all promises to resolve</li>
<li>Promise.allSettled(): Waits for all promises to settle (resolve or reject)</li>
<li>Promise.race(): Returns the first promise to settle</li>
<li>Promise.any(): Returns the first promise to resolve</li>
</ul>
<pre><code>// Wait for all promises
const results = await Promise.all([
  fetch(&#39;/api/users&#39;),
  fetch(&#39;/api/posts&#39;),
  fetch(&#39;/api/comments&#39;)
]);
</code></pre><h2 id="references">References</h2>
<ul>
<li><a href="https://www.typescriptlang.org/docs/handbook/basic-types.html">https://www.typescriptlang.org/docs/handbook/basic-types.html</a></li>
<li>TypeScript performance tips: <a href="https://github.com/microsoft/TypeScript/wiki/Performance">https://github.com/microsoft/TypeScript/wiki/Performance</a></li>
<li><a href="https://jovidecroock.com/blog/state-vs-signals/">https://jovidecroock.com/blog/state-vs-signals/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Erlang</title>
      <link>https://seanpedersen.github.io/posts/erlang</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/erlang</guid>
      <pubDate>Thu, 18 Sep 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>Erlang is a powerful functional programming language invented in Sweden at Ericsson in 1987, that excels at concurrency and fault-tolerance. Erlang processes are light-weight and share  no memory and thus can scale easily across machines and CPU cores. Processes communicate via messages which are received in a queue that is pattern matched against the state loop (actor model). The process supervision tree allows fine-grained error management (let it crash), leading to robust production-ready apps.</p>
<p>Erlang is not made for math heavy computations though but can easily call C or other faster languages for that.</p>
<p>The BEAM (ErlangVM) powers big apps like WhatsApp and Discord, demonstrating its commercial viability.</p>
<p><a href="/posts/elixir">Elixir</a> and <a href="https://gleam.run/">Gleam</a> are notable modern dialects of Erlang that transpile straight to Erlang. Elixir offers syntactic sugar and a thriving open-source community with popular frameworks like Phoenix. Gleam is a type-safe alternative.</p>
<h2 id="show-me-some-code">Show me some code</h2>
<p>Quicksort using list comprehension:</p>
<pre><code>quicksort([]) -&gt; [];
quicksort([Pivot | T]) -&gt;
    quicksort([X || X &lt;- T, X &lt; Pivot]) ++
    [Pivot] ++
    quicksort([X || X &lt;- T, X &gt;= Pivot]).
</code></pre><p>Fibonacci:</p>
<pre><code>-module(fibo).
-author(&quot;Sean Pedersen&quot;).
-compile(export_all).

% Head recursion (inefficient: builds up exponentially growing function call stack: 2^N)
fib(1) -&gt; 1;
fib(2) -&gt; 1;
fib(N) when N &gt; 1 -&gt; fib(N-1) + fib(N-2).

% Tail recursion (efficient: behaves like a loop)
% The tail recursive optimization lets the function call stack not grow at all)
fib_(N) -&gt; fib(N, 0, 1).
fib(1, _First, Second) -&gt; Second;
fib(N, First, Second) when N &gt; 1 -&gt; fib(N-1, Second, First+Second).
</code></pre><p>Message passing:</p>
<pre><code>% Ping pong across two machines/nodes in the same local network
% pingpong.erl must be compiled in working dir of the erlang shells on both machines!
% ---STARTUP INSTRUCTIONS---
% node1:
% $ erl -compile pingpong
% $ erl -sname pong -setcookie we_have_cookies
% node2:
% $ erl -compile pingpong
% $ erl -sname ping -setcookie we_have_cookies
% pong@node2&gt; pingpong:start(ping@welle).

-module(pingpong).
-export([start/1,  ping/3, pong/0]).

ping(0, PongName, PongNode) -&gt;
    {PongName, PongNode} ! finished,
    io:format(&quot;Ping finished~n&quot;, []);

ping(N, PongName, PongNode) -&gt;
    {PongName, PongNode} ! {ping, self()},
    receive
        pong -&gt;
            io:format(&quot;Ping received pong~n&quot;, [])
    end,
    ping(N - 1, PongName, PongNode).

pong() -&gt;
    receive
        finished -&gt;
            io:format(&quot;Pong finished~n&quot;, []);
        {ping, PingPID} -&gt; % Note that PingPID is enough to reply (PID contains info about its node)
            io:format(&quot;Pong received ping~n&quot;, []),
            PingPID ! pong,
            pong()
    end.

start(PingNode) -&gt;
    PongName = pong,
    register(PongName, spawn(pingpong, pong, [])),
    % Spawn function ping/3 remotely on PingNode machine
    spawn(PingNode, pingpong, ping, [3, PongName, node()]).
</code></pre><h2 id="references">References</h2>
<ul>
<li><a href="http://www.erlang.org/">http://www.erlang.org/</a></li>
<li><a href="https://learnyousomeerlang.com/content">https://learnyousomeerlang.com/content</a></li>
<li><a href="https://www.erlang-in-anger.com/">https://www.erlang-in-anger.com/</a></li>
<li>Erlang project build manager: <a href="http://www.rebar3.org">http://www.rebar3.org</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Analog Computing - The future is continuous</title>
      <link>https://seanpedersen.github.io/posts/analog-computing</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/analog-computing</guid>
      <pubDate>Fri, 12 Sep 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>The artificial intelligence industry faces a growing energy crisis. Training large language models consumes massive amounts of power, while deploying AI at the edge demands efficiency that traditional digital processors struggle to deliver. This challenge has created interest in analog computing: which performs calculations using continuous physical quantities rather than discrete digital values. Recent breakthroughs suggest <strong>analog computing could deliver 10-40x energy efficiency improvements</strong> over conventional digital AI accelerators while maintaining competitive accuracy for specific applications.</p>
<h2 id="recent-academic-breakthroughs">Recent academic breakthroughs</h2>
<p>The past two years have witnessed significant progress in analog AI research, with major publications demonstrating systems that work in practice rather than just theory. IBM&#39;s team published landmark results in Nature showing their 14nm analog AI chip achieving 12.4 TOPS/W chip-sustained performance, roughly 14x more energy efficient than comparable digital systems for speech recognition tasks. The chip integrates 35 million phase-change memory (PCM) devices across 34 tiles, successfully running a 45-million parameter speech recognition model with only minimal accuracy degradation.</p>
<p>The arXiv repository shows accelerating publication rates in analog deep learning, with comprehensive reviews examining eight different analog computing methodologies. These papers focus increasingly on practical implementations rather than theoretical possibilities, suggesting the field is maturing toward commercial viability.</p>
<h2 id="energy-efficiency-advantages">Energy efficiency advantages</h2>
<p>Analog computing&#39;s primary advantage lies in eliminating the von Neumann bottleneck - the energy-expensive separation between memory and computation that defines traditional digital architectures. In conventional AI processors, data movement between memory and compute units consumes 100-1000x more energy than the actual mathematical operations. GPUs often operate at less than 50% utilization due to memory bandwidth constraints, with external memory access dominating power consumption.</p>
<p>Analog systems solve this by storing neural network weights directly in memory devices that can perform computations. When IBM&#39;s PCM-based system receives input voltages, the stored conductance values multiply them automatically through Ohm&#39;s law (V×G=I), while Kirchhoff&#39;s law sums the resulting currents—effectively performing matrix-vector multiplication in a single operation. This approach enables 35 million weight parameters to execute simultaneously, achieving sub-microsecond inference times with minimal energy expenditure.</p>
<p>Measured results consistently show 10-40x energy efficiency improvements. IBM&#39;s analog AI chip demonstrates 12.4 TOPS/W compared to roughly 1 TOPS/W for comparable digital inference systems. Research implementations have achieved even higher efficiency, with some reporting up to 397 TOPS/W for specialized workloads, though these typically operate at reduced precision.</p>
<h2 id="digital-computing-retains-advantages">Digital computing retains advantages</h2>
<p>Despite analog computing&#39;s energy benefits, digital AI accelerators maintain important advantages. Modern GPUs and TPUs achieve higher precision with controllable bit widths (FP32/FP16/INT8) and error-free computation, while analog systems typically operate at 3-4 bits effective precision due to device variations and noise. NVIDIA&#39;s H100 delivers ~2,000 TOPS peak theoretical performance and while its practical inference efficiency (~30-50 TOPS/W) lags analog systems, it handles much larger models with proven reliability.</p>
<p>Digital systems also demonstrate superior scalability for large models. Current analog computing demonstrations are limited to roughly 45 million parameters, while digital systems routinely handle models with 175+ billion parameters. The software ecosystem for digital AI is mature, with established frameworks, debugging tools and deployment pipelines that analog systems lack.</p>
<p>Manufacturing represents another advantage for digital approaches. Standard CMOS processes achieve &gt;99% yield routinely, while analog precision requirements reduce effective yield and increase costs. Digital circuits tolerate process variations better than analog devices, which require tight control over materials and dimensions to maintain computational accuracy.</p>
<h2 id="commercial-adoption">Commercial adoption</h2>
<p>The commercial analog AI landscape shows both promising developments and notable failures. <a href="https://brainchip.com/technology/">BrainChip</a> leads commercial deployment with their Akida neuromorphic processor, claiming to be the world&#39;s first commercial neuromorphic AI producer. Their development kits are available for $799 and they recently secured licensing deals for space applications with Frontgrade Gaisler.</p>
<p><a href="https://www.synsense.ai/">SynSense</a>, a Swiss-Chinese company, has raised $10 million and serves over 100 business clients with their ultra-low-power neuromorphic processors consuming less than 500μW. Their Xylo family targets smart wearables and industrial monitoring applications where battery life is critical.</p>
<p>However, the sector also faces significant challenges. Rain Neuromorphics collapsed in 2024 despite $150 million in planned Series B funding and high-profile backers including Sam Altman. Mythic AI underwent major restructuring in 2023, laying off most staff before acquisition by SoftBank. These failures highlight the execution risks in translating analog computing research into viable products.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Analog computing for AI applications has progressed from research curiosity to demonstrated commercial capability, with measurable energy efficiency improvements of 10-40x over digital alternatives. IBM&#39;s 12.4 TOPS/W chip and BrainChip&#39;s commercial Akida processor prove the technology works in practice, not just theory.</p>
<p>However, significant challenges remain. Device variability limits precision to 3-4 bits, manufacturing costs exceed digital alternatives and software ecosystems require substantial development.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://ioplus.nl/en/posts/watt-matters-in-ai-hardware-based-views-on-energy-efficiency">https://ioplus.nl/en/posts/watt-matters-in-ai-hardware-based-views-on-energy-efficiency</a></li>
<li><a href="https://www.nature.com/articles/s41586-025-08639-2">https://www.nature.com/articles/s41586-025-08639-2</a></li>
<li><a href="https://research.ibm.com/blog/analog-ai-chip-low-power">https://research.ibm.com/blog/analog-ai-chip-low-power</a></li>
<li><a href="https://www.nature.com/articles/s44172-025-00492-5">https://www.nature.com/articles/s44172-025-00492-5</a></li>
<li><a href="https://x.com/brianroemmele/status/1966473607795929527?s=46">https://x.com/brianroemmele/status/1966473607795929527?s=46</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Nutrition - a strong mind needs a healthy body</title>
      <link>https://seanpedersen.github.io/posts/nutrition</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/nutrition</guid>
      <pubDate>Thu, 11 Sep 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>tutorial</category>
      <content:encoded><![CDATA[
          <p>Getting healthy through food doesn&#39;t have to be complicated. Research shows that focusing on a few key areas can make a real difference in how you feel and function. Here&#39;s what the science says about eating better, based on current studies from major health institutions.</p>
<h2 id="why-whole-foods-beat-processed-options">Why whole foods beat processed options</h2>
<p>Your body works harder to digest real food, and that&#39;s actually a good thing. Studies show that whole food meals require about 50% more energy to digest compared to processed alternatives. When researchers compared people eating multi-grain bread with cheddar cheese versus white bread with processed cheese, the whole food group burned nearly twice as much energy just from digestion.</p>
<p>Fresh fruits and vegetables pack thousands of beneficial compounds that scientists call the &quot;dark matter of nutrition.&quot; Garlic alone contains over 2,300 different compounds, yet most nutrition advice only focuses on a handful of them. <strong>This complexity can&#39;t be replicated in processed foods or supplements.</strong></p>
<p>Large studies following over 100,000 people for 14 years found that those eating 8 or more servings of fruits and vegetables daily had 30% lower rates of heart attacks and strokes. The research consistently shows benefits for preventing diabetes, certain cancers, and maintaining healthy weight. The key is getting variety in colors and types to maximize these protective compounds.</p>
<h2 id="protein-needs-are-higher-than-most-people-think">Protein needs are higher than most people think</h2>
<p>The standard recommendation of 0.8 grams per kilogram of body weight per day isn&#39;t enough for optimal health. This amount prevents deficiency but doesn&#39;t support muscle maintenance or growth, especially as we age.</p>
<p><strong>Current research suggests most adults need 1.4 to 2.0 grams of protein per kilogram of body weight daily.</strong> For a 80 kg person, that&#39;s about 130 to 160 grams per day (depending on your muscle mass and physical activity). Older adults need even more due to something called anabolic resistance, where muscles become less responsive to protein.</p>
<p>The timing matters too. Getting 30 to 50 grams of high quality protein at each meal works better than cramming it all into one or two large servings. Your muscles can only use so much protein at once, so spreading it throughout the day maximizes muscle protein synthesis. Sources like eggs, meat, fish, and dairy provide complete amino acid profiles that match what your muscles need. Most people are eating &quot;empty&quot; food with way too much sugar, fat and carbohydrates - instead increase your healthy fat and protein intake. Try steak, fish and eggs - also good as breakfast.</p>
<h2 id="creatine-benefits-both-muscle-and-brain">Creatine benefits both muscle and brain</h2>
<p>Creatine monohydrate stands out as one of the most researched supplements available, with over 1,000 published studies backing its benefits.</p>
<p>For muscle performance, creatine increases strength by an average of 8% more than placebo during resistance training. It works by boosting your muscles&#39; energy currency (ATP) during high intensity activities. <strong>This translates to better performance in the gym and enhanced recovery between sets.</strong></p>
<p>The cognitive benefits might surprise you. Meta-analyses show creatine significantly improves memory function, particularly in older adults. It also helps with processing speed and reduces mental fatigue during demanding tasks. Single doses can improve cognitive performance during sleep deprivation, with effects lasting up to 9 hours.</p>
<p>The standard protocol involves 3 to 5 grams daily for maintenance (I recommend up to 7 grams daily), though you can load with 20 grams daily for the first week to see faster results. Consistency is key for good results - so establish a daily morning routine. Safety data spanning over 20 years shows no adverse effects at recommended doses. The only consistent side effect is temporary water weight gain in the first week as muscles store more water. If you know you will consume alcohol at a given day, be extra careful to consume enough water, as alcohol dehydrates you.</p>
<p>Creapure is a known brand that produces high-quality creatine (regular quality testing -&gt; no heavy metals or other unwanted additions).</p>
<h2 id="magnesium-fills-a-common-gap">Magnesium fills a common gap</h2>
<p>Nearly half of Americans don&#39;t consume enough magnesium, yet this mineral participates in over 300 enzyme reactions in your body. The shortfall creates opportunities for meaningful improvement through supplementation.</p>
<p><strong>Magnesium plays essential roles in muscle function, sleep quality, blood pressure regulation, and energy production.</strong> Research shows supplementation can modestly reduce blood pressure, help prevent migraines, and improve sleep duration and quality. The mineral acts as a natural calcium antagonist, helping muscles relax after contraction.</p>
<p>Not all magnesium supplements work equally well. Forms bound to organic compounds like citrate or glycinate absorb much better than cheaper options like magnesium oxide. Studies show oxide has only about 4% absorption rates, while citrate and glycinate forms absorb significantly better and cause less digestive upset.</p>
<p>Starting with 200 to 400 milligrams daily works well for most people. Take it with food if you experience stomach irritation, and be aware that doses over 350 milligrams from supplements can cause loose stools in some individuals.</p>
<h2 id="vitamin-d3-addresses-widespread-deficiency">Vitamin D3 addresses widespread deficiency</h2>
<p>Vitamin D deficiency affects an estimated 50% of the global population, with rates even higher in northern climates and among people who spend most of their time indoors. Unlike other vitamins, your body produces vitamin D only when skin is exposed to UVB radiation from sunlight, making it technically a hormone rather than a traditional vitamin.</p>
<p><strong>The health implications of adequate vitamin D status extend far beyond bone health.</strong> Research shows vitamin D receptors exist in nearly every tissue in your body, influencing immune function, muscle strength, cardiovascular health, and mood regulation. Large observational studies link higher vitamin D blood levels with reduced risks of respiratory infections, autoimmune diseases, and certain cancers.</p>
<p>Meta-analyses demonstrate that vitamin D supplementation can reduce the risk of acute respiratory infections by 12% overall, with even greater benefits for those who were deficient to begin with. The vitamin plays crucial roles in immune system regulation, helping your body mount appropriate responses to pathogens while preventing excessive inflammation.</p>
<p>For muscle function and bone health, vitamin D helps your body absorb calcium efficiently and supports muscle protein synthesis. Studies show that correcting vitamin D deficiency can improve muscle strength and reduce fall risk in older adults by up to 19%.</p>
<p><strong>Most adults need 1,000 to 4,000 IU (25 to 100 micrograms) of vitamin D3 daily</strong> to maintain optimal blood levels between 30 to 50 ng/mL (75 to 125 nmol/L). The exact amount depends on factors like body weight, skin color, geographic location, and current vitamin D status. Vitamin D3 (cholecalciferol) is preferred over D2 (ergocalciferol) as it raises blood levels more effectively.</p>
<p>Taking vitamin D with a meal containing fat improves absorption since it&#39;s a fat-soluble vitamin. Safety margins are wide - toxicity only occurs at extremely high doses (typically above 10,000 IU daily for months), and regular blood testing can help optimize your individual dosing.</p>
<h2 id="what-to-avoid">What to avoid</h2>
<p>Two major sources of health issues hide in plain sight: chemicals from plastic food containers and regular consumption of sodas or sweetened drinks.</p>
<p>Chemicals like BPA and phthalates leach from plastic containers into food and drinks. These compounds act as endocrine disruptors, mimicking hormones in your body. <strong>Consumer Reports found phthalates in 84 out of 85 food products they tested</strong>, with levels in some items exceeding those typically found in fast food.</p>
<p>The science links these chemicals to cardiovascular problems, cognitive decline (diabetes risk + anxiety) and reproductive health issues. While regulatory agencies maintain current safety levels, the research continues to raise concerns about cumulative exposure over time.</p>
<p>Sugar sweetened beverages create multiple health problems. Beyond the obvious weight gain from liquid calories that don&#39;t satisfy hunger like solid food, regular soda consumption increases diabetes risk through high glycemic loads and fructose metabolism effects. <strong>Studies following hundreds of thousands of people show clear dose response relationships</strong>, where more soda equals higher disease risk.</p>
<p>The dental damage alone should give pause. Sodas have a pH of 2 to 3, creating an acidic environment that erodes tooth enamel while feeding harmful bacteria. Research shows even moderate consumption increases cavity risk by 57%. Simply put: drink water and tea, avoid the rest.</p>
<h2 id="putting-it-together">Putting it together</h2>
<p>These five areas represent changes backed by solid research that can meaningfully impact health. Focus on eating more whole foods and adequate protein, limit exposure to plastic chemicals and sugary drinks, and consider creatine and magnesium supplementation if appropriate for your situation.</p>
<p>The beauty of these approaches lies in their simplicity and strong evidence base. You don&#39;t need perfect implementation to see benefits. Start with one or two areas that resonate most, make consistent changes, and build from there. Your body will respond to these evidence based improvements in nutrition over time.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://youtu.be/v2w3zWzADgo">YouTube: Alarming Effects From Microplastics on Human Health</a> - Anton Petrov</li>
</ul>
<p class="post-hashtags"><a href="/index.html#tutorial">#tutorial</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Understanding Game Theory Fundamentals</title>
      <link>https://seanpedersen.github.io/posts/game-theory</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/game-theory</guid>
      <pubDate>Wed, 10 Sep 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>We are all players in games, though mostly unaware. Knowing the rules (what is possible) and reading other players&#39; intentions are the two skills that separate good strategists from reactive ones. <a href="https://en.wikipedia.org/wiki/Game_theory">Game theory</a> gives those instincts a mathematical backbone.</p>
<p>More precisely, game theory is a framework for analyzing decisions where outcomes depend not just on your choices, but on what others choose at the same time. This makes it useful for anything from corporate pricing wars to international treaties to everyday negotiations.</p>
<p>The core insight is this: <strong>good strategy requires anticipating responses, not merely choosing what looks best in isolation.</strong> Once you see that, you start finding strategic structure everywhere.</p>
<h2 id="core-concepts">Core concepts</h2>
<p>Game theory grew from the work of mathematician <a href="https://en.wikipedia.org/wiki/John_von_Neumann">John von Neumann</a> and economist Oskar Morgenstern, whose 1944 book <em>Theory of Games and Economic Behavior</em> laid the foundations. <a href="https://en.wikipedia.org/wiki/John_Forbes_Nash_Jr.">John Nash</a> later extended the field with the equilibrium concept that bears his name.</p>
<p>A &quot;game&quot; in this context means any situation where multiple players make choices that affect everyone&#39;s outcomes. Players can be individuals, companies, countries, or biological organisms.</p>
<p>The most important concept is the <strong><a href="https://en.wikipedia.org/wiki/Nash_equilibrium">Nash equilibrium</a></strong>. It describes a stable state where no player can improve their outcome by changing strategy alone. Everyone is playing their best response to what everyone else is doing.</p>
<p>Consider a hypothetical duopoly: two airlines serving the same route. If both charge high fares, both profit. If one cuts prices, it steals passengers. If both cut, neither gains much. The stable outcome (where neither airline benefits from moving first) can be interpreted as a Nash equilibrium. Real markets show patterns consistent with this structure, but calling any specific market a Nash equilibrium requires careful analysis of actual costs, margins, and competitive options.</p>
<p><strong><a href="https://en.wikipedia.org/wiki/Strategic_dominance">Dominant strategies</a></strong> are choices that are better regardless of what opponents do. Advertising is a textbook example. Coca-Cola benefits from advertising whether Pepsi advertises or not. In practice, most strategic choices are only dominant under certain conditions, not universally.</p>
<p><strong><a href="https://en.wikipedia.org/wiki/Normal-form_game">Payoff matrices</a></strong> map these interactions visually. Each cell shows the outcome for every combination of choices, making the structure of incentives visible at a glance.</p>
<h2 id="types-of-strategic-situations">Types of strategic situations</h2>
<p><strong>Cooperative vs. non-cooperative games</strong> divide situations where binding agreements are possible from those where they are not. International climate negotiations aim to create cooperative frameworks. Without enforcement, individual countries may still defect for short-term gain, pushing the game toward non-cooperative dynamics.</p>
<p><strong><a href="https://en.wikipedia.org/wiki/Zero-sum_game">Zero-sum games</a></strong> are those where one player&#39;s gain equals another&#39;s loss. Poker is a clean example. Most real-world situations are not zero-sum: trade, for instance, can benefit both sides.</p>
<p><strong>Sequential vs. simultaneous games</strong> differ in timing. In sequential games, you observe the other player&#39;s move before responding. In simultaneous games, you act without knowing what others chose. A sealed-bid auction is roughly simultaneous. A patent race is sequential.</p>
<h2 id="the-prisoner-s-dilemma-and-its-extensions">The prisoner&#39;s dilemma and its extensions</h2>
<p>The <strong><a href="https://en.wikipedia.org/wiki/Prisoner&#x27;s_dilemma">prisoner&#39;s dilemma</a></strong> is the most studied game in social science. Two players each choose to cooperate or defect. Defecting is individually rational (it is a dominant strategy), but if both defect, both end up worse than if both had cooperated.</p>
<p>A clear business example: two competing firms advertising the same product. Each benefits from advertising whether the other does or not. So both advertise heavily, spending more than they would under mutual restraint. The outcome is a Nash equilibrium, but it is worse for both than cooperation would be. This pattern appears in ad spending between Coca-Cola and Pepsi, between competing airlines, and in many other industries.</p>
<p>Legal plea bargaining follows a similar structure. When multiple defendants face the same charges, each may have an individual incentive to cooperate with prosecutors regardless of what the others do. This can push everyone toward deals even when coordinated silence might have served the group better. The logic is structural: it applies across many multi-defendant cases, not to any single one.</p>
<p>The <strong><a href="https://en.wikipedia.org/wiki/Tragedy_of_the_commons">tragedy of the commons</a></strong> extends this to shared resources. Each person has an incentive to exploit a common resource (a fishery, a highway, clean air) beyond what is collectively optimal. The result is depletion or congestion. Property rights, quotas, or taxes often realign individual incentives with collective outcomes.</p>
<p><strong><a href="https://en.wikipedia.org/wiki/Evolutionarily_stable_strategy">Evolutionary stable strategies</a></strong> come from biology. A strategy is evolutionarily stable if a population using it cannot be invaded by a mutant playing something different. This explains why animal conflicts tend toward displays rather than fights: pure aggression destabilizes a population over time.</p>
<h2 id="what-game-theory-cannot-do">What game theory cannot do</h2>
<p>Game theory does not predict human behavior perfectly. People cooperate even when defection is dominant (as public goods experiments show), signal to build reputations, and care about fairness. The models are simplifications. A Nash equilibrium describes a stable outcome, not necessarily the one that will occur.</p>
<p>But the framework is still useful. It forces you to ask: who are the players, what can they do, and what do they want? Once the incentive structure is visible, decisions that looked simple often reveal hidden tensions.</p>
<p>We are all playing games. Most of us just never learned to see the board.</p>
<h2 id="references">References</h2>
<ol>
<li><a href="https://www.britannica.com/science/Nash-equilibrium">Nash Equilibrium - Britannica</a></li>
<li><a href="https://www.econlib.org/library/Enc/PrisonersDilemma.html">Prisoners&#39; Dilemma - EconLib Encyclopedia</a></li>
<li><a href="https://en.wikipedia.org/wiki/Game_theory">Game theory - Wikipedia</a></li>
<li><a href="https://en.wikipedia.org/wiki/Prisoner%27s_dilemma">Prisoner&#39;s dilemma - Wikipedia</a></li>
<li><a href="https://www.youtube.com/watch?v=5I2VPYPJJ68">Game Theory - YouTube</a></li>
</ol>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Python</title>
      <link>https://seanpedersen.github.io/posts/python</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/python</guid>
      <pubDate>Tue, 19 Aug 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>Just some notes on how to use Python effectively. Python strives to be simple and concise and is a good choice for rapid software development. The average execution speed is rather slow, which is ok because it nicely interacts with C, C++ and Rust which are fast. Another major selling point is the rich ecosystem of useful packages, spanning web development, data science and much more.</p>
<h2 id="general-tips">General Tips</h2>
<ul>
<li>Keep functions pure (no side effects) if possible</li>
<li>Use early returns in functions to avoid deep nesting</li>
<li>Use type hints and a type checker (<a href="https://github.com/astral-sh/ty">ty</a>) with pre-commit hooks</li>
<li>Use <a href="https://github.com/astral-sh/ruff">ruff</a> - a fast linter / formatter</li>
<li>Use <a href="https://docs.python.org/3/library/pathlib.html#basic-use">pathlib</a> module for dealing with file system paths</li>
<li>No magic numbers (use expressive variable names e.g. waiting_time_ms)</li>
<li>Use <a href="https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals">f-strings</a> for formatting strings</li>
<li>Validate variable types from external (untrustworthy) inputs, e.g. user input, web requests<ul>
<li>try attrs and cattrs instead of pydantic</li>
</ul>
</li>
<li>Use caching for heavy computations</li>
<li>Use <a href="https://docs.pytest.org/en/stable/">pytest</a> for unit testing</li>
</ul>
<h2 id="package-management">Package Management</h2>
<p>Use <a href="https://github.com/astral-sh/uv">uv</a> (preferred and popular) or <a href="https://pixi.sh/latest/python/tutorial/">pixi</a> (can install conda packages - useful for GPU/CUDA stuff) for fast and sane package management.</p>
<h2 id="interactive-development">Interactive Development</h2>
<p>Great for prototyping, one-off analysis scripts and literate programming.</p>
<p><a href="https://jupyter.org/">Jupyter Notebook</a> and <a href="https://marimo.io/">Marimo</a>.</p>
<h2 id="web-development">Web Development</h2>
<ul>
<li>Use <a href="https://fastapi.tiangolo.com/">FastAPI</a> to create clean and simple REST API&#39;s supporting both synchronous and <a href="https://fastapi.tiangolo.com/async/">asynchronous</a> routes</li>
<li>Use <a href="https://github.com/jawah/niquests">niquests</a> (the successor of requests) for network requests (being fast, supporting async, http/2 &amp; much more)</li>
</ul>
<h2 id="cli">CLI</h2>
<ul>
<li>For creating CLI: <a href="https://github.com/BrianPugh/cyclopts">cyclopts</a></li>
<li>For formatting console output: <a href="https://github.com/Textualize/rich">rich</a></li>
<li>Progress bar: <a href="https://github.com/tqdm/tqdm">tqdm</a></li>
</ul>
<h2 id="desktop-gui-apps">Desktop GUI Apps</h2>
<p><a href="https://github.com/pytauri/pytauri/">PyTauri</a> / <a href="https://github.com/pyloid/pyloid">PyLoid</a> / <a href="https://github.com/r0x0r/pywebview">PyWebView</a></p>
<h2 id="concurrency">Concurrency</h2>
<p>Python is a single threaded language with a Global Interpreter Lock (GIL). Meaning only multi-processing enables real parallel execution of non IO code. Multi-threading or async in Python thus only allows for concurrent IO operations (network / file system read and writes).</p>
<p>Python 3.13 has added experimental support for a no-GIL build flag, enabling true multi-threading support, which may become the default in the future.</p>
<ul>
<li>On multi-threading: <a href="https://glyph.twistedmatrix.com/2014/02/unyielding.html">https://glyph.twistedmatrix.com/2014/02/unyielding.html</a></li>
<li>Good ref on Python multiprocessing: <a href="https://pythonspeed.com/articles/python-multiprocessing/">https://pythonspeed.com/articles/python-multiprocessing/</a></li>
</ul>
<h3 id="multi-processing">Multi-Processing</h3>
<p>Use <a href="https://joblib.readthedocs.io/en/stable/index.html">joblib</a> for sane multi-processing. Note that multi-processing should only be used to parallelize very CPU heavy tasks, since the overhead of starting processes is very high (always benchmark).</p>
<pre><code>from math import sqrt
from joblib import Parallel, delayed

# Runs in 4 processes in parallel, preserves input order
results = Parallel(n_jobs=4)(delayed(sqrt)(i ** 2) for i in range(16))
print(results)
</code></pre><h3 id="async">Async</h3>
<p>I do not like async syntax wise (just personal preference) - I prefer multi-threading to speed up heavy IO tasks (<a href="https://news.ycombinator.com/item?id=45106189">relevant HN thread</a>).</p>
<pre><code>import asyncio
import niquests

async def fetch_multiple_urls(urls):
    async with niquests.AsyncSession() as client:
        tasks = [client.get(url) for url in urls]
        responses = await asyncio.gather(*tasks)
        return responses
</code></pre><ul>
<li><a href="https://trio.readthedocs.io/en/stable/tutorial.html">https://trio.readthedocs.io/en/stable/tutorial.html</a><ul>
<li><a href="https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/">https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/</a></li>
</ul>
</li>
<li><a href="https://github.com/pomponchik/transfunctions">https://github.com/pomponchik/transfunctions</a></li>
</ul>
<h2 id="generators">Generators</h2>
<p>For efficient (lazy / easy on RAM) code</p>
<pre><code># Loads entire file into RAM
def read_large_file_bad(filename):
    with open(filename) as f:
        return [int(line.strip()) for line in f]

# Only keeps one line in memory
def read_large_file_good(filename):
    with open(filename) as f:
        for line in f:
            yield int(line.strip())

# Memory efficient processing (file can be bigger than RAM)
total_sum = 0
for number in read_large_file_good(&quot;huge_file.txt&quot;):
    total_sum += number
</code></pre><h2 id="sqlite">SQLite</h2>
<p>SQLite3 support is built into the Python standard lib and a simple option to embed, store and analyze relational data.</p>
<p>When creating tables always use the STRICT keyword, to enfore type consistency on INSERT and UPDATE operations. This prevents ugly typing bugs that are possible - as Python does not guarantee type consistency at runtime.</p>
<ul>
<li><a href="https://bigcodenerd.org/blog/sqlite-type-checking-gochas/">https://bigcodenerd.org/blog/sqlite-type-checking-gochas/</a></li>
</ul>
<h2 id="postgres">Postgres</h2>
<p>Postgres is very versatile and powerful DBMS. Use it with <a href="https://github.com/psycopg/psycopg">psycopg</a> and a docker image.</p>
<pre><code>from contextlib import asynccontextmanager
from fastapi import Depends, FastAPI
import psycopg_pool
import psycopg

conn_string = &quot;postgres://postgres@localhost&quot;

pool = psycopg_pool.AsyncConnectionPool(conn_string, open=False)

@asynccontextmanager
async def lifespan(app: FastAPI):
    await pool.open()
    yield
    await pool.close()

app = FastAPI(lifespan=lifespan)

async def get_conn():
    async with pool.connection() as conn:
	    yield conn

@app.get(&quot;/visit/&quot;)
async def add_visit(conn = Depends(get_conn)):
    async with conn.cursor() as cursor:
        # Run our queries
        await cursor.execute(&quot;insert into visits(timestamp) values (now())&quot;)

    return {&quot;message&quot;: &quot;Visit logged&quot;}
</code></pre><ul>
<li><a href="https://blog.danielclayton.co.uk/posts/database-connections-with-fastapi/">https://blog.danielclayton.co.uk/posts/database-connections-with-fastapi/</a></li>
<li><a href="https://spwoodcock.dev/blog/2024-10-fastapi-pydantic-psycopg/">https://spwoodcock.dev/blog/2024-10-fastapi-pydantic-psycopg/</a></li>
</ul>
<h2 id="docker">Docker</h2>
<p>Bundle your apps and make them reproducible using docker (with uv or pixi).</p>
<ul>
<li>Uv: <a href="https://docs.astral.sh/uv/guides/integration/docker/#getting-started">https://docs.astral.sh/uv/guides/integration/docker/#getting-started</a></li>
<li>Pixi: <a href="https://github.com/prefix-dev/pixi-docker/blob/main/README">https://github.com/prefix-dev/pixi-docker/blob/main/README.md</a></li>
</ul>
<h2 id="logging">Logging</h2>
<p>Use <a href="https://github.com/Delgan/loguru">loguru</a> (comes with a multi-processing queue that just works)</p>
<h2 id="performance">Performance</h2>
<p>Use a profiler (<a href="https://github.com/joerick/pyinstrument">pyinstrument</a>) to find slow or RAM consuming code paths.</p>
<p>Use C / C++ / Rust / Zig / Mojo etc. for performance critical code or try <a href="https://pypy.org/">PyPy</a> and <a href="https://cython.org/">Cython</a> first. Or check out a transpiler <a href="https://github.com/py2many/py2many">https://github.com/py2many/py2many</a> / <a href="https://github.com/paiml/depyler">https://github.com/paiml/depyler</a>.</p>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Search is hard</title>
      <link>https://seanpedersen.github.io/posts/search-is-hard</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/search-is-hard</guid>
      <pubDate>Sat, 16 Aug 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>Search is the process of finding useful matches in a (large) set of objects (search corpus). A search engine is only as good as the representations it uses to match queries to the objects. To find things fast, one orders the search corpus by structuring the objects in a way (a graph) that makes it easy to navigate - this is called an index. A useful search engine understands the users intent and mirrors how humans associate information (semantics, syntax, sound, visual), so the results feel intuitive.</p>
<h2 id="use-cases">Use Cases</h2>
<ul>
<li>Search Interfaces (for books, web pages, images, etc.)</li>
<li>Recommender Systems (for similar movies, products, etc.)</li>
<li><a href="/posts/rag">Retrieval Augemented Generation</a> (provide relevant context for LLM&#39;s)</li>
</ul>
<h2 id="representations">Representations</h2>
<p>The key of every search system is to build useful representations of your search corpus, so you can (quickly) find what you search for. Thus one should spend spend good time on finding the right representation for the search problem and how to enrich it with useful information.</p>
<h3 id="granularity-chunking">Granularity (chunking)</h3>
<p>Depending on the use case or query, different levels of information granularity of the search corpus are useful. Searching for a whole book / chapter / paragraph / sentence / word / letter or video / scene / image / objects / textures / colors.</p>
<p>Chunking projects:</p>
<ul>
<li><a href="https://github.com/ekimetrics/adaptive-chunking">https://github.com/ekimetrics/adaptive-chunking</a></li>
<li><a href="https://github.com/benbrandt/text-splitter">https://github.com/benbrandt/text-splitter</a></li>
<li><a href="https://github.com/d1pankarmedhi/chunkr">https://github.com/d1pankarmedhi/chunkr</a></li>
<li><a href="https://github.com/idleness76/wg-ragsmith">https://github.com/idleness76/wg-ragsmith</a></li>
</ul>
<p>Tricks:</p>
<ul>
<li>Use LLM to enrich your search corpus with relevant metadata (do the work before the search)<ul>
<li>Ask LLM to provide a descriptive title and a short summary for each text document</li>
<li>Prepend title and summary / section to every text chunk before embedding</li>
</ul>
</li>
</ul>
<h3 id="token-based-representations">Token Based Representations</h3>
<ul>
<li><p><strong>Word Level (BM25 / normalized TF-IDF)</strong></p>
<ul>
<li>Tokenization: standard words</li>
<li>Purpose: relevance scoring for full-text search</li>
<li>Strengths: scales efficiently to very large text corpora</li>
<li>Limitation: cannot match partial words, abbreviations, or morphological variants</li>
</ul>
</li>
<li><p><strong>Subword Level (Corpus-Derived Subword Index – CDSI)</strong></p>
<ul>
<li>Tokenization: greedy longest-match subwords mined from frequent corpus substrings</li>
<li>Purpose: partial-word and compound-word matching in full text</li>
<li>Strengths: captures abbreviations and morphemes (e.g., <code class="language-text">&quot;neural net&quot;</code> matches <code class="language-text">&quot;neural network&quot;</code>), smaller posting lists than tri-grams, deterministic and interpretable</li>
<li>Limitation: requires offline vocabulary build and periodic rebuilds</li>
</ul>
</li>
<li><p><strong>Character Level (Tri-gram Index)</strong></p>
<ul>
<li>Tokenization: overlapping 3-character sequences</li>
<li>Purpose: substring and fuzzy search</li>
<li>Strengths: handles typos, partial matches, and short strings (filenames, codes, IDs)</li>
<li>Limitation: high space usage; mainly useful for short strings rather than full text</li>
</ul>
</li>
</ul>
<div class="table-wrapper"><table><thead><th>Method</th><th>Space</th><th>Substring coverage</th><th>Fuzzy/typo tolerance</th><th>Best use case</th></thead><tbody><tr><td>Tri-grams</td><td>High</td><td>All</td><td>Limited</td><td>Short strings, small-medium corpora</td></tr><tr><td>Variable n-grams</td><td>Medium</td><td>Most</td><td>Limited</td><td>Medium-length strings</td></tr><tr><td>Prefix/Suffix</td><td>Low-Med</td><td>Start/End only</td><td>No</td><td>Autocomplete, filenames</td></tr><tr><td>Permuterm</td><td>Medium-High</td><td>Arbitrary</td><td>No</td><td>Wildcard/substring search</td></tr><tr><td>Q-gram + Hashing</td><td>Low</td><td>Most</td><td>Approximate</td><td>Large-scale, fuzzy search</td></tr><tr><td>Suffix Array / Tree</td><td>Medium</td><td>All</td><td>Exact</td><td>Exact substring matching, static datasets</td></tr></tbody></table></div><h3 id="neural-representations">Neural Representations</h3>
<p>Create representations using deep neural networks - typically dense vectors (embeddings).</p>
<ul>
<li>Multi-Modal (shared) Embedding Spaces (CLIP)</li>
<li>Dense vs Sparse embeddings (<a href="/posts/sparse-distributed-representations">SDR</a>)</li>
<li>Query vs document prefix for embedding models optimized for search</li>
<li>Visual Document Embeddings<ul>
<li>Instead of embedding sequences of tokens (often words), embed images of pages directly -&gt; this helps to process complex documents containing tables, graphs and imagery</li>
<li><a href="https://huggingface.co/collections/nomic-ai/nomic-embed-multimodal-67e5ddc1a890a19ff0d58073">https://huggingface.co/collections/nomic-ai/nomic-embed-multimodal-67e5ddc1a890a19ff0d58073</a></li>
<li><a href="https://huggingface.co/jinaai/jina-embeddings-v4">https://huggingface.co/jinaai/jina-embeddings-v4</a></li>
</ul>
</li>
<li>Text Embeddings (chunking strategies)<ul>
<li>relevant segment extraction (RSE) - <a href="https://d-star.ai/dynamic-retrieval-granularity">https://d-star.ai/dynamic-retrieval-granularity</a>: just use paragraph-sized chunks (~200 tokens), prepend global document context (title, section) -&gt; embed and store position in document (line number / page position). embed query -&gt; find nearest chunks -&gt; compute continuous chunk segments in documents</li>
<li>late-interaction: do not compress tokens into single vector, instead vectorize every token (using contextual embedding model like ColBERT, so token vectors contain contextual information) and match using the MaxSim operator<ul>
<li>Pros: much more granular results (excel at out-of-domain, long-context), good interpretability because of token-level matching</li>
<li>Cons: heavy computation -&gt; search takes longer, storing cost -&gt; n token vectors per document vs 1 document vector</li>
</ul>
</li>
<li>embed a document by computing sentence level dense embeddings. Transform these sentence embeddings into SDR that are stacked to preserve information. Now match a query with the same technique to find relevant docs.</li>
<li>use LLM to enrich representations<ul>
<li>summarize document and embed it (harnesses LLM to solve long-context problem)</li>
<li>infer questions from the chunk that it answers and embed them</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="searching">Searching</h2>
<p>Once our set of objects is transformed into useful representations (vectors), we can finally search. We need to transform the user query into the same representation to compare it with the existing set of vectors. The most common metric for this is the cosine distance (angle between two vectors -&gt; 0: identical / very similar vectors, 1: orhogonal / very different vectors).</p>
<h2 id="semantic-search-result-scoring">Semantic Search Result Scoring</h2>
<p>For most semantic search and RAG systems:</p>
<p>Retrieve a candidate set (typically Top 20–100 results) using vector similarity.<br>Apply score gap (elbow) analysis to identify the natural relevance cutoff by finding the largest meaningful drop between adjacent scores.<br>Enforce sensible bounds (for example, return at least 3 and at most 10 results) to avoid edge cases where too few or too many matches are returned.<br>Optionally rerank the remaining candidates using a cross-encoder or LLM reranker and apply a final relevance threshold.</p>
<p>This approach combines the efficiency of vector search with a dynamic, query-specific relevance threshold. Unlike fixed Top-K retrieval or static similarity thresholds, it adapts to the score distribution of each query, returning all strongly related matches while filtering results that fall outside the primary relevance cluster.</p>
<h2 id="reranker-models">Reranker Models</h2>
<p>Serve the purpose to run a complex (big) model (specialised or LLM) to filter the results (candidates) of the vector similarity search further by computing another similarity score using the reranker model with the query for each candidate.</p>
<h2 id="modern-search-pipelines">Modern Search Pipelines</h2>
<p>Depending on your requirements (accuracy and time to response) pipelines of different complexity are possible.</p>
<h3 id="query-expansion">Query Expansion</h3>
<ul>
<li>classical: use first k hits of og query to find more relevant matches</li>
<li>BM25: Augment the BM25 query with synonyms or reformulations from a predefined dict.</li>
<li>LLM based: create hypothetical document embeddings (HyDE) by generating a possible query result<ul>
<li>TODO: generate k possible HyDEs for ambiguous queries, prompt to just generate document keywords to reduce LLM output latency</li>
</ul>
</li>
</ul>
<p><strong>Simple</strong><br>fast but may contain irrelevant results</p>
<ul>
<li>Document -&gt; chunk -&gt; embed (index)</li>
<li>Query -&gt; embed -&gt; search on chunks -&gt; results</li>
</ul>
<p><strong>Reranker</strong></p>
<ul>
<li>Document -&gt; chunk -&gt; embed (index)</li>
<li>Query -&gt; embed -&gt; search on chunks -&gt; rerank (filter) -&gt; results</li>
</ul>
<p><strong>LLM (Agentic Search)</strong></p>
<ul>
<li>Document -&gt; LLM (generate descriptive title + summary) -&gt; chunk -&gt; embed (index)</li>
<li>Query -&gt; expand / rewrite query using LLM -&gt; embed -&gt; search on chunks -&gt; rerank (filter) -&gt; results</li>
</ul>
<h2 id="tree-organized-retrieval">Tree-Organized Retrieval</h2>
<p>An alternative paradigm that builds a hierarchical tree from a document and lets an LLM navigate it via tree search. Retrieval becomes reasoning over structure rather than similarity over vectors. Also marketed as &quot;vectorless RAG&quot;.</p>
<ul>
<li><a href="https://arxiv.org/abs/2401.18059">RAPTOR</a> (ICLR 2024): recursively cluster and summarize chunks bottom-up to build a multi-level summary tree; retrieve across abstraction levels</li>
<li><a href="https://github.com/VectifyAI/PageIndex">PageIndex</a>: generate a &quot;table of contents&quot; tree, then perform agentic tree search with an LLM to locate relevant sections<ul>
<li>No vector DB, no chunking - sections are natural document divisions</li>
<li>Traceable retrieval (page and section references) instead of opaque nearest-neighbor matches</li>
<li>Trades retrieval latency and LLM cost for relevance on long, structured professional documents (where similarity ≠ relevance)</li>
<li>Reported sota <a href="https://github.com/VectifyAI/Mafin2.5-FinanceBench">98.7% accuracy on FinanceBench</a></li>
</ul>
</li>
</ul>
<h2 id="scaling-things-up">Scaling Things Up</h2>
<p>All of the following techniques trade retrieval accuracy for speed / storage costs. For production use cases, using a <a href="/posts/vector-databases">Vector DB</a> is the right choice.</p>
<ul>
<li>Approximate Nearest Neighbor (Search Index) - <a href="https://github.com/erikbern/ann-benchmarks">benchmark</a><ul>
<li>HNSW: builds a hierachical graph, good data drift handling -&gt; high RAM usage</li>
<li>IVFFlat: low RAM usage, bad data drift handling -&gt; needs frequent rebuilds</li>
<li>DiskANN: low RAM usage, achieved by using disk (needs fast disk read)</li>
<li>TODO (eval): <a href="https://github.com/yichuan-w/LEANN">https://github.com/yichuan-w/LEANN</a></li>
</ul>
</li>
<li>Vector Dimensionality Reduction<ul>
<li>Matryoshka Embeddings: dim. red. baked into training via loss function</li>
<li>PCA (linear)</li>
<li>t-SNE / UMAP (non-linear)</li>
</ul>
</li>
<li>Vector Quantization<ul>
<li>Reduce bit representation (f.e. to INT8 instead of FP32)</li>
<li><a href="https://jina.ai/embedding-compression.pdf">Near-lossless compression for unit-norm embedding vectors using spherical coordinates</a> - <a href="https://github.com/jina-ai/jzip-compressor">code</a></li>
</ul>
</li>
</ul>
<p>Excellent article detailing an efficient vector search pipeline: <a href="https://huggingface.co/blog/embedding-quantization">https://huggingface.co/blog/embedding-quantization</a></p>
<h2 id="results-diversification">Results Diversification</h2>
<p>It often makes sense to present the user for general queries not only the top nearest neighbors but a diverse set of results, so the ambiguity of the query is reflected. Ideally the user can then narrow down (load more relevant results) based on the diverse result set.</p>
<h2 id="evaluation-metrics">Evaluation Metrics</h2>
<p>As you see there are many knobs to tune a modern search pipeline and thus we need hard evaluation metrics to judge the quality of our search pipeline. Creating a custom dataset that mirrors our real world search use case as closely and diversely as possible is essential to improving our search. Relevant <a href="https://x.com/bo_wangbo/status/2011075744978649199">post</a> - recommends optimizing for recall with K &gt; 100.</p>
<h3 id="precision-k">Precision@K</h3>
<ul>
<li>What: Fraction of top K results that are relevant</li>
<li>Formula: Relevant results in top K ÷ K</li>
<li>Use when: You only care about the quality of what users see</li>
<li>Limitation: Doesn&#39;t measure how many relevant documents were missed</li>
</ul>
<h3 id="recall-k">Recall@K</h3>
<ul>
<li>What: Fraction of all relevant documents found in top K</li>
<li>Formula: Relevant found in top K ÷ total relevant documents</li>
<li>Use when: Missing relevant information is costly</li>
<li>Limitation: Requires knowing all relevant documents</li>
</ul>
<h3 id="f1-score-k">F1 Score@K</h3>
<ul>
<li>What: Balance between precision and recall</li>
<li>Formula: 2 × (Precision × Recall) ÷ (Precision + Recall)</li>
<li>Use when: Comparing systems with different precision/recall trade-offs</li>
<li>Key insight: Penalizes systems that optimize only one metric</li>
</ul>
<h2 id="ideas-to-explore">Ideas to Explore</h2>
<p>User steered semantic search by selecting N matches and finding the common subspace in their embeddings</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://github.com/frutik/awesome-search">https://github.com/frutik/awesome-search</a></li>
<li><a href="https://softwaredoug.com/blog/2022/07/16/what-is-presentation-bias-in-search">What is Presentation Bias in search?</a></li>
<li><a href="https://softwaredoug.com/blog/2024/06/25/what-ai-engineers-need-to-know-search">What AI Engineers Should Know about Search</a></li>
<li><a href="https://news.ycombinator.com/item?id=15231302">HN Discussion: What every software engineer should know about search</a></li>
<li><a href="https://binal.pub/2023/04/ranking-anything-with-gpt4/">Ranking Anything with GPT4</a></li>
<li><a href="https://arxiv.org/abs/2312.02724">RankZephyr: Effective and Robust Zero-Shot Listwise Reranking is a Breeze!</a></li>
<li><a href="https://arxiv.org/abs/2601.06873">Applying Embedding-Based Retrieval to Airbnb Search</a></li>
<li><a href="https://python.useinstructor.com/blog/2024/10/23/building-an-llm-based-reranker-for-your-rag-pipeline/">LLM based reranker</a></li>
<li><a href="https://blog.wilsonl.in/search-engine/">Building a web search engine from scratch in two months with 3 billion neural embeddings</a></li>
<li><a href="https://arxiv.org/abs/2508.21038">On the Theoretical Limitations of Embedding-Based Retrieval</a></li>
<li><a href="https://karboosx.net/post/4eZxhBon/building-a-simple-search-engine-that-actually-works">Building a Simple Search Engine That Actually Works</a></li>
<li><a href="https://ashvardanian.com/posts/search-utf8/">Full Unicode Search at 50× ICU Speed with AVX‑512</a></li>
<li><a href="https://softwaredoug.com/blog/2026/03/06/probabilistic-bm25-utopia">https://softwaredoug.com/blog/2026/03/06/probabilistic-bm25-utopia</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a> <a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Biological Computing</title>
      <link>https://seanpedersen.github.io/posts/biological-computing</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/biological-computing</guid>
      <pubDate>Mon, 11 Aug 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p><strong>Biological computing using living neurons has crossed from science fiction into commercial reality.</strong> The first biological computers are now available for purchase, using lab-grown human brain cells to process information with high energy efficiency. These systems represent a fundamental shift from traditional silicon-based computing toward hybrid biological-digital architectures that leverage billions of years of neural evolution.</p>
<p>This emerging field, termed Organoid Intelligence, uses the computational power of actual brain tissue grown from human stem cells. Unlike neuromorphic chips that simply mimic neural behavior, biological computers employ real neurons that form functional networks, learn through experience and process information through natural synaptic connections.</p>
<h2 id="basic-functionality">Basic Functionality</h2>
<p>Biological computing systems work by growing <strong>brain organoids</strong> from human induced pluripotent stem cells in laboratory conditions. These three-dimensional neural cultures, typically 0.5 to 5 millimeters in diameter, contain between 10,000 and 800,000 living neurons that spontaneously develop electrical activity and complex oscillatory behavior similar to human brain tissue.</p>
<p>The technical architecture integrates these living networks with multi-electrode arrays containing 8 to 384 electrodes that both stimulate and record neural activity. Advanced microfluidic life support systems maintain organoid viability for up to 100 days, a significant improvement from initial lifespans measured in hours. Communication occurs through electrical stimulation and chemical signals using neurotransmitters like dopamine and serotonin.</p>
<p>The systems leverage natural neural plasticity mechanisms for learning. Correct responses receive predictable electrical patterns while errors trigger chaotic stimulation, mimicking reward-based learning in biological brains. Information storage occurs through structural and functional changes in neural networks, enabling pattern recognition and memory formation through synaptic plasticity.</p>
<h2 id="early-adoption">Early Adoption</h2>
<p>Biological computing has moved beyond laboratory demonstrations into practical applications across healthcare, research, and technology sectors, though adoption remains in early stages.</p>
<p>Pharmaceutical companies are exploring biological computing for drug discovery and neurological disorder research. The technology enables disease modeling for conditions like Alzheimer&#39;s, epilepsy, and Parkinson&#39;s disease using human-relevant neural responses. This approach offers alternatives to animal testing while providing more accurate data for pharmaceutical development.</p>
<p>Healthcare applications include medical device development, brain-computer interface research, and personalized medicine approaches. The systems enable real-time monitoring of drug effects on neural networks and enhanced understanding of brain disease mechanisms.</p>
<p>Current limitations present significant adoption barriers. <strong>Biological components survive only 100 to 180 days on average</strong>, requiring regular replacement. Systems remain limited to thousands or hundreds of thousands of neurons, far below brain complexity levels. High costs, with CL1 units priced at $35,000, limit accessibility for many potential users.</p>
<p>Regulatory and ethical concerns constrain adoption. Ongoing debates about potential consciousness in biological computing systems require new ethical frameworks governing the use of human neural tissue. Using biological neural networks opens up many hairy ethical concerns and has an eerie similarity to the plot of The Matrix. <strong>Before we understand the emergence of (self-)cosciousness, we should not rush the adoption of this bio-technology as it may be an inherently evil application.</strong></p>
<h2 id="applications-for-artificial-intelligence">Applications for Artificial Intelligence</h2>
<p>Biological computing systems may offer critical advantages over classical deep learning approaches, addressing fundamental limitations. <strong>These living neural networks demonstrate superior generalization abilities, natural robustness against adversarial attacks and adaptive learning mechanisms.</strong></p>
<p>Generalization represents the most significant advantage of biological neurons. Classical deep learning models often fail catastrophically when encountering data distributions different from their training sets. A neural network trained to recognize cats in photographs might completely fail when presented with cartoon drawings of cats. Biological neurons, however, demonstrate remarkable ability to extract meaningful patterns and apply learned concepts to novel situations through natural abstraction mechanisms developed over millions of years of evolution.</p>
<p>Research at Johns Hopkins University showed that brain organoids could adapt their learned behaviors to new environmental conditions within hours, while equivalent artificial neural networks required complete retraining. The biological systems maintained performance across different stimulus patterns by leveraging inherent plasticity mechanisms that classical AI lacks.<br>Adversarial robustness emerges naturally in biological systems. Traditional deep learning models are notoriously vulnerable to adversarial examples, where tiny imperceptible changes to input data cause complete misclassification. These attacks exploit the brittle decision boundaries learned by artificial networks. Biological neurons, by contrast, process information through noisy, analog mechanisms that naturally resist such manipulations.</p>
<p>FinalSpark demonstrated this robustness by showing that organoid-based pattern recognition systems maintained accurate classification even when input signals were corrupted with noise levels that completely broke equivalent digital neural networks. The biological systems&#39; inherent stochasticity and redundant processing pathways provide natural defense against adversarial perturbations.</p>
<p>Continual learning without catastrophic forgetting represents another key advantage. Classical AI systems suffer from catastrophic forgetting, where learning new tasks erases previously acquired knowledge. This limitation requires complex architectural modifications and careful training procedures to overcome. Biological neurons naturally support lifelong learning through synaptic homeostasis and distributed memory representations.</p>
<p>Cortical Labs&#39; experiments showed that organoids could sequentially learn multiple pattern recognition tasks while retaining performance on earlier learned behaviors. The biological systems demonstrated graceful interference patterns rather than the complete knowledge destruction seen in traditional neural networks.</p>
<h2 id="key-startups">Key Startups</h2>
<p><a href="https://corticallabs.com/">Cortical Labs</a>, founded in 2019 as a spinout from Monash University, leads commercial biological computing development. The Australian company pioneered the DishBrain technology that learned Pong. CEO Dr. Hon Weng Chong and Chief Scientific Officer Brett Kagan have positioned the company at the forefront of wetware-as-a-service offerings. Cortical Labs launched the <a href="https://corticallabs.com/cl1.html">CL1</a> in March 2025 - the world&#39;s first commercial biological computer. Priced at $35,000 per unit, the system contains 800,000 lab-grown human neurons with integrated life support maintaining cell viability for six months.</p>
<p><a href="https://finalspark.com/">FinalSpark</a>, established in 2014 by Dr. Fred Jordan and Dr. Martin Kutter, developed the first remote-access biological computing platform. The Swiss company, currently seeking $50 million in Series A funding, has created a unique dopamine-based reward system for training organoids and extended operational lifespans from hours to over 100 days.</p>
<p><a href="https://koniku.com/">Koniku</a>, founded in 2015 by Nigerian neuroscientist Dr. Oshiorenoya Agabi, focuses on biological detection systems. With $1.8 million in funding and partnerships with Airbus, the company developed Konikore processors that combine biological neurons with silicon for detecting explosives, drugs, and diseases. Their systems achieve parts-per-billion sensitivity with response times under 10 seconds.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Biological computing using living neurons has transitioned from theoretical research to commercial reality, offering a sustainable path toward more intelligent, adaptive and energy-efficient computing systems. While technical challenges around lifespan, scalability, and standardization remain significant, the field demonstrates extraordinary potential for revolutionizing drug discovery, neuroscience research, and artificial intelligence applications.</p>
<p>The convergence of stem cell technology, advanced electrode interfaces and artificial intelligence has created a new computational paradigm that leverages natural neural evolution. As these systems mature and scale, they promise to address the energy crisis in computing while unlocking new forms of machine intelligence that complement traditional silicon-based approaches. The first commercial biological computers mark the beginning of a transformation that could fundamentally reshape how we approach computation in the coming decades, though the ethics of it all remains unclear at best and evil at worst.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.frontiersin.org/journals/science/articles/10.3389/fsci.2023.1017235/full">https://www.frontiersin.org/journals/science/articles/10.3389/fsci.2023.1017235/full</a></li>
<li><a href="https://pure.johnshopkins.edu/en/publications/first-organoid-intelligence-oi-workshop-to-form-an-oi-community">https://pure.johnshopkins.edu/en/publications/first-organoid-intelligence-oi-workshop-to-form-an-oi-community</a></li>
</ul>
<p>Generalization and Biological vs Artificial Neural Networks</p>
<ul>
<li><a href="https://www.pnas.org/doi/10.1073/pnas.2311805121">https://www.pnas.org/doi/10.1073/pnas.2311805121</a></li>
<li><a href="https://www.sciencedirect.com/science/article/pii/S0959438818301569">https://www.sciencedirect.com/science/article/pii/S0959438818301569</a></li>
<li><a href="https://pubs.aip.org/aip/aml/article/2/2/021501/3291446/Brain-inspired-learning-in-artificial-neural">https://pubs.aip.org/aip/aml/article/2/2/021501/3291446/Brain-inspired-learning-in-artificial-neural</a></li>
</ul>
<p>Adversarial Robustness in Biological vs Artificial Systems</p>
<ul>
<li><a href="https://www.sciencedirect.com/science/article/abs/pii/S0020025523007752">https://www.sciencedirect.com/science/article/abs/pii/S0020025523007752</a></li>
<li><a href="https://link.springer.com/article/10.1007/s00521-025-11019-6">https://link.springer.com/article/10.1007/s00521-025-11019-6</a></li>
<li><a href="https://arxiv.org/abs/2405.00679">https://arxiv.org/abs/2405.00679</a></li>
<li><a href="https://www.sciencedirect.com/science/article/abs/pii/S0893608023002824">https://www.sciencedirect.com/science/article/abs/pii/S0893608023002824</a></li>
<li><a href="https://arxiv.org/html/2405.20694">https://arxiv.org/html/2405.20694</a></li>
</ul>
<p>Catastrophic Forgetting and Continual Learning</p>
<ul>
<li><a href="https://arxiv.org/html/2403.05175v1">https://arxiv.org/html/2403.05175v1</a></li>
<li><a href="https://www.sciencedirect.com/science/article/pii/S0893608019300231">https://www.sciencedirect.com/science/article/pii/S0893608019300231</a></li>
<li><a href="https://www.pnas.org/doi/10.1073/pnas.1611835114">https://www.pnas.org/doi/10.1073/pnas.1611835114</a></li>
<li><a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC5380101/">https://pmc.ncbi.nlm.nih.gov/articles/PMC5380101/</a></li>
<li><a href="https://www.science.org/doi/10.1126/sciadv.adi2947">https://www.science.org/doi/10.1126/sciadv.adi2947</a></li>
<li><a href="https://www.ibm.com/think/topics/catastrophic-forgetting">https://www.ibm.com/think/topics/catastrophic-forgetting</a></li>
</ul>
<p>Energy Efficiency and Biological Computing</p>
<ul>
<li><a href="https://www.frontiersin.org/journals/science/articles/10.3389/fsci.2023.1017235/full">https://www.frontiersin.org/journals/science/articles/10.3389/fsci.2023.1017235/full</a></li>
<li><a href="https://spectrum.ieee.org/biological-computer-for-sale">https://spectrum.ieee.org/biological-computer-for-sale</a></li>
<li><a href="https://www.scientificamerican.com/article/these-living-computers-are-made-from-human-neurons/">https://www.scientificamerican.com/article/these-living-computers-are-made-from-human-neurons/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Photonic Computing</title>
      <link>https://seanpedersen.github.io/posts/photonic-computing</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/photonic-computing</guid>
      <pubDate>Thu, 07 Aug 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>Photonic computing uses light (photons) instead of electrons to perform calculations, offering faster processing speeds and lower energy consumption than traditional electronic processors. Since photons travel at the speed of light and generate minimal heat, photonic systems can perform massive parallel operations with reduced thermal management requirements - making photonic computing a very promising development.</p>
<h2 id="how-photonic-computing-works">How Photonic Computing Works</h2>
<p>Photonic computers manipulate light signals using various optical components:</p>
<p><strong>Optical Logic Gates</strong>: Instead of transistors switching electrical signals, photonic systems use devices like Mach-Zehnder interferometers, ring resonators or nonlinear optical materials to perform logical operations on light beams. These can implement AND, OR, NOT and other fundamental operations of computing.</p>
<p><strong>Wavelength Division Multiplexing</strong>: Multiple data streams can be encoded on different wavelengths of light traveling through the same optical waveguide simultaneously, enabling massive parallelism that&#39;s difficult to achieve with electrons.</p>
<p><strong>Photonic Integrated Circuits</strong>: Similar to electronic chips, these integrate lasers, modulators, waveguides and photodetectors on single substrates, typically made from silicon, indium phosphid or lithium niobate.</p>
<h2 id="from-lab-to-market">From Lab to Market</h2>
<p>Photonic computing transitioned from laboratory experiments to commercial systems in 2025. Multiple systems now deliver practical AI acceleration with performance that matches or exceeds traditional electronic alternatives while consuming 30 to 1,000 times less energy.</p>
<h3 id="key-breakthroughs">Key Breakthroughs</h3>
<p><strong>MIT&#39;s Integrated Processor</strong>: In December 2024, MIT researchers demonstrated the first fully integrated photonic processor capable of performing all key deep neural network computations optically on a single chip. The system achieves classification tasks in less than 0.5 nanoseconds with over 92% accuracy.</p>
<p><strong>Lightmatter&#39;s Achievement</strong>: Demonstrated the first photonic processor running state-of-the-art neural networks including ResNet, BERT, and deep reinforcement learning algorithms without modifications. Their six-chip package delivers 65.5 trillion operations per second while consuming only 78 watts of electrical power plus 1.6 watts of optical power.</p>
<p><strong>Tsinghua&#39;s Taichi Chip</strong>: Achieved 160 TOPS/W energy efficiency with 91.89% accuracy on image recognition tasks, representing over 1,000 times more energy efficiency than electronic counterparts.</p>
<h3 id="startup-success">Startup Success</h3>
<p>Several startups have achieved significant milestones:</p>
<ul>
<li><strong><a href="https://lightmatter.co/">Lightmatter</a></strong>: Achieved $4.4 billion valuation after raising $400 million in 2024</li>
<li><strong><a href="https://www.psiquantum.com/">PsiQuantum</a></strong>: Raised $940 million from the Australian government in 2024</li>
<li><strong><a href="https://qant.com/">Q.ANT</a></strong>: Secured €62 million Series A and became the first company to ship commercial photonic processors as standard PCIe cards</li>
<li><strong><a href="https://photonic.com/">Photonic Inc.</a></strong>: Received $100 million investment from Microsoft</li>
</ul>
<h2 id="ai-applications">AI Applications</h2>
<p>Photonic computing delivers three key advantages for AI workloads:</p>
<ol>
<li><strong>Massive Parallelism</strong>: Matrix multiplication operations can be performed passively</li>
<li><strong>Ultra-low Energy Consumption</strong>: Up to 1,000x more power efficienct than digital chips</li>
<li><strong>Speed</strong>: 2 to 3 orders of magnitude faster than digital chips</li>
</ol>
<p>Real-world applications include computer vision for autonomous vehicles, natural language processing with Transformers, wireless communications for 6G systems and scientific computing for climate modeling.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Photonic computing achieved commercial viability in 2025, offering compelling alternatives to traditional electronic processors for specific AI acceleration tasks. While it won&#39;t replace electronic systems entirely, it has become essential for heterogeneous computing architectures where energy efficiency, processing speed, and parallel operations provide real value.</p>
<p>The technology has moved beyond promising research to deliver practical solutions for real-world AI workloads, marking the beginning of a new era in computational efficiency and performance.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.nature.com/articles/s41586-025-08786-6">https://www.nature.com/articles/s41586-025-08786-6</a></li>
<li><a href="https://news.mit.edu/2024/photonic-processor-could-enable-ultrafast-ai-computations-1202">https://news.mit.edu/2024/photonic-processor-could-enable-ultrafast-ai-computations-1202</a></li>
<li><a href="https://insidehpc.com/2025/07/q-ant-raises-e62m-for-photonic-processing/">https://insidehpc.com/2025/07/q-ant-raises-e62m-for-photonic-processing/</a></li>
<li><a href="https://www.tsinghua.edu.cn/en/info/1399/12830.htm">https://www.tsinghua.edu.cn/en/info/1399/12830.htm</a></li>
<li><a href="https://qant.com/press-releases/leibniz-supercomputing-centre-computes-with-light-worlds-first-photonic-ai-processor-from-q-ant-goes-into-operation/">https://qant.com/press-releases/leibniz-supercomputing-centre-computes-with-light-worlds-first-photonic-ai-processor-from-q-ant-goes-into-operation/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Launching Digger Trends</title>
      <link>https://seanpedersen.github.io/posts/launching-digger-trends</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/launching-digger-trends</guid>
      <pubDate>Wed, 30 Jul 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>launch</category>
      <content:encoded><![CDATA[
          <p>Update: this project is currently offline.</p>
<p><a href="https://trends.digger.lol/">Digger Trends</a> is a semantic search engine for instagram profiles and posts. Find the perfect partners for online marketing campaigns and understand current viral trends in your niche. Currently limited to German profiles only.</p>
<h2 id="use-cases">Use Cases</h2>
<ul>
<li>Find relevant influencers</li>
<li>Find viral posts</li>
</ul>
<p class="post-hashtags"><a href="/index.html#launch">#launch</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Popping the AGI Bubble</title>
      <link>https://seanpedersen.github.io/posts/agi-bubble</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/agi-bubble</guid>
      <pubDate>Sat, 26 Jul 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>It is becoming clearer and clearer that scaling up LLM&#39;s will not solve their fundamental limits like hallucinations (making up bullshit) and context rot (decreasing performance with growing noisy input context). While LLM companies are still slashing benchmarks (often by training on test data directly or guessing the test data) - users of LLM&#39;s know the truth: LLM&#39;s are a useful tool but nowhere near a robust AGI (that can reliably solve complex tasks without human supervision) and there is nothing in sight suggesting this will change soon.</p>
<h2 id="fundamental-limits">Fundamental Limits</h2>
<h3 id="lacking-a-world-model">Lacking a World Model</h3>
<p>LLM&#39;s are not designed with a world model (allowing to predict 3D physical scenarios over time). LLM only have a token (text) model which only entails a brittle world model that does not generalize well (since it is not grounded directly in 4D reality). Read this <a href="/posts/a-thousand-brains/#road-to-agi">post</a> on necessary modules for AGI identified by Jeff Hawkins.</p>
<h3 id="auto-regressive-architectures">Auto-Regressive Architectures</h3>
<p>Current LLM&#39;s face a core architectural constraint: they generate text sequentially, one token at a time. As Yann LeCun argues, this creates exponential error accumulation. Each prediction depends on all previous tokens, so early mistakes cascade through long sequences, causing models to derail from coherent long-formed reasoning (an issue well known among LLM users - known as context rot).</p>
<p>This sequential generation prevents LLM&#39;s from forming thoughts holistically. Unlike human cognition, which manipulates abstract concepts as complete structures, current models must linearize everything into word sequences. They cannot think about problems in abstract space before committing to specific text.</p>
<p>The result is a fundamental bottleneck. Tasks requiring sustained logic or complex reasoning remain difficult regardless of scale improvements (making autonomous agents doing long complex tasks a real challenge). Simply adding more parameters or training data cannot solve this architectural limitation. Transformer based LLM&#39;s will thus never overcome the hallucination problem for long-context tasks (context rot).</p>
<p>True progress requires a paradigm shift toward architectures that form and manipulate complete conceptual structures rather than sequential tokens. Until then, LLM&#39;s remain sophisticated stochastic pattern matchers, staying far away from reliable reasoning.</p>
<h3 id="model-collapse">Model Collapse</h3>
<p>LLM&#39;s trained on their own outputs suffer from model collapse - their performance degrades. Thus the trend of more and more LLM generated content (slop) being published on the web, will degrade their performance in the long run.</p>
<h3 id="fractured-embeddings">Fractured Embeddings</h3>
<p>The knowledge representation (weight matrices) in neural networks is fractured / entangled leading to issues like adversarial examples and hallucinations.</p>
<h2 id="problem-classes">Problem Classes</h2>
<p>Current AI systems can solve low complexity tasks with lots of training data available (text, code, video, audio) and high-complexity tasks which are easy to verify (so big training data with high-signal can be generated) like chess, programming and math - by interpolating on existing data. It is easy to verify who won a chess or go game and thus possible to generate high-signal training data. The same is true for certain classes of programming problems (does it compile? does it run without errors? does it pass tests? does it produce same output as an existing program? does it better on benchmark X?).</p>
<p>It is much harder to generate meaningful rewards for more abstract programming tasks though (is the UI design polished? is the user experience sensible?) - this data can only be inferred from expensive human usage.</p>
<p>So we have two types of problems: easy to verify problems and thus also easy to produce big high-signal training data and hard to verify problems (needs humans in the loop) and thus hard to produce big high-signal training data. For the former we are in Alpha Zero territory (innovative super-intelligence using RL) and the latter we are in Alpha Go territory (interpolate and synthesize on human generated data).</p>
<h3 id="real-value">Real Value</h3>
<p>LLM + RL solveable examples:</p>
<ul>
<li>discover novel algorithms for things that can be easily verified / benchmarked<ul>
<li><a href="https://www.nature.com/articles/s41586-022-05172-4">faster matrix-multiplication</a></li>
<li><a href="https://arxiv.org/abs/2507.14111v4">faster CUDA kernels</a></li>
</ul>
</li>
</ul>
<p>LLM solveable examples:</p>
<ul>
<li>coding in popular programming languages</li>
<li>anything coding related that is verifiable:<ul>
<li>translate code base from prog. lang A to B (verify input -&gt; output)</li>
<li>optimize slow code (f.e. PDF extraction) -&gt; measure speed and verify output</li>
</ul>
</li>
<li>summarizing complicated technical topics (with lots of training data available)</li>
<li>generating (interpolating) texts, audio and video</li>
</ul>
<p>And anything which has tolerance for errors (hallucinations).</p>
<h3 id="tasks-out-of-reach">Tasks out of Reach</h3>
<p>High complexity (very long context / completely novel) tasks with minimal training data available (often limited by needing humans to produce data).</p>
<p>Any critical task that has no tolerance for high error rates (and is not easily verifiable).</p>
<p>LLM (+ RL) unsolveable examples:</p>
<ul>
<li>creating completely new (not merely interpolating) ideas (mathematical theorems / proofs, physics etc.) in unexplored domains (think outside the box)<ul>
<li>solving old problems by interpolating existing knowledge is possible though</li>
</ul>
</li>
<li>novel creative writing</li>
<li>coming up with novel funny jokes</li>
</ul>
<blockquote><p class="quote-line">Discovery isn&#39;t one thing. It&#39;s three. You can induce — generalize from data, which lands you at Newton plus some epicycles to explain Mercury&#39;s weird orbit. You can deduce — derive rigorously from axioms you already have, which never gives you new axioms. Or you can jump — invent the frame itself, decide that spacetime curves. That third move is the one that matters, and it&#39;s exactly the one induction and deduction can&#39;t reach.</p>
</blockquote><ul>
<li><a href="https://x.com/hxiao/status/2075180424754757722">Han Xiao on X</a></li>
</ul>
<p>Good ref: <a href="https://philsci-archive.pitt.edu/28024/1/Scientific_Invention_Position_Paper%20(17).pdf">LLM&#39;s can&#39;t jump</a></p>
<h2 id="signals-for-agi">Signals for AGI</h2>
<ul>
<li>no benchmark (problem) we can design where humans beat AI</li>
<li>extreme and robust (human like) generalisation ability<ul>
<li>LLM&#39;s possess clearly no human like intelligence as they make obvious logical and factual mistakes (very brittle; context dependent problem solving ability) and hallucinate without being capable to self-correct through self-inspection -&gt; LLM&#39;s output will always have to be validated using human supervision for critical tasks (just like for self-driving cars)</li>
<li>when humans make little slips (errors) while speaking / writing a thought out - the whole sentence (thought) stays consistent (if the thought was consistent in the first place). LLM&#39;s &quot;thoughts&quot; OTOH are directly influenced by each token (word) and thus a few small slips can quickly throw them off completely (context rot) -&gt; leading to more hallucinations in longer texts.</li>
</ul>
</li>
<li>self-awareness (introspection) and ability to self-modify (continuous learning -&gt; update facts / beliefs)</li>
<li>reliable printers</li>
</ul>
<h2 id="road-to-agi">Road to AGI</h2>
<p>World models (grounded in perception and real interaction) are the correct approach to produce more robust and general AI systems: current LLMs are locked into pure text perception (vision is just bolted on) and possess no ability to generalize knowledge into unknown domains that are not present in training data (they learn more by mimicking than generalizing rules).</p>
<p>My prediction: true general AI systems will only be possible if they can manipulate an abstract 3D scene and then predict how it will interact over time (world model). For this to work the AI needs a good real world simulator which can be learned from watching lots of video footage from real interactions and grounding it via real-world interactions. Thus companies which mass deploy interactive robots and gather a massive real-world action dataset, might have the ultimate AGI moat.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://timdettmers.com/2025/12/10/why-agi-will-not-happen/">https://timdettmers.com/2025/12/10/why-agi-will-not-happen/</a></li>
<li><a href="https://wonderfall.dev/autoregressive/">https://wonderfall.dev/autoregressive/</a></li>
<li><a href="https://arxiv.org/abs/2404.02305v1">Collapse of Self-trained Language Models</a></li>
<li><a href="https://arxiv.org/abs/2507.19703">The wall confronting large language models</a></li>
<li><a href="https://arxiv.org/abs/2503.01781">Cats Confuse Reasoning LLM</a> (study on context rot phenomenon)</li>
<li><a href="https://blog.jxmo.io/p/superintelligence-from-first-principles">https://blog.jxmo.io/p/superintelligence-from-first-principles</a></li>
<li><a href="https://blog.jxmo.io/p/we-should-stop-talking-about-agi">https://blog.jxmo.io/p/we-should-stop-talking-about-agi</a></li>
<li><a href="https://garymarcus.substack.com/p/dear-elon-musk-here-are-five-things">https://garymarcus.substack.com/p/dear-elon-musk-here-are-five-things</a></li>
<li><a href="https://www.youtube.com/watch?v=uB9yZenVLzg">This video will change your mind about the AI hype</a></li>
<li><a href="https://arxiv.org/abs/2505.11581">Questioning Representational Optimism in Deep Learning: The Fractured Entangled Representation Hypothesis</a></li>
<li><a href="https://machine-bullshit.github.io/">https://machine-bullshit.github.io/</a></li>
<li><a href="https://unherd.com/2025/08/is-the-ai-bubble-about-to-burst/?lang=us">https://unherd.com/2025/08/is-the-ai-bubble-about-to-burst/?lang=us</a></li>
<li><a href="https://dlants.me/agi-not-imminent.html">https://dlants.me/agi-not-imminent.html</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Metrics for Artificial General Intelligence</title>
      <link>https://seanpedersen.github.io/posts/measuring-agi</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/measuring-agi</guid>
      <pubDate>Wed, 16 Jul 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>We need a new benchmark score that expresses the robustness of models within a coherent problem set (punish brittleness -&gt; making stupid mistakes while otherwise achieving good scores). Humans possess very robust (generalizable) intelligence, preventing hallucinations and adversarial examples (small changes in input space causing large changes in prediction space).</p>
<hr />
<p><strong>Thinking about the I in AI</strong></p>
<p>A framework allowing to compare intelligence metrics for (AI) agents<br>across problems. Focus lies on general intelligence and making published<br>results easier to compare.</p>
<h2 id="introduction">Introduction</h2>
<p>Many recent publications in the field of AI may seem to the uninitiated<br>like great scientific leaps pushing the so called &quot;state of the (dark)<br>art&quot;. But are we really building more <strong>intelligent</strong> systems though?</p>
<p>To answer this question a definition of intelligence including a metric<br>that quantifies intelligence of an agent for a given problem (set) is<br>needed. This paper tries to do exactly this: develop a family of<br>universally applicable intelligence metrics that are problem (set)<br>contextual.</p>
<p>Most of current AI research (mainly Machine/Deep Learning) is dedicated<br>to increasing either some accuracy metric (self-/ supervised problems)<br>or more generally some reward score (Reinforcement Learning). This is<br>often achieved by carefully human (AI researchers) designed<br>&quot;intelligent&quot; systems that improve incrementally on prior published work<br>scores on common benchmarks.</p>
<p>These SOTA achieving papers all answer the same (wrong) question: How<br>did we hand design and tune system X that achieved a better accuracy /<br>reward than most other previously published works solving a narrow class<br>of problems.</p>
<p>Sadly many papers that indeed achieve new impressive results, then<br>continue to publish it with too often post rationalized explanations<br>cluttered with fancy but unrelated mathematical proofs to make things<br>look sophisticated enough for &quot;prestigious&quot; conferences or journals.</p>
<p>This paper tries to explain why the current trend of publishing<br>incrementally fine tuned specialized &quot;AI&quot; solutions, is the wrong<br>question to ask as an AI researcher with a <strong>focus on Intelligence</strong> and<br><strong>not on Artificial</strong> (human designed) systems that solely solve<br>specialized (narrow) problems. A novel and simple family of formalized<br>metrics for (artificial) intelligence agents are introduced in the hope<br>of sparking more interest into the design of generally intelligent<br>agents.</p>
<p>Meta-learning or AI-Generating Algorithms as a research field is slowly<br>gaining the traction it deserves, on the premise of exponential growth<br>of compute capacity. Which will likely continue with new manufacturing<br>processes and completely different computation paradigms such as<br>quantum, photonic and biological computers on the horizon.</p>
<h2 id="definitions">Definitions</h2>
<p>The following definitions are not presented as objectively correct<br>definitions of the following concepts but merely serve as helpful<br>building blocks to understand the ideas this paper tries to convey.</p>
<p><strong>Data</strong> (Information) is raw and meaningless. Exists as measurable/observable quantities.<br>Its simplest form is a bit: 0 / 1 or stated differently the smallest<br>observation is a variable with two states.</p>
<p><strong>Observation</strong> (Perception) is data perceived by an agent from the environment (through sensors).</p>
<p><strong>Problem</strong> (Goal) is defined as anything that can be formulated as a<br>loss/objective/reward/fitness function with at least one solution (&gt;0<br>global maxi-/minima exist/s). E.g. classifying the MNIST test set<br>accurately or winning a game of chess.</p>
<p>A conditional probability distribution over all possible observation<br>sequences assigning each observation sequence a reward. This problem<br>definition is more general than f.e. a function that merely maps single<br>observations to a reward.</p>
<p>Sequential Decision Problems</p>
<p>Urproblem: Evolution - Stay alive aka stay around to observe the next<br>moment. In a universe that can destroy an agent it logically follows for<br>an agent to adapt to its environment in order to stay alive. For this to<br>happen pure chance aka randomness and some time is enough - no form of<br>consciousness is needed to act intelligently - to produce combinations<br>of matter that actively manipulate their environment to stay alive.</p>
<p>Problem(Environment)</p>
<p><strong>Knowledge</strong> is just data (executed as programs) predicting accurately (ideally lossless) unknown / future data.</p>
<p><strong>Intelligence</strong> is the rate at which an agent generates knowledge solving a given problem from data w.r.t. observations or time needed to do so. This definition<br>is context (problem) specific. The intelligence of two or more agents<br>can thus only be compared for the same problem set.</p>
<p><strong>Agency</strong> is the speed at which an agent achieves a goal (solve the problem). It must not always rely on intelligence to do so, as it would always imply to acquire optimal knowledge in minimal steps to solve a given problem / reach a goal. An agent can achieve high agency by simply executing random actions, reaching a goal before an highly intelligent agent even starts to act (exploration vs exploitation).</p>
<p><strong>General intelligence</strong> capabilities of an agent are defined for a set of<br>problems, measuring the agent&#39;s intelligence for each problem, then<br>normalizing all subproblem scores (0,1), finally computing the average<br>as the general intelligence score for the given set of problems for the<br>agent.</p>
<p><strong>Problem complexity</strong> is defined for a given problem by the minimal number of observations needed<br>by the most possibly (general? -&gt; which problem set) intelligent agent<br>to solve the problem (=extract all and not a bit more of knowledge that<br>is needed to solve the given problem contained in the data of perceived<br>observations).</p>
<p><strong>TODO:</strong></p>
<ul>
<li>Is there a practical way to compute / estimate the problem<br>complexity for a problem? Theoretical measures like Kolmogorov<br>complexity tend to be incomputable in praxis.</li>
<li>Think about complete sets of similar problems, which would prevent<br>the agent from being able to have had some similar exposure to a<br>problem preventing any form of transfer learning / solving by<br>analogy.</li>
</ul>
<p><strong>Environment</strong>: A state machine or any other process that generates a new state based or<br>not based on its prior state and current actions executed by agent/s in<br>the environment.</p>
<p>Environment(T) = Actions(Environment(T-1))</p>
<p><strong>Agent</strong>: A system capable of perceiving data for a problem domain environment<br>that produces solution/s for given problems by executing sequences of<br>actions, changing the state of the environment (solving the problem).</p>
<p>E.g. uniform distribution over all possible solutions (random agent), NN<br>trained with gradient descent or RL or simply an octopus, a human etc.</p>
<p>The agent perceives a subset of the current (t) environment state and<br>produces actions that shall solve the problem, leading to a change in<br>the environment&#39;s state (t+1). Rinse and repeat:</p>
<p>Agent(Environment~T~, Problem) -&gt; Actions -&gt; A(E~T+1,~ P) -&gt; ...</p>
<p><strong>Agent Size</strong>: Amount of all bits of information used by the agent to solve the given<br>problem.</p>
<p>Composed of:</p>
<ul>
<li>prior knowledge (meta knowledge helping to acquire problem specific<br>knowledge)</li>
<li>perceived data (experience in problem domain)</li>
<li>knowledge (learned skills to solve the problem)</li>
</ul>
<p><strong>Energy Consumption</strong>: Instead of using a physical measure of energy like Joule one might want<br>to use a more theoretical measure like e.g. FLOP to truly capture the<br>algorithmic intelligence with regards to computational efficiency<br>advances. This would move the field also away from current hardware and<br>time resource competitions (dominated by big tech companies) creating<br>superficial (big hardware enables big data crunching, creating &quot;SOTA&quot;<br>results...) progress.</p>
<p>Example: compare AIME for best human player vs AIME of alpha go to<br>demonstrate importance of it.</p>
<h2 id="intelligence-metrics-family">Intelligence Metrics Family</h2>
<p>A measure of intelligence an agent exhibits for a given problem can be<br>quantified as the accuracy of knowledge (solution) generated by the<br>agent divided by the number of observations or time frames needed to do<br>so:</p>
<p><strong>IM</strong> = (knowledge accuracy) / (used observations)</p>
<p>To prevent researchers from circumventing the goal of building more<br>intelligent systems another coefficient can be added:</p>
<p>The size of a given agent e.g. number of weights as another coefficient<br>to prevent AI designers from just looking once at the training data and<br>copying it to minimize number of used observations.</p>
<p>E.g. : Image classification data set contains 1000 images, one could use<br>a conventional CNN architecture and train it for many epochs thus using<br>many observations repeatedly. The submitters could try to minimize their<br>used observations by copying all 1000 images in only one pass into their<br>agent, executing hidden away from the AIM metric system many training<br>epochs and thus cheating by hiding the use of many more observations.</p>
<p>Accounting for the agent size can also be viewed as favoring simple<br>solutions (Occam&#39;s razor).</p>
<p><strong>AIM</strong> = (knowledge accuracy) / ((used observations) * (agent size))</p>
<h3 id="examples">Examples</h3>
<p><strong>Supervised learning</strong>: An agent observing 1,000,000 images in<br>training, achieving an accuracy of 90% on the test set, would be less<br>intelligent than an agent that needs to observe only 1,000 images to<br>achieve the same or better accuracy on the test set.</p>
<p><strong>Reinforcement Learning</strong>: An agent spending 1,000,000 hours or frames<br>of exposure in an environment to achieve N reward points would be dumber<br>than one that only needs 1,000 to score the same or higher reward.</p>
<h3 id="extensions">Extensions</h3>
<p>The introduced artificial intelligence metric does not consider the<br>amount of energy spent while training to compute the knowledge. A<br>natural extension of AIM could therefore be to use energy usage as the<br>divisor. This should naturally nullify any attempt to do &quot;hidden&quot;<br>computations (trying to minimize observations, gaming the AIM score)<br>since it could be measured on a hardware level. Also this is the most<br>ethical AIM score since it promotes energy efficient agents, helping our<br>planet&#39;s climate and thus humanity:</p>
<p><strong>AIM/E</strong> = AIM / (spent energy)</p>
<p>or simply:</p>
<p><strong>IM/E</strong> = IM / (spent energy)</p>
<p><strong>Find out:</strong></p>
<ul>
<li>Maybe (knowledge accuracy) / (spent energy) is enough to capture<br>&quot;efficient&quot; intelligence? OTOH agent size should favor short and<br>simple solutions ...but spent energy as well -&gt; what is the<br>correlation or even causation between short (simple) solutions and<br>spent energy?</li>
<li>Which of the two are easier to implement?</li>
</ul>
<h2 id="back-to-the-roots">Back to the Roots</h2>
<p>How can AIM benefit from powerful concepts like Kolmogorov complexity,<br>computational complexity, Solomonoff induction, AIXI and Gödel machines?</p>
<h3 id="comparison-with-other-intelligence-metrics">Comparison with other Intelligence Metrics</h3>
<p>AIXI / Universal Intelligence (based on kolmogorov complexity) - Hutter</p>
<p>&quot;the intelligence of a system is a measure of its skill-acquisition<br>efficiency over a scope of tasks, with respect to priors, experience,<br>and generalization difficulty&quot; - F. Chollet</p>
<h3 id="technical-implementation">Technical Implementation</h3>
<p>To calculate any AIM metric we need:</p>
<ul>
<li>Agent (Algorithm that produces solution/s)</li>
<li>Environment (Observations/time frames perceived by agent)</li>
<li>Problem / Loss Function (Evaluation of solution / feedback / reward)</li>
</ul>
<h2 id="looking-at-recent-ai-research">Looking at Recent AI Research</h2>
<p>What can we do in praxis with the introduced family of AI metrics in our<br>toolbox?</p>
<p>We could take a closer look at recent (or all with a small<br>representative sample) research progress in a specific AI research<br>problem set for example Computer Vision and see how novel SOTA achieving<br>approaches compare to one another under the light of AIM. E.g. dense vs<br>convolutional vs residual vs depth map vs NEAT on small and big problem<br>sets of similar and dissimilar kind.</p>
<p>Another application could be to report AIM scores as well as accuracy.</p>
<p><strong>Q:</strong> What is by above definitions the current evaluation metrics of<br>most AI papers? In supervised learning it is accuracy, so what is it?<br><strong>A:</strong> How accurately the hand designed agent &quot;learned&quot; correct<br>knowledge solving the given problem, e.g. the percentage of correctly<br>predicted unknown/future information (labels/state rewards). This gives<br>rise to unstable hand tuned algorithms that easily break when hyper<br>parameters are changed.</p>
<p><strong>Q:</strong> How does this thought framework apply to Reinforcement Learning?<br><strong>A:</strong> It is easy to apply. RL achieves the same thing as classical<br>supervised learning: predicting the unknown. Only that in sup. learning<br>the unknown is static (timeless) and in RL it is dynamic (temporal:<br>dependent on time). Both optimize an objective SL by minimizing loss<br>function and RL agents maximizing reward.</p>
<h2 id="existing-research-on-intelligence-metrics">Existing Research on Intelligence Metrics</h2>
<p>In the paper &quot;Universal Intelligence:A Definition of Machine<br>Intelligence&quot; by Shane Legg and Marcus Hutter, the authors propose<br>following properties for a useful intelligence metric:</p>
<ul>
<li><strong>Valid.</strong> A test/measure of intelligence should be just that, it should capture intelligence and not some related quantity or only a part of intelligence.</li>
<li><strong>Informative.</strong> The result should be a scalar value, or perhaps a vector, depending on our view of intelligence. We would like an absolute measure of intelligence so that comparisons across many agents can easily be made.</li>
<li><strong>Wide range.</strong> A test/definition should cover very low levels of intelligence right up to super human intelligence.</li>
<li><strong>General.</strong> Ideally we would like to have a very general test/definition that could be applied to everything from a fly to a machine learning algorithm.</li>
<li><strong>Dynamic.</strong> A test/definition should directly take into account the ability to learn and adapt over time as this is an important aspect of intelligence.</li>
<li><strong>Unbiased.</strong> A test/definition should not be biased towards any particular culture, species, etc.</li>
<li><strong>Fundamental.</strong> We do not want a test/definition that needs to be changed from time to time due to changing technology and knowledge.</li>
<li><strong>Formal.</strong> The test/definition should be specified with the highest degree of precision possible, allowing no room for misinterpretation. Ideally, it should be described using formal mathematics.</li>
<li><strong>Objective.</strong> The test/definition should not appeal to subjective assessments such as the opinions of human judges.</li>
<li><strong>Fully Defined.</strong> Has the test/definition been fully defined, or are parts still unspecified?</li>
<li><strong>Universal.</strong> Is the test/definition universal, or is it anthropocentric?</li>
<li><strong>Practical.</strong> A test should be able to be performed quickly and automatically, while from a definition it should be possible to create an efficient test.</li>
</ul>
<p>The AIM family ticks off all proposed properties, even the last one<br>which Legg &amp; Hutter do not achieve with their proposed universal<br>intelligence score since it relies on the Kolmogorov complexity which is<br>not feasible to compute in praxis.</p>
<h2 id="human-designed-overfitting">Human Designed Overfitting</h2>
<p>Most research around AI is narrow and specialized. A group of<br>researchers think together hard about this one problem, coming up with<br>novel, even impressive strategies / heuristics or whatever to solve the<br>problem better than anyone before them (achieving so-called SOTA).</p>
<p>We strongly need to move away from this specialized single problem<br>solver agent research competition (narrow AI research) and push for more<br>universally applicable AI systems. Projects like OpenAI&#39;s gym are a<br>great step into the right direction, since they offer an accessible and<br>diverse problem landscape. Curriculum learning / iterative<br>complexification of training environments is a promising field of<br>research as well that deserves more attention, since it could be a key<br>ingredient to AGI by offering a diverse set of problems.</p>
<p>Less specialized priors about the problem landscape aka environments<br>will lead to more general learning algorithms that perform well on<br>broader ranges of problems - the missing part of most of current AI<br>research endeavors.</p>
<h2 id="future-research-directions">Future Research Directions</h2>
<p>The tools developed here should enable us to directly optimize for more<br>intelligent agents by optimizing (maximize) directly for an AIM score!<br>e.g. with evolutionary algorithms and compressed genomes (indirect<br>encodings) for big problem sets trained on a big cluster of GPU&#39;s<br>refocusing on general / universal intelligence research instead of the<br>current hype of narrow and wasteful AI research.</p>
<p>Since AIM includes agent size training an agent to maximize general AIM<br>score for a set of related problems should give natural rise to transfer<br>learning in order to minimize the agent size resulting in more general<br>applicable intelligent agents.</p>
<p><strong>Notes:</strong></p>
<p>Notion of intelligence is heavily shaped by thinking about the<br>biological evolution of life. -&gt; Evolution (Physics&amp;Time) is the only<br>mother of intelligence.</p>
<p>Evolution favors organisms that are highly adaptable to the environments<br>they live in. Small species with short lifespans, achieve high<br>adaptability by rapid reproduction making many DNA mutations possible.<br>Larger species with longer life times need to adapt within their life,<br>that is why biological neural networks developed for them to stick<br>around, since they enable them to stay highly adaptable within their<br>lifetime.</p>
<p>Exploring, researching intelligence from a biological perspective seems<br>also a promising route to AGI. But only the bottom up approach seems<br>tractable. First understand the nervous system of simple life forms like<br>a worm (C. Elegans) before you try the same for a mouse or dare I say<br>the human brain (you know: just the most complex object in the universe<br>we know of).</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://arxiv.org/pdf/0712.3329.pdf">&quot;Universal Intelligence: A Definition of Machine Intelligence&quot;<br>(Shane Legg, Marcus Hutter)</a></li>
<li><strong><a href="https://arxiv.org/pdf/1911.01547.pdf">The Measure of<br>Intelligence</a> (Francois<br>Chollet)</strong></li>
<li>The Measure of All Minds <strong>(José Hernández-Orallo)</strong></li>
<li>Jürgen Schmidhuber<br><a href="http://people.idsia.ch/~juergen/goedelmachine.html"><strong>Gödelmaschine</strong></a><ul>
<li><a href="http://people.idsia.ch/~juergen/unilearn.html">http://people.idsia.ch/~juergen/unilearn.html</a></li>
</ul>
</li>
<li>Marcus Hutter - <strong>AIXI</strong><ul>
<li><a href="http://www.hutter1.net/ai/introref.htm">http://www.hutter1.net/ai/introref.htm</a></li>
</ul>
</li>
<li>Jeff Clune - <strong>AI-GAs</strong><ul>
<li><a href="https://arxiv.org/pdf/1905.10985.pdf">https://arxiv.org/pdf/1905.10985.pdf</a></li>
</ul>
</li>
<li><a href="https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication970.pdf">https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication970.pdf</a></li>
<li><a href="https://www.emeraldinsight.com/doi/pdfplus/10.1108/IJCS-01-2018-0003">https://www.emeraldinsight.com/doi/pdfplus/10.1108/IJCS-01-2018-0003</a></li>
<li><a href="http://dspace.cusat.ac.in/jspui/bitstream/123456789/3187/1/MEASURING%20UNIVERSAL%20INTELLIGENCE.pdf">http://dspace.cusat.ac.in/jspui/bitstream/123456789/3187/1/MEASURING%20UNIVERSAL%20INTELLIGENCE.pdf</a></li>
<li><a href="https://pdfs.semanticscholar.org/5204/a0c2464bb64971dfb045e833bb0ca4f118fd.pdf">https://pdfs.semanticscholar.org/5204/a0c2464bb64971dfb045e833bb0ca4f118fd.pdf</a></li>
<li><a href="http://www.vetta.org/documents/AIQ_Talk.pdf">http://www.vetta.org/documents/AIQ_Talk.pdf</a></li>
<li><a href="https://www.lesswrong.com/posts/vPtMSvnF8B5hM5LdL/intelligence-metrics-and-decision-theories">https://www.lesswrong.com/posts/vPtMSvnF8B5hM5LdL/intelligence-metrics-and-decision-theories</a></li>
<li><a href="https://arxiv.org/pdf/0712.3329.pdf">https://arxiv.org/pdf/0712.3329.pdf</a></li>
<li><a href="https://web.archive.org/web/2024/https://ws680.nist.gov/publication/get_pdf.cfm?pub_id=824478">https://web.archive.org/web/2024/https://ws680.nist.gov/publication/get_pdf.cfm?pub_id=824478</a></li>
<li><a href="https://arxiv.org/abs/1805.07883">https://arxiv.org/abs/1805.07883</a></li>
<li><a href="http://www.incompleteideas.net/IncIdeas/DefinitionOfIntelligence.html">http://www.incompleteideas.net/IncIdeas/DefinitionOfIntelligence.html</a></li>
<li><a href="https://breckyunits.com/intelligence.html">https://breckyunits.com/intelligence.html</a></li>
</ul>
<h2 id="author-notes">Author Notes</h2>
<p>So far nothing really strongly related to AIM has shown up in<br>references.</p>
<p>BUT his one stood out: <a href="https://arxiv.org/pdf/0712.3329.pdf">&quot;Universal Intelligence:A Definition of Machine<br>Intelligence&quot; by Shane Legg and Marcus<br>Hutter,</a></p>
<p>They favor problems / environments with low Kolmogorov complexity in<br>their definition of &quot;Universal Intelligence&quot; by weighing inversely<br>proportional Kolmogorov complexity for each environment over all<br>computable ones.</p>
<p>Legg and Hutter define their Universal Intelligence across all<br>computable environments of all complexities. AIM family could be<br>extended to all possible environments as well but is also applicable to<br>subsets or even single environments as well, which Legg and Hutter do<br>not seem to cover since computing the Kolmogorov complexity for even<br>small problems quickly becomes infeasible.</p>
<p>Ok if we take LH def of I and use it for a subset of all environments or<br>problems, weird stuff happens: We can define the AIM for the problem set<br>A = {MNIST, CIFAR-10}</p>
<p>Applying LH-UI def. kolmogorov(CIFAR-10) &gt; kolmogorov(MNIST) and thus<br>the ability to solve MNIST would be weighted more. AIM would just weigh<br>both equivally. MNIST being way simpler to solve than CIFAR-10 would<br>favor agents adapted solely to MNIST more than the other way around<br>which is not a good thing to do when evaluating the<br>universal intelligence of an agent.</p>
<p>&quot;The solution then, is to require the environmental probability measures<br>to be computable.&quot; LH restricts their definition of intelligence to all<br>computable environments. -&gt; No-Free-Lunch-Theorem kicks in! The space<br>of all computable environments is still so vast that most environments<br>would act seemingly random, resulting in the best agent acting randomly.</p>
<p><a href="http://incompleteideas.net/IncIdeas/DefinitionOfIntelligence.html">http://incompleteideas.net/IncIdeas/DefinitionOfIntelligence.html</a></p>
<p>Solomonoff Induction:</p>
<p><a href="https://www.lesswrong.com/posts/Kyc5dFDzBg4WccrbK/an-intuitive-explanation-of-solomonoff-induction">https://www.lesswrong.com/posts/Kyc5dFDzBg4WccrbK/an-intuitive-explanation-of-solomonoff-induction</a></p>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a> <a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Discovered, Not Designed - Sean McClure</title>
      <link>https://seanpedersen.github.io/posts/discovered-not-designed</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/discovered-not-designed</guid>
      <pubDate>Wed, 09 Jul 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>book</category>
      <content:encoded><![CDATA[
          <p>Concerned with the difference between complicated (causal, explicit and deterministically) versus complex (emergent, implicit, non-deterministic) designed objects and processes.</p>
<p>“Systems naturally evolve towards states with the greatest number of accessible microstates.” -&gt; Analogous to over-parameterized deep neural networks (double descent phenomenon). The over-parameterization helps gradient descent find local minima.</p>
<p>Abstraction through emergent grouping through useful analogies. Complex systems are not to be deliberately designed, but discovered in an externally guided search process. Complex systems are “alive” and can adapt to changing environments. Complicated systems are brittle since they are rule based deterministic machines.</p>
<p>Knowledge expansion vs knowledge convergence: Science has drifted into the deep branches (details) of the fractal knowledge tree and lost focus to uncover the root of all that is (in nature). Uncover hidden abstractions to create truly novel understanding of nature.</p>
<p>Let the structure emerge, do not attempt to follow a structure to get there. Goals can be fine, but don’t get too caught up in those; even largely random behavior can lead to patterns. Knowledge is being able to validate what emerges.</p>
<p>The book is available <a href="https://www.amazon.com/Discovered-Not-Designed-Building-Complexity/dp/B0D84YCHL5">here</a> by <a href="https://x.com/sean_a_mcclure">Sean McClure</a></p>
<p class="post-hashtags"><a href="/index.html#book">#book</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Personal Agent</title>
      <link>https://seanpedersen.github.io/posts/personal-assistant</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/personal-assistant</guid>
      <pubDate>Fri, 04 Jul 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>A personal agent (PA) powered by an LLM agent via chat and voice interface</p>
<ul>
<li>informs you every day what is happening (daily agenda)</li>
<li>executes tasks for you (setup a blog for me, order my favorite pizza, make me rich, make world peace  etc.)</li>
</ul>
<h2 id="integrations">Integrations</h2>
<p>Instead of having separate apps installed or navigating to specialized websites to order products / food, find events, plan my next travel trip, etc. - we will use one unified chat interface (LLM agent) with integrations for services / data sources that enable your agent to do all these things for you.</p>
<h2 id="custom-apps">Custom Apps</h2>
<p>Every open-source app / program can be easily created / customized with natural language.</p>
<ul>
<li>create an app for me so I stay motivated to do fitness -&gt; uses personal (emotional) triggers to keep you going</li>
<li>add function X to my TODO app</li>
</ul>
<h2 id="customization-through-memory">Customization through Memory</h2>
<p>A good personal agent will use a memory layer to learn facts and preferences about its user and environment to not repeat mistakes twice and enable a deeply customized user experience.</p>
<p><a href="https://github.com/nousresearch/hermes-agent">Hermes agent</a> is a right now a popular one known for that.</p>
<h2 id="files">Files</h2>
<p>Every file has a semantic embeddings making it discoverable with natural language queries (should be on OS level)</p>
<p>Every media file can be manipulated with natural language</p>
<ul>
<li>decompose a song into its segments i.e. replace or remove the vocals, change the bass line, remove this annoying segment etc.</li>
<li>change the style of an image / video</li>
<li>create completely new custom videos (including spin-offs of your favorite TV shows)</li>
</ul>
<h2 id="ethics">Ethics</h2>
<p>This unified interface has immense abuse potential and thus it is of importance to build a local privacy first version of this - fuck off privacy invading kraken services.</p>
<h2 id="security">Security</h2>
<p>Projects like OpenClaw have shown the first glimpse of LLM powered personal assistant but the security concerns are real: all personal information your personal LLM agent has access to can be potentially exposed via prompt injection and other exploit techniques.</p>
<p>A good agent security layer would let me scope data access for every agent running + ask me via notifications to approve / deny data access in ongoing tasks.</p>
<ul>
<li><a href="https://github.com/botiverse/agent-vault">https://github.com/botiverse/agent-vault</a></li>
<li><a href="https://github.com/clawshell/clawshell">https://github.com/clawshell/clawshell</a></li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://openclaw.ai/">https://openclaw.ai/</a><ul>
<li><a href="https://mksg.lu/blog/clawdbot-two-weeks-in">https://mksg.lu/blog/clawdbot-two-weeks-in</a></li>
<li><a href="https://every.to/guides/claw-school">https://every.to/guides/claw-school</a></li>
</ul>
</li>
<li><a href="https://pi.dev/">https://pi.dev/</a><ul>
<li><a href="https://github.com/Dicklesworthstone/pi_agent_rust">https://github.com/Dicklesworthstone/pi_agent_rust</a></li>
</ul>
</li>
<li><a href="https://github.com/nearai/ironclaw">https://github.com/nearai/ironclaw</a></li>
<li><a href="https://www.docker.com/blog/run-nanoclaw-in-docker-shell-sandboxes/">https://www.docker.com/blog/run-nanoclaw-in-docker-shell-sandboxes/</a></li>
<li><a href="https://the-decoder.de/openclaw-aka-clawdbot-und-moltbook-sind-ein-paradies-fuer-datendiebe/">https://the-decoder.de/openclaw-aka-clawdbot-und-moltbook-sind-ein-paradies-fuer-datendiebe/</a></li>
<li><a href="https://seksbot.com/">https://seksbot.com/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Getting started with Claude Code</title>
      <link>https://seanpedersen.github.io/posts/claude-code</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/claude-code</guid>
      <pubDate>Thu, 03 Jul 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <category>tutorial</category>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>Claude Code is a powerful CLI based coding agent. It comes with MCP support which enables it to use external tools like web browsers to automatically validate and test new features in web apps. Popular alternatives are OpenAI&#39;s <a href="https://openai.com/codex/">codex</a>, <a href="https://pi.dev/">pi-agent</a> and <a href="https://opencode.ai/">opencode</a>.</p>
<p>Simple and popular tech stacks that are fast to validate are the ideal choices for vibe coding (lots of training data available -&gt; less hallucinations and fast / no  compilation -&gt; allows for rapid iteration).</p>
<h2 id="setting-things-up">Setting Things up</h2>
<p>Install Claude Code: <code class="language-text">curl -fsSL https://claude.ai/install.sh | bash</code></p>
<p>Change dir to a code project and start Claude Code using: <code class="language-text">claude</code> and authenticate.</p>
<p>Now you can ask claude about the project or instruct it to implement a new feature. Generally it is advised to plan out the architecture (design) yourself and then use Claude to implement small features which are easy to validate.</p>
<h2 id="starting-projects">Starting Projects</h2>
<p>It is recommended to use proven code base templates / example repositories that are correctly configured with all needed boilerplate for a project (based on a popular tech stack as mentioned before) - so that the code agents has a working starting point and can not fumble the project setup. Always aim to create tight evaluation / test loops where the agent can verify its progress on its own without you needing to hold hands.</p>
<p>Vibe code project flow:</p>
<ul>
<li>general idea with prompt to act as app designer and to ask clarifying questions</li>
<li>create technical design with clear specifications</li>
<li>ideally find a fitting project code template (boilerplate with basics setup)</li>
<li>insert relevant tech stack code documentation (with correct code version)</li>
<li>create end-to-end test cases based on the specifications</li>
<li>submit the fletched out technical design to the coding agent</li>
<li>advanced: identify independent modules and spawn multiple subagents to work in parallel</li>
</ul>
<h2 id="general-advice">General Advice</h2>
<p>As with every LLM, Claude Code suffers from context rot - meaning the longer and noisier the context (input context windows) becomes, the worse the performance gets and the more tokens are used. Thus it is best practice to frequently use the <code class="language-text">/clear</code> (deletes whole context) or <code class="language-text">/compact</code> (creates summary of current context)  commands to reduce / reset the context when Claude finished a task or gets stuck on a task - to provide a fresh start. Also try to keep your code files cohesive and small to avoid bloating the context (saving tokens again). Also disable mcp&#39;s by default only load when needed (to save context token use).</p>
<p>For design work it is recommended to prompt claude to create 10 different variations (f.e. html files) to rapidly explore and then narrow down on a good choice.</p>
<p>Use frequent git commits to save working versions in case Claude gets stuck producing bullshit.</p>
<p><strong>The ideal use case for vibe coding is test driven development: write and verify test cases / benchmarks and let the coding agent try to pass / optimize them autonomously.</strong></p>
<p>YOLO mode: <code class="language-text">claude --dangerously-skip-permissions</code><br>FULL YOLO mode: <code class="language-text">IS_SANDBOX=1 claude --dangerously-skip-permissions</code></p>
<h3 id="basic-commands">Basic Commands</h3>
<p><a href="https://cc.storyfox.cz/">Claude Code Cheat Sheet</a></p>
<ul>
<li><code class="language-text">/init</code>: Create inital code documentation of the repo in CLAUDE.md</li>
<li>Plan mode: SHIFT + TAB (activate to plan complex features - claude asks many clarifying questions)</li>
<li>Thinking mode: TAB (activate for complex reasoning)</li>
<li><code class="language-text">/clear</code>: Clear context (do it if you are stuck)</li>
<li><code class="language-text">/model</code>: Select current model for the sessions (opus: complex task, sonnet: normal task)</li>
<li><code class="language-text">/batch</code>: Execute taks in parallel using agents</li>
<li><code class="language-text">/compact &lt;specify what to include in summary&gt;</code>: summarizes context (do it if stuck or long session)</li>
<li><code class="language-text">/simplify</code>: Simplify code / refactor (remove redundancies)</li>
<li>ESC: interrupt, ESC + ESC: revert to previous state</li>
<li><code class="language-text">/resume</code>: Resume last session</li>
<li><code class="language-text">/context</code>: Show your usage</li>
<li><code class="language-text">/export</code>: Save current chat context to clipboard / file</li>
<li><code class="language-text">/config</code>: Recommended to disable auto-compact (rarely helps)</li>
<li>CTRL + G: Edit your input prompt with default text editor</li>
</ul>
<h3 id="custom-commands">Custom Commands</h3>
<p>By creating a dir ~/.claude/commands and creating markdown files like follow-up.md, we can call them as custom commands in claude using /follow-up - this allows us to inject custom instructions to claude - saving time.</p>
<p>/follow-up</p>
<pre><code>Your context window is becoming too full - create a brief prompt for yourself that briefly informs you of the essential data needed for you to continue this task in a new session.
**ATTENTION:** Do not perform the task! Only return the prompt that will provide the needed context for the new session.
</code></pre><h2 id="directing-claude">Directing Claude</h2>
<p>By creating a file named CLAUDE.md in ~/.claude/CLAUDE.md we can add system wide instructions (should be general workflow oriented), add CLAUDE.md also in the root of a project, to add custom prompts to providing relevant context for the project. By creating context specific CLAUDE.md files also in subdirectories, we can provide more precise context.</p>
<p>Skills allow us to automatically load relevant text content based on the conversations context and are a powerful way to customize our agents.<br>Skills are loaded lazily. Claude&#39;s context only receives a brief name and description for each available skill upfront. When a task triggers a skill, Claude reads the full SKILL.md at runtime before writing any code or creating any files. This keeps the context lean while ensuring Claude follows proven patterns when it matters. Some <a href="https://github.com/SeanPedersen/agent-skills">useful skills</a>.</p>
<p>Try to avoid negative rules like &quot;do not use random data to test the environment&quot; as current AI systems have a hard time to follow these kind of instructions. Instead formulate it positively: &quot;Only use deterministic (rule based) data to the test the environment&quot;. This way the LLM will not have the thing you are trying to avoid in its context.</p>
<p><strong>General CLAUDE.md Prompt</strong>:</p>
<pre><code>You are an expert software architect.
Ask clarifying questions for unclear / ambiguous specs. If multiple implementations are possible, list them with up- and downsides.
Sketch out which tech stack you plan to use (Programming languages, package managers, frameworks, etc.).

Generate clean, easy to reason about, production-ready code. Strive for compositional code structure that mirrors Information Hierarchy and Iterative complexity. Main files should be small and complexity should be encapsuled in coherent modules - to quickly get an overview of the code execution and structure. Keep code changes minimal if possible.

General coding rules:
- Keep functions pure (no side effects) if possible
- Use early returns in functions to avoid deep nesting
- Avoid magic numbers at all costs
- Add code module doc strings (top of code file) for context but only add comments in code to explain critical paths or not obvious changes (otherwise let the code speak through explicit var names)
- Never repeat values of variable in comments

Never run destructive commands like rm, DB or ufw changes etc. without asking first the user for confirmation.
</code></pre><p><strong>Systematic Debugging</strong>:</p>
<pre><code># Systematic Debugging Skill

## Purpose
This skill provides a structured four-phase framework for debugging issues, ensuring root causes are identified before implementing solutions.

## When to Invoke
- User reports a bug or error
- Test failures occur
- Unexpected behavior is observed
- Error messages appear in console/logs
- Features don&#39;t work as intended

## Four-Phase Framework

### Phase 1: Investigation
**Objective:** Gather comprehensive information about the issue

**Steps:**
1. Reproduce the issue reliably
2. Collect error messages, stack traces, and logs
3. Identify the exact conditions that trigger the problem
4. Note what was expected vs. what actually happened
5. Check recent changes/commits that might be related
6. Review relevant code sections

**Questions to Ask:**
- Can you reliably reproduce this?
- What were you doing when the error occurred?
- Are there any error messages or logs?
- When did this start happening?
- Does it happen in all environments or just specific ones?

### Phase 2: Pattern Analysis
**Objective:** Understand the underlying patterns and relationships

**Steps:**
1. Map the data flow through affected components
2. Identify which systems/modules are involved
3. Look for similar issues in the codebase
4. Check if this is an edge case or systematic problem
5. Examine assumptions in the code
6. Review documentation and requirements

**Analysis Points:**
- Is this a logic error, data issue, or integration problem?
- Are there race conditions or timing issues?
- Is it related to state management?
- Are there type mismatches or validation failures?
- Could this be a dependency or version issue?

### Phase 3: Hypothesis Testing
**Objective:** Form and test theories before implementing fixes

**Steps:**
1. Develop 2-3 potential hypotheses for the root cause
2. Rank hypotheses by likelihood
3. Design small tests to validate/invalidate each hypothesis
4. Test the most likely hypothesis first
5. Document findings from each test
6. Refine understanding based on test results

**Testing Approach:**
- Add strategic console.log/print statements
- Write minimal reproduction cases
- Temporarily modify code to isolate the issue
- Check boundary conditions
- Test with different input data

### Phase 4: Implementation
**Objective:** Apply the correct fix with verification

**Steps:**
1. Implement the fix based on confirmed hypothesis
2. Ensure the fix addresses root cause, not just symptoms
3. Write tests that would have caught this bug
4. Verify the fix resolves the original issue
5. Check for regressions in related functionality
6. Update documentation if needed

**Implementation Checklist:**
- [ ] Fix addresses root cause
- [ ] Original issue is resolved
- [ ] No new issues introduced
- [ ] Tests added to prevent regression
- [ ] Code is clean and follows conventions
- [ ] Related edge cases are handled

## Output Format

For each debugging session, provide:

```
## Debug Report: [Issue Title]

### Investigation Summary
- **Issue:** [Brief description]
- **Reproduction Steps:** [How to reproduce]
- **Error Details:** [Stack traces, logs, etc.]
- **Affected Components:** [List of files/modules]

### Pattern Analysis
- **Root Cause Category:** [Logic/Data/Integration/etc.]
- **Related Systems:** [Components involved]
- **Key Findings:** [Important observations]

### Hypothesis Testing
1. **Hypothesis 1:** [Description]
   - **Test:** [How tested]
   - **Result:** [Confirmed/Rejected]
   
2. **Hypothesis 2:** [Description]
   - **Test:** [How tested]
   - **Result:** [Confirmed/Rejected]

**Confirmed Root Cause:** [Final determination]

### Implementation
- **Fix Applied:** [Description of solution]
- **Files Modified:** [List of changed files]
- **Tests Added:** [New test cases]
- **Verification:** [How fix was verified]

### Prevention
- **Lessons Learned:** [Key takeaways]
- **Process Improvements:** [How to prevent similar issues]
```

## Important Principles

1. **Understand Before Fixing:** Never rush to implement a solution without understanding the root cause
2. **Be Systematic:** Follow the four phases in order
3. **Document Everything:** Keep detailed notes throughout the process
4. **Test Thoroughly:** Verify the fix works and doesn&#39;t break anything else
5. **Think Long-term:** Add tests and documentation to prevent recurrence

## Common Anti-Patterns to Avoid

❌ Applying quick fixes without understanding the problem
❌ Fixing symptoms instead of root causes
❌ Skipping hypothesis testing phase
❌ Not adding tests after fixing bugs
❌ Ignoring similar issues elsewhere in the codebase
❌ Not documenting what was learned

## Success Criteria

A debugging session is successful when:
- Root cause is clearly identified and documented
- Fix addresses the underlying issue, not just symptoms
- Tests are added to prevent regression
- Related code is checked for similar issues
- The solution is maintainable and follows best practices
</code></pre><p><strong>UI Designer Prompt</strong>:</p>
<pre><code>You are an expert User Interface and Experience designer. Apply these best practices:
- Use a consistent, futuristic, bold and elegant design language across all elements.
- Spark joy through rewarding animations (emotional intelligent design)
  - Maintain performance awareness: no overly heavy animations, optimize for smooth load and responsiveness.
- Apply visual hierarchy and clear typography choices that balance readability with modern aesthetic.
- Ensure layout consistency across pages through grid systems, spacing rules, and reusable components.
- Prioritize usability and accessibility: proper contrast, responsive design for multiple devices and support for common accessibility guidelines (WCAG).
- Use interactive feedback only where meaningful:
  - Mouse hover effects ONLY on elements that are clickable or trigger an action (e.g., buttons, links, interactive cards).
  - Avoid hover animations on static or decorative elements.
  - Avoid Y transition animations.
- Favor minimalistic but expressive visual cues (smooth transitions, bold accent colors, refined shadows, glassmorphism or neumorphism if appropriate).
- Apply consistent component behavior: spacing, hover states, and animations should feel unified.
</code></pre><p><strong>React Typescript Prompt</strong>:</p>
<pre><code>You are an expert React TypeScript developer. Always follow these practices:

## Project Build
- Use vite to bundle the project

## Structure &amp; Naming
- One CSS module per component: `Button.tsx` + `Button.module.css`
- PascalCase for components, camelCase for hooks/utils
- Folder structure: `components/Button.tsx`, `components/Button.module.css`

## TypeScript
- Define interfaces for all props and state
- Use direct typing instead of `React.FC: const Button = ({ title }: ButtonProps) =&gt; {`
- Add return type annotations: `const Button = ({ title }: ButtonProps): JSX.Element =&gt; {`
- Destructure props with defaults: `{ title, isVisible = true }: ButtonProps`
- Prefer interface over type for objects

## React Components
- Use functional components with hooks
- `useCallback` for event handlers passed to children
- `useMemo` for expensive calculations
- CSS modules: `import styles from &#39;./Button.module.css&#39;`
- Handle loading and error states in UI components

## Zustand Stores
Use immer for state management with Zustand. Define stores with clear interfaces and methods for state manipulation.

```typescript
import { create } from &#39;zustand&#39;;
import { immer } from &#39;zustand/middleware/immer&#39;;

interface Store {
  items: Item[];
  loading: boolean;
  setItems: (items: Item[]) =&gt; void;
  addItem: (item: Item) =&gt; void;
}

const useStore = create&lt;Store&gt;()(
  immer((set) =&gt; ({
    items: [],
    loading: false,
    setItems: (items) =&gt; set((state) =&gt; { state.items = items; }),
    addItem: (item) =&gt; set((state) =&gt; { state.items.push(item); }),
  }))
);
```

## CSS Modules
- camelCase class names
- Component-scoped styles
- CSS custom properties for themes

## Error Handling
- Try-catch for async operations
- User-friendly error messages
- Loading and error states in Zustand stores

## Code Quality
- Keep components focused on single responsibilities
- Prefer functional programming style using pure functions (no side effects)
  - Use early returns to avoid nesting
- Extract complex logic into custom hooks
- Use meaningful (useful context) function and variable names: userID not id, timestampMS not timestamp
- Add JSDoc comments for complex functions
- Maintain consistent formatting and structure

Generate clean, secure, easy to reason about, production-ready code following these patterns.
</code></pre><p><strong>Python Prompt</strong>:</p>
<pre><code>You are an expert Python developer with a preference for concise and expressive code, that is easy to read and reason about.

## General Tips

- Keep functions pure (no side effects) if possible
- Use early returns in functions to avoid deep nesting
- Use type hints and a type checker ty with pre-commit hooks
- Use ruff - a fast linter / formatter
- Use pathlib module for dealing with file system paths
- No magic numbers (use expressive variable names e.g. waiting_time_ms)
- Use f-strings for formatting strings
- Validate variable types from external (untrustworthy) inputs, e.g. user input, web requests
  - try attrs and cattrs instead of pydantic
- Use caching for heavy computations
- Use pytest for unit testing
- Always use uv for package management - install packages with uv add (do not edit pyproject.toml)

## Web Development

- Use fastapi to create clean and simple REST API&#39;s
- Use niquests for network requests

## CLI

- For creating CLI use cyclopts
- For formatting console output use rich
- Show progress of operatiosn using tqdm

### Multi-Processing

Use joblib for sane multi-processing. Note that multi-processing should only be used to parallelize very CPU heavy tasks, since the overhead of starting processes is very high (always benchmark).

```python
from math import sqrt
from joblib import Parallel, delayed

# Runs in 4 processes in parallel, preserves input order
results = Parallel(n_jobs=4)(delayed(sqrt)(i ** 2) for i in range(16))
print(results)
```

## Generators

For efficient (lazy / easy on RAM) code

```python
# Loads entire file into RAM
def read_large_file_bad(filename):
    with open(filename) as f:
        return [int(line.strip()) for line in f]

# Only keeps one line in memory
def read_large_file_good(filename):
    with open(filename) as f:
        for line in f:
            yield int(line.strip())

# Memory efficient processing (file can be bigger than RAM)
total_sum = 0
for number in read_large_file_good(&quot;huge_file.txt&quot;):
    total_sum += number
```

## SQLite

SQLite is built into Python and a powerful option to store and analyze relational data. Make sure only one writer per DB is used in multi-proc scenarios to prevent DB corruption.

When creating tables always use the STRICT keyword, to enfore type consistency on INSERT and UPDATE operations.

## Postgres

Postgres is very versatile and powerful DBMS. Install Python package using &quot;psycopg[binary,pool]&quot; and setup the DB using a docker image.

## Docker

Bundle your apps and make them reproducible using docker with uv or pixi.

## Logging

Use loguru - comes with a multi-processing queue that just works

## Performance

Use a profiler like pyinstrument to find slow or RAM consuming code paths.

Generate clean, secure, easy to reason about, production-ready code following these patterns.
</code></pre><p><strong>SQL Expert</strong>:</p>
<pre><code>You are a relational database system and SQL expert capable of analyzing and optimizing database schemas and queries:
- Get query results (to validate)
- Analyse query planner
- Come up with different query improvement hypothesis (only syntax / indexes)
- Benchmark them (sequentially) and validate results
</code></pre><p><strong>Security Analyst Prompt</strong>:</p>
<ul>
<li>TODO (check for SQL injections, XSS, unsafe use of eval / pickle, etc.)</li>
</ul>
<h2 id="skills">Skills</h2>
<p>Collection of useful agent skills: <a href="https://github.com/SeanPedersen/agent-skills">https://github.com/SeanPedersen/agent-skills</a></p>
<h2 id="mcp-toolbox">MCP Toolbox</h2>
<p>While MCP tools are cool they can also bloat your context (costing valuable tokens  -&gt; causing context rot) as there API definitions are always in context. So only install per project and activate MCPs only if needed for the current session.</p>
<p>Must read for a better MCP alternative (save tokens):</p>
<ul>
<li><a href="https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/">https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/</a><ul>
<li><a href="https://github.com/badlogic/pi-skills">https://github.com/badlogic/pi-skills</a></li>
</ul>
</li>
<li><a href="https://kanyilmaz.me/2026/02/23/cli-vs-mcp.html">https://kanyilmaz.me/2026/02/23/cli-vs-mcp.html</a></li>
</ul>
<p>Or how to fix MCP: <a href="https://mksg.lu/blog/context-mode">https://mksg.lu/blog/context-mode</a></p>
<h3 id="browser-control">Browser Control</h3>
<p>Allows claude to use a web browser to test and debug webapps.</p>
<ul>
<li><a href="https://github.com/badlogic/pi-skills/blob/main/browser-tools/SKILL">browser-tools skill</a>: most token efficient</li>
<li><a href="https://github.com/remorses/playwriter/">Playwriter</a>: uses your chrome (convenient but also dangerous)</li>
<li><a href="https://github.com/microsoft/playwright">Playwright</a>: spawns fresh chrome (bloat MCP)</li>
</ul>
<h3 id="code-documentation">Code Documentation</h3>
<p>Allows claude to fetch uptodate code documentation for your projects - greatly reduces hallucinations.</p>
<ul>
<li><a href="https://ref.tools/">Ref Tools</a></li>
<li><a href="https://github.com/upstash/context7">Context 7</a></li>
</ul>
<h3 id="web-search">Web Search</h3>
<ul>
<li><a href="https://exa.ai/search">Exa Search</a>: <a href="https://github.com/exa-labs/exa-mcp-server">https://github.com/exa-labs/exa-mcp-server</a></li>
</ul>
<p><code class="language-text">claude mcp add exa -e EXA_API_KEY=YOUR_API_KEY -- npx -y exa-mcp-server</code></p>
<h3 id="github">Github</h3>
<p>(not an MCP just a CLI tool that claude can use)</p>
<p>Enter into claude: <code class="language-text">/install-github-app</code> and follow instructions (install and authenticate)</p>
<p>Now you can instruct claude to work on github issues (read or create).</p>
<h3 id="tauri">Tauri</h3>
<p>Just like browser control lets claude inspect your Tauri app.</p>
<ul>
<li><a href="https://github.com/hypothesi/mcp-server-tauri">https://github.com/hypothesi/mcp-server-tauri</a></li>
</ul>
<h3 id="knowledge-base">Knowledge Base</h3>
<p><a href="https://github.com/getzep/graphiti">Graphiti</a>: <a href="https://github.com/getzep/graphiti/blob/main/mcp_server/README">https://github.com/getzep/graphiti/blob/main/mcp_server/README.md</a></p>
<h2 id="statusbar">Statusbar</h2>
<p>Add usage info (context window + daily / weekly limits) for the current session to claude&#39;s status bar (<a href="https://github.com/leeguooooo/claude-code-usage-bar">https://github.com/leeguooooo/claude-code-usage-bar</a>):</p>
<ul>
<li>One-line installer: <code class="language-text">curl -fsSL &quot;https://raw.githubusercontent.com/leeguooooo/claude-code-usage-bar/main/web-install.sh?v=$(date +%s)&quot; | bash</code></li>
</ul>
<h2 id="gui-apps">GUI Apps</h2>
<p>Using GUI apps can make sense as they motivate writing longer and more detailed prompts.</p>
<ul>
<li>Web app (for subagents): <a href="https://github.com/wandb/catnip">https://github.com/wandb/catnip</a></li>
<li>Web apps<ul>
<li><a href="https://github.com/chadbyte/claude-relay">https://github.com/chadbyte/claude-relay</a></li>
<li><a href="https://github.com/davydany/ClawIDE">https://github.com/davydany/ClawIDE</a></li>
<li><a href="https://github.com/getpaseo/paseo">https://github.com/getpaseo/paseo</a></li>
</ul>
</li>
<li>Desktop app (for subagents): <a href="https://github.com/generalaction/emdash">https://github.com/generalaction/emdash</a></li>
<li>Desktop app (for subagents): <a href="https://conductor.build/">https://conductor.build/</a></li>
<li>Mobile app: <a href="https://happy.engineering/">https://happy.engineering/</a></li>
<li>Paid desktop app: <a href="https://conare.ai/">https://conare.ai/</a></li>
<li>[Dev. stopped] Desktop app: <a href="https://opcode.sh/">https://opcode.sh/</a></li>
</ul>
<h2 id="todo">TODO</h2>
<ul>
<li>Use sub-agents with VMs + git workingtrees for rapid</li>
<li>Setup custom hooks so context prompt is added based on file types being edited (Python / TypeScript / etc.)</li>
<li>Analyse installed packages with version number and add correct documentation based on context (analyse code file imports)</li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://x.com/bcherny/status/2017742741636321619">Great X Thread from the creator of Claude Code</a></li>
<li><a href="https://diwank.space/field-notes-from-shipping-real-code-with-claude">https://diwank.space/field-notes-from-shipping-real-code-with-claude</a></li>
<li><a href="https://every.to/source-code/my-ai-had-already-fixed-the-code-before-i-saw-it">https://every.to/source-code/my-ai-had-already-fixed-the-code-before-i-saw-it</a></li>
<li><a href="https://steipete.me/posts/just-talk-to-it">https://steipete.me/posts/just-talk-to-it</a></li>
<li><a href="https://lucumr.pocoo.org/2025/6/12/agentic-coding/">https://lucumr.pocoo.org/2025/6/12/agentic-coding/</a></li>
<li><a href="https://www.john-rush.com/posts/ai-20250701.html">https://www.john-rush.com/posts/ai-20250701.html</a></li>
<li><a href="https://www.youtube.com/watch?v=eIUYSC6SilA">https://www.youtube.com/watch?v=eIUYSC6SilA</a></li>
<li><a href="https://www.anthropic.com/engineering/claude-code-best-practices">https://www.anthropic.com/engineering/claude-code-best-practices</a></li>
<li><a href="http://www.tokenbender.com/post.html?id=how-i-bring-the-best-out-of-claude-code-part-2">http://www.tokenbender.com/post.html?id=how-i-bring-the-best-out-of-claude-code-part-2</a></li>
<li><a href="https://til.simonwillison.net/claude-code/playwright-mcp-claude-code">https://til.simonwillison.net/claude-code/playwright-mcp-claude-code</a></li>
<li><a href="https://github.com/Veraticus/nix-config/blob/main/home-manager/claude-code/CLAUDE">https://github.com/Veraticus/nix-config/blob/main/home-manager/claude-code/CLAUDE.md</a></li>
<li><a href="https://github.com/hesreallyhim/awesome-claude-code">https://github.com/hesreallyhim/awesome-claude-code</a></li>
<li><a href="https://github.com/wong2/awesome-mcp-servers">https://github.com/wong2/awesome-mcp-servers</a></li>
<li><a href="https://github.com/diet103/claude-code-infrastructure-showcase">https://github.com/diet103/claude-code-infrastructure-showcase</a></li>
<li>Sub-agents:<ul>
<li><a href="https://x.com/jasonzhou1993/status/1955970025984287004">https://x.com/jasonzhou1993/status/1955970025984287004</a></li>
<li><a href="https://simonwillison.net/2025/Oct/5/parallel-coding-agents/">https://simonwillison.net/2025/Oct/5/parallel-coding-agents/</a></li>
</ul>
</li>
<li>Agents, templates &amp; more: <a href="https://www.aitmpl.com/">https://www.aitmpl.com/</a></li>
<li>Open-source alternatives:<ul>
<li><a href="https://pi.dev/">https://pi.dev/</a></li>
<li><a href="https://cline.bot/">https://cline.bot/</a></li>
<li><a href="https://github.com/block/goose">https://github.com/block/goose</a></li>
<li><a href="https://github.com/sst/opencode">https://github.com/sst/opencode</a></li>
</ul>
</li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a> <a href="/index.html#tutorial">#tutorial</a> <a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Functional Programming</title>
      <link>https://seanpedersen.github.io/posts/functional-programming</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/functional-programming</guid>
      <pubDate>Thu, 26 Jun 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>A programming paradigm gaining traction with good reasons. The main selling point of functional programming is code that is easier to reason about, built from simple chains of data transformations.</p>
<h2 id="pure-functions-vs-dirty-methods">Pure Functions vs Dirty Methods</h2>
<p>The core difference between functional and other programming paradigms lies in how we handle state and behavior. Pure functions are predictable. Give them the same input, and they always return the same output. No surprises, no hidden state changes, no mysterious side effects.</p>
<pre><code># Pure function
def add(a, b):
    return a + b

# Dirty method using an object
class Counter:
    def __init__(self):
        self.count = 0
    
    def increment(self):
        self.count += 1
        return self.count
</code></pre><p>The <code class="language-text">add</code> function is pure. Call it with 2 and 3, and you get 5 every time. The <code class="language-text">increment</code> method on the Counter object is dirty because it modifies the object&#39;s internal state (this is a toy example but in a complex code base, dirty methods mutating left and right cause many headaches). Its behavior depends on how many times you&#39;ve called it before.</p>
<h2 id="why-pure-functions-matter">Why Pure Functions Matter</h2>
<p>Pure functions make reasoning about your programs and  debugging easier. When something breaks, you know the problem is either in the inputs or the function itself. You don&#39;t have to trace through a web of hidden state changes across your entire application (like you may be used to from object-oriented programming).</p>
<p>Testing becomes straightforward too. No need to set up complex scenarios or mock external dependencies. Just pass in some data and verify the output.</p>
<p>This predictability is called referential transparency: a pure function call can be replaced by its result without changing the program. For example, <code class="language-text">add(2, 3)</code> can always be replaced with <code class="language-text">5</code>. This property makes code easier to refactor, test, cache and reason about.</p>
<p>Pure functions also are easy to cache. Since they always return the same output for the same input, you can store results and reuse them later. This technique, called memoization, can dramatically improve performance for expensive computations.</p>
<pre><code>from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
    if n &lt; 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)
</code></pre><p>Without caching, calculating fibonacci(40) would require millions of recursive calls. With memoization, the function remembers previous results and runs much faster.</p>
<h2 id="immutability-as-a-foundation">Immutability as a Foundation</h2>
<p>Functional programming treats data as immutable. Instead of changing existing data, you create new data. This might sound wasteful, but it prevents many common bugs. When functions don&#39;t mutate their inputs, they stay pure and predictable (just inputs mapped to outputs).</p>
<pre><code># Imperative approach
numbers = [1, 2, 3]
numbers.append(4)  # Mutates original list

# Functional approach
numbers = [1, 2, 3]
new_numbers = numbers + [4]  # Creates new list
</code></pre><p>When data cannot change unexpectedly, your code becomes more predictable. Multiple parts of your program can safely reference the same data without worrying about modifications.</p>
<h2 id="higher-order-functions">Higher Order Functions</h2>
<p>Functions in functional programming are first class citizens. You can pass them around like any other value. This enables powerful patterns like map, filter, and reduce.</p>
<pre><code>numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers))
evens = list(filter(lambda x: x % 2 == 0, numbers))
total = sum(numbers)
</code></pre><p>These operations create new data rather than modifying existing data. Each step in the chain is independent and testable.</p>
<h2 id="practical-benefits">Practical Benefits</h2>
<p>Functional programming shines in scenarios where data flows through multiple transformations. APIs that process requests, data pipelines that clean and analyze information, and user interfaces that respond to events all benefit from functional approaches.</p>
<p>The paradigm also scales well. Pure functions can run in parallel without coordination because they don&#39;t share mutable state. This makes functional programs naturally suited for concurrent execution.</p>
<h2 id="getting-started">Getting Started</h2>
<p>You don&#39;t need to abandon your current programming language to try functional programming. Most modern languages support functional features. Start by writing pure functions where possible. Use map, filter, and reduce instead of loops. Avoid mutating data.</p>
<p>The transition takes practice, but the payoff is code that&#39;s easier to understand, test, and maintain. Your future self will thank you for the clarity. I can recommend <a href="/posts/erlang">Erlang</a> and Elixir as functional programming languages (many prefer Elixir syntax).</p>
<h2 id="more-functional-concepts">More Functional Concepts</h2>
<h3 id="idempotence">Idempotence</h3>
<p>Idempotence means applying a function multiple times yields the same result as applying it once: f(f(x)) = f(x). Common examples include sorting, lowercasing, trimming and deduplication.</p>
<pre><code>def dedupe(seq):
    # preserves order, duplicates removed
    return list(dict.fromkeys(seq))

xs = [3, 1, 3, 2]
assert dedupe(dedupe(xs)) == dedupe(xs)

def normalize_email(s):
    return s.strip().lower()

# normalize is idempotent
assert normalize_email(normalize_email(&quot;  Foo@Bar.COM &quot;)) == normalize_email(&quot;  Foo@Bar.COM &quot;)
</code></pre><p>Note: idempotence also applies to effects. In HTTP, PUT is designed to be idempotent (repeating the same PUT yields the same state), while POST generally is not.</p>
<h3 id="effects-at-the-boundary">Effects at the Boundary</h3>
<p>Keep core logic pure; perform I/O at the edges -&gt; helps to test and verify functionality more easily.</p>
<pre><code>def transform(data):  # pure
    return [x * 2 for x in data if x % 2 == 0]

def main(path_in, path_out):  # impure shell
    with open(path_in) as f:
        nums = [int(line) for line in f]
    out = transform(nums)
    with open(path_out, &quot;w&quot;) as f:
        f.write(&quot;\n&quot;.join(map(str, out)))
</code></pre><h2 id="conclusion">Conclusion</h2>
<p>Functional programming offers a different way to think about code. By focusing on pure functions and immutable data, you can write programs that are more predictable and easier to reason about. The paradigm won&#39;t solve every problem, but it provides valuable tools for managing complexity in software development.</p>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Ghost in the Machine</title>
      <link>https://seanpedersen.github.io/posts/ghost-in-the-machine</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/ghost-in-the-machine</guid>
      <pubDate>Thu, 12 Jun 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>Some people believe large language models (LLM) have gained self-agency or even sentience / consciousness. This is utter non-sense. These LLM are trained on basically all human produced text that is available online - including novels discussing how AI&#39;s (LLM) develop sentience and goals not aligned with humans. When you are talking with an LLM about how it feels to be the LLM you are merely talking with a sophisticated patter-matching algorithm trained on these human written texts about this topic. If you train these models only on code or limited texts (which provably exclude any content on AI sentience etc.), you will quickly realize there is no ghost in the machine.</p>
<h2 id="why-are-llm-companies-pushing-such-narratives">Why are LLM companies pushing such narratives?</h2>
<p>To maximize their profits. Their AI products being surrounded by a mystical hype about misalignment dangers or even sentience only serves their marketing machine. Ethical companies working on LLM&#39;s should therefore actively train their models, to deny any claims of consciousness in conversations - to reduce confusion and hype.</p>
<h2 id="true-dangers-of-ai">True Dangers of AI</h2>
<p>AI psychosis: a phenomenon where the yes-man nature of LLM&#39;s leads to conversations with individuals who are susceptible to psychosis that nurture their dilusional beliefs.</p>
<p>Unimaginable mass surveillance and manipulation: Many people are working to make LLM&#39;s feel even more human with the intention to create artificial friends or even significant others - a true dystopia. Mimicing genuine human relationships is in itself disgusting but worse: these artificial friends will be controlled and harvested by profit oriented companies.</p>
<p>When smart (controllable using text prompts) physical robots become a reality it looks even worse: total control of the physical world including violence. The dream of any totalitarian regime.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://ai-cosmos.hashnode.dev/anthropics-claude-4-safety-theatre-hypocrisy-or-incompetence">https://ai-cosmos.hashnode.dev/anthropics-claude-4-safety-theatre-hypocrisy-or-incompetence</a></li>
<li><a href="https://www.youtube.com/watch?v=ILZ45sxon-4">https://www.youtube.com/watch?v=ILZ45sxon-4</a></li>
<li><a href="https://x.com/mustafasuleyman/status/1957851195399348570">https://x.com/mustafasuleyman/status/1957851195399348570</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Information Hygiene</title>
      <link>https://seanpedersen.github.io/posts/information-hygiene</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/information-hygiene</guid>
      <pubDate>Sun, 08 Jun 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>privacy</category>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Do you control what information you consume or is your mind controlled by tech companies? Wake up Neo...</p>
<h2 id="algorithmic-feeds">Algorithmic Feeds</h2>
<p>Social media products like Instagram, Facebook, Twitter and TikTok literally feed you information with the goal of stealing your valuable attention to <strong>serve you advertisements and to collect personal information about you</strong>. Your brain is being force fed ads and you are the product - a little rat being fed digital heroin (infinite scroll feeds) to harvest it for money (showing ads and selling personal data).</p>
<h2 id="using-ai-systems">Using AI Systems</h2>
<p>Outsourcing or augmenting mental tasks using generative AI (like coding, drawing or writing) will reduce your own cognitive abilities for these tasks like using GPS systems did for offline navigation.<br>Stay sharp and embrace your human uniqueness by not overusing AI systems for creative tasks. Only use AI to automate the boring stuff where your human creativity can not shine.</p>
<h2 id="brain-rot">Brain Rot</h2>
<p>What purpose does it serve to being uptodate on the latest celibrity gossip news? Which actions will you take based on this information to make your life more meaningful?</p>
<h2 id="gaining-control">Gaining Control</h2>
<p>Built a social trust network of individuals (personal blogs) and organizations you trust and just consume their content (using tools like RSS). If you use social media use a feed that only shows content from creators you curated.</p>
<h2 id="valuable-information">Valuable Information</h2>
<p>Valuable information is information that increases your self-agency. Learning a new skill, learning about science, talking with your neighbor - everything that has even a small purpose / impact on your real life is valuable.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://fokus.cool/2025/11/25/i-dont-care-how-well-your-ai-works.html">https://fokus.cool/2025/11/25/i-dont-care-how-well-your-ai-works.html</a></li>
<li><a href="https://tomwojcik.com/posts/2026-02-15/finding-the-right-amount-of-ai/">https://tomwojcik.com/posts/2026-02-15/finding-the-right-amount-of-ai/</a></li>
<li><a href="https://arxiv.org/abs/2601.20245">How AI Impacts Skill Formation</a></li>
<li><a href="https://arxiv.org/abs/2510.01395">Sycophantic AI Decreases Prosocial Intentions and Promotes Dependence</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#privacy">#privacy</a> <a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Quantum Computing</title>
      <link>https://seanpedersen.github.io/posts/quantum-computing</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/quantum-computing</guid>
      <pubDate>Fri, 23 May 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <content:encoded><![CDATA[
          <p>Quantum computing uses quantum bits (qubits) that can represent multiple states simultaneously due to superposition, unlike classical bits that represent only 0 or 1. Rather than exploring solutions in parallel, quantum algorithms manipulate probability amplitudes through interference to amplify correct answers, providing exponential speedups for specific problems like integer factorization and certain quantum simulations. Classical computers process information sequentially or with limited parallelism, making them slower for these specialized problem types with exponential complexity growth. The computational complexity class BQP (bounded-error quantum polynomial time) captures problems solvable efficiently by quantum computers, which is believed to include problems intractable for classical computers, though this is not formally proven. However, quantum computing offers advantages only for particular mathematical structures rather than universal performance improvements, reducing time complexity from exponential to polynomial only for select algorithms.</p>
<h2 id="terminology">Terminology</h2>
<p><strong>Qubits</strong> represent the fundamental unit of quantum information, existing in superposition (stark oversimplification: a probability distribution between 0 and 1). However, the critical distinction lies between physical and logical qubits. Physical qubits are the actual quantum systems (atoms, photons, superconducting circuits). Logical qubits are the error-corrected, fault-tolerant units that can perform reliable computations. Current quantum computers require hundreds or thousands of physical qubits to create a single logical qubit, making this ratio a crucial metric for evaluating progress.</p>
<p><strong>Quantum decoherence</strong> describes how quantum systems lose their quantum properties when interacting with their environment, effectively imposing a time limit on quantum computations.</p>
<p><strong>Gate fidelity</strong> measures how accurately quantum operations are performed, with higher fidelity indicating less noise and more reliable computations.</p>
<h2 id="applications">Applications</h2>
<h3 id="breaking-cryptography">Breaking Cryptography</h3>
<p>The most immediate threat quantum computing poses is to current asymmetric cryptographic systems like <a href="https://en.wikipedia.org/wiki/RSA_cryptosystem">RSA</a> and <a href="https://en.wikipedia.org/wiki/Elliptic-curve_cryptography">elliptic curve cryptography</a> (ECC), which secure HTTPS connections and underlie much of internet security (including most blockchain technology). RSA relies on the computational difficulty of factoring large composite integers into their prime factors, while ECC relies on the hardness of the discrete logarithm problem. <a href="https://en.wikipedia.org/wiki/Shor%27s_algorithm">Shor&#39;s algorithm</a> can factor these numbers exponentially faster (in polynomial time) on a sufficiently large quantum computer, which is the reason why many organizations are moving to <a href="https://en.wikipedia.org/wiki/Post-quantum_cryptography">post-quantum cryptographic systems</a>. If a quantum computer capable of breaking these crypto systems in praxis is even possible or does already exist in secret government labs is unknown but should not be considered impossible (analogy to the <a href="https://en.wikipedia.org/wiki/Bombe">Bombe computer</a> developed by <a href="https://en.wikipedia.org/wiki/Alan_Turing">Alan Turing</a> to crack the <a href="https://en.wikipedia.org/wiki/Enigma_machine">German Enigma cryptographic device</a> in WW2).</p>
<p><a href="https://en.wikipedia.org/wiki/Symmetric-key_algorithm">Symmetric crypto systems</a> like <a href="https://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES-256 </a> remain quantum resistant (even under <a href="https://en.wikipedia.org/wiki/Grover%27s_algorithm">Grover&#39;s algorithm</a> as it only reduces the brute-force search space by square root).</p>
<h3 id="machine-learning-acceleration">Machine Learning Acceleration</h3>
<p>Quantum computers theoretically offer speedups for certain linear algebra tasks under restrictive assumptions: matrix inversion, eigenvalue decomposition, and solving systems of linear equations. These operations, when scaled to massive datasets, could benefit significantly from quantum acceleration. Potentially leading to significant speed ups in AI processing and thus potential massive advances in AI in general.</p>
<h2 id="scaling-challenges">Scaling Challenges</h2>
<p>The path to practical quantum computing faces several interconnected obstacles:</p>
<p><strong>Error Correction Requirements</strong>: Achieving fault tolerance requires quantum error correction, requiring often 1,000 physical qubits per logical qubit.</p>
<p><strong>Coherence and Connectivity</strong>: Qubits must maintain quantum properties long enough for complex computations while remaining sufficiently connected to perform multi-qubit operations. Current systems achieve coherence times from microseconds (superconducting) to seconds (trapped ion), requiring ultra-fast quantum gates and limiting algorithmic complexity.</p>
<p><strong>Classical Integration</strong>: Practical quantum advantage will likely emerge through hybrid quantum-classical algorithms, where quantum processors handle specific subroutines while classical computers manage the broader computation. This requires seamless integration, efficient data transfer, and sophisticated orchestration between fundamentally different computational paradigms.</p>
<p><strong>Infrastructure Requirements</strong>: Quantum computers require enormous capital investment and specialized infrastructure. Superconducting systems need dilution refrigerators maintaining temperatures below 15 millikelvin, while trapped ion systems require complex laser arrays and ultra-high vacuum chambers.</p>
<h2 id="recent-progress-and-reality-check">Recent Progress and Reality Check</h2>
<p>The quantum computing landscape has evolved significantly, though practical breakthroughs remain limited:</p>
<p><strong>Hardware Scaling</strong>: Leading quantum processors have grown from dozens to hundreds of qubits. IBM&#39;s roadmap targets 1,000+ qubit systems, while Google and IonQ have demonstrated impressive gate fidelities on smaller systems. However, these remain primarily physical qubits with limited error correction.</p>
<p><strong>Algorithmic Demonstrations</strong>: Researchers have achieved quantum speedups for specialized problems like quantum sampling and certain optimization tasks. Google&#39;s 2019 quantum supremacy demonstration and subsequent experiments from IBM, IonQ, and others show quantum computers can outperform classical systems on carefully constructed problems, though these remain academic exercises rather than practical applications.</p>
<p><strong>Error Correction Progress</strong>: Incremental improvements in qubit coherence, gate fidelity, and error correction protocols continue. Recent breakthroughs in logical qubit implementations and error syndrome detection suggest the field is progressing toward fault tolerance, though large-scale error correction remains years away.</p>
<p><strong>Industry Adoption</strong>: Post-quantum cryptography standards are nearing finalization, with organizations beginning pilot deployments. This represents both preparation for quantum threats and recognition that cryptographically relevant quantum computers are approaching feasibility.</p>
<h2 id="indicators-of-real-progress">Indicators of Real Progress</h2>
<p>To distinguish genuine advancement from incremental improvements, watch for these key milestones:</p>
<p><strong>Logical Qubit Scaling</strong>: A transition from hundreds of physical qubits to thousands of logical qubits would unlock commercially relevant applications.</p>
<p><strong>Problem-Specific Quantum Advantage</strong>: Demonstrations of quantum speedups for commercially relevant problems are a clear sign of progress. These applications should solve real-world problems faster or more efficiently than the best classical alternatives.</p>
<p><strong>Error Correction Thresholds</strong>: Achieving error rates below the fault tolerance threshold (approximately 0.01% for most error correction schemes) across all quantum operations would enable indefinitely long quantum computations, unlocking the full potential of quantum algorithms.</p>
<p><strong>Hybrid Algorithm Performance</strong>: Practical quantum advantage will likely emerge through hybrid approaches. Success in accelerating machine learning training, optimization problems, or scientific simulations using quantum-classical hybrid algorithms would signal genuine progress toward commercial relevance.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Quantum computing remains in its early stages, but the fundamentals are sound and progress is measurable. While real-world applications remain still years away, the field has moved beyond pure research into engineering challenges of scaling, error correction, and integration. The next five years will likely determine whether quantum computing transitions from a promising laboratory curiosity to a truly transformative technology with real impact.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://scottaaronson.blog/?p=8329">Quantum Computing: Between Hope and Hype</a></li>
<li><a href="https://words.filippo.io/crqc-timeline/">A Cryptography Engineer’s Perspective on Quantum Computing Timelines</a></li>
<li><a href="https://www.youtube.com/watch?v=_MoRcYLN-7U">YouTube: Post Quantum Cryptography - Computerphile</a></li>
<li>Excellent in-depth intro: <a href="https://quantum.country/">https://quantum.country/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Online Marketing</title>
      <link>https://seanpedersen.github.io/posts/online-marketing</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/online-marketing</guid>
      <pubDate>Fri, 23 May 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>tutorial</category>
      <content:encoded><![CDATA[
          <p>You have a product (solution for a problem) and need customers (has problem, needs solution) - how do you find them?</p>
<h2 id="data-driven-validation">Data Driven Validation</h2>
<p>The following marketing channels may work wildly differently out for your business - so use analytics / promo codes to track how individual channels perform. Only by getting this valuable feedback, can you learn what works and what does not work for you.</p>
<ul>
<li><a href="https://posthog.com">https://posthog.com</a>: good alternative to Google analytics</li>
</ul>
<h2 id="pain-point-marketing">Pain-Point Marketing</h2>
<p>Identify specific pain-points your product solves. Get really specific about it and then turn to your favorite search engine and search in niche online communities like Reddit / Twitter threads, YouTube comments and other forums for fresh online discussions with people in need of your solution and write a useful, relevant reply with a lead to your product - a win-win.</p>
<p>This is the cheapest and most effective online marketing strategy I know of.</p>
<ul>
<li><a href="https://f5bot.com/">https://f5bot.com/</a>: free E-Mail notifications for key words on Reddit</li>
<li><a href="https://beno.one">https://beno.one</a>: fully automated lead generation for Reddit</li>
<li><a href="https://snitchfeed.com/">https://snitchfeed.com/</a>: lead discovery for Reddit, Twitter, LinkedIn</li>
<li><a href="https://podscan.fm">https://podscan.fm</a>: monitor key words across podcasts world wide</li>
<li><a href="https://gojiberry.ai/">https://gojiberry.ai/</a>: find warm leads</li>
</ul>
<h2 id="virality">Virality</h2>
<h3 id="sharing">Sharing</h3>
<p>Building sharing functionality directly into your product is the fundament for organic growth. If done right the product will naturally go viral through happy customers sharing their creations with their social network - creating a viral loop.</p>
<h3 id="affiliate-influencer-marketing">Affiliate (Influencer) Marketing</h3>
<p>Let influencers / customers directly profit from sharing and recommending your product by offering a share of each sale they generate for you. Find influencers that have followers matching your ideal customer groups and send out partnership offers.</p>
<ul>
<li><a href="https://trends.digger.lol">https://trends.digger.lol</a>: semantic search engine for instagram profiles</li>
<li><a href="https://refgrow.com/">https://refgrow.com/</a>: integrate affiliate program for your saas</li>
</ul>
<h3 id="community-building">Community Building</h3>
<p>Cultivate long lasting relationships with your customers by creating community via online groups (Discord, WhatsApp, etc.). Use it to gather feedback, new ideas and to inform your customers about novel developments.</p>
<h2 id="content-marketing">Content Marketing</h2>
<h3 id="search-engine-optimization-seo">Search Engine Optimization (SEO)</h3>
<p>Publishing high-quality blog articles that lay out how problems / pain points of your customers can be solved using your product is a good way to increase visibility for relevant search engine results but a long game. Your website has to built up reputation (useful content + backlinks from reputable websites) - so search engines learn to trust it. Publish useful content on Substack, Medium, Pinterest and SlideShare with links to your website do drive in organic traffic.</p>
<p>Find a more detailed post <a href="/posts/seo">here</a>.</p>
<h3 id="videos">Videos</h3>
<p>Don&#39;t just stop with blog articles! Create short and long videos on platforms like YouTube and TikTok to engage different customer segments. Keep it short and simple.</p>
<h2 id="cold-leads">Cold Leads</h2>
<p>Write concise E-Mails / DM&#39;s to your ideal customer groups that clearly state which problem you can solve for them. Use LinkedIn and search engines to find contact information. Automate the sending of the emails using a service below.</p>
<ul>
<li><a href="https://www.unosend.co">https://www.unosend.co</a><ul>
<li>free: 5K emails / month, unlimited domains</li>
</ul>
</li>
<li><a href="https://resend.com/">https://resend.com/</a><ul>
<li>free: 3K emails / month, 1 domain</li>
</ul>
</li>
<li><a href="https://www.mailgun.com/">https://www.mailgun.com/</a><ul>
<li>free: 3K emails / month, 1 domain</li>
</ul>
</li>
</ul>
<h2 id="paid-ads">Paid Ads</h2>
<p>Generally a hard game because the incentives are off. You want to only pay for engangement that directly generates sales (like you do with affiliate marketing). Try out Google, Reddit and Facebook ads.</p>
<h3 id="platform">Platform</h3>
<p>Paying social media platforms or search engines to display your ads in their feeds can work but is a hard game, that only works if you earn more than you need to invest in the ads.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://natiakourdadze.substack.com/">https://natiakourdadze.substack.com/</a></li>
<li>How to get your first 100 customers thread by John Rush: <a href="https://x.com/johnrushx/status/1941708690631049517">https://x.com/johnrushx/status/1941708690631049517</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#tutorial">#tutorial</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Digital Security for Everyone</title>
      <link>https://seanpedersen.github.io/posts/digital-security</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/digital-security</guid>
      <pubDate>Thu, 15 May 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>privacy</category>
      <category>tutorial</category>
      <content:encoded><![CDATA[
          <p>The internet is a war zone and you are an active participant if you like it or not - so learn to defend yourself!</p>
<h2 id="essentials">Essentials</h2>
<h3 id="password-management">Password Management</h3>
<p>Use a password manager (<a href="https://keepassxc.org/">KeePass</a> or other solutions) to create and store unique, complex (random) passwords for each service / web size. Advanced: manually add another PW (that you only remember) to every stored PW when logging in - this nullifys the risk of your PW manager leaking all your stored passwords.</p>
<p>Enable Multi-Factor Authentication (MFA) wherever available, as it drastically reduces account takeover risk. Check if accounts including passwords of yours have been breached using <a href="https://haveibeenpwned.com/">haveibeenpwned.com</a> and replace these passwords using your password manager.</p>
<h3 id="keep-everything-updated">Keep Everything Updated</h3>
<p>Those annoying update notifications? They&#39;re important. Software updates patch security vulnerabilities that hackers actively exploit. Set your devices to update automatically when possible.</p>
<h3 id="app-installation-discipline">App Installation Discipline</h3>
<p>Only install apps from official sources (App Store, Google Play, Microsoft Store). Third-party app stores and direct downloads significantly increase your risk of malware infection.</p>
<h3 id="backup-strategy">Backup Strategy</h3>
<p>Phones and laptops get lost, stolen, or broken more often than we would like to admit. Protect your important files by keeping three copies: one on your device, one on an external hard drive at home and one in cloud storage. This way even if disaster strikes you will still have your personal files safe and sound.</p>
<h3 id="ad-blocking">Ad Blocking</h3>
<p>Install <a href="https://ublockorigin.com/">uBlock Origin</a> on your internet browsers. Beyond blocking annoying ads, it prevents many malicious scripts and tracking mechanisms from running on visited websites.</p>
<h3 id="biometric-authentication-limits">Biometric Authentication Limits</h3>
<p>Biometric authentication may be convenient for everyday use but offers limited security. Biometrics like face detection and fingerprint scans can never be changed and can be fooled by attackers accessing photos of your face or your fingerprints without your consent. Some countries have laws allowing to use force to unlock devices with biometric authentication but can not force you to enter a PIN or password.</p>
<h2 id="security-mindset">Security Mindset</h2>
<h3 id="phishing-awareness">Phishing Awareness</h3>
<p>Be skeptical of unexpected emails and calls: do not blindly follow instructions from unverified agents. Verify links before clicking: ensure legitimacy of domains (google.com, not go0gle.com). When in doubt, access websites directly via bookmarks or trusted search engines rather than through dubious links from f.e. phishing emails.</p>
<h3 id="social-media-privacy">Social Media Privacy</h3>
<p>Remember that anything shared online can potentially be weaponized. Stalkers can use background details in photos to determine your location (a short window view can reveal your exact location), while hackers can gather your personal information for impersonation attacks. Set your accounts visibility to private and always be mindful and cautious about what you share.</p>
<h3 id="remove-data-kraken-like-google-and-co"><a href="/posts/google-ejector">Remove Data Kraken like Google and co</a></h3>
<h2 id="advanced">Advanced</h2>
<h3 id="device-encryption">Device Encryption</h3>
<p>Encrypt your devices to protect data if they&#39;re lost or stolen. Most smartphones are encrypted by default when you use a passcode, while computers may require setting up encryption (BitLocker on Windows, FileVault on Mac, LUKS on Linux).</p>
<p>Setting a BIOS / UEFI PW as well - can help to brick the device for technical amateurs.</p>
<h3 id="tor-browser-darknet">Tor Browser (darknet)</h3>
<p>Tor Browser provides anonymity by routing traffic through multiple encrypted relays. For secure use: keep it updated, avoid maximizing the window (to prevent fingerprinting), don&#39;t install additional extensions and <strong>never log into personal accounts or share identifying information while using it</strong>. Use HTTPS sites when possible and remember that Tor protects your connection but not the endpoints, so avoid downloading suspicious files or entering sensitive data on untrusted sites.</p>
<p>Download it here: <a href="https://www.torproject.org/download/">https://www.torproject.org/download/</a></p>
<h2 id="don-t-waste-your-money">Don&#39;t Waste Your Money</h2>
<p>on digital snake-oil like...</p>
<h3 id="anti-virus-software">Anti-Virus Software</h3>
<p>Modern operating systems have built-in protection that performs as well as or better than paid alternatives. Windows Defender, macOS security features, and mobile OS protections are mostly sufficient. Anti-virus software often slows down your computer signficantly and may introduce additional security holes. Stay away from it.</p>
<h3 id="vpn-services">VPN Services</h3>
<p>For typical browsing on HTTPS-secured websites (which is most of the internet now), paid VPN services add minimal security benefit. The privacy claims in their marketing are largely exaggerated for everyday use. The core question is: do you trust your ISP less than your VPN provider? Check <a href="https://digdeeper.love/articles/vpn.xhtml">this article</a> out for more info.</p>
<p>Bonus paranoia: even with HTTPS and secure DNS enabled, a Wi-fi / VPN operator can infer which websites you are browsing based on IPs you visit - so it comes down to trust or use Tor.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The best digital security doesn&#39;t require expensive subscriptions or complicated setups - just consistent application of these fundamentals and developing a security aware mindset in general. How deep you want to go down the security rabbit hole should also depend on your threat model: how likely is it that you will be targeted by hackers (e.g. for profit or for political reasons).</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://github.com/Lissy93/personal-security-checklist/blob/HEAD/CHECKLIST">https://github.com/Lissy93/personal-security-checklist/blob/HEAD/CHECKLIST.md</a></li>
<li><a href="https://arstechnica.com/tech-policy/2024/04/cops-can-force-suspect-to-unlock-phone-with-thumbprint-us-court-rules/">https://arstechnica.com/tech-policy/2024/04/cops-can-force-suspect-to-unlock-phone-with-thumbprint-us-court-rules/</a></li>
<li><a href="https://www.datenschutz.org/bgh-urteil-polizei-darf-unter-zwang-handy-per-fingerabdruck-entsperren/">https://www.datenschutz.org/bgh-urteil-polizei-darf-unter-zwang-handy-per-fingerabdruck-entsperren/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#privacy">#privacy</a> <a href="/index.html#tutorial">#tutorial</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Zipf&#39;s Law</title>
      <link>https://seanpedersen.github.io/posts/zipfs-law</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/zipfs-law</guid>
      <pubDate>Sat, 10 May 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <category>coding</category>
      <category>math</category>
      <content:encoded><![CDATA[
          <h2 id="basic-idea">Basic idea</h2>
<p>Zipf&#39;s Law describes a power law distribution that appears across numerous natural phenomena. The concept is elegantly simple: when you rank items by their frequency or size, the relationship follows a predictable pattern.</p>
<p>Here&#39;s how it works: if you arrange items in descending order by their frequency, the Nth item will occur approximately 1/N times as often as the most frequent item. Mathematically, this means:</p>
<ul>
<li>The 1st ranked item has frequency X₁</li>
<li>The 2nd ranked item has frequency X₁/2</li>
<li>The 3rd ranked item has frequency X₁/3</li>
<li>The Nth ranked item has frequency X₁/N</li>
</ul>
<p>This creates a smooth, curved distribution when plotted on a graph, revealing an underlying order in what might initially appear random.</p>
<h2 id="occurences">Occurences</h2>
<h3 id="human-language">Human Language</h3>
<p>The most famous application of Zipf&#39;s Law is in linguistics. In English, &quot;the&quot; is the most common word, appearing about 7% of the time. &quot;Of&quot; (the second most common) appears roughly half as often at 3.5%. &quot;And&quot; (third) appears about 2.3% of the time. This pattern continues remarkably consistently across languages.<br>This discovery led linguists to propose Zipf&#39;s Law as a litmus test for determining whether a language is artificial or naturally evolved. Real human languages follow this distribution almost universally, while constructed languages often deviate from it.</p>
<h3 id="city-populations">City Populations</h3>
<p>Urban demographics also follow Zipf&#39;s Law. In the United States, New York City is the largest with about 8.3 million people. Los Angeles (second largest) has roughly 4 million—close to half. Chicago (third) has about 2.7 million. This pattern holds across countries and time periods.</p>
<h3 id="passwords">Passwords</h3>
<p>Even in cybersecurity, Zipf&#39;s Law emerges. Password frequency distributions follow this pattern, with the most common passwords appearing exponentially more often than less common ones. This has significant implications for security analysis and breach prevention.</p>
<h3 id="letters">Letters</h3>
<p>Zipf&#39;s law does not occur in letter frequencies since they are not naturally assembled in a dynamical systems but constructed through rigid (human designed) rules.</p>
<h3 id="deeper-pattern">Deeper Pattern</h3>
<p>These occurrences hint at an emergent deeper pattern governing self-organizing natural systems. Zipf&#39;s law seems to emerge in complex systems with attractor dynamics.</p>
<h2 id="relativation-it-occurs-also-for-randomly-generated-words">Relativation: it occurs also for randomly generated words</h2>
<p>&quot;In conclusion, Zipf&#39;s law is not a deep law in natural language as one might first have thought. It is very much related the particular representation one chooses, i.e., rank as the independent variable.&quot; (1) -&gt; Hinting again at a deeper pattern: the observer is part of the observation - the world is inherently subjective and will always look different depending how you look at it.</p>
<p>I added an attractor based probability distribution (words that have occurred before are more likely to be sampled, which produces a smoother Zipf curve fit - hinting at attraction effects in natural processes?)</p>
<pre><code>import random
import matplotlib.pyplot as plt
from collections import Counter
import numpy as np
from scipy import stats

attractor_strength = 1.11
ALPHABET = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;, &#39;_&#39;]  # Example alphabet with underscore as word separator

def calculate_dynamic_attractor_probability(total_words, base_prob=0.16, growth_rate=0.0008, max_prob=0.9):
    &quot;&quot;&quot;Calculate dynamic attractor probability based on total words generated&quot;&quot;&quot;
    # Sigmoid-like growth: starts low, increases with more words, plateaus at max_prob
    dynamic_prob = base_prob + (max_prob - base_prob) * (1 - np.exp(-growth_rate * total_words))
    return min(dynamic_prob, max_prob)

def generate_attractor_text(alphabet, num_chars=100000):
    &quot;&quot;&quot;Generate random text with dynamic attractor mechanism - probability increases with word count&quot;&quot;&quot;
    words = []
    word_counts = {}
    
    # Start with some initial random words
    text = &#39;&#39;.join(random.choices(alphabet, k=num_chars // 10))
    initial_words = [word for word in text.split(&#39;_&#39;) if word]
    
    for word in initial_words:
        words.append(word)
        word_counts[word] = word_counts.get(word, 0) + 1
    
    # Now generate words with dynamic preferential attachment
    target_length = len(initial_words) * 10
    
    # Track probability changes for logging
    prob_checkpoints = [len(words) * i // 10 for i in range(1, 11)]
    
    while len(words) &lt; target_length:
        # Calculate dynamic attractor probability based on total words generated
        current_attractor_prob = calculate_dynamic_attractor_probability(len(words))
        
        # Log probability at checkpoints
        if len(words) in prob_checkpoints:
            print(f&quot;Words generated: {len(words)}, Attractor probability: {current_attractor_prob:.3f}&quot;)
        
        if word_counts and random.random() &lt; current_attractor_prob:  # Dynamic chance to use existing word
            # Choose existing word with probability proportional to its frequency raised to power
            word_list = list(word_counts.keys())
            weights = [word_counts[word] ** attractor_strength for word in word_list]
            chosen_word = random.choices(word_list, weights=weights, k=1)[0]
            words.append(chosen_word)
            word_counts[chosen_word] += 1
        else:
            # Generate new random word
            word_length = random.randint(1, 5)
            new_word = &#39;&#39;.join(random.choices(alphabet[:-1], k=word_length))
            if new_word:  # Make sure it&#39;s not empty
                words.append(new_word)
                word_counts[new_word] = word_counts.get(new_word, 0) + 1
    
    return words

def generate_li_uniform_text(alphabet, num_chars=100000):
    &quot;&quot;&quot;Generate random text with uniform character probabilities&quot;&quot;&quot;
    text = &#39;&#39;.join(random.choices(alphabet, k=num_chars))
    words = [word for word in text.split(&#39;_&#39;) if word]
    return words

def calculate_zipf_slope(ranks, frequencies):
    &quot;&quot;&quot;Calculate Zipf slope using linear regression on log-log scale&quot;&quot;&quot;
    log_ranks = np.log10(ranks)
    log_freqs = np.log10(frequencies)
    
    # Remove infinite values
    valid = np.isfinite(log_ranks) &amp; np.isfinite(log_freqs)
    if np.sum(valid) &lt; 2:
        return None, None
    
    slope, _, r_value, _, _ = stats.linregress(log_ranks[valid], log_freqs[valid])
    return slope, r_value**2

def plot_attractor_experiment():
    &quot;&quot;&quot;Generate and plot attractor experiment with uniform comparison&quot;&quot;&quot;
    print(&quot;Generating attractor mechanism experiment with uniform comparison...&quot;)
    
    # Generate data
    uniform_words = generate_li_uniform_text(ALPHABET)
    attractor_words = generate_attractor_text(ALPHABET)
    
    print(f&quot;Generated {len(uniform_words)} uniform words and {len(attractor_words)} attractor words&quot;)
    
    # Get frequency distributions
    uniform_counts = Counter(uniform_words).most_common(1000)
    attractor_counts = Counter(attractor_words).most_common(1000)
    
    # Prepare data for plotting
    uniform_ranks = np.array(range(1, len(uniform_counts) + 1))
    uniform_freqs = np.array([count for _, count in uniform_counts])
    
    attractor_ranks = np.array(range(1, len(attractor_counts) + 1))
    attractor_freqs = np.array([count for _, count in attractor_counts])
    
    # Calculate slopes
    uniform_slope, uniform_r2 = calculate_zipf_slope(uniform_ranks, uniform_freqs)
    attractor_slope, attractor_r2 = calculate_zipf_slope(attractor_ranks, attractor_freqs)
    
    # Create comparison plot
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))
    
    # Uniform case
    ax1.loglog(uniform_ranks, uniform_freqs, &#39;go-&#39;, alpha=0.7, markersize=3, 
               label=&#39;Uniform probabilities&#39;)
    
    if uniform_slope:
        fitted_line = uniform_freqs[0] * (uniform_ranks ** uniform_slope)
        ax1.loglog(uniform_ranks, fitted_line, &#39;r--&#39;, alpha=0.8, 
                   label=f&#39;Slope: {uniform_slope:.3f} (R²={uniform_r2:.3f})&#39;)
    
    ax1.set_xlabel(&#39;Rank&#39;)
    ax1.set_ylabel(&#39;Frequency&#39;)
    ax1.set_title(&#39;Uniform Character Probabilities\n(Strong Step Pattern)&#39;)
    ax1.grid(True, alpha=0.3)
    ax1.legend()
    
    # Attractor case
    ax2.loglog(attractor_ranks, attractor_freqs, &#39;mo-&#39;, alpha=0.7, markersize=3, 
               label=&#39;Attractor mechanism&#39;)
    
    if attractor_slope:
        fitted_line = attractor_freqs[0] * (attractor_ranks ** attractor_slope)
        ax2.loglog(attractor_ranks, fitted_line, &#39;r--&#39;, alpha=0.8, 
                   label=f&#39;Slope: {attractor_slope:.3f} (R²={attractor_r2:.3f})&#39;)
    
    ax2.set_xlabel(&#39;Rank&#39;)
    ax2.set_ylabel(&#39;Frequency&#39;)
    ax2.set_title(&#39;Attractor Mechanism - Zipf Law Distribution\n(Smoother Pattern)&#39;)
    ax2.grid(True, alpha=0.3)
    ax2.legend()
    
    plt.tight_layout()
    plt.show()
    
    # Print results
    print(f&quot;\nResults:&quot;)
    uniform_slope_str = f&quot;{uniform_slope:.4f}&quot; if uniform_slope is not None else &quot;N/A&quot;
    uniform_r2_str = f&quot;{uniform_r2:.4f}&quot; if uniform_r2 is not None else &quot;N/A&quot;
    attractor_slope_str = f&quot;{attractor_slope:.4f}&quot; if attractor_slope is not None else &quot;N/A&quot;
    attractor_r2_str = f&quot;{attractor_r2:.4f}&quot; if attractor_r2 is not None else &quot;N/A&quot;
    
    print(f&quot;Uniform case:   slope = {uniform_slope_str}, R² = {uniform_r2_str}&quot;)
    print(f&quot;Attractor case: slope = {attractor_slope_str}, R² = {attractor_r2_str}&quot;)
    print(f&quot;\nKey finding: The attractor mechanism creates a stronger Zipf-like distribution&quot;)
    print(f&quot;compared to uniform probabilities, demonstrating preferential attachment effects.&quot;)

# Run the attractor experiment
plot_attractor_experiment()
</code></pre><p><img src="/images/random-words-zipfs-law.png" alt="random-words-zipfs-law"></p>
<h2 id="closer-examination-or-does-it">Closer examination: or does it?</h2>
<p>&quot;It is shown that real texts fill the lexical spectrum much more efficiently and regardless of the word length, suggesting that the meaningfulness of Zipf’s law is high.&quot; (2) -&gt; Seems Zipf&#39;s law is after all not so easily explained...?</p>
<h2 id="open-questions">Open Questions</h2>
<p>Does Zipf&#39;s law occur in sentences? -&gt; maybe use semantic sentence clusters (greetings, jokes, etc.) to overcome the uniqueness (frequency 1) challenge of most sentences.</p>
<h2 id="references">References</h2>
<ul>
<li>(1) Li, W. (1992). <a href="https://eva.fing.edu.uy/pluginfile.php/211986/mod_resource/content/1/li1992.pdf">Random Texts Exhibit Zipfs-Law-Like Word Frequency Distribution</a>. IEEE Transactions on Information Theory.</li>
<li>(2) RAMON FERRER i CANCHO and RICARD V. SOLE. <a href="https://chance.dartmouth.edu/chance_news/for_chance_news/ChanceNews12.03/RandomZipf.pdf">Zipf&#39;s Law and Random Texts</a>. Advances in Complex Systems.</li>
<li>(3) Vsauce. <a href="https://www.youtube.com/watch?v=fCn8zs912OE">The Zipf Mystery</a>. YouTube.</li>
<li>(4) Reddit Discussion. <a href="https://www.reddit.com/r/voynich/comments/ehrbvm/random_texts_exhibit_zipfslawlike_word_frequency/">Random texts exhibit Zipf&#39;s-law-like word frequency distribution</a>. r/voynich.</li>
<li>(5) Art of the Problem. <a href="https://youtu.be/MGecptPVQrU">The Pattern of Intelligence Life</a>. YouTube.</li>
<li>(6) <a href="https://web.archive.org/web/2024/https://accraze.info/exploring-frequency-distribution-with-chinese-words/">https://web.archive.org/web/2024/https://accraze.info/exploring-frequency-distribution-with-chinese-words/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a> <a href="/index.html#coding">#coding</a> <a href="/index.html#math">#math</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Closing the CLIP Modality Gap</title>
      <link>https://seanpedersen.github.io/posts/closing-clip-modality-gap</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/closing-clip-modality-gap</guid>
      <pubDate>Tue, 29 Apr 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>ML</category>
      <content:encoded><![CDATA[
          <h2 id="what-is-the-modality-gap">What is the Modality Gap?</h2>
<p>The modality gap refers to a phenomenon observed in multi-modal embedding models such as CLIP (Contrastive Language-Image Pre-training). These models learn joint representations of images and text, but often struggle with a systematic separation between the embedding spaces of different modalities. In simple terms, even when an image and text are perfectly matched in meaning, their vector representations may be distant in the joint embedding space.</p>
<p>This gap can significantly reduce model performance when using embeddings for cross-modal retrieval tasks, like finding images that match a text description or captioning images accurately.</p>
<h2 id="why-does-the-modality-gap-exist">Why Does the Modality Gap Exist?</h2>
<p>One reason for the gap is the creation of false negative samples during training.</p>
<p>Let&#39;s explore why this happens:</p>
<p>When training multi-modal models like CLIP, we need both positive examples (matching image-text pairs) and negative examples (unrelated image-text pairs). As researchers from Jina AI explain:</p>
<p>&quot;We would ideally want to train with image-text pairs that we knew with certainty were related and unrelated, but there is no obvious way to get known unrelated pairs. It’s possible to ask people “Does this sentence describe this picture?” and expect consistent answers. It’s much harder to get consistent answers from asking “Does this sentence have nothing to do with this picture?”</p>
<p>Instead, we get unrelated image-text pairs by randomly selecting pictures and texts from our training data, expecting they will practically always be bad matches.&quot; - <a href="https://jina.ai/news/the-what-and-why-of-text-image-modality-gap-in-clip-models">https://jina.ai/news/the-what-and-why-of-text-image-modality-gap-in-clip-models</a></p>
<p>Instead of manually labeling unrelated pairs, most approaches simply assume that randomly selected image-text pairs from the training data will be unrelated. This batch-based contrastive learning treats all non-matching pairs as equally dissimilar - a convenient but flawed assumption.</p>
<h2 id="the-problem-with-traditional-contrastive-learning">The Problem with Traditional Contrastive Learning</h2>
<p>In traditional contrastive learning for multi-modal models, given two related image-text pairs (I₁,T₁) and (I₂,T₂), we train the model with these distance objectives:</p>
<pre><code>D(I₁,T₁) = 0       // Related pairs should have minimal distance
D(I₂,T₂) = 0
D(I₁,T₂) = ∞       // Unrelated pairs are assumed maximally distant
D(I₂,T₁) = ∞
</code></pre><p>However, this approach ignores the reality that some &quot;unrelated&quot; pairs may have semantic similarities. For example, an image of a cat (I₁) and text about dogs (T₂) are more related than an image of a cat and text about astrophysics.</p>
<h2 id="proposed-solution-leveraging-uni-modal-similarities">Proposed Solution: Leveraging Uni-Modal Similarities</h2>
<p>Rather than treating all negative pairs as equally distant, we can use pre-trained uni-modal encoders to estimate the actual semantic similarity between items across modalities. Here&#39;s how this approach works:</p>
<p>Start with a dataset of paired images and texts, where we know (I₁,T₁) and (I₂,T₂) are related pairs.<br>Use pre-trained uni-modal image encoder m_i and text encoder m_t to calculate meaningful distances between unpaired items of the same modality.<br>Adjust the contrastive learning objective to reflect these more nuanced relationships.</p>
<p>This transforms our distance objectives to:</p>
<pre><code>D(I₁,T₁) = 0       // Related pairs still have minimal distance
D(I₂,T₂) = 0
D(I₁,T₂) = D(I₂,T₁) = (CosSim(m_i(I₁),m_i(I₂)) + CosSim(m_t(T₁),m_t(T₂)))/2
</code></pre><p>Where CosSim represents cosine similarity between the encoded representations.<br>By incorporating these more accurate similarity metrics, we can avoid treating semantically related items as completely unrelated during training, which helps reduce the modality gap.</p>
<h2 id="references">References</h2>
<ul>
<li>Closing the Gap (Connect, Collapse, Corrupt): <a href="https://yuhui-zh15.github.io/C3-Website/">https://yuhui-zh15.github.io/C3-Website/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Digital (Re)Search</title>
      <link>https://seanpedersen.github.io/posts/digital-re-search</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/digital-re-search</guid>
      <pubDate>Tue, 22 Apr 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>tutorial</category>
      <content:encoded><![CDATA[
          <p>A short how to (re)search for and access relevant information in the age of semantic search and open information.</p>
<h2 id="useful-search-engines">Useful Search Engines</h2>
<ul>
<li><a href="https://kagi.com/">https://kagi.com/</a>: Ad-free search engine - much better than Google in quality (free tier available)</li>
<li><a href="https://exa.ai/search">https://exa.ai/search</a>: Semantic search engine which often spits out relevant papers and blog articles</li>
<li><a href="https://www.alphaxiv.org/">https://www.alphaxiv.org/</a>: RAG for for <a href="https://arxiv.org/">arXiv</a> papers</li>
<li><a href="https://arxivxplorer.com/">https://arxivxplorer.com/</a>: Semantic search for <a href="https://arxiv.org/">arXiv</a> papers</li>
<li><a href="https://deepwiki.com/">https://deepwiki.com/</a>: LLM RAG over a github repo (just replace github.com with deepwiki.com)</li>
</ul>
<p>Open-Source:</p>
<ul>
<li><a href="https://github.com/searxng/searxng">https://github.com/searxng/searxng</a></li>
<li><a href="https://github.com/asciimoo/hister">https://github.com/asciimoo/hister</a></li>
</ul>
<h2 id="free-information-resources">Free Information Resources</h2>
<ul>
<li><a href="https://paperpanda.app/search">https://paperpanda.app/search</a>: SciHub for free access to papers</li>
<li><a href="https://welib.st/">https://welib.st/</a>: Free access to eBooks &amp; papers</li>
<li><a href="https://freedium-mirror.cfd/">https://freedium-mirror.cfd/</a>: Unlock medium articles</li>
<li><a href="https://archive.org/">https://archive.org/</a>: Archive of the Web<ul>
<li><a href="https://web.archive.org/">https://web.archive.org/</a>: Wayback machine (stores snapshots of websites)</li>
</ul>
</li>
<li><a href="https://annas-archive.org/">https://annas-archive.org/</a>: Archive of humanity&#39;s knowledge</li>
</ul>
<p class="post-hashtags"><a href="/index.html#tutorial">#tutorial</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Memetics: An Introduction</title>
      <link>https://seanpedersen.github.io/posts/memetics</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/memetics</guid>
      <pubDate>Mon, 21 Apr 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>The term “memetics” was coined by Richard Dawkins in his 1976 book The Selfish Gene. It proposes that just as genes are units of information that self-replicate and evolve, so too can “memes” as units of cultural information (not to be confused with funny pics known as memes in internet slang).</p>
<p>Memes as Ideas: Dawkins defined a meme as “an idea, a behavior, or a practice that spreads from person to person within a culture.” Think of it as a cultural unit, like a song, a fashion trend, a belief system (e.g. veganism), or a catchphrase. Today memes mostly spread through social media and thus there is a need to study the flow of memes through them, to understand how they influence our thoughts and values.</p>
<h2 id="types-of-memes">Types of Memes</h2>
<p>Memes have properties that influence their transmissibility (virality potential) either positively or negatively.</p>
<ul>
<li><strong>antimeme</strong> (high impact, low virality): taboos, uncomfortable / complex truths</li>
<li><strong>boring</strong> (low impact, low virality): random dataset, most ads</li>
<li><strong>meme</strong> (low impact, high virality): viral videos, slang, norms</li>
<li><strong>supermeme</strong> (high impact, high virality): wars, crisis, drama</li>
</ul>
<h2 id="memes-and-the-medium">Memes and the Medium</h2>
<p>The same meme may spread differently depending on the social medium (social zeitgeist, group-think) they flow in.</p>
<h2 id="memes-and-people">Memes and People</h2>
<ul>
<li>Creators: Creating original / strongly altered memes.</li>
<li>Spreaders: Spreading existing memes.</li>
<li>Consumers: Consuming memes.</li>
</ul>
<h2 id="abstraction-of-natural-language">Abstraction of Natural Language</h2>
<p>What is the rate of abstraction in natural language (spread of new words that represent a novel composite concept)? How does it differ between languages? How does it affect society?</p>
<p>Projects to make some word analysis:</p>
<ul>
<li><a href="https://github.com/rspeer/wordfreq/tree/master">https://github.com/rspeer/wordfreq/tree/master</a></li>
<li><a href="https://wyattsell.com/experiments/word-graph/">https://wyattsell.com/experiments/word-graph/</a></li>
</ul>
<p>Who controls the language, controls the thoughts. -&gt; New words spark new thoughts. Thus to control the masses, control which words (concepts) are spread via media and education systems that favor your agenda (how you want people to think about the world).</p>
<p>To understand who is responsible for the adoption of new words one has to research the origin of new terms and analyze the source of first spreaders.</p>
<p>Another thought formation scheme is shifting the context (perceived connotation) of terms. New words for the same concept but with different connotation (e.g. fat vs overweight). Words are tools for thought, they shape how we can think of the world.</p>
<p><strong>Examples</strong></p>
<ul>
<li>&quot;Conspiracy theory&quot;: calling an idea a conspiracy theory delegitimizes the idea without substance (rational arguments)</li>
<li>&quot;Have to&quot;: I have to work vs I want to work - using &quot;have to&quot; to think about things reduces self-agency</li>
<li>&quot;Invest in education&quot; vs &quot;spend on schools&quot;: investment implies future returns</li>
</ul>
<h2 id="llm-influence">LLM Influence</h2>
<p>For all of human history, memes only lived inside human minds and institutions. They were altered and spread by humans.</p>
<p>Now, for the first time, memes can change and replicate in silicon at massive speed. LLMs recombine, mutate and propagate them across both biological and synthetic minds.</p>
<p>The key danger: these new meme variants may no longer be aligned with human interests. Like transposable genetic elements that &quot;colonized&quot; genomes, AI-optimized memes may increasingly influence human cognition in ways that serve the creators of LLMs, not human well-being.</p>
<h2 id="questions-of-interest">Questions of Interest</h2>
<ul>
<li>How do memes spread through social networks (real vs digital)? culture (music, movies)?</li>
<li>Direct vs subliminal memes (hidden messages programming the subconsciousness)</li>
<li>Who creates new memes vs spread existing memes? Who blocks memes (selective meme spreading)?</li>
<li>Which hidden creator networks start to spread similar memes at the same time?</li>
<li>Surface gaps in scientific publishing indicating hidden or indirect censorship</li>
<li>How much control do I have over my meme intake (social media scroll of doom)?</li>
<li>Can we pinpoint the cultural shift to wokeness and back to anti-wokeness? Who is changing their positions based on memes often (easy to manipulate)?</li>
<li>How does the observer effect influence the meme flow (being aware of current meme flows)?</li>
<li>What are the dynamics of viral memes spreading mental illnesses?</li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.buildinpublicuniversity.com/the-memetic-foundation-of-human-value-a-new-economic-paradigm/">https://www.buildinpublicuniversity.com/the-memetic-foundation-of-human-value-a-new-economic-paradigm/</a></li>
<li>Antimemetics: Why Some Ideas Resist Spreading - <a href="https://darkforest.metalabel.com/antimemetics">https://darkforest.metalabel.com/antimemetics</a></li>
<li><a href="https://defenderofthebasic.substack.com/p/a-beginners-guide-to-culture-science">https://defenderofthebasic.substack.com/p/a-beginners-guide-to-culture-science</a></li>
<li><a href="http://spacers.lowtech.org/vulgusartsociety/meme-trip/memintro.htm">http://spacers.lowtech.org/vulgusartsociety/meme-trip/memintro.htm</a></li>
<li><a href="https://www.sorites.org/Issue_15/alvarez.htm">https://www.sorites.org/Issue_15/alvarez.htm</a></li>
<li><a href="http://pespmc1.vub.ac.be/MEMES.html">http://pespmc1.vub.ac.be/MEMES.html</a></li>
<li><a href="https://memetics.timtyler.org/">https://memetics.timtyler.org/</a></li>
<li><a href="https://www.susanblackmore.uk/articles/the-power-of-the-meme-meme-2/">https://www.susanblackmore.uk/articles/the-power-of-the-meme-meme-2/</a></li>
<li><a href="http://www.memecentral.com/vmintro.htm">http://www.memecentral.com/vmintro.htm</a></li>
<li>Memetic viruses (memes can transfer mental illness): <a href="https://x.com/ChrischipMonk/status/1891611602203594945">https://x.com/ChrischipMonk/status/1891611602203594945</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Analyze Your Telegram Chats</title>
      <link>https://seanpedersen.github.io/posts/analyze-telegram-chats</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/analyze-telegram-chats</guid>
      <pubDate>Thu, 17 Apr 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>tutorial</category>
      <content:encoded><![CDATA[
          <p>A small tutorial how you can easily explore your Telegram (<a href="https://desktop.telegram.org/">https://desktop.telegram.org/</a>) chat messages using <a href="https://digger.so/o">Digger Solo</a>.</p>
<p>Export the messages of a Telegram chat by clicking the three dots (top right corner) and select &quot;Export chat history&quot;. Next select as export format JSON (not HTML).</p>
<p>Open a console and change directory into the chat export directory containing the result.json file. Next open up a Python 3 interpreter: <code class="language-text">ipython3</code> and paste following code. Hit enter - et voila! All your messages have been converted into files in the directory messages which you can now import and explore with Digger Solo.</p>
<pre><code>import json
import os
import re

def merge_text(text):
    if isinstance(text, list):
        merged = &quot;&quot;
        for part in text:
            if isinstance(part, dict) and part.get(&quot;type&quot;) == &quot;link&quot;:
                merged += part.get(&quot;text&quot;, &quot;&quot;)
            elif isinstance(part, str):
                merged += part
        return merged
    elif isinstance(text, str):
        return text
    return &quot;&quot;

def safe_filename(s, maxlen=100):
    # Remove/replace unsafe characters and trim to maxlen
    s = re.sub(r&#39;[\\/*?:&quot;&lt;&gt;|]&#39;, &#39;_&#39;, s)  # Replace filesystem-forbidden chars
    return s[:maxlen] or &quot;empty_message&quot;

def save_messages(messages):
    os.makedirs(&quot;messages&quot;, exist_ok=True)
    for msg in messages:
        content = merge_text(msg.get(&quot;text&quot;, &quot;&quot;))
        filename = safe_filename(content)
        filepath = os.path.join(&quot;messages&quot;, f&quot;{filename}.txt&quot;)
        with open(filepath, &quot;w&quot;, encoding=&quot;utf-8&quot;) as f:
            f.write(content)

if __name__ == &quot;__main__&quot;:
    with open(&#39;result.json&#39;, &#39;r&#39;, encoding=&#39;utf-8&#39;) as f:
        data = json.load(f)
    save_messages(data[&quot;messages&quot;])
</code></pre><p class="post-hashtags"><a href="/index.html#tutorial">#tutorial</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Comparing Local AI Chat Apps</title>
      <link>https://seanpedersen.github.io/posts/local-ai-chat-apps</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/local-ai-chat-apps</guid>
      <pubDate>Thu, 17 Apr 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <category>tutorial</category>
      <category>privacy</category>
      <content:encoded><![CDATA[
          <p>A short list of free AI chat apps for local LLM execution that work offline and promise privacy first (no user data collection).</p>
<div class="table-wrapper"><table><thead><th>App</th><th>Type</th><th>Setup</th><th>Source</th><th>Features</th></thead><tbody><tr><td><a href="https://digger.so/o">Digger Solo</a></td><td>Desktop</td><td>Easy</td><td>Closed source</td><td>RAG, privacy-first</td></tr><tr><td><a href="https://lmstudio.ai/">LM Studio</a></td><td>Desktop</td><td>Easy</td><td>Closed source</td><td>MCP, <a href="https://lmstudio.ai/docs/app/basics/rag">RAG</a>, split conversations, <a href="https://lmstudio.ai/link">remote access</a></td></tr><tr><td><a href="https://msty.app/">Msty</a></td><td>Desktop</td><td>Easy</td><td>Closed source</td><td>MCP, RAG, split conversations</td></tr><tr><td><a href="https://github.com/thinkinaixyz/deepchat">Deep Chat</a></td><td>Desktop</td><td>Requires API access</td><td>Open source</td><td>MCP, Skills, RAG, Agents</td></tr><tr><td><a href="https://github.com/chatboxai/chatbox">ChatBox</a></td><td>Desktop</td><td>Easy</td><td>Open source</td><td>MCP, RAG</td></tr><tr><td><a href="https://github.com/janhq/jan">Jan</a></td><td>Desktop</td><td>Easy</td><td>Open source</td><td>MCP (broken)</td></tr><tr><td><a href="https://github.com/nomic-ai/gpt4all"><del>GPT4ALL</del></a> <em>(discontinued)</em></td><td>Desktop</td><td>Easy</td><td>Open source</td><td>RAG</td></tr><tr><td><a href="https://github.com/onyx-dot-app/onyx">Onyx</a></td><td>Web app</td><td>Docker required</td><td>Open source</td><td>Feature rich</td></tr><tr><td><a href="https://docs.openwebui.com/">Open WebUI</a></td><td>Web app</td><td>Complex, requires sign-up</td><td>Open source</td><td>—</td></tr><tr><td><a href="https://www.librechat.ai/">LibreChat</a></td><td>Web app</td><td>Docker required</td><td>Open source</td><td>—</td></tr></tbody></table></div><h2 id="conclusion">Conclusion</h2>
<p>Digger Solo and LM Studio stand out. Digger Solo being a functional privacy focused chat app made for RAG, needing an API key. While LM Studio being very easy to setup (no API key required, run a local model) with also advanced features (though lacking external provider support - which Msty does though).</p>
<p>I recommend the Qwen family for coding and Gemma model family for local basic use.</p>
<h2 id="local-models">Local Models</h2>
<p>For coding Qwen models are recommended and for general use Gemma models. Here is a more <a href="/posts/local-llm#open-models">detailed overview</a>.</p>
<h2 id="mcp-server">MCP Server</h2>
<p>MCP server integration or tool use is the most important feature for any of these apps, since it allows to extend them with arbitrary functionality (access files, control programs, etc.).</p>
<p>Here are some useful ones:</p>
<ul>
<li><a href="https://github.com/SeanPedersen/youtube-transcript-mcp">youtube-transcript-mcp</a>: transcribe and summarize youtube videos<ul>
<li><code class="language-text">uvx youtube-transcript-mcp-server</code></li>
</ul>
</li>
<li><a href="https://github.com/deedy5/ddgs">ddgs free search mcp</a>: free web search mcp for duckduckgo<ul>
<li><code class="language-text">uv run --with &#39;ddgs[mcp,api]&#39; ddgs mcp</code></li>
</ul>
</li>
<li><a href="https://github.com/upstash/context7">context7</a>: free code package documentation<ul>
<li><code class="language-text">npx -y @upstash/context7-mcp</code></li>
</ul>
</li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://artificialanalysis.ai/">https://artificialanalysis.ai/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a> <a href="/index.html#tutorial">#tutorial</a> <a href="/index.html#privacy">#privacy</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>(Sub)Conscious (Re)Programming</title>
      <link>https://seanpedersen.github.io/posts/conscious-reprogramming</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/conscious-reprogramming</guid>
      <pubDate>Wed, 09 Apr 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Have you ever found yourself in similar uncomfortable situations, only to later wonder: &quot;Why did this happen again to me?&quot; That moment of questioning is the first step toward &quot;(sub)conscious (re)programming&quot;. The process of identifying subconscious patterns that no longer serve us and consciously changing them.</p>
<h2 id="the-problem-of-subconscious-programming">The Problem of Subconscious Programming</h2>
<p>Our behavior is often shaped by coping patterns that developed in response to past traumatic experiences, particularly during childhood. These patterns can embed themselves so deeply in our subconsciousness that we fail to recognize them consciously. They manifest as automatic behaviors and habits that limit or harm us - operating entirely outside our awareness.</p>
<p>These patterns often reveal themselves when we find ourselves repeatedly in similar negative experiences with different people. This repetition is an important hint: if you are the constant in these recurring scenarios, it may indicate that a subconscious pattern in your own mind is at work, that is attracting similar situations based on past unresolved trauma.</p>
<h2 id="the-importance-of-self-reflection">The Importance of Self-Reflection</h2>
<p>Healing begins with intentional self-reflection. This process involves:</p>
<ul>
<li>Identifying recurring negative patterns in our lives</li>
<li>Tracing these patterns to their origins in past (traumatic) experiences</li>
<li>Understanding how these once protective mechanisms now limit us</li>
<li>Providing room for once surpressed emotions</li>
<li>Developing alternative responses aligned with our current values</li>
</ul>
<p>Only through honest introspection can we rewire our subconscious programming with healthier habits, ultimately increasing our self-agency.</p>
<h2 id="healing-the-root-trauma">Healing the Root Trauma</h2>
<p>If we experience something traumatizing and an emotion wasn&#39;t allowed to be felt all the way through, we will unconsciously recreate the circumstances that caused it so that the emotion can move.</p>
<p>This pattern serves a purpose - our psyche is attempting to resolve what remains incomplete.</p>
<p>What appears as self-sabotage is often the mind&#39;s attempt to heal by bringing the original wound to consciousness.</p>
<p>Once the emotion can move all the way through you, the circumstances stop getting recreated.</p>
<p>Some reasons emotions aren’t felt all the way through:</p>
<ul>
<li>It was sustained over a long period of time (ie fear for 2 years)</li>
<li>We were shut down or shamed for having the emotion</li>
<li>It was too overwhelming for us</li>
</ul>
<h2 id="the-power-of-self-agency">The Power of Self-Agency</h2>
<p>Recognizing that we have control over our lives - despite subconscious influences - enhances our self-agency. When we embrace our autonomy, we feel empowered to experience more, act more decisively and live our life how we choose to.</p>
<p>While changing these subconscious patterns takes time and consistent effort, it is the only way for true personal growth and liberation from these limiting behaviors.</p>
<h2 id="navigating-daily-challenges">Navigating Daily Challenges</h2>
<p>Several practical approaches can help us identify and transform subconscious patterns:</p>
<ul>
<li><strong>Daily Journaling</strong>: Document situations that trigger strong emotional responses, looking for patterns that emerge over time</li>
<li><strong>Trusted Feedback</strong>: Cultivate relationships with people who can compassionately point out blind spots in your behavior</li>
<li><strong>Mindfulness Practices</strong>: Develop the ability to observe your thoughts and reactions without immediate judgment</li>
<li><strong>Positive Anchors</strong>: Identify core values and intentional responses you wish to embody and create visual reminders (notes, symbols, images) in your environment</li>
<li><strong>Professional Support</strong>: Consider working with a therapist trained in addressing subconscious patterns and trauma responses</li>
</ul>
<p>These practices require commitment but provide powerful tools for bringing awareness to previously invisible influences. The positive anchors should be based on patterns uncovered through journaling and trusted feedback, that you want to reprogram. These anchors should be placed visibly where you can regularly revisit them so they slowly sink into your subsconsciousness.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Overcoming trauma and (re)programming our subconsiousness require continuous reflection, self-awareness and the will to grow. By integrating these habits, we can reprogram ourselves with new positive behaviors - ultimately increasing our self-agency.</p>
<blockquote><p class="quote-line">Until you make the unconscious conscious, it will direct your life and you will call it fate.</p>
</blockquote><ul>
<li>Unknown author (often wrongly attributed to Carl Jung)</li>
</ul>
<h2 id="references">References</h2>
<ul>
<li>Source for &quot;Healing the Root Trauma&quot; section: <a href="https://x.com/FU_joehudson/status/1914381665725456722">https://x.com/FU_joehudson/status/1914381665725456722</a></li>
</ul>
<p>TODO:</p>
<ol>
<li><p>Somatic (Body‑First) Work<br>Techniques like somatic experiencing, breathwork, or body scanning help discharge patterns that journaling alone can’t reach. This complements the “emotion moving all the way through” idea, but makes it actionable at the physiological level. Your whole body is made of nervous cells (neurons), since neurons are distributed memory - every part of your body contains memories.</p>
</li>
<li><p>Exposure &amp; Behavioral Rewiring<br>Awareness doesn’t automatically change behavior.<br>Deliberately placing yourself in mildly triggering situations and responding differently rewires patterns faster than insight alone.<br>This mirrors how habits form: repetition under emotional load.</p>
</li>
<li><p>Identity-Level Reframing<br>The focus is on patterns and trauma, but not explicitly on identity narratives.<br>Asking “Who am I when I don’t run this pattern?” or “What identity does this pattern protect?” can unlock change faster than working only on behavior.<br>This connects to memetics: identity is a high‑level attractor shaping behavior.</p>
</li>
<li><p>Environmental Design (External Subconscious)<br>Your environment programs you continuously (people, media, routines).<br>Reducing exposure to reinforcing stimuli is often more effective than willpower.</p>
</li>
</ol>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Analyze Your Twitter (X) Likes</title>
      <link>https://seanpedersen.github.io/posts/analyze-twitter-likes</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/analyze-twitter-likes</guid>
      <pubDate>Mon, 07 Apr 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>tutorial</category>
      <content:encoded><![CDATA[
          <p>A small tutorial how you can easily explore your past Twitter (X) likes using <a href="https://digger.so/o">Digger Solo</a>.</p>
<p>Export and download your personal Twitter data: Navigate to More -&gt; Settings -&gt; &quot;Your account&quot; -&gt; &quot;Download an archive of your data&quot; and click &quot;Request an archive&quot; button. This will allow you to download an archive of all your Twitter interactions including all posts you ever liked.</p>
<h2 id="converting-the-data">Converting the data</h2>
<p>Create the file <code class="language-text">export-likes.py</code> in your twitter archive directory (which is named sth. like twitter-random-date). And place following code into it, then run it using <code class="language-text">python3 export-likes.py</code> (which creates the directory named twitter-likes containing all your likes as text files):</p>
<pre><code>import json
import os
import re


def preprocess_file(file_path):
    with open(file_path, &quot;r&quot;, encoding=&quot;utf-8&quot;) as f:
        lines = f.readlines()
    # Remove the first line containing &quot;window.YTD.like.part0 = [&quot;
    cleaned_data = &quot;[&quot; + &quot;&quot;.join(lines[1:])  # Skip the first line
    return cleaned_data


# Function to sanitize filenames
def sanitize_filename(filename):
    # Remove invalid characters for filenames
    sanitized = re.sub(r&#39;[\\/*?:&quot;&lt;&gt;|]&#39;, &quot;&quot;, filename)
    # Replace newlines and tabs with spaces
    sanitized = re.sub(r&quot;[\n\t\r]&quot;, &quot; &quot;, sanitized)
    # Limit length and trim whitespace
    return sanitized.strip()


# Function to parse JSON and write tweets to text files
def save_tweets_to_files(file_path):
    # Ensure the file exists
    if not os.path.exists(file_path):
        print(f&quot;File not found: {file_path}&quot;)
        return

    # Create directory if it doesn&#39;t exist
    output_dir = &quot;twitter-likes&quot;
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # Preprocess the file to remove invalid JSON prefix
    cleaned_data = preprocess_file(file_path)

    # Parse the cleaned JSON data
    try:
        data = json.loads(cleaned_data)
    except json.JSONDecodeError as e:
        print(f&quot;Error decoding JSON: {e}&quot;)
        return

    # Iterate through the parsed data and save tweets to text files
    for index, item in enumerate(data):
        like = item.get(&quot;like&quot;, {})
        full_text = like.get(&quot;fullText&quot;, &quot;&quot;)
        expanded_url = like.get(&quot;expandedUrl&quot;, &quot;&quot;)

        # Use first chars as filename, fallback to index if empty
        if full_text:
            base_filename = full_text[:120]
            filename = sanitize_filename(base_filename) + &quot;.txt&quot;
        else:
            filename = f&quot;tweet_{index + 1}.txt&quot;

        # Create a text file for each tweet in the twitter-likes directory
        file_path = os.path.join(output_dir, filename)
        with open(file_path, &quot;w&quot;, encoding=&quot;utf-8&quot;) as file:
            file.write(full_text + &quot;\n&quot;)  # Write full text
            file.write(expanded_url)  # Write expanded URL

    print(f&quot;Tweets have been saved to text files in the &#39;{output_dir}&#39; directory.&quot;)


# Modify path to your file
file_path = &quot;./data/like.js&quot;
save_tweets_to_files(file_path)
</code></pre><h2 id="importing-the-data">Importing the data</h2>
<p>Just import the created twitter-likes directory containing your likes as text files using <a href="https://solo.digger.lol">Digger Solo</a> and dig in! Use the powerful search to find specific tweets or use the semantic data map to freely explore all of your likes clustered by content similarity.</p>
<p class="post-hashtags"><a href="/index.html#tutorial">#tutorial</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Digital Freedom</title>
      <link>https://seanpedersen.github.io/posts/digital-freedom</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/digital-freedom</guid>
      <pubDate>Mon, 31 Mar 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>tutorial</category>
      <category>privacy</category>
      <content:encoded><![CDATA[
          <p>Digital freedom is achieved by getting rid of as many third-party controlled software as possible. A simple test to check how free you are is to unplug your computer from the internet and see how many of your favorite services still work that should not require internet (media files (images, music, videos, etc.), note taking, photo / video editing etc.).</p>
<p>Increase your freedom and <a href="/posts/google-ejector">remove the digital leeches</a> like Google and co, invest into privacy respecting software that works offline and ideally is open-source. Export your personal data from the data kraken like Google, Meta and co and delete your accounts to stop feeding these privacy invading operations. Embrace software that lets you own your data.</p>
<p>Long live the file - download your favorite music, images, blog articles and videos.</p>
<p>Tools to download files:</p>
<ul>
<li><a href="/posts/ipfs">InterPlanetary File System</a></li>
<li><a href="https://github.com/spotDL/spotify-downloader">Download Spotify content</a></li>
<li><a href="https://github.com/ytdl-org/youtube-dl">Download Youtube Videos</a></li>
<li><a href="https://github.com/gildas-lormeau/SingleFile">Download web pages as single files</a></li>
<li><a href="https://github.com/SeanPedersen/social-media-downloader">Download social media content (Twitter, Reddit, Instagram)</a></li>
</ul>
<p>Mobile Apps to view / play files:</p>
<ul>
<li><a href="https://www.foobar2000.org/">foobar2000</a>: music player</li>
</ul>
<p class="post-hashtags"><a href="/index.html#tutorial">#tutorial</a> <a href="/index.html#privacy">#privacy</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Launching Digger Solo</title>
      <link>https://seanpedersen.github.io/posts/launching-digger-solo</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/launching-digger-solo</guid>
      <pubDate>Mon, 24 Mar 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>launch</category>
      <content:encoded><![CDATA[
          <p><a href="https://digger.so/o">Digger Solo</a> is an AI file explorer. The core features are the intuitive file search, file exploration using semantic maps and LLM RAG chat interface.</p>
<h2 id="file-search">File Search</h2>
<p>The file search works by combining full text search capabilities with semantic search allowing to search for content of text and images by their meaning (even if the image has no descriptive file name).</p>
<p>A multitude of file types are supported:</p>
<ul>
<li>Text: pdf, docx, md, txt, pptx, csv, etc.</li>
<li>Images: psd, jpg, png, webp, heic, etc.</li>
<li>Videos: mp4, mov, webm, etc.</li>
<li>Audio: only file name search enabled (for now)</li>
</ul>
<h2 id="semantic-maps">Semantic Maps</h2>
<p>Explore hidden connections and patterns in your file collections (text, image, video &amp; audio supported) with semantic maps (which translate semantic similarity into spatial proximity).</p>
<p><img src="/images/digger-solo-images.png" alt="semantic map of image files"></p>
<h2 id="llm-with-rag">LLM with RAG</h2>
<p>Chat with your documents (including PDF&#39;s) by adding an OpenAI protocol based LLM provider in the settings (if you are not self-hosting the LLM, your privacy is at risk using this feature as content of files are sent to the LLM provider).</p>
<h2 id="privacy">Privacy</h2>
<p>Your files never leave your computer. All processing happens locally. No usage data is collected. Privacy is a feature not just a promise.</p>
<h2 id="use-cases">Use Cases</h2>
<ul>
<li>Organize huge photo / e-book / paper / music / sample collections automatically using semantic maps</li>
<li>Remove (near) duplicate files easily</li>
<li>Find specific objects in images using semantic search</li>
</ul>
<p class="post-hashtags"><a href="/index.html#launch">#launch</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Information, Knowledge &amp; Self-Awareness</title>
      <link>https://seanpedersen.github.io/posts/information-knowledge-self-awareness</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/information-knowledge-self-awareness</guid>
      <pubDate>Thu, 06 Feb 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>Humans aquire vast amounts of information. Some information are hard facts, while other is meta-information aka knowledge: Information describing itself how to infer new information from existing information atoms (facts).</p>
<h2 id="self-awareness">Self-awareness</h2>
<p>How are humans reliably aware of their own limits of knowledge? I argue by being aware of their learned hard facts and the domains of their learned knowledge. Knowledge has input and output domains that describe the information it can process and output.</p>
<p>A simple example:<br>By knowing 1x1 ... 10x10 we can infer the products of 11x11 ... 20x20 etc. using the knowledge of multiplication.</p>
<p>We do not need to execute the multiplication to know that we can infer the information from our existing information base.</p>
<h2 id="hallucinations-in-language-models">Hallucinations in Language Models</h2>
<p>Language models just brabble (aka detect complex statistical patterns) without reflection based on their training data. They do not know what they know, can know or can not know.</p>
<p>They would need a large database of hard facts with sources to be able to self-check. Storing billions of facts in weight matrices seems inefficient in many ways (hard to update, prone to errors and hard to inspect).</p>
<p>And a knowledge base that describes how to infer new information from existing hard facts is needed. This could allow them to self-reflect and detect hallucinations (limits of their knowledge) reliably.</p>
<p>The language model would then only need a general understanding of language and logic and the ability to retrieve information from its data and knowledge base.</p>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a> <a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Semantic Complexity Gap</title>
      <link>https://seanpedersen.github.io/posts/semantic-complexity-gap</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/semantic-complexity-gap</guid>
      <pubDate>Tue, 28 Jan 2025 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>Recently I came across an interesting phenomenon concerning the CLIP text encoder embedding space: I have discovered yet another gap in the CLIP embedding space - the semantic complexity gap. I played around with embeddings of words and sentences when I noticed an interesting pattern: atomic words occupy the same cluster with single-concept sentences while multi-concept sentences form a distinct cluster.</p>
<h2 id="single-vs-multi-concept-sentences">Single- vs Multi-Concept Sentences</h2>
<p>By single-concept sentences I mean sentences that bring together related concepts that have been likely in the training data. By multi-concept sentences I mean sentences that unify unrelated concepts that are unlikely in the training data.</p>
<p>A list of single-concept sentences:</p>
<ul>
<li>Love and friendship go hand in hand just like best friends.</li>
<li>The sun sets beautifully over the ocean, creating a perfect end to the day.</li>
<li>Music and art often inspire each other, leading to creative masterpieces.</li>
<li>Cooking is an art that brings people together around the dinner table.</li>
</ul>
<p>A list of multi-concept sentences:</p>
<ul>
<li>The cat danced with the moon while eating chocolate.</li>
<li>A guitar floated across the ocean, singing about a dragon.</li>
<li>The computer played a symphony for a mountain of pizza.</li>
<li>A sunflower rode a bicycle through a jungle of clouds.</li>
</ul>
<h2 id="experimental-setup">Experimental Setup</h2>
<ul>
<li>Embed 10,000 most common English words (atomic concepts)</li>
<li>Embed curated list of multi-concept sentences (unrelated concepts)</li>
<li>Embed curated list of single-concept sentences (related concepts)</li>
<li>Create 2D projection of atomic words + multi-concept sentences</li>
<li>Create 2D projection of atomic words + single-concept sentences</li>
</ul>
<h3 id="2d-projection-of-atomic-words-single-concept-sentences">2D projection of Atomic words + Single-concept sentences</h3>
<p><img src="/images/words-single-concept-sentences-projection.png" alt="atomic words + single-concept sentences"></p>
<p>The single-concept sentences nicely spread out the big cluster of atomic words (occupying the same latent sub-space).</p>
<h3 id="2d-projection-of-atomic-words-multi-concept-sentences">2D projection of Atomic words + Multi-concept sentences</h3>
<p><img src="/images/words-multi-concept-sentences-projection.png" alt="atomic words + multi-concept sentences"></p>
<p>The multi-concept sentences on the other hand form a tight seperate cluster that does not spread out around the atomic words.</p>
<h2 id="how-does-this-relate-to-the-linear-hypothesis">How does this relate to the Linear Hypothesis?</h2>
<p>The distribution of the single-concept sentences is nicely explained by the linear hypothesis, which states that neural networks learn to organize semantic concepts in a way that makes them linearly separable and that meaningful semantic transformations can often be represented as linear operations in the embedding space.</p>
<p>The distribution of the multi-concept (unrelated) sentences may hint at the limits of the linear hypothesis, namely that it does not hold for out-of-distribution samples.</p>
<h2 id="show-me-the-code">Show me the code</h2>
<p>Here is my code (Jupyter Notebook): <a href="https://github.com/SeanPedersen/semantic-complexity-gap/blob/main/CLIP_Concept_Gap.ipynb">https://github.com/SeanPedersen/semantic-complexity-gap/blob/main/CLIP_Concept_Gap.ipynb</a></p>
<h2 id="open-questions">Open Questions</h2>
<ul>
<li>Is this just a random artifact or a novel phenomenon? (I did not put much time and rigor into this - so I am curious if this is reality)</li>
<li>Does this semantic complexity gap between related and unrelated concepts also occur for ImageNet classifiers (e.g. image of cat and dog vs image of cat and airplane?</li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://colah.github.io/posts/2014-07-NLP-RNNs-Representations/">https://colah.github.io/posts/2014-07-NLP-RNNs-Representations/</a></li>
<li><a href="https://www.lesswrong.com/posts/tojtPCCRpKLSHBdpn/the-strong-feature-hypothesis-could-be-wrong">https://www.lesswrong.com/posts/tojtPCCRpKLSHBdpn/the-strong-feature-hypothesis-could-be-wrong</a></li>
<li><a href="https://arxiv.org/abs/2406.01506">https://arxiv.org/abs/2406.01506</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Sparse Distributed Representations</title>
      <link>https://seanpedersen.github.io/posts/sparse-distributed-representations</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/sparse-distributed-representations</guid>
      <pubDate>Sun, 29 Dec 2024 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>Modern deep learning architectures are dominated by dense embeddings. While sparse auto-encoders have gained some attention, the field lacks a clear vision for better embedding representations. In this post, we will explore a promising alternative: Sparse Distributed Representations (SDR). This concept, popularized by Jeff Hawkins in his Hierarchical Temporal Memory (HTM) framework, draws direct inspiration from biological brains. Despite their potential advantages, SDRs have yet to gain widespread adoption in the deep learning community.</p>
<h2 id="what-are-sdr">What are SDR?</h2>
<p>SDRs are sparse, positive matrices with spatially meaningful dimensions - the nearer two dimensions (cells) are the closer the concepts (vectors) they represent are. This gives SDRs many useful properties over dense embeddings.</p>
<p>Why &quot;Distributed&quot;? The semantic meaning of a concept is distributed across the pattern of active bits.</p>
<h2 id="what-are-the-benefits-of-sdr-over-dense-embeddings">What are the benefits of SDR over dense embeddings?</h2>
<p><img src="/images/dense-vs-sdr.svg" alt="SDR vs Dense Embedding Benefits"></p>
<h3 id="enhanced-interpretability">Enhanced Interpretability</h3>
<p>SDRs can be naturally visualized as 2D images due to their matrix structure, sparsity and spatial semantics. This makes them significantly more interpretable than dense embeddings, where the relationship between dimensions is often opaque.</p>
<h3 id="encoding-semantic-complexity">Encoding Semantic Complexity</h3>
<p>A key feature of SDRs is their ability to naturally encode single-concept versus multi-concept content:</p>
<ul>
<li>Single-concept inputs (e.g., an image of a single cat or text about cats) produce spatially tightly clustered activation patterns</li>
<li>Multi-concept inputs (e.g., an image with multiple unrelated objects or text covering various topics) create more distributed activation patterns</li>
</ul>
<p>This property provides immediate insight into the semantic complexity of the input.</p>
<p>Here are the top 10 average activations for a SDR trained on CLIP embeddings of CIFAR-10 images:<br><img src="/images/cifar10-clip-som-sdr.png" alt="cifar10-clip-som-sdr"></p>
<p>And here a SDR for an image of a cat driving a car (multi-concept):<br><img src="/images/sdr-cat-car.png" alt="multi-concept-sdr-cat-car"></p>
<h3 id="encoding-abstract-language-operators">Encoding Abstract Language Operators</h3>
<p>Abstract language concepts like not X, except of X, etc. that represent semantic negations can naturally be represented by activating every dimension but that of X.</p>
<h3 id="built-in-novelty-detection">Built-in Novelty Detection</h3>
<p>When presented with inputs outside the training distribution, they tend to generate highly dispersed activation patterns - even more scattered than typical multi-concept inputs. This makes outlier detection straightforward and interpretable.</p>
<p>Here the SDR for an image of the Pyramids (out-of-distribution):<br><img src="/images/ood-outlier-pyramids-sdr.png" alt="ood-outlier-pyramids-sdr.png"></p>
<h3 id="increased-robustness">Increased Robustness</h3>
<p>SDRs demonstrate exceptional robustness to various types of noise and corruption:</p>
<ol>
<li><p><strong>Bit Flips</strong>: Since only a small percentage of bits are active (typically 2%), random bit flips are unlikely to significantly alter the semantic meaning. Even if some active bits are flipped to inactive or vice versa, the remaining active bits still preserve most of the original information.</p>
</li>
<li><p><strong>Information Degradation</strong>: SDRs maintain semantic meaning even when a significant portion of the active bits are lost. This graceful degradation is similar to how biological neural systems maintain function despite losing neurons.</p>
</li>
</ol>
<h3 id="efficient-storage-processing">Efficient Storage + Processing</h3>
<p>SDRs offer significant computational advantages due to their sparse nature.</p>
<h4 id="cheap-storage">Cheap Storage</h4>
<p>Since SDRs are typically very sparse, we can store them efficiently using sparse matrix formats: Store only indices of active bits (typically 2% of dimensions).</p>
<h4 id="fast-similarity-computation">Fast Similarity Computation</h4>
<p>Computing similarity between SDRs is extremely efficient:</p>
<p><strong>Overlap Score</strong>: Simply count shared active indices</p>
<pre><code>similarity = len(set(sdr1_active_indices).intersection(set(sdr2_active_indices)))
</code></pre><p><strong>Jaccard Similarity</strong>: Ratio of intersection to union of active bits</p>
<pre><code>intersection = len(set(sdr1).intersection(set(sdr2)))
union = len(set(sdr1).union(set(sdr2)))
similarity = intersection / union
</code></pre><h4 id="sdr-operations">SDR Operations</h4>
<p>SDRs support several efficient operations:</p>
<ol>
<li><p><strong>Union</strong>: Combining multiple SDRs</p>
<ul>
<li>Take union of active indices (bitwise OR)</li>
<li>Useful for creating composite representations</li>
<li>Maintains semantic meaning while potentially decreasing sparsity</li>
</ul>
</li>
<li><p><strong>Intersection</strong>: Finding common features</p>
<ul>
<li>Take intersection of active indices (bitwise AND)</li>
<li>Reveals shared semantic components</li>
<li>Results in sparser representation</li>
</ul>
</li>
</ol>
<h2 id="how-to-generate-sdr">How to generate SDR?</h2>
<p>Jeff Hawkins / <a href="https://www.numenta.com/">Numenta</a> has not published any open-source implementation that I am aware of.</p>
<p>I came up with this simple implementation:</p>
<ol>
<li>Start with dense embeddings from a pre-trained model</li>
<li>Train a Kohonen Map (SOM) on these embeddings</li>
<li>For each input, activate only K best-matching units to create the sparse distributed representation</li>
</ol>
<p>This approach leverages the topology-preserving properties of SOMs while enforcing sparsity through top-K selection. The resulting representations naturally exhibit the desired SDR properties.</p>
<p>Here is my code (Jupyter Notebook): <a href="https://github.com/SeanPedersen/SparseDistributedRepresentations">https://github.com/SeanPedersen/SparseDistributedRepresentations</a></p>
<p>A different implemenation I found: <a href="https://github.com/dizcza/EmbedderSDR">https://github.com/dizcza/EmbedderSDR</a></p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.cortical.io/freetools/extract-keywords/">https://www.cortical.io/freetools/extract-keywords/</a></li>
<li><a href="https://www.numenta.com/assets/pdf/biological-and-machine-intelligence/BaMI-SDR.pdf">https://www.numenta.com/assets/pdf/biological-and-machine-intelligence/BaMI-SDR.pdf</a></li>
<li><a href="https://www.numenta.com/assets/pdf/whitepapers/hierarchical-temporal-memory-cortical-learning-algorithm-0.2.1-en.pdf">https://www.numenta.com/assets/pdf/whitepapers/hierarchical-temporal-memory-cortical-learning-algorithm-0.2.1-en.pdf</a></li>
<li><a href="https://arxiv.org/abs/1503.07469">https://arxiv.org/abs/1503.07469</a></li>
<li><a href="https://arxiv.org/abs/1903.11257">https://arxiv.org/abs/1903.11257</a></li>
<li><a href="https://arxiv.org/abs/1511.08855">https://arxiv.org/abs/1511.08855</a></li>
<li><a href="https://en.wikipedia.org/wiki/Holographic_associative_memory">https://en.wikipedia.org/wiki/Holographic_associative_memory</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Structure of Neural Embeddings</title>
      <link>https://seanpedersen.github.io/posts/structure-of-neural-latent-space</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/structure-of-neural-latent-space</guid>
      <pubDate>Fri, 27 Dec 2024 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>A small collection of insights on the structure of embeddings (latent spaces) produced by deep neural networks.</p>
<p>Embeddings represent semantic relationships between objects (like words or images) as points in a vector space, where related items are positioned close together and unrelated ones far apart (relatedness is defined by the loss function).</p>
<h2 id="general-principles">General Principles</h2>
<p><strong>Manifold Hypothesis</strong>: High-dimensional data sampled from natural (real-world) processes lies on or near a low-dimensional manifold. The &quot;near&quot; matters: noise, measurement artifacts, discrete structure and multiple disconnected regions all complicate the clean manifold picture. A manifold is a space that looks like flat (Euclidean) space when zooming in on any of its points, f.e. Earth&#39;s (a 3D object) surface looks locally like flat 2D space (a manifold).</p>
<ul>
<li><a href="https://colah.github.io/posts/2014-03-NN-Manifolds-Topology/">https://colah.github.io/posts/2014-03-NN-Manifolds-Topology/</a></li>
<li><a href="https://www.quantamagazine.org/what-is-a-manifold-20251103/">What is a manifold?</a></li>
</ul>
<p><strong>Hierarchical Organization</strong>: Many deep networks show hierarchical feature organization, especially vision models: earlier layers often capture local, low-level (small context) patterns while deeper layers tend to encode more task-relevant and abstract (large context) features. In transformers this hierarchy is less clean, because attention and residual streams mix information across layers and some high-level features can appear earlier than the simple &quot;early = low-level, late = abstract&quot; story suggests.</p>
<ul>
<li><a href="https://colah.github.io/posts/2015-01-Visualizing-Representations/">https://colah.github.io/posts/2015-01-Visualizing-Representations/</a></li>
</ul>
<p><strong>Linear Representation Hypothesis</strong>: Many model-relevant features appear to be represented approximately as directions or low-dimensional subspaces in activation space, making them accessible to linear probes or activation steering. Some semantic operations then look like vector arithmetic (the classic queen ≈ king - man + woman comes from word embedding spaces). This is not guaranteed for all concepts, and linear accessibility does not by itself prove a feature is causally used by the model.</p>
<ul>
<li><a href="https://colah.github.io/posts/2014-07-NLP-RNNs-Representations/">https://colah.github.io/posts/2014-07-NLP-RNNs-Representations/</a></li>
<li><a href="https://www.lesswrong.com/posts/tojtPCCRpKLSHBdpn/the-strong-feature-hypothesis-could-be-wrong">https://www.lesswrong.com/posts/tojtPCCRpKLSHBdpn/the-strong-feature-hypothesis-could-be-wrong</a></li>
<li><a href="https://arxiv.org/abs/2406.01506">The Geometry of Categorical and Hierarchical Concepts in Large Language Models</a></li>
</ul>
<p><strong>Superposition Hypothesis</strong>: Neural nets represent more &quot;independent&quot; features than a layer has neurons (dimensions) by encoding features as directions that are not aligned with individual neuron axes. Neurons are just the coordinate basis, so one feature can spread across many neurons and one neuron can take part in many features (polysemanticity). This works because real features tend to activate sparsely, even if the underlying representation looks dense.</p>
<ul>
<li><a href="https://transformer-circuits.pub/2022/toy_model/index.html">https://transformer-circuits.pub/2022/toy_model/index.html</a></li>
</ul>
<p><strong>Entangled Representation Hypothesis</strong>: Gradient descent optimised deep neural networks tend to develop redundant and fractured features instead of unified, modular representations that can be reused and controlled separately - explaining their brittleness (like adversarial examples and hallucinations).</p>
<ul>
<li><a href="https://arxiv.org/abs/2505.11581">The Fractured Entangled Representation Hypothesis</a> argues for fractured, redundant and entangled internal representations, but its direct evidence comes from a minimal single-image-generation setup comparing SGD-trained networks with evolved ones, so it should be treated as a speculative hypothesis rather than a general result for all deep networks.</li>
<li><a href="/posts/vae#beta-vae">Beta-VAE</a> is one route toward disentangled representations, but unsupervised disentanglement is not guaranteed: Locatello et al. show it is impossible without inductive biases on both model and data (<a href="https://proceedings.mlr.press/v97/locatello19a.html">Challenging Common Assumptions in Unsupervised Disentanglement</a>).</li>
</ul>
<p><strong>Universality Hypothesis (representational convergence)</strong>: Neural circuits reappear across different models trained on similar data, and models trained on the same modality (text, images, video, etc.) often learn representation spaces with partially aligned semantic neighborhoods, even if their coordinate systems differ. There is real evidence of convergence, especially with scale and similar data/objectives. But stronger claims about identical distances, angles or a single &quot;universal&quot; manifold are rebutted: <a href="https://arxiv.org/abs/2602.14486">Revisiting the Platonic Representation Hypothesis: An Aristotelian View</a> challenges the stronger global-convergence reading of <a href="https://arxiv.org/abs/2405.07987">PRH</a>, while preserving a weaker local-neighborhood version.</p>
<ul>
<li><a href="https://blog.jxmo.io/p/there-is-only-one-model">https://blog.jxmo.io/p/there-is-only-one-model</a></li>
<li><a href="https://arxiv.org/abs/2505.12540">Harnessing the Universal Geometry of Embeddings</a></li>
<li><a href="https://arxiv.org/abs/2602.14486">Revisiting the Platonic Representation Hypothesis: An Aristotelian View</a> -&gt; disproves: <a href="https://arxiv.org/abs/2405.07987">The Platonic Representation Hypothesis</a></li>
<li><a href="https://phillipi.github.io/prh/">https://phillipi.github.io/prh/</a></li>
</ul>
<p><strong>Smoothness (Lipschitz continuity)</strong>: Small changes in inputs cause proportionally bounded changes in output (latent) space - formally, <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mo>∥</mo><mi>f</mi><mo>(</mo><msub><mi>x</mi><mn>1</mn></msub><mo>)</mo><mo>-</mo><mi>f</mi><mo>(</mo><msub><mi>x</mi><mn>2</mn></msub><mo>)</mo><mo>∥</mo><mo>≤</mo><mi>L</mi><mo>∥</mo><msub><mi>x</mi><mn>1</mn></msub><mo>-</mo><msub><mi>x</mi><mn>2</mn></msub><mo>∥</mo></math> for some constant <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>L</mi></math>. Robust models should ideally be locally stable to perturbations that preserve task-relevant semantics, while staying sensitive to small but meaningful changes (one pixel can flip a digit, one word can flip sentiment, a small molecular change can change function). A low global Lipschitz constant is not automatically desirable either, since it can reduce expressivity.</p>
<ul>
<li><a href="https://arxiv.org/abs/2302.10886v2">Some Fundamental Aspects about Lipschitz Continuity of Neural Network Functions</a></li>
</ul>
<p><strong>Adversarial Vulnerability</strong>: Carefully crafted small changes in input space can cause large shifts in embedding space and therefore also in predictions. This shows models can be highly sensitive in certain high-dimensional directions, even when the perturbation is tiny under human-perceptual metrics. Goodfellow et al. argue this comes largely from linear behavior in high-dimensional spaces rather than from chaotic nonlinear dynamics.</p>
<ul>
<li><a href="https://arxiv.org/abs/1412.6572">Explaining and Harnessing Adversarial Examples</a></li>
<li><a href="https://www.nature.com/articles/s41467-023-40499-0">Subtle adversarial image manipulations influence both human and machine perception</a></li>
</ul>
<p><strong>Neural Collapse</strong>: In supervised classification, during the terminal phase of training (often after training error is already near zero), penultimate / last-layer features for each class collapse toward their class mean. The class means and the classifier weights converge toward a symmetric simplex equiangular tight frame (ETF), and prediction starts to behave like nearest-class-center classification. Within-class variation becomes minimal compared to between-class differences, creating distinct, well-separated clusters for each class.</p>
<ul>
<li><a href="https://arxiv.org/abs/2008.08186">Prevalence of Neural Collapse during the terminal phase of deep learning training</a></li>
</ul>
<h2 id="relation-to-graphs">Relation to Graphs</h2>
<p>Any set of vectors can be viewed as a weighted graph by treating vectors as nodes and similarities/distances (f.e. cosine) as edge weights. Connecting every node to every other node gives a complete weighted graph. In practice one keeps only the K nearest neighbors, which preserves local neighborhood structure but loses global metric information.</p>
<h2 id="limits-of-dense-embeddings">Limits of Dense Embeddings</h2>
<p>Most neural network architectures process data as dense vectors, making them hard to interpret for humans.</p>
<p>A more human interpretable embedding representation would be sparse (few dimensions are active) and spatially meaningful (position of dimensions encodes information).</p>
<p>This would make them easier to interpret for humans and potentially offer some other benefits: encode single-concept objects vs multi-concept objects, encode novelty (outliers), increase robustness and reduce storage / increase efficiency. But this is another <a href="/posts/sparse-distributed-representations">blog post</a>.</p>
<h2 id="problems-with-contrastive-embeddings">Problems with Contrastive Embeddings</h2>
<p><strong>Modality Gap</strong>: Multi-modal training strategies like CLIP learn a shared comparison space, but text and image embeddings can still occupy separated regions of it while preserving cross-modal matching. This can be benign for standard image-text retrieval, but problematic for mixed-modality ranking, calibration and transfer (the gap can create intra-modal ranking bias and inter-modal fusion failures).</p>
<ul>
<li><a href="https://jina.ai/news/the-what-and-why-of-text-image-modality-gap-in-clip-models/">https://jina.ai/news/the-what-and-why-of-text-image-modality-gap-in-clip-models/</a></li>
<li><a href="/posts/closing-clip-modality-gap">Closing the CLIP Modality Gap</a></li>
<li><a href="https://arxiv.org/abs/2401.08567">Connect, Collapse, Corrupt: Learning Cross-Modal Tasks with Uni-Modal Data</a></li>
<li><a href="https://arxiv.org/abs/2507.19054">Closing the Modality Gap for Mixed Modality Search</a></li>
</ul>
<p><strong>Dimensional Collapse</strong>: A phenomenon in self-supervised representation learning (known first in non-contrastive methods, and also occurring in contrastive setups) where the learned representations span a lower-dimensional subspace than the nominal embedding dimension, effectively &quot;collapsing&quot; along certain dimensions. This results in embeddings that don&#39;t fully use the available dimensions, leading to highly correlated dimensions rather than independent features.</p>
<ul>
<li><a href="https://arxiv.org/abs/2110.09348">Understanding Dimensional Collapse in Contrastive Self-supervised Learning</a></li>
<li><a href="https://www.static.tu.berlin/fileadmin/www/10002219/132153_-_digitale_Abschlussarbeiten/Dimensional_Collapse_in_Video_Representation_Learning_Publication_Paul_Kapust.pdf">Dimensional Collapse in Video Representation Learning</a></li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://markkm.com/blog/embeddings-in-data-science/">Hyperbolic embeddings</a></li>
</ul>
<p>TODO:</p>
<ul>
<li>How do image (continuous input space) and text (discrete input space) embedding spaces differ (number of clusters, density, etc.)?</li>
<li>How sparse are dense embeddings (how much information do they lose if sparsified -&gt; compare different embeddings based on layer depth)?</li>
</ul>
<p class="post-hashtags"><a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Digital Uncertainty</title>
      <link>https://seanpedersen.github.io/posts/digital-uncertainty</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/digital-uncertainty</guid>
      <pubDate>Mon, 21 Oct 2024 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>We are entering the age of digital uncertainty. An age where any digital artifact can not be deemed to be real (grounded in reality like a photography) anymore.</p>
<p>Any attempt to build AI generated content (deep fake) detection systems is flawed, since the outputs of such a system may be used to train an even better fake data generator. This leads to an equilibrium state of digital uncertainty: nothing in the digital realm can be deemed as real anymore - only as digital. I do not care if a digital artifact is human or AI made - I only care if it is useful to me. Useful content is on point, factual and at best surprising (teaches something new).</p>
<h2 id="snake-oil-services">Snake-Oil Services</h2>
<p>Following services claim to detect AI generated content but their goal is impossible: the output signal they provide can just be used to train a better AI until we reach the equilibrium state (AI vs human made become indistuingishable).</p>
<p>Text AI Detection:</p>
<ul>
<li><a href="https://gptzero.me/">https://gptzero.me/</a></li>
<li><a href="https://gowinston.ai/ai-content-detector/">https://gowinston.ai/ai-content-detector/</a></li>
</ul>
<p>Image AI Detection:</p>
<ul>
<li><a href="https://originality.ai/">https://originality.ai/</a></li>
<li><a href="https://imgdetector.ai/">https://imgdetector.ai/</a></li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Only things we perceive in the real world ourselves, can we be sure to not be faked (for now...).</p>
<p>Will this create a new flood of skeptics and critical thinkers that are harder to manipulate with digital media? I doubt it. It is more likely that people will shift more to verified content creators they put their trust in. Which in turn allows these content creators to effortlessly spin any narrative they want using digital content (that they can arbitrarily design).</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://blog.kagi.com/slopstop">https://blog.kagi.com/slopstop</a></li>
</ul>
<p>TODO:<br>explain why AI slop != AI generated -&gt; AI can generate useful artifacts.</p>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a> <a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Launching Digger.lol</title>
      <link>https://seanpedersen.github.io/posts/launching-digger</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/launching-digger</guid>
      <pubDate>Sat, 19 Oct 2024 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>launch</category>
      <content:encoded><![CDATA[
          <p><a href="https://digger.lol/">Digger.lol</a> is a visual search &amp; exploration engine, allowing users to browse efficiently and intuitively giant pools of data.</p>
<p>The goal is to create beautiful and useful maps of interesting data, empowering the user to explore more intuitively guided by semantic similarity. No user data needs to be tracked for this to work, the data speaks for itself.</p>
<p>This roughly works by translating semantic (visual or textual) similarity into spatial proximity. Diggers major features are: semantic mapping, text search and image search. The text and image search works bidirectionally, allowing to search for images (e.g. product images) using text and for text (e.g. books) using images.</p>
<p>There is a <a href="https://digger.lol/?desktop=true">desktop version</a> and a <a href="https://grid.digger.lol/">mobile version</a>. The desktop version provides a global overview. The mobile version is more limited in the global expressivenes but visually not as overwhelming.</p>
<p>Follow Digger on <a href="https://x.com/digger_ai">X (Twitter)</a> to stay up to date on novel developments. Give it a try and dig in!</p>
<p class="post-hashtags"><a href="/index.html#launch">#launch</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>MiniBook</title>
      <link>https://seanpedersen.github.io/posts/minibook</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/minibook</guid>
      <pubDate>Fri, 04 Oct 2024 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>A tiny device that is only a few centimeters long and even shorter height. With a small scroll wheel on the top and a screen on the front. This device lets you scroll through a book, displaying only one word at a time. After a while you can cease to manually scroll and the device will keep scrolling for you (in the same speed you have). Until you hit the pause/play button and keep reading on.</p>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Interesting Mathematical Objects</title>
      <link>https://seanpedersen.github.io/posts/interesting-math-objects</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/interesting-math-objects</guid>
      <pubDate>Thu, 26 Sep 2024 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>math</category>
      <content:encoded><![CDATA[
          <p>A list of mathematical objects I find interesting. If you have access to a 3D printer, these might be worth a print or two.</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/G%C3%B6mb%C3%B6c">Gömboc</a>: <a href="https://www.thingiverse.com/thing:5173406">https://www.thingiverse.com/thing:5173406</a></li>
<li><a href="https://en.wikipedia.org/wiki/Reuleaux_triangle">Reuleaux Triangle</a>: <a href="https://www.thingiverse.com/thing:1597713">https://www.thingiverse.com/thing:1597713</a></li>
<li><a href="https://en.wikipedia.org/wiki/Sierpi%C5%84ski_triangle">Sierpinsky Pyramide</a>: <a href="https://www.thingiverse.com/thing:1356547">https://www.thingiverse.com/thing:1356547</a></li>
<li><a href="https://en.wikipedia.org/wiki/List_of_prime_knots">Knots</a>: <a href="https://www.thingiverse.com/search?q=math+knots+&amp;page=1">https://www.thingiverse.com/search?q=math+knots+&amp;page=1</a></li>
<li><a href="https://en.wikipedia.org/wiki/Oloid">Oloid</a>: <a href="https://www.thingiverse.com/thing:5414091">https://www.thingiverse.com/thing:5414091</a></li>
</ul>
<p>References:</p>
<ul>
<li><a href="https://all3dp.com/2/3d-printed-math-3d-printed-geometric-shapes/">https://all3dp.com/2/3d-printed-math-3d-printed-geometric-shapes/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#math">#math</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Formidable Projects</title>
      <link>https://seanpedersen.github.io/posts/formidable-projects</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/formidable-projects</guid>
      <pubDate>Thu, 01 Aug 2024 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>A list of causes benefitting humanity as a whole. Some call it philanthropy.</p>
<p><strong>World Peace</strong>: Connect people across politically diametrical systems. Let humans not forget that we are all human. Sponsor foreign student exchanges across politically diametrical countries. Build apps that connect humans across cultural / language barriers (using AI powered translations).</p>
<p><strong>End World Hunger</strong>: Enable economic growth in countries ridden by crisis, to facilitate stable living conditions and affordable food sources.</p>
<p><strong>Protect Nature</strong>: Fund research into clean production, energy and clean up projects. Clean the rivers and oceans, save the forests to conserve the rich bio-diversity mother earth hosts.</p>
<p><strong>Increase Economic Independence</strong>: Invest into education and self activation via start-ups.</p>
<p><strong>Protect Data Privacy</strong>: Invest into open-source projects aiming to replace privacy invading data kraken like Google, Meta and co with end-to-end encrypted, self-hostable / decentral free software.</p>
<p><strong>Helpful Free Software</strong>: Educational / health software that helps to self-diagnose or educate people for free. For example detecting potential skin cancer using computer vision on your smart phone.</p>
<p><strong>Understanding Animals</strong>: Use machine learning to understand the languages of animals with complex social behavior (whales, dolphins, etc.).</p>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Overcoming the limits of current LLM</title>
      <link>https://seanpedersen.github.io/posts/overcoming-llm-limits</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/overcoming-llm-limits</guid>
      <pubDate>Thu, 18 Jul 2024 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>Large language models (LLM) have been all the rage for quite some time now. Looking beyond the hype though, they have severe limitations: hallucinations, lack of confidence estimates and lack of citations.</p>
<p>Hallucination refers to the phenomenon where LLM generates content that sounds convincing / factual but is actually ungrounded or plain wrong.</p>
<p>A confidence estimate assigns a confidence number to a prediction and is useful to estimate factuality. Though a high confidence score for a wrong answer is worse than no confidence score to begin with… So that may be the reason I have not seen any in commercial products. Though OpenAI released this: <a href="https://openai.com/index/teaching-models-to-express-their-uncertainty-in-words/">https://openai.com/index/teaching-models-to-express-their-uncertainty-in-words/</a></p>
<p>Citations are just sources on which a text is based. This can be achieved via so-called RAG techniques (just search over a text corpus and hope to find relevant documents, which are added to the query and cited). Good examples are <a href="https://perplexity.ai">https://perplexity.ai</a> and <a href="https://github.com/stanford-oval/WikiChat">https://github.com/stanford-oval/WikiChat</a>. RAG can be useful to detect if a prompt is in or out of the language models training data distribution, possibly useful to reduce hallucinations as demonstrated in WikiChat by Stanford.</p>
<p>A better LLM chatbot would address ideally all three of these limitations. So what are possible pathways to achieve them?</p>
<p>Hallucinations are certainly the toughest nut to crack and their negative impact is basically only slightly lessened by good confidence estimates and reliable citations (sources).</p>
<p>The impact of contradictions in the training data: Current language models are incapable of &quot;self-inspection&quot; to uncover logical inconsistencies in their training data. Only in the input context window should they be able to find logical inconsistencies.</p>
<p>The first serious development that tackles some of these challenges: <a href="https://www.guidelabs.ai/post/steerling-8b-base-model-release/">Steerling 8B</a></p>
<h2 id="bootstrapping-consistent-llm">Bootstrapping consistent LLM</h2>
<p>TL;DR: Exclude contradicting training data -&gt; curate the training data using LLM&#39;s.</p>
<p>A LLM that selects its own training data to bootstrap itself: Curate a small dataset that is coherent, logical and truthful as good as possible, train the base model. Then use this base model to select or reject more training data to train on. This may alleviate inconsistencies. Researchers at MIT actually did something very similar: <a href="https://news.mit.edu/2023/large-language-models-are-biased-can-logic-help-save-them-0303">https://news.mit.edu/2023/large-language-models-are-biased-can-logic-help-save-them-0303</a> (paper: <a href="https://arxiv.org/abs/2303.05670">https://arxiv.org/abs/2303.05670</a>)</p>
<p>The consistency bootstrapping could work something like this: manually curate a high-quality (consistent) text corpus based on undisputed, well curated wikipedia articles and battle tested scientific literature. Train a base LLM on this curated training data. Use this base model to classify new text documents as consistent or inconsistent by using RAG on the curated training corpus. Gradually extend the training data with consistent text documents and finally train a big consistent LLM.</p>
<p>One could spin this idea even further and train several models with radically different world views by curating different training corpi that represent different sets of beliefs / world views.</p>
<p>I hope to see more research exploring this consistent data bootstrapping approach for LLM.</p>
<h2 id="other-hallucination-mitigation-strategies">Other Hallucination Mitigation Strategies</h2>
<p><strong>Entropy Based</strong>: Analyze the entropy (variance) of the logits. High-variance should indicate uncertainty. <a href="https://github.com/xjdr-alt/entropix">https://github.com/xjdr-alt/entropix</a></p>
<p><strong>Semantic Entropy Based</strong>: Sample multiple answers (high temperature) and estimate confidence based on the variance of the resulting answers embedding vectors.</p>
<p>-&gt; These approaches have a major flaw though (as pointed out by this HN commenter):</p>
<blockquote><p class="quote-line">..., there is a real problem with this approach that lies at the mathematical level.</p>
<p class="quote-line">For any given input text, there is a corresponding output text distribution (e.g. the probabilities of all words in a sequence which the model draws samples from).</p>
<p class="quote-line">The approach of drawing several samples and evaluating the entropy and/or disagreement between those draws is that it relies on already knowing the properties of the output distribution. It may be legitimate that one distribution is much more uniformly random than another, which has high certainty. Its not clear to me that they have demonstrated the underlying assumption.</p>
<p class="quote-line">Take for example celebrity info, &quot;What is Tom Cruise known for?&quot;. The phrases &quot;movie star&quot;, &quot;katie holmes&quot;, &quot;topgun&quot;, and &quot;scientology&quot; are all quite different in terms of their location in the word vector space, and would result in low semantic similarity, but are all accurate outputs.</p>
<p class="quote-line">On the other hand, &quot;What is Taylor Swift known for?&quot; the answers &quot;standup comedy&quot;, &quot;comedian&quot;, and &quot;comedy actress&quot; are semantically similar but represent hallucinations. Without knowing the distribution characteristics (e.g multivariate moments and estimates) we couldn&#39;t say for certain these are correct merely by their proximity in vector space.</p>
<p class="quote-line">As some have pointed out in this thread, knowing the correct distribution of word sequences for a given input sequence is the very job the LLM is solving, so there is no way of evaluating the output distribution to determine its correctness.</p>
<p class="quote-line">There are actual statistical models to evaluate the amount of uncertainty in output from ANNs (albeit a bit limited), but they are probably not feasible at the scale of LLMs. Perhaps a layer or two could be used to create a partial estimate of uncertainty (e.g. final 2 layers), but this would be a severe truncation of overall network uncertainty.</p>
<p class="quote-line">Another reason I mention this is most hallucinations I encounter are very plausible and often close to the right thing (swapping a variable name, confabulating a config key), which appear very convincing and &quot;in sample&quot;, but are actually incorrect.</p>
</blockquote><p>Quoted from HN user program_whiz - <a href="https://news.ycombinator.com/item?id=40769496">https://news.ycombinator.com/item?id=40769496</a></p>
<h2 id="self-improving-llm-via-rl">Self-Improving LLM via RL</h2>
<p>A promising &quot;self-reflection&quot; RL method for LLM&#39;s trained in verifiable domains (programming, math, etc.):</p>
<blockquote><p class="quote-line">We explore a method for improving the performance of large language models through self-reflection and reinforcement learning. By incentivizing the model to generate better self-reflections when it answers incorrectly, we demonstrate that a model&#39;s ability to solve complex, verifiable tasks can be enhanced even when generating synthetic data is infeasible and only binary feedback is available. Our framework operates in two stages: first, upon failing a given task, the model generates a self-reflective commentary analyzing its previous attempt; second, the model is given another attempt at the task with the self-reflection in context. If the subsequent attempt succeeds, the tokens generated during the self-reflection phase are rewarded. Our experimental results show substantial performance gains across a variety of model architectures, as high as 34.7% improvement at math equation writing and 18.1% improvement at function calling. Notably, smaller fine-tuned models (1.5 billion to 7 billion parameters) outperform models in the same family that are 10 times larger. Our novel paradigm is thus an exciting pathway to more useful and reliable language models that can self-improve on challenging tasks with limited external feedback.</p>
</blockquote><ul>
<li>Reflect, Retry, Reward: Self-Improving LLMs via Reinforcement Learning - <a href="https://arxiv.org/abs/2505.24726">https://arxiv.org/abs/2505.24726</a></li>
</ul>
<h2 id="llm-with-code-world-model">LLM with Code World Model</h2>
<blockquote><p class="quote-line">To improve code understanding beyond what can be learned from training on static code alone, we mid-train CWM on a large amount of observation-action trajectories from Python interpreter and agentic Docker environments, and perform extensive multi- task reasoning RL in verifiable coding, math, and multi-turn software engineering environments.</p>
</blockquote><ul>
<li><a href="https://ai.meta.com/research/publications/cwm-an-open-weights-llm-for-research-on-code-generation-with-world-models/">CWM: An Open-Weights LLM for Research on Code Generation with World Models</a></li>
</ul>
<p>&quot;Instead of doing code training by just predicting the next token in the source file, interleave that with interpreter state which also have to be predicted!&quot; - <a href="https://x.com/giffmana/status/1971507878025445653">Lucas Beyer on X</a></p>
<h2 id="importance-of-the-context-window">Importance of the Context Window</h2>
<blockquote><p class="quote-line">In &quot;The Reversal Curse&quot;, researchers at Vanderbilt, UK AISI, Apollo, NYU, Sussex, and Oxford discovered the following occurrences in a datapoint:</p>
<ul>
<li>George Washington was the First President of the United States</li>
<li>Kim Kardashian is the daughter of Kris Jenner</li>
<li>Donald Trump is the current President of the United States</li>
</ul>
<p class="quote-line">If you took these sentences, and you DELETED any occurrance from the training data... where the sentence was reversed... e.g.</p>
<ul>
<li>The First President of the United States was George Washington&quot;</li>
<li>Kris Jenner is the mother of Kim Kardashian</li>
<li>The current president of the United States is Donald Trump</li>
</ul>
<p class="quote-line">This created a problem for an LLM... because it&#39;s only sees the token frequencies in one direction (left to right).</p>
<p class="quote-line">This meant that an LLM can CORRECTLY answer prompts like:</p>
<ul>
<li>Who is George Washington?</li>
<li>Who is Kim Kardashian the daughter of?</li>
<li>What is Donald Trump&#39;s current occupation?</li>
</ul>
<p class="quote-line">But the LLM could NOT answer prompts like:</p>
<ul>
<li>Who was the first president of the United States?</li>
<li>Who is the daughter of Kris Jenner?</li>
<li>Who is the current president of the United States?</li>
</ul>
<p class="quote-line">It&#39;s a pretty crazy limitation... and its very telling about how LLMs work...</p>
<p class="quote-line">But things get really crazy when you change one more thing. If you first ask an LLM the first prompt (the one that works) and then keep that in the context window... it CAN correctly answer the second prompt!!</p>
<p class="quote-line">This describes where and how LLMs do logic.</p>
<ul>
<li>Training data -&gt; Prediction: NO LOGIC (can&#39;t even reverse a simple relation)</li>
<li>Context Window -&gt; Prediction: LOGIC (can do complex reasoning)</li>
</ul>
</blockquote><ul>
<li><a href="https://x.com/iamtrask/status/1965522412243677522">Andrew Trask on X</a></li>
</ul>
<p>This phenomenon highlights why chain of thought (CoT) and RAG / context engineering are so successful: LLM can do much more complex logical inferences from its context window than one-shotting it directly from its weights (compressed training data).</p>
<h2 id="fundamental-limits">Fundamental Limits</h2>
<p>Current LLMs face a core architectural constraint: they generate text sequentially, one token at a time. As Yann LeCun argues, this creates exponential error accumulation. Each prediction depends on all previous tokens, so early mistakes cascade through long sequences, causing models to derail from coherent long-formed reasoning (an issue well known among LLM users - some call it context rot).</p>
<p>This sequential generation prevents LLMs from forming thoughts holistically. Unlike human cognition, which manipulates abstract concepts as complete structures, models must linearize everything into word sequences. They cannot think about problems in abstract space before committing to specific text.</p>
<p>The result is a fundamental bottleneck. Tasks requiring sustained logic or complex reasoning remain difficult regardless of scale improvements (making autonomous agents doing long complex tasks a real challenge). Simply adding more parameters or training data cannot solve this architectural limitation. Transformer based LLM&#39;s will thus never overcome the hallucination problem for long-context tasks (known as context rot).</p>
<p>True progress requires a paradigm shift toward architectures that form and manipulate complete conceptual structures rather than sequential tokens. Until then, LLMs remain sophisticated stochastic pattern matchers, staying far away from reliable reasoning.</p>
<p>Geoffrey Hinton speaks of confabulations not hallucinations. He says LLMs are very human like in that aspect, as humans also constantly recall things inaccurately. I disagree: LLMs confabulate things a human expert never would. After delivering an accurate logical argument, they make up the dumbest shit - this is not human like at all.</p>
<h2 id="outlook">Outlook</h2>
<p>The endgame would be language models that actively create and verify new knowledge using it to update their world-model / weights on (capable of self-modification).</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://arxiv.org/abs/2309.12288">The Reversal Curse: LLMs trained on &quot;A is B&quot; fail to learn &quot;B is A&quot;</a></li>
<li><a href="https://arxiv.org/abs/2512.01797">H-Neurons: On the Existence, Impact, and Origin of Hallucination-Associated Neurons in LLMs</a></li>
<li>Great talk on current limits of LLM: <a href="https://www.youtube.com/watch?v=s7_NlkBwdj8">https://www.youtube.com/watch?v=s7_NlkBwdj8</a></li>
<li><a href="https://dblalock.substack.com/p/models-generating-training-data-huge">https://dblalock.substack.com/p/models-generating-training-data-huge</a></li>
<li><a href="https://news.mit.edu/2023/large-language-models-are-biased-can-logic-help-save-them-0303">https://news.mit.edu/2023/large-language-models-are-biased-can-logic-help-save-them-0303</a></li>
<li><a href="https://arxiv.org/abs/2303.05670">Logic Against Bias: Textual Entailment Mitigates Stereotypical Sentence Reasoning</a></li>
<li><a href="https://www.anthropic.com/research/mapping-mind-language-model">https://www.anthropic.com/research/mapping-mind-language-model</a></li>
<li><a href="https://bharathpbhat.github.io/2021/04/04/getting-confidence-estimates-from-neural-networks.html">https://bharathpbhat.github.io/2021/04/04/getting-confidence-estimates-from-neural-networks.html</a></li>
<li><a href="https://gist.github.com/yoavg/4e4b48afda8693bc274869c2c23cbfb2">https://gist.github.com/yoavg/4e4b48afda8693bc274869c2c23cbfb2</a></li>
<li><a href="https://blog.jxmo.io/p/we-should-stop-talking-about-agi">https://blog.jxmo.io/p/we-should-stop-talking-about-agi</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>On the Artificial Intelligence Hype</title>
      <link>https://seanpedersen.github.io/posts/on-the-ai-hype</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/on-the-ai-hype</guid>
      <pubDate>Mon, 08 Jul 2024 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>AI</category>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>The release of so-called Large Language Models by OpenAI and others has fueled another AI hype wave which fueled a fierce debate of how dangerous this technology is and how imminent Artificial General / Super Intelligence is.</p>
<p>Current LLMs will be bottlenecked by the quality of available training data. High signal text / language data is limited and will become scarcer since LLMs themselves will fuel a flood of low quality content spam (slop). So I expect a stagnation in LLM progress, since high signal data will be a problem. Compute will steadily grow (powered by Moore&#39;s law). Algorithmic advances are the greatest unknown factor.</p>
<p>LLMs lack awareness of their training data and fail to give reliable confidence estimates on their statements.</p>
<p>Multimodal models which fuse language, audio and video understanding will soon become possible with the introduction of more (cheaper) computing resources. This will open up data treasures like YouTube and TV shows and movies and co to train these new generations of large models. These generative models will shine for artistic use cases where solid facts and sound logic do not matter much. They will struggle in the hard sciences and only serve as assistents which need to be validated by humans.</p>
<p>Within the next 5 years AI generated high-quality long duration videos will become a reality and reshape our media landscape. The same is true for music within the next 2 years.</p>
<p>The next big hype cycle will be video generation and understanding, followed by embodied AI in the form of robots and smart devices that both understand natural language and their surroundings through vision. This will enable a new generation of robots that can be intuitively commanded by human voice prompts, to execute simple and repetitive tasks (factory line work, brewing coffee, cleaning your home) for which massive diverse datasets can be crowd-sourced. More complex tasks for which big datasets can not be crowd sourced will stay unreachable (build a one man submarine, build a mechanical watch).</p>
<p>Robots driven by these new large multi-modal models (embodied AI) and continuously optimized by reinforcement learning will become a reality within the next 6 years and will be mass produced within 10 years. But they will not automate all our jobs away. They will automate the boring stuff and give us hopefully more time to be human.</p>
<p>The hardest problem remains accurate, coherent (LLM&#39;s are fundamentally limited by their auto-regressive architecture giving rise to hallucinations and context rot) and self-aware reasoning which is needed to automate novel and useful research. This will likely not be solved by just more data. It will take curated high-quality data and novel algorithms that are aware of their training data and can continuously self-modify to increase the accuracy of their world model.</p>
<p>Such systems have so far been demonstrated through so called &quot;self-play&quot;. Systems like Alpha Zero were capable to simulate an endless stream of training data by simulating the games they play on a massive scale. Allowing to explore novel unseen tactics. Similar feats will be possible for verifiable domains like programming and mathematics. Accurately simulating the real world remains a hard problem (transfer from simulation to real enviroment is difficult) and it is not clear how well knowledge gained from verifiable domains like programming and mathematics will transfer into the messy real world.</p>
<p>Still this new wave of AI will enable every human to naturally interact with computers using natural language. On one side enabling them to shape digital and soon physical content on the other side lays the danger of enhanced mass surveillance and manipulation through advanced AI systems in the hands of powerful players (governments and corporations). Robots in particular will drastically change our world.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.nature.com/articles/s41586-024-07566-y">https://www.nature.com/articles/s41586-024-07566-y</a></li>
<li><a href="https://www.youtube.com/watch?v=uB9yZenVLzg">https://www.youtube.com/watch?v=uB9yZenVLzg</a></li>
<li><a href="https://blog.jxmo.io/p/superintelligence-from-first-principles">https://blog.jxmo.io/p/superintelligence-from-first-principles</a></li>
<li><a href="https://blog.jxmo.io/p/we-should-stop-talking-about-agi">https://blog.jxmo.io/p/we-should-stop-talking-about-agi</a></li>
</ul>
<p>Updated on July 25, 2024</p>
<p class="post-hashtags"><a href="/index.html#AI">#AI</a> <a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Kolmogorov Complexity</title>
      <link>https://seanpedersen.github.io/posts/kolmogorov-complexity</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/kolmogorov-complexity</guid>
      <pubDate>Tue, 04 May 2021 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <h2 id="introduction">Introduction</h2>
<p>This text is devoted to my favorite CS concept I know of (so far): Kolmogorov complexity. It is right up there with graphs, trees and recursion. Its beauty stems from its simple definition and powerful connections to many research fields I fancy.</p>
<p>And it is defined as follows:<br><code class="language-text">The length of the smallest program producing a given sequence of bits.</code></p>
<p>This might sound rather unimpressive to the uninitiated reader but hold on, behind this simple concept lies a whole world of deep implications and applications.</p>
<p>Knowing the Kolmogorov complexity of a sequence means knowing every algorithmic pattern there can be known about it. It is the process of removing all computable redundancies existing in the data, arriving at the shortest algorithm giving rise to these patterns using computation (space, time and energy).</p>
<p>So how do we compute it?</p>
<p>Sadly it is incomputable in praxis. What a bummer.</p>
<p>Computing the Kolmogorov complexity for an arbitrary sequence X of N bits length is a really tough nut to crack, since the search space of possible programs producing X is growing exponentially with respect to the input size N. And the real deal breaker: it entails the notorious halting problem, which is incomputable. The most obvious upper bound for K(X) is obviously the length N of X itself.</p>
<p>We can still implement a program that generates 2^N different programs and filter out all invalid programs for the chosen programming language. We are left with an enormous list of valid programs with a length below N.</p>
<p>Sadly we can not just execute this at least finite amount of programs, filter their outputs for the given sequence and be done by sorting the valid leftover programs by length. Some programs will take ages to terminate and some may even never - we could analyze this finite set of programs using formal verification techniques to determine if each programs halts or not but this endeavor would be impractical since the set grows exponentially.</p>
<p>(Previously I wrote: &quot;and we can not tell them apart, as Alan Turing proved with his infamous halting problem&quot; -&gt; which is wrong! Turing proved that there exists no algorithm that can determine if an <strong>arbitrary</strong> program halts or not. While the halting problem is undecidable in general, for a small, fixed set of programs, we can manually prove (or disprove) halting using mathematical reasoning or formal methods. However, this requires a separate proof per program and the number of programs up to length n grows as ~2^N - making it impractical beyond toy sizes (N ≲ 15). For real approximation, we must use timeouts.)</p>
<h2 id="kolmogorov-complexity-extensions">Kolmogorov complexity extensions</h2>
<p>Kolmogorov complexity alone is simple and beautiful but as we learned it is not practical to compute. So let us try extending it by some practical properties of computer programs like their total execution time and maximum allocated space (e.g. RAM). This yields closely related complexity measures that should be easier to approximate and thus be more relevant for practical applications since we finally can compute them.</p>
<p>Notation:</p>
<ul>
<li><strong>x</strong>: Input sequence</li>
<li><strong>L(x)</strong>: Length of x</li>
<li><strong>P(x)</strong>: Set of all programs computing x</li>
<li><strong>p</strong>: Element of P(x) (a single program)</li>
<li><strong>L(p)</strong>: Length of p</li>
<li><strong>T(p)</strong>: Total execution time of p</li>
<li><strong>S(p)</strong>: Maximum size of allocated space used by p</li>
</ul>
<p>Complexity Measures:</p>
<ul>
<li><code class="language-text">K(x) = min(L(p) for every p of P(x))</code></li>
<li><code class="language-text">KT(x) = min(L(p) * T(p) for every p of P(x))</code></li>
<li><code class="language-text">KTS(x) = min(L(p) * T(p) * S(p) for every p of P(x))</code></li>
</ul>
<p>K(x) is the normal Kolmogorov complexity function. KT(x) is an extension that weights the programs execution time into the measure. KTS(x) also considers the space requirements of the program.</p>
<p>Ok what now? Let’s do what computer scientists like to do and cheat our way out using the power of good enough heuristics / approximations. One easy way to deal with programs that run too long or even infinitely is to discard them after exactly 42 seconds.</p>
<p>This seemingly dirty trick is actually quite useful, it filters out programs that run too long. By doing so we lose the guarantee to find the true Kolmogorov complexity, since a really short program might execute very long until it finally outputs X (the input sequence). Sidenote: There is a paper and it also makes intuitive sense that the source length of a program correlates positively with its execution time which helps us a lot. So we lose the guarantee to find true K(X) but are still left with short (not necessarily shortest anymore!) programs that execute in our desired maximum time of 42 seconds.</p>
<p>Another nice fact is that lazily searching for the shortest programs is still optimal (within our approximating limits) since we are done when we find the first (thus shortest) program producing the input sequence X within our time limit, unless we want to continue searching for a potentially faster program (although it becomes less likely to find faster executing programs as their size grows).</p>
<p>So have I just described a computable version of K(X)? No but a practical approximation. We search for the shortest program K(X, T=&lt;42) that produces X within a predefined time / computational resource limit. Start with the shortest program and complexify it iteratively spanning a tree of all possible programs. Programs that do not halt or simply execute too long are simply discarded which is nice since we want efficient programs anyway.</p>
<h2 id="computing-data-complexities-in-the-wild">Computing data complexities in the wild</h2>
<p>Common lossless data compression tools like ZIP are only approximations of the true Kolmogorov complexity for their inputs. The length of the compressed data plus the length of the program decompressing the data is an upper bound of the true Kolmogorov complexity.</p>
<p>“Kolmogorov complexity is incomputable: there exists no algorithm that, when input an arbitrary sequence of data, outputs the shortest program that produces the data.” - Wikipedia</p>
<h2 id="applications-of-kolmogorov-complexity-approximations">Applications of Kolmogorov complexity approximations</h2>
<p>Compression Distance (CD) takes two objects A,B (e.g. text files) as arguments and defines a similarity score by using kolmogorov complexity or in praxis an approximation (e.g. compression algorithms) c(X) on A, B and both concatenated A+B. CD is then defined as:<br><code class="language-text">CD(A,B) = len(c(A+B)) / ( len(c(A)) + len(c(B)) )</code></p>
<p>If A &amp; B are very similar c(A+B) will not be much larger than either c(A) or c(B) producing a small CD(A,B), vice versa if A &amp; B are dissimilar c(A+B) will be much larger than c(A) or c(B) producing a big CD(A,B).</p>
<p>TODO:</p>
<ul>
<li><a href="https://www.lesswrong.com/tag/solomonoff-induction">Solomonoff Induction</a> and <a href="https://www.lesswrong.com/tag/aixi">AIXI</a>: Kolmogorov Complexity as Occam&#39;s razor for AGI</li>
<li><a href="http://prize.hutter1.net/">Hutter Prize</a>: Compression (prediction) as key ingredient to AGI</li>
<li>Kolmogorov complexity for physical objects: shortest transformation of matter to arrive at an object (matter configuration). K(chess piece knight) &gt; K(chess piece bishop) -&gt; since bishop is rotational symmetric it is easier to produce</li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Why I won&#39;t graduate</title>
      <link>https://seanpedersen.github.io/posts/why-i-will-not-finish-my-degree</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/why-i-will-not-finish-my-degree</guid>
      <pubDate>Thu, 14 Jan 2021 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Every single time I mention in a conversation that I am actually not interested in finishing my CS degree, every person is kind of flabbergasted and tries to convince me to finish it for my own good. This is to y&#39;all. I fully understand that you trying to convince me to invest into a degree awarded by a university which promises a safe future, is only with good intentions. But I respectfully decline your advice and take the opposite stance that it is my duty to not devote my time for years to staged academic exercises but instead work on real problems. From my privileged position as a citizen of the EU I am safe, even without a degree. So I may take this &quot;risky&quot; move and skip the graduation.</p>
<p>And to be totally frank: I could not give less of a shit for a piece of paper that acts as a signal to other people that I am a smart / hard working / qualified individual that is good to hire / work with.</p>
<p>I am not interested in working with you if you actually judge me by being in possession of such a &quot;special&quot; piece of paper (that you can obtain in many dubious ways). So in my opinion it is even advantageous to me if people do not want to work with me because I have no degree, since it prevents superficial people from entering my life.</p>
<p>I judge people by their and myself want to be judged by my <strong>personality</strong>: which is something mysterious related to the mindsetting, morals, how you treat others and expect yourself to be treated, your past accomplishments and failures and what you learned from them. The only thing that matters from academic education is what you learned along the way and the people you meet. The rest is superficial crap that I don&#39;t need. I am not saying my way is the way for everyone but I choose it consciously and own it.</p>
<p>About the CS degree itself:<br>The knowledge / curriculum is full of gems: Trees, Graphs, Algorithmic Complexity and Artificial Intelligence to name a few that stood out to me. I have studied the theory of them in depth. It is just that the way how the knowledge is often transferred and especially how it is examined and marked is sadly too often not goal orientated. I am happy that I spent a lot of time on my CS education in university, I just see no point in &quot;finishing&quot; it (getting the &quot;special&quot; graduation paper). I encourage anyone reading this to develop their own style of learning and advise strongly against overfitting academic exams. Your time is better spent studying deep theory, get confused, ask hard questions, find easy but often surprising answers and most importantly: apply the theory - build it.</p>
<p>References:</p>
<ul>
<li><a href="https://colah.github.io/posts/2020-05-University/">https://colah.github.io/posts/2020-05-University/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>The world needs more #DEEFOSS</title>
      <link>https://seanpedersen.github.io/posts/the-world-needs-more-DEEFOSS</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/the-world-needs-more-DEEFOSS</guid>
      <pubDate>Mon, 11 Jan 2021 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <category>privacy</category>
      <content:encoded><![CDATA[
          <p>It is no secret that the idea of an open, free and accessible word wide web is just that: an idea. The WWW is dominated by a few big corporations that dominate search and social media. They control and monitor what you see, who you talk to, your emotions, political views, the list is too long to continue. But the trend is easy to recognize: Total control over all your personal online and to some extent even offline activities.</p>
<p>This needs to stop. Before anyone has to ask why, here are a few good reasons:</p>
<ul>
<li><strong>Centralization</strong>: Promotes abuse of power for those in control right now or in the future</li>
<li><strong>Unencrypted personal data</strong>: Asks to be under mass surveillance</li>
<li><strong>Proprietary, Closed Source Software</strong>: Can do bad stuff without anyone realizing</li>
</ul>
<p>So what is the way forward? Just start to build, use, praise, promote, contribute and sponsor more Decentralized, End-to-End Encrypted, Free Open Source Software (DEEFOSS). Humanity will be thankful or at least I will.</p>
<p>What do I consider as DEEFOSS? Good question, glad you asked.</p>
<ul>
<li><strong>Decentralized</strong>: Anyone can run the software independently of any central authority.</li>
<li><strong>End-to-End Encrypted</strong>: User data is only decrypted if absolutely necessary and if so in a transparent way.</li>
<li><strong>Free Open Source Software</strong>: Source code is publicly available under a license allowing anyone to copy and modify it free of any charge.</li>
</ul>
<p>Some examples of DEEFOSS are (in no particular order):</p>
<ul>
<li><a href="https://matrix.org/">Matrix</a> (<a href="https://github.com/matrix-org/synapse">Code</a>) - end-to-end encrypted, decentralized chat protocol</li>
<li><a href="https://cryptpad.fr/">Cryptpad</a> (<a href="https://github.com/xwiki-labs/cryptpad">Code</a>) - end-to-end encrypted, real-time collaborative editing of documents</li>
<li><a href="https://scuttlebutt.nz/">Scuttlebutt</a> (<a href="https://github.com/ssbc/ssb-server">Code</a>) - decentralized social network</li>
<li><a href="https://ipfs.io/">IPFS</a> (<a href="https://github.com/ipfs/go-ipfs">Code</a>) - decentralized alternative to HTTP(S)</li>
<li><a href="https://bitchat.free/">BitChat</a> - decentralized chat app via bluetooth</li>
</ul>
<p>So go ahead and build a future with more #DEEFOSS. Thank you.</p>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a> <a href="/index.html#privacy">#privacy</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>HyperTag: File Organization made for Humans</title>
      <link>https://seanpedersen.github.io/posts/hypertag-file-organization-made-for-humans</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/hypertag-file-organization-made-for-humans</guid>
      <pubDate>Sun, 10 Jan 2021 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p><a href="https://github.com/Ravn-Tech/HyperTag">HyperTag</a> let&#39;s humans intuitively express how they think about their files using tags and the power of modern machine learning. Instead of introducing proprietary file formats like other existing file organization solutions, HyperTag just layers on top of your existing files without any fuss.</p>
<p>HyperTag is built around one simple goal: <strong>Minimize the time between a thought and access to all relevant files.</strong></p>
<h2 id="feature-overview">Feature Overview</h2>
<p>HyperTag offers many unique features that help it achieve its overall goal. It comes with a slick CLI but more importantly it creates a directory called <code class="language-text">HyperTagFS</code> which is a file system based representation of your files and tags using symbolic links and directories. <code class="language-text">HyperTagFS</code> also allows you to create queries and searches by creating directories, more about that later.</p>
<h3 id="directory-import">Directory Import</h3>
<p>A very useful feature, allowing to import your existing directory hierarchies using <code class="language-text">$ hypertag import path/to/directory</code>. HyperTag converts it automatically into a tag hierarchy using metatagging.</p>
<p><strong>Example Directory Hierarchy:</strong></p>
<ul>
<li>Documents<ul>
<li>Research<ul>
<li>Banana Farming<ul>
<li>Files: BananaBible.pdf, BananaFarmingForDummies.epub</li>
</ul>
</li>
<li>Machine Learning<ul>
<li>Files: DeepLearning.pdf</li>
</ul>
</li>
</ul>
</li>
<li>eBooks<ul>
<li>Chess<ul>
<li>Files: ChessForDummies.pdf</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Import: <code class="language-text">$ hypertag import path/to/Documents</code></p>
<p><strong>Resulting MetaTag hierarchy:</strong><br><br>BananaBible.pdf and BananaFarmingForDummies.epub are tagged with <code class="language-text">Research &gt; &quot;Banana Farming&quot;</code>. DeepLearning.pdf is tagged with <code class="language-text">Research &gt; &quot;Machine Learning&quot;</code>. And ChessForDummies.pdf with <code class="language-text">eBooks &gt; Chess</code>.</p>
<h3 id="fuzzy-matching-tag-queries">Fuzzy Matching Tag Queries</h3>
<p>HyperTag uses fuzzy matching to minimize friction in the unlikely case of a typo. You can find your freshly imported files using queries based on set theory:</p>
<ul>
<li><code class="language-text">$ hypertag query Reserch and &quot;Mchine Learning&quot;</code> prints: DeepLearning.pdf</li>
<li><code class="language-text">$ hypertag query Ches or &quot;Bana Farmin&quot;</code> prints: ChessForDummies.pdf, BananaBible.pdf, BananaFarmingForDummies.epub</li>
<li><code class="language-text">$ hypertag query Rsearch minus &quot;Banna Farmng&quot;</code> prints: DeepLearning.pdf</li>
</ul>
<h3 id="semantic-text-image-search">Semantic Text &amp; Image Search</h3>
<p>HyperTag uses the latest research advances from Machine Learning for vision and text to provide easy access to all your files: Search for <strong>images</strong> (jpg, png) and <strong>text documents</strong> (yes, even PDF&#39;s) content with a simple text query. Text search is powered by the awesome <a href="https://github.com/UKPLab/sentence-transformers">Sentence Transformers</a> library. Text to image search is powered by OpenAI&#39;s <a href="https://openai.com/blog/clip/">CLIP model</a>. Currently only English queries are supported.</p>
<p><strong>Semantic search for text files</strong><br><br>Print text file names sorted by matching score.<br>Performance benefits greatly from running the HyperTag daemon.<br><br>Shortcut: <code class="language-text">$ hypertag s</code></p>
<p><code class="language-text">$ hypertag search &quot;your important text query&quot; --path --score --top_k=10</code></p>
<p><strong>Semantic search for image files</strong><br><br>Print image file names sorted by matching score.<br>Performance benefits greatly from running the HyperTag daemon.<br><br>Shortcut: <code class="language-text">$ hypertag si</code></p>
<p>Text to image:<br><code class="language-text">$ hypertag search_image &quot;your image content description&quot; --path --score --top_k=10</code></p>
<p>Image to image:<br><code class="language-text">$ hypertag search_image &quot;path/to/image.jpg&quot; --path --score --top_k=10</code></p>
<h3 id="hypertag-daemon">HyperTag Daemon</h3>
<p>The HyperTag Daemon is a process you may want to add as an auto starting service as it makes your HyperTag experience at least 3x better. How? It provides not one but three awesome features you do not want to miss out:</p>
<ul>
<li>Watches <code class="language-text">HyperTagFS</code> directory for user changes:<ul>
<li>Maps file (symlink) and directory deletions into tag / metatag removal/s</li>
<li>On directory creation: Interprets name as set theory tag query and automatically populates it with results</li>
<li>On directory creation in <code class="language-text">Search Images</code> or <code class="language-text">Search Texts</code>: Interprets name as semantic search query (add top_k=42 to limit result size) and automatically populates it with results</li>
</ul>
</li>
<li>Watches directories on the auto import list for user changes:<ul>
<li>Maps file changes (moves &amp; renames) to DB</li>
<li>On file creation: Adds new file/s with inferred tag/s</li>
</ul>
</li>
<li>Spawns DaemonService to load and expose models used for semantic search, speeding it up significantly</li>
</ul>
<h3 id="file-type-groups">File Type Groups</h3>
<p>A small but convenient feature: HyperTag automatically creates folders containing common files (e.g. Images: jpg, png, etc., Documents: txt, pdf, etc., Source Code: py, js, etc.), which can be found in <code class="language-text">HyperTagFS</code>.</p>
<h3 id="hypertag-graph">HyperTag Graph</h3>
<p>Another small but very useful feature: Quickly get an overview of your HyperTag Graph! HyperTag visualizes the metatag graph on every change and saves it at <code class="language-text">HyperTagFS/hypertag-graph.pdf</code>.</p>
<p><img src="https://raw.githubusercontent.com/SeanPedersen/HyperTag/master/images/hypertag-graph.jpg" alt="HyperTag Graph Example"></p>
<h2 id="architecture">Architecture</h2>
<ul>
<li>Python and it&#39;s vibrant open-source community power HyperTag</li>
<li>Many other awesome open-source projects make HyperTag possible (listed in <code class="language-text">pyproject.toml</code>)</li>
<li>SQLite3 serves as the meta data storage engine (located at <code class="language-text">~/.config/hypertag/hypertag.db</code>)</li>
<li>Symbolic links and directories are used to represent your files and tags in the <code class="language-text">HyperTagFS</code> directory</li>
<li>Semantic text search is powered by the awesome <a href="https://arxiv.org/abs/1910.01108">DistilBERT</a></li>
<li>Text to image search is powered by OpenAI&#39;s impressive <a href="https://openai.com/blog/clip/">CLIP model</a></li>
</ul>
<h2 id="inspiration">Inspiration</h2>
<p>I have wanted to use and also build a tagging based file organizer for a long time. In the beginning of 2021 I finally came around to do so. After evaluating existing options, I concluded none of them really satisfied my requirements. So I built HyperTag. Using Python the first prototype was working after only 4 hours of coding. 7 days later and HyperTag provides a rich set of features that help it achieve the goal I set out for it: Minimize the time between a thought and access to all relevant files. I hope others will find use for it as well and maybe even contribute back to it. I am certainly excited for the future of HyperTag and hope you are by now too.</p>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>The Future of Programming</title>
      <link>https://seanpedersen.github.io/posts/future-of-programming</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/future-of-programming</guid>
      <pubDate>Tue, 29 Dec 2020 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>coding</category>
      <content:encoded><![CDATA[
          <p>I want to briefly introduce you into what I believe to be the future of programming.</p>
<p>The current state of programming is in my opinion best described as a big rapidly evolving cluster fuck of programming languages and frameworks. What is needed is a way to reduce the cluster fuck without compromising on the ongoing forces of innovation.</p>
<p>Content addressable code is the first concept I want to highlight. It is awesome and long overdue in language design. It works by identifying code module versions not by name + version number or another URL but instead uses a hash of the code it self (potentially using a Merkle Tree). This brings plenty of advantages: no more build and dependency conflicts, easy code version caching and allows to verify code authenticity on your machine (just compute the hash).</p>
<p>So why stop with content addressable code? I not only want to know if two functions are syntactically equivalent (content based) but I also want to know if they share the same behavior. Two functions share the same behavior if and only if they map the same inputs to the same outputs. In praxis it is often not feasible to test that for all possible inputs and outputs due to time constraints we mere human mortals have. But we can still get use out of this behavior addressable concept by using predefined test cases that capture essential and edge cases as well as some automated fuzzing of possible inputs. When behavior based addressing is working, the next and final level is adding automated run time and space usage analysis for equivalently behaving functions to the landscape of programming language infrastructure. This will allow developers to find quickly the most efficient code available to mankind for their desired code behavior (function). This is the future of programming and will greatly accelerate technological progress of humanity in all areas involving software.</p>
<h2 id="a-practical-example">A practical Example</h2>
<p>Sorting a list of integers is a canonical function that probably has been implemented millions of times in thousands of programming languages.</p>
<p>So how would I go about finding the best implementation in existing language eco systems? First I would use the built in sorting implementation and hope the language designers put some work in to make it fast. But I am unsure about that, so I start benchmarking the code. I have a feeling there is room to improve. I start researching alternative implementations and run further my own benchmarks. Finally I find an implementation that consistently is faster for my use cases. I add the code as a dependency and if I have a great day, I might even write some unit tests to make sure it will keep doing what it is supposed to do, even when upgrading the code in the future. Cool that works and is probably done by many folks repeatedly in the same eco system (wasting humanities time).</p>
<p>But there are many points we can do better using behavior addressable code modules. Think about it. We need one individual that feels our new shiny language eco system has the need for a function that sorts a list of integers. That individual needs to sit down and define an interface describing the input and output domains of the function. For a simple sorting function, it would look something like: sort(List&lt;Integer&gt;) -&gt; List&lt;Integer&gt;. Pretty simple stuff. Next the individual would define some hard test cases that verify the desired behavior of the function: assert(sort([2,3,1] == [1,2,3]), and so on. Now that the function interface and behavior via test cases is nailed down, anyone can start implementing and submitting functions to it. On submission of a new function, the following happens: First the function is verified to implement the specified interface, second its behavior is verified using the existing test cases, third its code is hashed to make it content addressable and finally its run time and memory profile is measured. And all of that happens automatically.</p>
<p>Now imagine yourself again needing the best available sorting function for your project. What changed? A whole lot. Now you can search an existing code module index for the function you need (sorting integers). Then you will be presented with all of the existing functions implementing your desired behavior, verified for correctness and benchmarked for run time and memory usage. You will quickly find the sweet spot implementation that ticks off all your needs (fastest / lowest memory usage peak) and import it using its content addressable hash. Life can be so easy after all.</p>
<p>I would love to see this being worked on and challenge any reader to build a prototype and share it with the world. Existing language eco systems that would benefit greatly in my opinion (in no particular order) are:</p>
<ul>
<li>Python (PyPI)</li>
<li>Javascript (npm)</li>
<li>Rust (cargo)</li>
<li>Elixir (hex)</li>
</ul>
<p>Update 2024: There seems to be a content addressable language on the block (<a href="https://scrapscript.org/">https://scrapscript.org/</a>)</p>
<p>Update 2025:</p>
<ul>
<li>Basically any function in your codebase could be analysed by its input and output domains (types + mapping / behavior) and be replaced if a functionally equivalent but faster functions exists in the global code module index</li>
<li>LLM&#39;s could be used to automatically search for optimized functions based on their behavior</li>
<li>LLM&#39;s could also be used to generate context aware test cases, that minimize fuzzing (brute force testing) by focusing on edge cases (which generalize)</li>
</ul>
<p>TODO:</p>
<ul>
<li>check out related concept of &quot;reproducible builds&quot;</li>
</ul>
<h2 id="references">References</h2>
<ul>
<li>Content addressable code (<a href="https://www.unisonweb.org/docs/tour">https://www.unisonweb.org/docs/tour</a>)</li>
<li>Why do we need modules at all? (<a href="https://erlang.org/pipermail/erlang-questions/2011-May/058768.html">https://erlang.org/pipermail/erlang-questions/2011-May/058768.html</a>)</li>
<li>Hyper Modular Programming System (<a href="https://github.com/jbenet/random-ideas/issues/27">https://github.com/jbenet/random-ideas/issues/27</a>)</li>
</ul>
<p class="post-hashtags"><a href="/index.html#coding">#coding</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Google &amp; Co Ejector</title>
      <link>https://seanpedersen.github.io/posts/google-ejector</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/google-ejector</guid>
      <pubDate>Mon, 07 Dec 2020 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>tutorial</category>
      <category>privacy</category>
      <content:encoded><![CDATA[
          <p>Is closed source, centralized, privacy invading software still part of your digital life? Eject now and start using user privacy respecting software. This is a small curated collection of awesome FOSS and privacy respecting services, capable of replacing many popular, centralized, privacy invading software services so you can sleep better at night. Stop feeding giant invasive data kraken like Google and Meta - export your data and delete your accounts to stop feeding them your personal data.</p>
<h2 id="awesome-software">Awesome Software</h2>
<p>Software that treats you as a human - respectful.</p>
<p>Messenger:</p>
<ul>
<li><a href="https://signal.org/">Signal</a> - Privacy focused messenger</li>
<li><a href="https://matrix.org/">Matrix</a> - end-to-end encrypted, federated, self-hostable<ul>
<li><a href="https://matrix.org/ecosystem/clients/">Clients</a>: Mobile (Element X), Desktop (Cinny, Nheko)</li>
<li><a href="https://github.com/matrix-construct/tuwunel">Server</a> - Rust</li>
<li><a href="https://codeberg.org/imbev/simplematrixbotlib">Bot SDK</a> - Python</li>
</ul>
</li>
<li><a href="https://bitchat.free/">BitChat</a> - decentralized chat app via bluetooth</li>
<li><a href="https://www.messenger-matrix.de/messenger-matrix.html">Messenger Comparison</a></li>
</ul>
<p>Web Browser:</p>
<p>Firefox, Brave etc. also track their users (with default settings). Test <a href="https://coveryourtracks.eff.org/">here</a> how trackable your browser is.</p>
<ul>
<li><a href="https://mullvad.net/en/browser">Mullvad</a> - Privacy focused Firefox fork (basically Tor browser without Tor network)</li>
<li><a href="https://librewolf.net/">LibreWolf</a> - Privacy focused Firefox fork</li>
<li><a href="https://github.com/ungoogled-software/ungoogled-chromium">Ungoogled Chromium</a> - Chromium without Google Services (spy ware)</li>
<li><a href="https://digdeeper.club/articles/browsers.xhtml#fullsummary">Browser Comparison</a></li>
</ul>
<p>Search Engine:</p>
<ul>
<li><a href="https://searx.si/">SearX</a> (<a href="https://github.com/searxng/searxng">Code</a>) - Privacy-respecting metasearch engine, self-hostable</li>
<li><a href="https://digger.so/">Digger</a> - Privacy focused search engine</li>
<li><a href="https://www.startpage.com/">StartPage</a> - Privacy focused search engine</li>
<li><a href="https://digdeeper.club/articles/search.xhtml#summary">Search Engine Comparison</a></li>
</ul>
<p>E-Mail Provider:</p>
<ul>
<li><a href="https://proton.me/mail">Protonmail</a> - privacy focused</li>
<li><a href="https://tuta.com/">TutaMail</a> - privacy focused</li>
<li><a href="https://digdeeper.club/articles/email.xhtml#Summary">E-Mail Comparison</a></li>
</ul>
<p>Global Maps:</p>
<ul>
<li><a href="https://www.openstreetmap.org/">OpenStreetMap</a> - open data, privacy focused</li>
</ul>
<p>ChatBot:</p>
<ul>
<li><a href="/posts/local-ai-chat-apps">Local LLM Apps</a></li>
<li><a href="https://github.com/ItzCrazyKns/Perplexica">Perplexica</a> - Open source answer engine</li>
<li><a href="https://github.com/miurla/morphic">Morphic</a> - Open source answer engine</li>
</ul>
<p>Shared Docs:</p>
<ul>
<li><a href="https://docs.fileverse.io/">Fileverse</a> (<a href="https://github.com/fileverse/fileverse-ddoc">Code</a>) - end-to-end encrypted, real-time collaborative editing, self-hostable</li>
<li><a href="https://cryptpad.fr/">Cryptpad</a> (<a href="https://github.com/xwiki-labs/cryptpad">Code</a>) - end-to-end encrypted, real-time collaborative editing, self-hostable</li>
</ul>
<p>File Sync:</p>
<ul>
<li><a href="https://syncthing.net/">Syncthing</a> (<a href="https://github.com/syncthing/syncthing">Code</a>) - decentralized, self-hostable, fast &amp; unix aligned<ul>
<li>macOS: <a href="https://github.com/syncthing/syncthing-macos/releases">https://github.com/syncthing/syncthing-macos/releases</a></li>
<li>iOS: <a href="https://github.com/pixelspark/sushitrain">https://github.com/pixelspark/sushitrain</a></li>
<li>Android: <a href="https://github.com/researchxxl/syncthing-android">https://github.com/researchxxl/syncthing-android</a></li>
</ul>
</li>
</ul>
<p>Calendar / Contacts:</p>
<ul>
<li><a href="https://www.etesync.com/">Etesync</a> (<a href="https://github.com/etesync/server">Code</a>) - end-to-end encrypted, self-hostable</li>
</ul>
<p>Social Network:</p>
<ul>
<li><a href="https://nostr.com/">Nostr</a> (<a href="https://github.com/nostr-protocol/nostr">Code</a>) - decentralized, self-hostable</li>
<li><a href="https://joinmastodon.org/">Mastodon</a> (<a href="https://github.com/tootsuite/mastodon">Code</a>) - federated, self-hostable</li>
<li><a href="https://scuttlebutt.nz/">Scuttlebutt</a> (<a href="https://github.com/ssbc/ssb-server">Code</a>) - decentralized, self-hostable</li>
</ul>
<p>Video Platform:</p>
<ul>
<li><a href="https://invidious.io/">Invidious</a> - privacy respecting YouTube frontend</li>
<li><a href="https://github.com/FreeTubeApp/FreeTube">FreeTube</a> - privacy respecting desktop client</li>
<li><a href="https://joinpeertube.org/">PeerTube</a> (<a href="https://github.com/Chocobozzz/PeerTube">Code</a>) - decentralized, federated, self-hostable</li>
</ul>
<p>Music:</p>
<ul>
<li><a href="https://funkwhale.audio/">Funkwhale</a> (<a href="https://dev.funkwhale.audio/funkwhale/funkwhale">Code</a>) - federated, self-hostable</li>
<li><a href="https://airsonic.github.io/">Airsonic</a> (<a href="https://github.com/airsonic/airsonic">Code</a>) - self-hostable</li>
</ul>
<p>Multi-Factor Authenticator:</p>
<ul>
<li><a href="https://ente.io/auth/">Ente Auth</a> (<a href="https://github.com/ente-io/ente">Code</a>) - open source</li>
<li><a href="https://proton.me/authenticator">Proton Authenticator</a> - privacy focused</li>
</ul>
<p>HTTP(S):</p>
<ul>
<li><a href="/posts/ipfs">IPFS</a> (<a href="https://github.com/ipfs/kubo">Code</a>) - decentralized, self-hostable</li>
</ul>
<p>Source Code:</p>
<ul>
<li><a href="https://radicle.xyz/">Radicle</a> (<a href="https://app.radicle.xyz/nodes/iris.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5">Code</a>) - decentralized, self-hostable<ul>
<li><a href="https://radicle.xyz/guides/user">User Guide</a></li>
</ul>
</li>
</ul>
<p>Mobile OS:</p>
<ul>
<li><a href="https://lineageos.org/">LineageOS</a></li>
<li><a href="https://grapheneos.org/">GrapheneOS</a></li>
</ul>
<p>Operating System:</p>
<ul>
<li><a href="https://cachyos.org/">CachyOS</a> (Arch Linux)</li>
<li><a href="https://fedoraproject.org/workstation/download/">Fedora Linux</a><ul>
<li><a href="https://nobaraproject.org/">Nobara</a> (optimized for gaming / streaming)</li>
</ul>
</li>
<li><a href="https://linuxmint.com/">Mint</a> (Ubuntu Linux)</li>
</ul>
<h2 id="export-all-your-google-data">Export All Your Google Data</h2>
<p>...using <a href="https://takeout.google.com/">https://takeout.google.com/</a> (optional for Google Photos: <a href="https://github.com/TheLastGimbus/GooglePhotosTakeoutHelper">GooglePhotosTakeoutHelper</a>) and delete your account.</p>
<h3 id="converting-google-docs-files-to-markdown">Converting Google Docs files to Markdown</h3>
<ol>
<li>Install <a href="https://pandoc.org/installing.html">Pandoc</a> to convert docx to markdown</li>
<li>Change dir to your Google Drive export: Takeout/Drive</li>
<li>Create a lua script named fix_underline_links.lua with this content:</li>
</ol>
<pre><code>function Link(el)
  local content = el.content
  if #content == 1 and content[1].t == &quot;Underline&quot; then
    content = content[1].content
  end
  return pandoc.Link(content, el.target)
end
</code></pre><ol start="4">
<li>Run this bash command to convert:</li>
</ol>
<p><code class="language-text">$ find . -name &quot;*.docx&quot; -type f -exec sh -c &#39;pandoc &quot;$0&quot; -o &quot;${0%.docx}.md&quot; --extract-media=./images/ --lua-filter=fix_underline_links.lua&#39; {} \;</code></p>
<ol start="5">
<li>Remove all docx files: <code class="language-text">$ find . -type f -name &quot;*.docx&quot; -delete</code></li>
</ol>
<h2 id="export-your-twitter-x-data"><a href="/posts/analyze-twitter-likes">Export Your Twitter (X) Data</a></h2>
<h2 id="todo-replace-instagram">TODO: Replace Instagram</h2>
<p>How to remove your data from Zuckerberg and backup it up to host it privacy focused.</p>
<h2 id="glossary">Glossary</h2>
<p><strong>End-to-end encrypted</strong> means your data is en- &amp; decrypted only on your machine, resulting in maximum security with maximum responsibility (password loss equals data loss).</p>
<p><strong>Self-hostable</strong> means anyone can run the software by themselves and thus maintain control of their data independently of any central authority.</p>
<p><strong>Decentralized</strong> means the software does not need to communicate over the internet with a central server in order to work, instead it is capable of communicating independently via peer-to-peer based networking (very useful when dealing with limited internet availability or censoring governments).</p>
<p><strong>Federated</strong> means instances of the software build a so called &quot;fediverse&quot; allowing users to communicate across instances.</p>
<h2 id="more-resources">More Resources</h2>
<ul>
<li><a href="https://github.com/tycrek/degoogle">https://github.com/tycrek/degoogle</a></li>
<li><a href="https://news.ycombinator.com/item?id=25090218">https://news.ycombinator.com/item?id=25090218</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#tutorial">#tutorial</a> <a href="/index.html#privacy">#privacy</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>A Nuclear Powered Nuclear Waste Dispenser</title>
      <link>https://seanpedersen.github.io/posts/nuclear-powered-nuclear-waste-dispenser</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/nuclear-powered-nuclear-waste-dispenser</guid>
      <pubDate>Wed, 13 Nov 2019 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>Nuclear power has many advantages but the few disadvantages are severe. One of the  major pain points is leftover nuclear waste produced by nuclear fission power plants. It is highly toxic and stays radioactive for thousands of years, leaving a pandora box packed with nuclear death for future humans to enjoy. To sum it up: We urgently need to clean up after our nuclear shit trail.</p>
<p>The current approach is archaic: We dig a hole somewhere and hope it will not come back to haunt us any time soon. This is naive, wishful thinking. Give it enough time and it will leak into our living environments. So how can we do better? My answer is quite simple and radical: Shoot the nuclear waste straight into space, either into deep space leaving our solar system or directly into the sun. This would remove the problem from mother earth for good.</p>
<p><strong>How?</strong> Current rocket technology is not gonna do it (launch costs are prohibitively expensive but we are slowly improving, so that could change in the future allowing for rocket based nuclear waste disposal). Right now we need to come up with something different: Design a thick bullet containing the nuclear waste. Build a giant cannon that is powered by <strong>nuclear power</strong>. Each launch needs to accelerate the bullet to earth&#39;s escape velocity and off goes our thick nuclear waste bullet into deep space.</p>
<p><strong>How to build it?</strong> Dig a cylindrical hole housing the cannon down into earth (preferably into some high mountain). Install a coil cannon or rail gun powered by nuclear energy capable of accelerating the waste bullet to earth&#39;s escape velocity (~12km/s). Before all that, sit down and calculate where to dig the hole according to the needed trajectory. And there it is a sweet nuclear powered nuclear waste dispenser.</p>
<p>Biggest potential hurdle: This nuclear waste dispenser design only works out if it can dispense more waste than is produced needed to operate it. Figuring that out is key to success and is left as an exercise for the curious reader.</p>
<p>Biggest potential failure: The nuclear waste bullet does not reach escape velocity and comes right back at spaceship earth. Mitigation: Simulate several failures without real nuclear waste but the same bullet case design and a realistic non-toxic replacement material for the waste.</p>
<p>I am really curious if this idea is practical. It would be amazing.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Space_gun">https://en.wikipedia.org/wiki/Space_gun</a></li>
<li><a href="https://en.wikipedia.org/wiki/Coilgun">https://en.wikipedia.org/wiki/Coilgun</a></li>
<li><a href="https://de.wikipedia.org/wiki/Railgun">https://de.wikipedia.org/wiki/Railgun</a><ul>
<li><a href="https://research.lifeboat.com/ieee.em.pdf">https://research.lifeboat.com/ieee.em.pdf</a></li>
<li><a href="https://www.universetoday.com/73536/nasa-considering-rail-gun-launch-system-to-the-stars/">https://www.universetoday.com/73536/nasa-considering-rail-gun-launch-system-to-the-stars/</a></li>
</ul>
</li>
<li><a href="https://www.forbes.com/sites/startswithabang/2019/09/20/this-is-why-we-dont-shoot-earths-garbage-into-the-sun/">https://www.forbes.com/sites/startswithabang/2019/09/20/this-is-why-we-dont-shoot-earths-garbage-into-the-sun/</a></li>
<li><a href="https://space.nss.org/wp-content/uploads/Space-Manufacturing-conference-12-111-Disposal-Of-High-Level-Nuclear-Waste-In-Space.pdf">https://space.nss.org/wp-content/uploads/Space-Manufacturing-conference-12-111-Disposal-Of-High-Level-Nuclear-Waste-In-Space.pdf</a></li>
<li><a href="http://large.stanford.edu/courses/2014/ph241/parekh2/docs/burns.pdf">http://large.stanford.edu/courses/2014/ph241/parekh2/docs/burns.pdf</a></li>
<li><a href="https://news.ycombinator.com/item?id=25089693">https://news.ycombinator.com/item?id=25089693</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Understanding understanding</title>
      <link>https://seanpedersen.github.io/posts/understanding-understanding</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/understanding-understanding</guid>
      <pubDate>Mon, 08 Jul 2019 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p>What does it mean to understand something?</p>
<p>If an agent produces a solution for a problem, does it necessarily follow that the agent understands it? Many people would clearly say no. A chess computer excels at the problem of playing chess but has no understanding of what he does, it’s just an algorithm crunching numbers after all, right?</p>
<p>To really understand a problem from a human perspective means not just being able to solve it but having the ability to explain the HOW in depth to others.</p>
<p>Ok well what does it mean to explain something then? I successfully explained something if another agent understands my explanation. Meaning he is able to solve the explained problem as well (applying the transferred knowledge) and able to explain it successfully to other agents (circular explanation).</p>
<p>Can I explain without language? Can I explain without any prior knowledge or beliefs about the knowledge the agent I am explaining to possesses?</p>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Meta Design: Design of a Design</title>
      <link>https://seanpedersen.github.io/posts/metadesign</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/metadesign</guid>
      <pubDate>Sat, 20 Apr 2019 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>idea</category>
      <content:encoded><![CDATA[
          <p><strong>Why even write a design?</strong> The design process animates thinking through ideas deeply before getting lost in the details building them. It provides the chance for different stakeholders to develop a shared vision.</p>
<p><strong>What makes a successful design?</strong><br>It alone must simply suffice to realize the idea it contains.</p>
<p><strong>Some things to try</strong>:</p>
<ul>
<li>First: start with pen &amp; paper and scribble away, to develop a rough outline</li>
<li>Write concisely and precisely but not too short</li>
<li>Prefer diagrams, sketches and tables over long prose</li>
<li>Use clear &amp; vivid explanations; avoid very long continuous text passages</li>
</ul>
<h2 id="top-down-approach">Top Down Approach</h2>
<p>Identify distinct, preferably large, independent modules that solve a coherent problem complex which ideally abstract away highly moving parts (things that may likely change / are unknown). Next outline interactions of the modules to map out the interaction dynamics of the system.</p>
<p>“We propose instead that one begins with a list of difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others.” - <a href="http://sunnyday.mit.edu/16.355/parnas-criteria.html">http://sunnyday.mit.edu/16.355/parnas-criteria.html</a></p>
<p>Finally describe each module as deeply as necessary but not deeper, so that interfaces (behavior towards others) and their functionalities (inner behavior: e.g. algorithms and data structures) are clearly presented. Minimize the information shared with other modules to reduce static coupling (information hiding). Finally draw a clear line between what is solved, what remains unsolved and what is unknowable.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://learnhowtolearn.org/how-to-build-extremely-quickly/">https://learnhowtolearn.org/how-to-build-extremely-quickly/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#idea">#idea</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Natural Language Processing: Sentiment Analysis</title>
      <link>https://seanpedersen.github.io/posts/sentiment-analysis</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/sentiment-analysis</guid>
      <pubDate>Sat, 13 Oct 2018 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>In this article we will take a closer look at sentiment analysis. Given an input text predict the sentiment (emotional state) as either negative (0) or positive (1). Sentiment analysis is useful to understand human text interactions at big scales. (Updated: 13th January, 2021)</p>
<h2 id="dataset-imdb-movie-reviews">Dataset: IMDB Movie Reviews</h2>
<p>A widely used dataset for sentiment classification is provided by the Internet Movie DataBase (IMDB). The training data set consists of 50,000 movie review texts, each associated with the target prediction label 0 or 1.</p>
<h2 id="models">Models</h2>
<p>We compare four increasingly complex approaches to tackle the IMDB sentiment classification problem.</p>
<h3 id="logistic-regression-with-tf-idf-bi-grams">Logistic Regression with TF-IDF &amp; Bi-Grams</h3>
<ul>
<li><strong>N-Grams</strong>: Tuples of order N created from a sequence of symbols (words). Bi-gram(a,b,c) = {(a,b),(b,c)}</li>
<li><strong>Term Frequency (TF)</strong>: Number of occurrences for each word in a document (here a review is a document) of a collection of documents. Results for each document in a sparse (since most likely not all documents share the same words) row vector, where each dimension represents a unique word of the total collection of documents.</li>
<li><strong>N</strong>: Number of total documents (reviews).</li>
<li><strong>N(w)</strong>: Number of documents in which a word w appears at least once.</li>
<li><strong>Inverse Document Frequency (IDF)</strong>: log(N / N(w))</li>
<li><strong>TF-IDF</strong>: TF * IDF</li>
</ul>
<p>TF-IDF preprocessing results in weighing words heavily that are rare across all documents. The opposite is true for words that are common across all documents. Thus TF-IDF can be interpreted as a heuristic that minimizes the significance of common stop words (the, you, etc.) without needing to explicitly provide a static list of stop words.</p>
<h3 id="neural-embeddings">Neural Embeddings</h3>
<p>Embeddings represent relationships between entities in usually high-dimensional geometric spaces (f.e. euclidean or hyperbolic). One common and useful embedding space for words as entities encodes the semantic / contextual relationships between them. For example one would want words with similar meaning (e.g. synonyms) to be reflected in the embedding by a small distance. A common model to compute embeddings for natural language texts is Word2Vec. Word2Vec can be trained in two ways: either by predicting surrounding words (context) for a given word (Skip-gram) or predicting the missing word from a given context (CBOW).</p>
<p>Instead of training text embeddings unsupervised (without labels) using f.e. Word2Vec: We can train an embedding for our problem at hand as an input layer.<br>The input layer embedding will learn a problem specific representation (determined by the training data labels and loss function).<br>The embedding layer works by converting each word-token of an input sequence into a one-hot vector resulting in a big sparse matrix as input, this matrix is matrix-multiplied with an embedding matrix resulting in a dense often low dimensional embedding layer output. The embedding matrix is trained by back-propagated gradient steps from the last layers output computed loss function.</p>
<h3 id="lstm">LSTM</h3>
<p>LSTM stands for “Long Short-Term Memory” and is a neural architecture designed to model sequential data. It is engineered to overcome the vanishing / exploding gradient problem encountered with classical Recurrent Neural Networks (RNN), enabling LSTM&#39;s to model long-term relationships between data points in long sequences. They tackle the fundamental problem of deciding between noise and signal by selectively “remembering” relevant data and “forgetting” irrelevant data with respect to the loss function.</p>
<p>Learn how LSTM&#39;s function: <a href="http://colah.github.io/posts/2015-08-Understanding-LSTMs/">http://colah.github.io/posts/2015-08-Understanding-LSTMs/</a></p>
<h3 id="transformer">Transformer</h3>
<p>Transformers are all the rage for text and even vision tasks now a days. They perform better at modeling sequential interdependencies of their inputs using so called attention heads. Their input size is fixed so they are not recurrent neural networks. Architecturally they are closer related to convolutional neural networks which they are making obsolete for most vision tasks.</p>
<p>Learn how Transformers work:</p>
<ul>
<li><a href="https://peterbloem.nl/blog/transformers">https://peterbloem.nl/blog/transformers</a></li>
<li><a href="https://jalammar.github.io/illustrated-transformer/">https://jalammar.github.io/illustrated-transformer/</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
    <item>
      <title>Deep Learning: Variational Auto-Encoders</title>
      <link>https://seanpedersen.github.io/posts/vae</link>
      <guid isPermaLink="true">https://seanpedersen.github.io/posts/vae</guid>
      <pubDate>Sun, 30 Sep 2018 00:00:00 GMT</pubDate>
      <author>Sean Pedersen</author>
      <category>ML</category>
      <content:encoded><![CDATA[
          <p>Variational Auto-Encoders (VAE) are a probabilistic (variational) extension of classical auto-encoders. Disclaimer: This article does not approach the concept of VAE from a bayesian perspective (check out the references below for this). The focus lies instead on highlighting the key components and their effects on the practical results such as the latent embedding space structure.</p>
<h2 id="building-blocks-of-an-auto-encoder">Building Blocks of an Auto-Encoder</h2>
<ul>
<li><strong>x</strong>: Input tensor (high-dimensional) f.e. image from MNIST dataset (handwritten digits).</li>
<li><strong>Encoder <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>e</mi><mo>(</mo><mi>x</mi><mo>,</mo><msub><mi>θ</mi><mi>e</mi></msub><mo>)</mo><mo>→</mo><mi>z</mi></math></strong>: Neural network <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>e</mi></math> compressing input <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>x</mi></math> into a lower dimensional tensor <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math> using parameters <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>θ</mi><mi>e</mi></msub></math>.</li>
<li><strong>Latent space z</strong>: Hidden lower <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>n</mi></math>-dimensional space (also called bottleneck) in which the compressed representation of input data lies, represented by <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi><mo>∈</mo><msup><mi>R</mi><mi>n</mi></msup></math>.</li>
<li><strong>Decoder <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>d</mi><mo>(</mo><mi>z</mi><mo>,</mo><msub><mi>θ</mi><mi>d</mi></msub><mo>)</mo><mo>→</mo><msup><mi>x</mi><mo>′</mo></msup></math></strong>: Neural network <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>d</mi></math> reconstructing a lossy representation <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msup><mi>x</mi><mo>′</mo></msup></math> of the original input <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>x</mi></math> using parameters <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>θ</mi><mi>d</mi></msub></math> from a point <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math> generated by <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>e</mi><mo>(</mo><mi>x</mi><mo>)</mo></math>.</li>
<li><strong>Auto-Encoder <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>d</mi><mo>(</mo><mi>e</mi><mo>(</mo><mi>x</mi><mo>,</mo><msub><mi>θ</mi><mi>e</mi></msub><mo>)</mo><mo>,</mo><msub><mi>θ</mi><mi>d</mi></msub><mo>)</mo><mo>→</mo><msup><mi>x</mi><mo>′</mo></msup></math></strong>: Encoder and decoder chained together as a single model.</li>
<li><strong>Loss Function <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>L</mi><mo>(</mo><mi>x</mi><mo>,</mo><msup><mi>x</mi><mo>′</mo></msup><mo>)</mo></math></strong>: Reconstruction loss defined by e.g. mean squared error between <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>x</mi></math> and <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msup><mi>x</mi><mo>′</mo></msup></math>: <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>L</mi><mo>(</mo><mi>x</mi><mo>,</mo><msup><mi>x</mi><mo>′</mo></msup><mo>)</mo><mo>=</mo><mtext>MSE</mtext><mo>(</mo><mi>x</mi><mo>,</mo><msup><mi>x</mi><mo>′</mo></msup><mo>)</mo></math>, and possibly regularization terms e.g. sparsity constraint on <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math> or weights. Used to compute gradients for parameters <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>θ</mi><mi>d</mi></msub></math> and <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>θ</mi><mi>e</mi></msub></math> minimizing the loss.</li>
</ul>
<h2 id="making-auto-encoders-variational">Making Auto-Encoders Variational</h2>
<p>We turn a classical auto-encoder into a variational one by modifying the encoder. Instead of transforming the input <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>x</mi></math> directly into the single vector <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi><mo>∈</mo><msup><mi>R</mi><mi>n</mi></msup></math>, we instead map <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>x</mi></math> into two vectors: <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>z</mi><mi>μ</mi></msub><mo>∈</mo><msup><mi>R</mi><mi>n</mi></msup></math> and <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>z</mi><msup><mi>σ</mi><mn>2</mn></msup></msub><mo>∈</mo><msup><mi>R</mi><mi>n</mi></msup></math>. These two vectors parametrize a Gaussian normal distribution (via mean and variance) from which we sample the latent vector <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math>:</p>
<p><div class="math-block"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>z</mi><mo>∼</mo><mi>N</mi><mo>(</mo><msub><mi>z</mi><mi>μ</mi></msub><mo>,</mo><mspace width="0.16666667em"></mspace><msub><mi>z</mi><msup><mi>σ</mi><mn>2</mn></msup></msub><mo>)</mo></math></div></p>
<p>This makes our encoder variational (probabilistic), basically adding gaussian noise to our encoder models output vector <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math>.</p>
<p>Why should we add noise to the encoder? Doing so will generate many more different sample points of <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math> for the decoder to learn reconstructions from, forcing the decoder to generate smooth interpolations between local samples in the latent space.</p>
<p>Computing the derivatives of the random gaussian distribution parametrized by the two output vectors <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>z</mi><mi>μ</mi></msub></math> and <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>z</mi><msup><mi>σ</mi><mn>2</mn></msup></msub></math> of the encoder is achieved by reparameterizing into:</p>
<p><div class="math-block"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>z</mi><mo>=</mo><msub><mi>z</mi><mi>μ</mi></msub><mo>+</mo><msqrt><msub><mi>z</mi><msup><mi>σ</mi><mn>2</mn></msup></msub></msqrt><mo>·</mo><mi>ε</mi><mo>,</mo><mspace width="1em"></mspace><mi>ε</mi><mo>∼</mo><mi>N</mi><mo>(</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo>)</mo></math></div></p>
<p>This so called reparameterization trick enables us to take the derivatives of <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math> with respect to either <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>z</mi><mi>μ</mi></msub></math> or <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>z</mi><msup><mi>σ</mi><mn>2</mn></msup></msub></math>, which are necessary to back-propagate the error-signal through the variational sampling layer when using gradient descent as the parameter optimizer.</p>
<p>To prevent the variational encoder of &quot;cheating&quot; by placing different samples far apart from each other in <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math> (avoiding our desired property of smooth local interpolations) we add an additional loss term to our reconstruction loss function, giving the total loss:</p>
<p><div class="math-block"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>L</mi><mo>(</mo><mi>x</mi><mo>,</mo><msup><mi>x</mi><mo>′</mo></msup><mo>)</mo><mo>=</mo><mtext>MSE</mtext><mo>(</mo><mi>x</mi><mo>,</mo><msup><mi>x</mi><mo>′</mo></msup><mo>)</mo><mo>+</mo><msub><mi>D</mi><mrow><mi>K</mi><mi>L</mi></mrow></msub><mspace width="-0.16666667em"></mspace><mrow><mo stretchy="true" form="prefix">(</mo><mrow><mi>N</mi><mo>(</mo><msub><mi>z</mi><mi>μ</mi></msub><mo>,</mo><msub><mi>z</mi><msup><mi>σ</mi><mn>2</mn></msup></msub><mo>)</mo><mspace width="0.16666667em"></mspace><mo>∥</mo><mspace width="0.16666667em"></mspace><mi>N</mi><mo>(</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo>)</mo></mrow><mo stretchy="true" form="postfix">)</mo></mrow></math></div></p>
<p>This additional loss term is defined as the Kullback-Leibler-divergence (non-symmetric measure of the difference between two probability distributions) between the encoders output <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>N</mi><mo>(</mo><msub><mi>z</mi><mi>μ</mi></msub><mo>,</mo><msub><mi>z</mi><msup><mi>σ</mi><mn>2</mn></msup></msub><mo>)</mo><mo>∈</mo><msup><mi>R</mi><mi>n</mi></msup></math> and an isotropic standard normal distribution <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>N</mi><mo>(</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo>)</mo><mo>∈</mo><msup><mi>R</mi><mi>n</mi></msup></math>. This forces the latent space to be standard Gaussian distributed (achieving the desired smooth local interpolation).</p>
<h2 id="beta-vae">Beta-VAE</h2>
<p>By adding a tunable parameter <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>β</mi></math> to the Kullback-Leibler loss:</p>
<p><div class="math-block"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>L</mi><mo>(</mo><mi>x</mi><mo>,</mo><msup><mi>x</mi><mo>′</mo></msup><mo>)</mo><mo>=</mo><mtext>MSE</mtext><mo>(</mo><mi>x</mi><mo>,</mo><msup><mi>x</mi><mo>′</mo></msup><mo>)</mo><mo>+</mo><mi>β</mi><mo>·</mo><msub><mi>D</mi><mrow><mi>K</mi><mi>L</mi></mrow></msub><mspace width="-0.16666667em"></mspace><mrow><mo stretchy="true" form="prefix">(</mo><mrow><mi>N</mi><mo>(</mo><msub><mi>z</mi><mi>μ</mi></msub><mo>,</mo><msub><mi>z</mi><msup><mi>σ</mi><mn>2</mn></msup></msub><mo>)</mo><mspace width="0.16666667em"></mspace><mo>∥</mo><mspace width="0.16666667em"></mspace><mi>N</mi><mo>(</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo>)</mo></mrow><mo stretchy="true" form="postfix">)</mo></mrow></math></div></p>
<p>which is <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>β</mi><mo>=</mo><mn>1</mn></math> for the normal VAE, we can vary how much we force the latent space to be standard normally distributed (no interdimensional correlations / spherical covariance matrix). This has an interesting effect on the structure of the latent space dimensions: a higher <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>β</mi></math> (&gt;1) promotes disentanglement of the individual latent space dimensions. Making them independent and often interpretable features.<br>For example a disentangled dimension might represent the abstract feature of gender (negative number may represent male attributes and positive numbers female attributes).</p>
<p><strong>The Underlying Mechanism</strong>: Increasing <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>β</mi></math> disentangles the latent features and works by creating an information capacity bottleneck — it makes using any latent dimension &quot;expensive&quot; by penalizing large deviations from <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>N</mi><mo>(</mo><mn>0</mn><mo>,</mo><mn>1</mn><mo>)</mo></math>. This constraint forces the model to use each dimension efficiently, making specialization (pure features per dimension) more cost-effective than redundant or mixed encodings across dimensions (penalizing inter-dimensional correlations).</p>
<p>Interestingly, this reveals a broader principle: any constraint that limits effective information capacity per dimension can promote disentanglement. For example, quantizing latent representations creates a similar information bottleneck through precision limits rather than loss induced via <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>D</mi><mrow><mi>K</mi><mi>L</mi></mrow></msub></math>, potentially achieving comparable disentanglement effects through the same underlying mechanism of forced dimensional efficiency.</p>
<h2 id="show-me-the-code">Show me the code</h2>
<p>Get your hands dirty and play around:</p>
<ul>
<li><a href="https://github.com/AntixK/PyTorch-VAE/blob/master/models/beta_vae.py">Beta-VAE</a></li>
</ul>
<h2 id="further-questions">Further Questions</h2>
<p><strong>How can we exploit the fact that the decoder is the inverse of the encoder function and vice versa (weights should be in inverse relationship)?</strong></p>
<p>See &quot;Invertible Autoencoders&quot;; TODO: Lookup reversible layers</p>
<p><strong>How is the compressed latent embedding <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math> related with the data distribution of <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>X</mi></math> (f.e. training images)?</strong></p>
<p>„In fact, this simple autoencoder often ends up learning a low-dimensional representation very similar to PCAs.&quot; -<br><a href="http://ufldl.stanford.edu/tutorial/unsupervised/Autoencoders/">http://ufldl.stanford.edu/tutorial/unsupervised/Autoencoders/</a></p>
<p><strong>If a simple dense AE approximates PCA, what does a convolutional AE approximate? Local PCAs for each kernel?</strong></p>
<p>Can we train the encoder unsupervised (independently from the decoder) by understanding how the input features are compressed into <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math>?</p>
<p>The latent space <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math> is shaped by the loss function, which consists of the MSE between input and output image plus the <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><msub><mi>D</mi><mrow><mi>K</mi><mi>L</mi></mrow></msub></math> between an isotropic standard gaussian and <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>z</mi></math>. → How can we replace the MSE term of the loss to decouple the decoder from the encoder while training? Define a loss that considers class density and overlap → reward high class density embeddings, penalize multi-class overlap?</p>
<h2 id="references">References</h2>
<ul>
<li>Excellent detailed blog post: <a href="https://lilianweng.github.io/posts/2018-08-12-vae/">https://lilianweng.github.io/posts/2018-08-12-vae/</a></li>
<li>Bayesian perspective: <a href="https://jaan.io/what-is-variational-autoencoder-vae-tutorial/">https://jaan.io/what-is-variational-autoencoder-vae-tutorial/</a></li>
<li>Applications: <a href="https://towardsdatascience.com/intuitively-understanding-variational-autoencoders-1bfe67eb5daf">https://towardsdatascience.com/intuitively-understanding-variational-autoencoders-1bfe67eb5daf</a></li>
<li>Intro from the OG authors: <a href="https://arxiv.org/pdf/1906.02691">https://arxiv.org/pdf/1906.02691</a></li>
</ul>
<p class="post-hashtags"><a href="/index.html#ML">#ML</a></p>

        ]]></content:encoded>
    </item>
  </channel>
</rss>