10 interesting stories served every morning and every evening.
Your computer modem screeches as it tries to connect to something called the internet. Maybe it works. Maybe you try again.
For the first time in history, you can exchange letters with someone across the world in seconds. Only 2000-something websites exist, so you could theoretically visit them all over a weekend. Most websites are just text on gray backgrounds with the occasional pixelated image. Loading times are brutal. A single image takes a minute, a 1-minute video could take hours. Most people do not trust putting their credit cards online. The advice everyone gives: don’t trust strangers on the internet.
People split into two camps very soon.
Optimists predict grand transformations. Some believe digital commerce will overtake physical retail within years. Others insist we’ll wander around in virtual reality worlds.
“I expect that within the next five years more than one in ten people will wear head-mounted computer displays while traveling in buses, trains, and planes.” - Nicholas Negroponte, MIT Professor, 1993
If you told the average person in 1995 that within 25 years, we’d consume news from strangers on social media over newspapers, watch shows on-demand in place of cable TV, find romantic partners through apps more than through friends, and flip “don’t trust strangers on the internet” so completely that we’d let internet strangers pick us up in their personal vehicles and sleep in their spare bedrooms, most people would find that hard to believe.
We’re in 1995 again. This time with Artificial Intelligence.
And both sides of today’s debate are making similar mistakes.
One side warns that AI will eliminate entire professions and cause mass unemployment within a couple of years. The other claims that AI will create more jobs than it destroys. One camp dismisses AI as overhyped vaporware destined for a bubble burst, while the other predicts it will automate every knowledge task and reshape civilization within the decade.
Both are part right and part wrong.
Geoffrey Hinton, who some call the Father of AI, warned in 2016 that AI would trigger mass unemployment. “People should stop training radiologists now,” he declared, certain that AI would replace them within years.
Yet as Deena Mousa, a researcher, shows in “The Algorithm Will See You Now,” AI hasn’t replaced radiologists, despite predictions. It is thriving.
In 2025, American diagnostic radiology residency programs offered a record 1,208 positions across all radiology specialties, a four percent increase from 2024, and the field’s vacancy rates are at all-time highs. In 2025, radiology was the second-highest-paid medical specialty in the country, with an average income of $520,000, over 48 percent higher than the average salary in 2015.
Mousa identifies a few factors for why the prediction failed - real-world complexity, the job involves more than image recognition, and regulatory/insurance hurdles. Most critical she points is Jevons Paradox, which is the economic principle that a technological improvement in resource efficiency leads to an increase in the total consumption of that resource, rather than a decrease. Her argument is that as AI makes radiologists more productive, better diagnostics and faster turnaround at lower costs mean more people get scans. So employment doesn’t decrease. It increases.
This is also the Tech world’s consensus. Microsoft CEO Satya Nadella agrees, as does Box CEO Aaron Levie, who suggests:
“The least understood yet most important concept in the world is Jevons Paradox. When we make a technology more efficient, demand goes well beyond the original level. AI is the perfect example of this—almost anything that AI is applied to will see more demand, not less.”
First, as Andrej Karpathy, the computer scientist who coined the term vibe coding, points out, radiology is not the right job to look for initial job displacements.
“Radiology is too multi-faceted, too high risk, too regulated. When looking for jobs that will change a lot due to AI on shorter time scales, I’d look in other places - jobs that look like repetition of one rote task, each task being relatively independent, closed (not requiring too much context), short (in time), forgiving (the cost of mistake is low), and of course automatable giving current (and digital) capability. Even then, I’d expect to see AI adopted as a tool at first, where jobs change and refactor (e.g. more monitoring or supervising than manual doing, etc).”
Second, the tech consensus that we will see increased employment actually depends on the industry. Specifically, how much unfulfilled demand can be unlocked in that industry, and whether this unfulfilled demand growth outpaces continued automation and productivity improvement.
To understand this better, look at what actually happened in three industries over a 200-year period from 1800 to 2000. In the paper Automation and jobs: when technology boosts employment, James Bessen, an economist, shows the employment, productivity, and demand data for textile, iron & steel, and motor vehicle industries.
After automation, both textile and iron/steel workers saw employment increase for nearly a century before experiencing a steep decline. Vehicle manufacturing, by contrast, holds steady and hasn’t seen the same steep decline yet.
To answer why those two industries saw sharp declines but motor vehicle manufacturing did not, first look at the productivity of workers in all three industries:
Then look at the demand across those three industries:
What the graphs show is a consistent pattern (note: the productivity and demand graphs are logarithmic, meaning productivity and demand grew exponentially). Early on, a service or product is expensive because many workers are needed to produce it. Most people can’t afford it or use them sparingly. For example, in the early 1800s, most people could only afford a pair of pants or shirt. Then automation makes workers dramatically more productive. A textile worker in 1900 could produce fifty times more than one in 1800. This productivity explosion crashes prices, which creates massive new demand. Suddenly everyone can afford multiple outfits instead of just one or two. Employment and productivity both surge (note: employment growth masks internal segment displacement and wage changes. See footnote)
Once demand saturates, employment doesn’t further increase but holds steady at peak demand. But as automation continues and workers keep getting more productive, employment starts to decline. In textiles, mechanization enabled massive output growth but ultimately displaced workers once consumption plateaued while automation and productivity continued climbing. We probably don’t need infinite clothing. Similarly, patients will likely never need a million radiology reports, no matter how cheap they become and so radiologists will eventually hit a ceiling. We don’t need infinite food, clothing, tax returns, and so on.
Motor vehicles, in Bessen’s graphs, tell a different story because demand remains far from saturated. Most people globally still don’t own cars. Automation hasn’t completely conquered manufacturing either (Tesla’s retreat from full manufacturing automation proves the current technical limits). When both demand and automation potential remain high, employment can sustain or even grow despite productivity gains.
Software presents an even more interesting question. How many apps do you need? What about software that generates applications on demand, that creates entire software ecosystems autonomously? Until now, handcrafted software was the constraint. Expensive software engineers and their labor costs limited what companies could afford to build. Automation changes this equation by making those engineers far more productive. Both consumer and enterprise software markets suggest significant unmet demand because businesses have consistently left projects unbuilt. They couldn’t justify the development costs or had to allocate limited resources to their top priority projects. I saw this firsthand at Amazon. Thousands of ideas went unfunded not because they lacked business value, but because of the lack of engineering resources to build them. If AI can produce software at a fraction of the cost, that unleashes enormous latent demand. The key question then is if and when that demand will saturate.
So to generalize, for each industry, employment hinges on a race between two forces:
The magnitude and growth of unmet market demand, andWhether that demand growth outpaces productivity improvements from automation.
Different industries will experience different outcomes depending on who’s winning that demand and productivity race.
The second debate centers on whether this AI boom is a bubble waiting to burst.
The dotcom boom of the 1990s saw a wave of companies adding “.com” to their name to ride the mania and watch their valuations soar. Infra companies poured billions into fiber optics and undersea cables - expensive projects only possible because people believed the hype. All of this eventually burst in spectacular fashion in the dotcom crash in 2000-2001. Infrastructure companies like Cisco briefly became the most valuable in the world only to come tumbling down. Pets.com served as the poster child of this exuberance raising $82.5 million in its IPO, spending millions on a Super Bowl ad only to collapse nine months later.
But the dotcom bubble also got several things right. More importantly, it eventually bought us the physical infrastructure that made YouTube, Netflix, and Facebook possible. Sure, companies like Worldcom, NorthPoint, and Global Crossing making these investments went bankrupt, but they also laid the foundation for the future. Although the crash proved the skeptics right in the short term, it proved the optimists were directionally correct in the long term.
Today’s AI boom shows similar exuberance. Consider the AI startup founded by former OpenAI executive Mira Murati, which raised $2 billion at a $10 billion valuation, the largest seed round in history. This despite having no product and declining to reveal what it’s building or how it will generate returns. Several AI wrappers have raised millions in seed funding with little to no moat.
Yet some investments will outlast the hype and will likely help future AI companies even if this is a bubble. For example, the annual capital expenditures of Hyperscalers that have more than doubled since ChatGPT’s release - Microsoft, Google, Meta, and Amazon are collectively spending almost half a trillion dollars on data centers, chips, and compute infrastructure. Regardless of which specific companies survive, this infrastructure being built now will create the foundation for our AI future - from inference capacity to the power generation needed to support it.
The infrastructure investments may have long-term value, but are we already in bubble territory? Azeem Azhar, a tech analyst and investor, provides an excellent practical framework to answer the AI bubble question. He benchmarks today’s AI boom using five gauges: economic strain (investment as a share of GDP), industry strain (capex to revenue ratios), revenue growth trajectories (doubling time), valuation heat (price-to-earnings multiples), and funding quality (the resilience of capital sources). His analysis shows that AI remains in a demand-led boom rather than a bubble, but if two of the five gauges head into red, we will be in bubble territory.
The demand is real. After all OpenAI is one of the fastest-growing companies in history. But that alone doesn’t prevent bubbles. OpenAI will likely be fine given its product-market fit, but many other AI companies face the same unit economics questions that plagued dotcom companies in the 1990s. Pets.com had millions of users too (a then large portion of internet users), but as the tech axiom goes, you can acquire infinite customers and generate infinite revenue if you sell dollars for 85 cents. So despite the demand, the pattern may rhyme with the 1990s. Expect overbuilding. Expect some spectacular failures. But also expect the infrastructure to outlast the hype cycle and enable things we can’t yet imagine.
So where does this leave us?
We’re early in the AI revolution. We’re at that metaphorical screeching modem phase of the internet era. Just as infrastructure companies poured billions into fiber optics, hyperscalers now pour billions into compute. Startups add “.ai” to their names like companies once added “.com” as they seek higher valuations. The hype will cycle through both euphoria and despair. Some predictions will look laughably wrong. Some that seem crazy will prove conservative.
Different industries will experience different outcomes. Unlike what the Jevons optimists suggest, demand for many things plateaus once human needs are met. Employment outcomes in any industry depend on the magnitude and growth of unmet market demand and whether that demand growth outpaces productivity improvements from automation.
Cost reduction will unlock market segments. Aswath Damodaran, a finance professor, (in)famously undervalued Uber assuming it would only capture a portion of the existing taxi market. He missed that making rides dramatically cheaper would expand the market itself as people took Ubers to destinations they’d never have paid taxi prices to reach. AI will similarly enable products and services currently too expensive to build with human intelligence. A restaurant owner might use AI to create custom supply chain software that say at $100,000 with human developers would never have been built. A non-profit might deploy AI to contest a legal battle that was previously unaffordable.
We can predict change, but we can’t predict the details. No one in 1995 predicted we’d date strangers from the internet, ride in their ubers, or sleep in their airbnbs. Or that a job called influencers would become the most sought-after career among young people. Human creativity generates outcomes we can’t forecast with our current mental models. Expect new domains and industries to emerge. AI has already helped us decode more animal communication in the last five years than in the last fifty. Can we predict what jobs a technology that allows us to have full-blown conversations with them will unlock? A job that doesn’t exist today will likely be the most sought-after job in 2050. We can’t name it because it hasn’t been invented yet.
Job categories will transform. Even as the internet made some jobs obsolete, it also transformed others and created new categories. Expect the same with AI. Karpathy ends with a question:
About 6 months ago, I was also asked to vote if we will have less or more software engineers in 5 years. Exercise left for the reader.
To answer this question, go back to 1995 and ask the same question but with journalists. You might have predicted more journalists because the internet would create more demand by enabling you to reach the whole world. You’d be right for 10 or so years as employment in journalism grew until the early 2000s. But 30 years later, the number of newspapers and the number of journalists both have declined, even though more “journalism” happens than ever. Just not by people we call journalists. Bloggers, influencers, YouTubers, and newsletter writers do the work that traditional journalists used to do.
The same pattern will play out with software engineers. We’ll see more people doing software engineering work and in a decade or so, what “software engineer” means will have transformed. Consider the restaurant owner from earlier who uses AI to create custom inventory software that is useful only for them. They won’t call themselves a software engineer.
So just like in 1995, if the AI optimists today say that within 25 years, we’d prefer news from AI over social media influencers, watch AI-generated characters in place of human actors, find romantic partners through AI matchmakers more than through dating apps (or perhaps use AI romantic partners itself), and flip “don’t trust AI” so completely that we’d rely on AI for life-or-death decisions and trust it to raise our children, most people would find that hard to believe. Even with all the intelligence, both natural and artificial, no one can predict with certainty what our AI future will look like. Not the tech CEOs, not the AI researchers, and certainly not some random guy pontificating on the internet. But whether we get the details right or not, our AI future is loading.
...
Read the original on www.wreflection.com »
An error fare to Iceland pops up. It’s cheap enough to feel like a typo and most likely will be gone in minutes. I’m moderately obsessed with ways to travel on budget, so I keep an eye on these.
Before I click Buy, I need to know (fast!) if it actually works for me: would I need a visa, are there any odd passport requirements, can I quickly sort out the driving permit, would it affect my Schengen 90/180 window, break UK presence tests or accidentally prevent a tax residency I am chasing.
It isn’t one check, it’s a stack of small unfriendly ones, and takes around 20 minutes to process. Some bits are fun, like hunting for a seat upgrade, but mostly it’s counting midnights and expiry dates so a cheap weekend doesn’t become an expensive lesson.
I’ve been doing this dance for a decade now. In 2015 I made a spreadsheet for a US visa application that wanted ten years of travel history, down to the day. The spreadsheet grew: UK work visa, Indefinite Leave to Remain and citizenship applications, Canadian work permits. Any government form that asked “where have you been?” got its answer from the same battered CSV. It worked well enough, in the sense that I was never detained.
It also made me think that this was a solvable problem I was solving badly. I built a ledger to answer “where was I on 15 March 2023?” Instead, I ran simulations to check, “if I book this, what breaks later?”
The only question is whether the computer can answer all of faster than I do, and leave December, the next border control, and the end of the tax year blissfully uneventful.
That twenty-minute panic before buying a flight comes from one basic problem: none of the systems that judge you will tell you your state.
Schengen is running one check. The UK is running another. Tax residency is running a third. Your passport is running its own quiet clock in the background. None of them explain themselves, and none of them agree on what “a day” even is.
Schengen cares about presence across rolling windows. The UK counts how many midnights you were physically in the country in a tax year that, for historical reasons , starts on 6 April out of all options. Some countries track how many days you’ve spent in certain places and change the medical paperwork they expect from you once you cross a threshold. Meanwhile your passport might fail you with its expiry date, validity rules that may apply on arrival or departure depending on routing, and a finite number of blank facing pages that some countries require.
None of that is easily exposed. The officer at the desk can see it but you can’t. That’s parsing the State—both kinds. The government’s view of you, and the state machine that tracks it.
The rules aren’t just complex—they’re occasionally specific in ways that make you regret leaving the house in the first place.
To apply for British citizenship, you need to prove you were physically in the UK on your application date but five years ago. Not approximately five years, not that week—that exact day when you press “submit” on the form minus five years. Miss it by 24 hours and your application is reject after months of waiting, and you have to pay a hefty fee to re-apply.
Transiting through a UK airport? Leaving the terminal doesn’t count as presence unless you do something “unrelated to your travel”—buy a sausage roll at Greggs, see a play in West End, meet a friend. The guidance doesn’t even specify a minimum spend.
Morocco runs on UTC+1 most of the year but switches to UTC during Ramadan to shorten the fasting day. Which means “days spent in Morocco” depends on your timezone database version and whether you remembered to update it.
It would be alright with a single source of truth, but all these facts are scattered across (semi)official websites and PDFs, and you’re supposed to figure it out yourself.
So the job isn’t “log trips” (I already did that for ten years in a spreadsheet). The job is: given what I’ve already done and what I’m about to do, does this plan quietly break anything, and if so, where, and by how much.
“You’re at 56 days because Amsterdam contributed 12, Prague 3, Barcelona 10, Iceland would add a month, and February doesn’t count anymore” is something I can trust, argue with, or fix. “You’re fine” isn’t.
That’s where this stops being a spreadsheet and starts being a linter. Apparently I want the compiler warning before I press Buy.
If I want a compiler warning I trust, the compiler has to agree with the officer about what a day is.
For the past five years I’ve been working on an app for people with epilepsy, managing timezones, medication reminders, and edge cases. We juggled multiple sources of truth and multiple storage styles (some records in UTC, some in local time with timezones stored separately—historical reasons, obviously).
This time, I tried to learn from that: facts are stored as instants, reasoning happens in local days of the jurisdiction that cares.
Take this routing: depart Dublin morning of November the 17th, brief Newark layover, a longer one in Mexico City, 23-hour Heathrow stop, then Tenerife. Ask five immigration systems “how many tax residency days?” and you get five answers:
* US: zero (foreign-to-foreign transit under 24 hours).
* Mexico: two (you cross midnight twice).
* UK: zero (even though you cross midnight once), unless you went landside for non-travel reasons, then one.
* Schengen: one (entry day counts, exit day will count too, even if both are only for 15 minutes).
Each stop has same or similar conditions, but different state machines are asking different questions. I pin the timezone database version that produced each result, and when rules or clocks shift, I recompute so I could show both answers if needed. Yesterday should stay reproducible even when tomorrow disagrees.
In other words, the linter is meant to answer the same question in various disguises: “what happens if I do this?”
Can I book Christmas in the Alps with three summer weekends planned in Europe? Does it matter if I leave UK before the tax year ends? What passport should I travel on? Does anything expire between booking and boarding?
Every question has the same shape: simulate forward, find what breaks, decide if you care. The goal isn’t to convince border officers—it’s to not make mistakes they’d catch. Trips get assembled from whatever I can verify later: geotagged photos, background location, manual entries. A resolver turns that into “present on this local day” and keeps track of why.
I don’t hardcode rules, I ship interpretations instead: each jurisdiction has a small versioned blob that says what counts, how the window is measured, where that reading came from.
The paperwork gets the same treatment because documents are state machines too. A passport isn’t just means of identity; it has constraints and timers. Some requirements, like six months validity are legacy and usually exist to keep deportations possible without issuing emergency documents, but still need to be checked.
Before I buy anything the linter should tell me that I don’t have the correct flavour of IDP (and man, getting those in Scotland since they delegated it from Post Offices to corner shops is tough), that a Dubai connection flips a “valid on arrival” buffer into “invalid on departure”. Quiet warnings, early enough to change dates or renew the right booklet, and clear enough that I won’t have to improvise at a counter.
If the world changes—new examples, revised guidance, a delayed system finally launches—I don’t rewrite history. I version the assumption, keep both answers recorded, and move on.
Keeping all those rules up-to-date is hard, so rather than maintaining rules for every country, I parse a few databases, then let users configure their own tracking goals. A user emailed about Cyprus’s fast-tracked tax residency scheme; another pointed out I’d missed a few countries entirely. The app gets better as people use it, which feels more honest than pretending to be a global authority on 195 countries’ immigration rules.
The app is local by default. Calculations happen on-device, and if you’re in airplane mode, it still works. Network is always the bottleneck, and I’m the person who spent a weekend reverse-engineering gym entry to save 44 seconds. I’m not adding server round-trips when you’re standing at a gate.
Being local also means no liability. Personal immigration history is exactly the kind of data governments might want. Keeping it off my servers means nobody can demand I hand it over. Some friends asked about cloud sync: I keep saying no. Not because sync is hard—it is, though surely Claude Code can do that for me —but because the moment you add a server you add retention policies, jurisdiction questions, and a magnet for legal demands. If you want it on another device, export a file and move it yourself like the ancestors did it.
The first version just counted Schengen days, then I added the UK’s midnight arithmetic because I needed it for my own calculations. Then documents with their expiry rules because I was tired of manually looking them up. Then the what-if layer because adding and deleting trips to see impact felt like manually diffing state. Then visa requirements and IDP rules: none of this was planned, it accumulated from use, the same way my fermentation tracker grew from “can I eat this?” to HACCP compliance documents.
I shipped it because keeping it private felt unfinished, and because I’d like fewer people spending twenty minutes researching whether a £62 return flight will cause problems six months later.
That Iceland error fare? I bought it. The app told me I wouldn’t need an IDP, that the trip wouldn’t push me over any Schengen threshold, that I’d leave with 34 days of margin in my 90/180 window, and—importantly—that booking it would mean I’d stop being a UK tax resident given my upcoming Canada move. Useful things to know before clicking purchase. The officer at Keflavík looked at his screen, agreed with his systems, and waved me through.
I called the app Residency and you can get it here. No subscriptions, costs less than an airport martini, and you’ll likely regret it less a few hours later.
You can’t cURL a border. But you can track your own state carefully enough that when the governments know the answer, so do you.
Working on problems where rules are complex and official documentation is contradictory? I build systems that handle state when the state won’t tell you your state. work@drobinin.com
...
Read the original on drobinin.com »
OK, I said there would never be a version three of htmx.
But, technically, I never said anything about a version four…
In The Future of htmx I said the following:
We are going to work to ensure that htmx is extremely stable in both API & implementation. This means accepting and documenting the quirks of the current implementation.
Earlier this year, on a whim, I created fixi.js, a hyperminimalist implementation of the ideas in htmx. That work gave me a chance to get a lot more familiar with the fetch() and, especially, the
async infrastructure available in JavaScript.
In doing that work I began to wonder if that, while the htmx API
is (at least reasonably) correct, maybe there was room for a more dramatic change of the implementation that took advantage of these features in order to simplify the library.
Further, changing from ye olde XMLHttpRequest
(a legacy of htmx 1.0 IE support) to fetch() would be a pretty violent change, guaranteed to break at least some stuff.
So I began thinking: if we are going to consider moving to fetch, then maybe we should also use this update as a chance address at least some of the quirks & cruft that htmx has acquired over its lifetime.
So, eventually & reluctantly, I have changed my mind: there will be another major version of htmx.
However, in order to keep my word that there will not be a htmx 3.0, the next release will instead be htmx 4.0.
With htmx 4.0 we are rebuilding the internals of htmx, based on the lessons learned from fixi.js and five+ years of supporting htmx.
There are three major simplifying changes:
The biggest internal change is that fetch() will replace XMLHttpRequest as the core ajax infrastructure. This won’t actually have a huge effect on most usages of htmx except that the events model will necessarily change due to the differences between fetch() and XMLHttpRequest.
I feel that my biggest mistake in htmx 1.0 & 2.0 was making attribute inheritance implicit. I was inspired by CSS in doing this, and the results have been roughly the same as CSS: powerful & maddening.
In htmx 4.0, attribute inheritance will be explicit rather than implicit, via the :inherited modifier:
Here the hx-target attribute is explicitly declared as inherited on the enclosing div and, if it wasn’t, the
button elements would not inherit the target from it.
This will be the most significant upgrade change to deal with for most htmx users.
Another constant source of pain for both us and for htmx users is history support. htmx 2.0 stores history in local cache to make navigation faster. Unfortunately, snapshotting the DOM is often brittle because of third-party modifications, hidden state, etc. There is a terrible simplicity to the web 1.0 model of blowing everything away and starting over. There are also security concerns storing history information in session storage.
In htmx 2.0, we often end up recommending that people facing history-related issues simply disable the cache entirely, and that usually fixes the problems.
In htmx 4.0, history support will no longer snapshot the DOM and keep it locally. It will, rather, issue a network request for the restored content. This is the behavior of 2.0 on a history cache-miss, and it works reliably with little effort on behalf of htmx users.
We will offer an extension that enables history caching like in htmx 2.0, but it will be opt-in, rather than the default.
This tremendously simplifies the htmx codebase and should make the out-of-the-box behavior much more plug-and-play.
What Stays The Same?
The core functionality of htmx will remain the same, hx-get, hx-post,
hx-target, hx-boost, hx-swap, hx-trigger, etc.
Except for adding an :inherited modifier on a few attributes, many htmx projects will “just work” with htmx 4.
These changes will make the long term maintenance & sustainability of the project much stronger. It will also take pressure off the 2.0 releases, which can now focus on stability rather than contemplating new features.
That said, htmx 2.0 users will face an upgrade project when moving to 4.0 in a way that they did not have to in moving from 1.0 to 2.0.
I am sorry about that, and want to offer three things to address it:
htmx 2.0 (like htmx 1.0 & intercooler.js 1.0) will be supported in perpetuity, so there is absolutely no pressure to
upgrade your application: if htmx 2.0 is satisfying your hypermedia needs, you can stick with it.
We will create extensions that revert htmx 4 to htmx 2 behaviors as much as is feasible (e.g. Supporting the old implicit
attribute inheritance model, at least)
We will roll htmx 4.0 out slowly, over a multi-year period. As with the htmx 1.0 -> 2.0 upgrade, there will be a long
period where htmx 2.x is latest and htmx 4.x is next
Of course, it isn’t all bad. Beyond simplifying the implementation of htmx significantly, switching to fetch also gives us the opportunity to add some nice new features to htmx
By switching to fetch(), we can take advantage of its support for
readable streams, which allow for a stream of content to be swapped into the DOM, rather than a single response.
htmx 1.0 had Server Sent Event support integrated into the library. In htmx 2.0 we pulled this functionality out as an extension. It turns out that SSE is just a specialized version of a streaming response, so in adding streaming support, it’s an almost-free free two-fer to add that back into core as well.
This will make incremental response swapping much cleaner and well-supported in htmx.
Three years ago I had an idea for a DOM morphing algorithm that improved on the initial algorithm pioneered by morphdom.
The idea was to use “id sets” to make smarter decisions regarding which nodes to preserve and which nodes to delete when merging changes into the DOM, and I called this idea “idiomorph”. Idiomorph has gone on to be adopted by many other web project such as Hotwire.
We strongly considered including it in htmx 2.0, but I decided not too because it worked well as an extension and htmx 2.0 had already grown larger than I wanted.
In 4.0, with the complexity savings we achieved by moving to fetch(), we can now comfortably fit a morphInner and
morphOuter swap into core, thanks to the excellent work of Michael West.
htmx has, since very early on, supported a concept of “Out-of-band” swaps: content that is removed from the main HTML response and swapped into the DOM elsewhere. I have always been a bit ambivalent about them, because they move away from Locality of Behavior, but there is no doubt that they are useful and often crucial for achieving certain UI patterns.
Out-of-band swaps started off very simply: if you marked an element as hx-swap-oob=‘true’, htmx would swap the element as the outer HTML of any existing element already in the DOM with that id. Easy-peasy.
However, over time, people started asking for different functionality around Out-of-band swaps: prepending, appending, etc. and the feature began acquiring some fairly baroque syntax to handle all these needs.
We have come to the conclusion that the problem is that there are really two use cases, both currently trying to be filled by Out-of-band swaps:
Therefore, we are introducing the notion of s in htmx 4.0
A partial element is, under the covers, a template element and, thus, can contain any sort of content you like. It specifies on itself all the standard htmx options regarding swapping, hx-target and hx-swap in particular, allowing you full access to all the standard swapping behavior of htmx without using a specialized syntax. This tremendously simplifies the mental model for these sorts of needs, and dovetails well with the streaming support we intend to offer.
Out-of-band swaps will be retained in htmx 4.0, but will go back to their initial, simple focus of simply replacing an existing element by id.
htmx 2.0 has had View Transition support since
April of 2023. In the interceding two years, support for the feature has grown across browsers (c’mon, safari, you can do it) and we’ve gained experience with the feature.
One thing that has become apparent to us while using them is that, to use them in a stable manner, it is important to establish a queue of transitions, so each can complete before the other begins. If you don’t do this, you can get visually ugly transition cancellations.
So, in htmx 4.0 we have added this queue which will ensure that all view transitions complete smoothly.
CSS transitions will continue to work as before as well, although the swapping model is again made much simpler by the async runtime.
We may enable View Transitions by default, the jury is still out on that.
A wonderful thing about fetch() and the async support in general is that it is much easier to guarantee a stable order of events. By linearizing asynchronous code and allowing us to use standard language features like try/catch, the event model of htmx should be much more predictable and comprehensible.
We are going to adopt a new standard for event naming to make things even clearer:
So, for example, htmx:before:request will be triggered before a request is made.
Another opportunity we have is to take advantage of the async behavior of fetch() for much better performance in our preload extension (where we issue a speculative (GET only!) request in anticipation of an actual trigger). We have also added an optimistic update extension to the core extensions, again made easy by the new async features.
In general, we have opened up the internals of the htmx request/response/swap cycle much more fully to extension developers, up to and including allowing them to replace the fetch() implementation used by htmx for a particular request. There should not be a need for any hacks to get the behavior you want out of htmx now: the events and the open “context” object should provide the ability to do almost anything.
In htmx 2.0, I somewhat reluctantly added the hx-on attributes to support light scripting inline on elements. I added this because HTML does not allow you to listen for arbitrary events via on
attributes: only standard DOM events like onclick can be responded to.
We hemmed and hawed about the syntax and so, unfortunately, there are a few different ways to do it.
In htmx 4.0 we will adopt a single standard for the hx-on attributes: hx-on:. Additionally, we are working to improve the htmx JavaScript API (especially around async operation support) and will make those features available in hx-on:
Get A Response Then Remove It 3 Seconds Later
htmx will never support a fully featured scripting mechanism in core, we recommend something like
Alpine.js for that, but our hope is that we can provide a relatively minimalist API that allows for easy, light async scripting of the DOM.
I should note that htmx 4.0 will continue to work with eval() disabled, but you will need to forego a few features like
hx-on if you choose to do so.
All in all, our hope is that htmx 4.0 will feel an awful lot like 2.0, but with better features and, we hope, with fewer bugs.
As always, software takes as long as it takes.
However, our current planned timeline is:
An alpha release is available today: htmx@4.0.0-alpha1
A 4.0.0 release should be available in early-to-mid 2026
4.0 will be marked latest in early-2027ish
You can track our progress (and see quite a bit of dust flying around) in the four branch on
github and at:
Thank you for your patience and pardon our dust!
“Well, when events change, I change my mind. What do you do?” –Paul Samuelson or John Maynard Keynes
...
Read the original on htmx.org »
Arthur Whitney is an esteemed computer scientist who led the design on a few well-known pieces of software:
* kdb, a high-performance database built on K used in fintech
* Shakti, which is like kdb but faster, designed for trillion-row datasets.
I’ve never even seen a trillion numbers, much less calculated them, but kdb is apparently a standard tool on Wall Street. They probably care about money, so I’ll assume kdb does its job well. His languages take significantly after APL, which was a very popular language for similar applications before the invention of (qwerty) keyboards.
But I’m not here to talk about boring things like “using software to make incomprehensible amounts of money in finance” or “human beings and their careers”, I’m here to talk about how a guy writes C code weird. For a very simple version of the programming language K, there’s a publicly available interpreter he wrote in a few days using about 50 lines of C to show the basics of interpreter writing. This is the C (specifically the January 16, 2024 version #2):
typedef char*s,c;s Q=(s)128;
#define _(e…) ({e;})
#define x(a,e…) _(s x=a;e)
#define $(a,b) if(a)b;else
#define i(n,e) {int $n=n;int i=0;for(;i#include”a.h”//fF[+-!#,@] atom/vector 1byte(int/token) clang-13 -Os -oa a.c -w
#define r(n,e) _(s r=m(n);i(n,r[i]=e)r)
f(w,write(1,ax?&x:x,ax?1:strlen(x));x)F(err,w(a);w((s)58);w(x);w((s)10);Q)
_i(wi,s b[5];sprintf(b,“%d ”,x);w(b);0)
f(W,Q(x)$(ax,wi(ix))i(nx,wi(xi))w(10);x)
f(srt,Qz(1)0)f(uni,Qz(1)0)F(Cut,Qz(1)0)F(Drp,Qz(1)0)_i(m,s a=malloc(1+x);*a++=x;a)
#define A(c) ((s)memchr(a,c,na)?:a+na)-a
#define g(a,v) ax?255&a:r(nx,v)
f(not,g(!ix,!xi))f(sub,g(-ix,-xi))F(At,Qr(aa)g(a[ix],a[xi]))F(_A,Qr(aa)g(A(ix),A(xi)))
f(ind,Qr(!ax)0>ix?r(-ix,-ix-1-i):r(ix,i))F(Ind,Qr(!aa)Qd(1>ia)g(ix%ia,xi%ia))
#define G(f,o) F(f,ax?aa?255&ia o ix:Ltn==f?f(sub(x),sub(a)):f(x,a):r(nx,(aa?ia:a[i])o xi))
G(Ltn,
This is the entire interpreter, and this is apparently how he normally writes code. Opinions on his coding style are divided, though general consensus seems to be that it’s incomprehensible. As daunting as it is, I figured I should give it a chance for a few reasons.
* As I work on larger and larger codebases, scrolling up and down to track information has become a more common annoyance. Whitney’s talked about coding the way he does to avoid exactly that: he wants to keep his logic on one screen.
Perhaps learning to read code like this could give me ideas on writing my own code more compactly.
* In a Hacker News comments section, somebody asked “would you rather spend 10 days reading 100,000 lines of code, or 4 days reading 1000?”, and that raises a good point.
The complexity of the code is because even a simple interpreter is pretty complex. Writing it in 500 lines wouldn’t make the complexity go away, it just spreads it out.
Does writing in this more compact format feel more daunting because you’re exposed to more of the complexity at once? I think so.
Does showing it all at once actually help you understand the whole thing faster? I don’t know.
* Reading code has become a more important part of my job than writing it, so I should challenge my reading skills, regardless.
* It confuses people, and that’s basically the same as being smart.
So I’m going to go line by line and explain my understanding. I tried to use the notes provided in the repo only when I was stuck, which was a few times early on, but by the end I could understand it pretty well.
typedef char*s,c;
This already shows some funky C. It defines s as char *, and c as char, because the * attaches to the name, not the type. It’s an oddity of C syntax that I’ve never been a fan of. Otherwise this is pretty straight forward: s is for string, and c is for character.
s Q=(s)128;
Fuck. Shit. He assigned 128 to a string named Q. What does it mean? s is char *. Why is Q a pointer to the address 128? I thought I must have misunderstood, and s was actually a character or something, but it’s clearly specified as char *. s is for string! I couldn’t figure out the meaning, so I soon gave up and looked at the annotated code. The char * is unsigned long long in other versions, and they explain that the type is used for both integers and pointers. The code operates on vectors of 8-bit integers, either as ASCII or numbers, so it makes some sense to use char * from a memory layout perspective, but I don’t use pointers as integers very often.
#define _(e…) ({e;})
#define x(a,e…) _(s x=a;e)
#define $(a,b) if(a)b;else
#define i(n,e) {int $n=n;int i=0;for(;i
These are all pretty straight forward, with one subtle caveat I only realized from the annotated code. They’re all macros to make common operations more compact: wrapping an expression in a block, defining a variable x and using it, conditional statements, and running an expression n times.
The subtle thing the annotations point out is the first macro, ({e;}). The parentheses around curly brackets make this a statement expression, a non-standard C extension that allows you to treat a block of statements as a single expression, if the last statement is an expression that provides a value. In other words, int x = ({int a = func1(); int b = func2(a); a+b;}); sets x to whatever a+b is. This is used everywhere in the code after this.
#define Q(e) if(Q==(e))return Q;
#define Qs(e,s) if(e)return err(__func__,s);
#define Qr(e) Qs(e,“rank”)
#define Qd(e) Qs(e,“domain”)
#define Qz(e) Qs(e,“nyi”)
These are error macros using that mysterious Q defined earlier. Q seems to have been used to represent errors, possibly short for “Quit”. The Qr/d/z functions seem to be types of errors. I have no idea what “nyi” means (I figure it out later).
#define _s(f,e,x…) s f(x){return _(e);}
#define _i(f,e) _s(f,e,c x)
#define f(f,e) _s(f,e,s x)
#define F(f,e) _s(f,e,s a,s x)
These replace function declarations, and we can see that _ macro being used to add an implicit return.
_s could be used like
_s(my_function, puts(“I rock!!!“); x*5+e, s x, int e)
, which would create basically this standard C:
char *my_function(char *x, int e) {
puts(“I rock!!!“);
return x*5+e;
All the macros except the base _s also add implicit arguments like a and x and you bet it’s hard to tell them apart.
#define ax (256>x)
This was another one that baffled me until I looked at the annotations. Remember how I said s values were either integers or pointers? 256 is the cutoff value for these integers, which the annotations call atoms, so ax means “is x an atom?”
#define ix (c)x
#define nx x[-1]
#define xi x[i]
These aren’t too confusing. ix casts x to a char. nx implies x is some sort of fat pointer, meaning there’s probably a length at x[-1], but we’ll see. xi just indexes x as a normal pointer, using our implicitly defined i from the i(…) macro.
#define aa x(a,ax)
#define ia x(a,ix)
#define na x(a,nx)
These copy ax, ix, and nx respectively to work on the a variable, which is an implicit argument in functions defined using the F(f,e) macro. You remembered the x(name, expression) macro for assigning to a locally-scoped x, right?
#define oo w(“oo\n”)
It prints oo. It’s not used anywhere.
I wound up not needing to refer to the annotated code at all to understand this. The C code is mostly using everything in the headers to build the interpreter.
#define r(n,e) _(s r=m(n);i(n,r[i]=e)r)
We create a vector r from m(n) (which is defined later (it’s malloc)), fill r with the results of e, and return it out of the statement expression.
f(w,write(1,ax?&x:x,ax?1:strlen(x));x)
This defines s w(s x), which is our print function. If x is an atom (ax?), we print it as a single character by getting its address (&x) and providing a length of 1. If it’s a vector, we print it as a string using strlen to calculate how long it is, so now we also know vectors must be null-terminated here.
write and strlen are standard functions that we call without including the headers, because fuck headers. Let the linker figure it out.
F(err,w(a);w((s)58);w(x);w((s)10);Q)
Our fancy shmancy error printing function, s err(s a, s x). The confusing thing is that : and the newline are represented by their ASCII numbers 58 and 10, respectively. This just prints a message in the format {a}:{x}\n and returns our special error value Q.
_i(wi,s b[5];sprintf(b,“%d ”,x);w(b);0)
Defines s wi(c x), which takes x as a char, formats it as an integer in up to 5*sizeof(char*)/sizeof(char) characters (40 on 64-bit machines), and writes that.
f(W,Q(x)$(ax,wi(ix))i(nx,wi(xi))w(10);x)
Another print function, s W(s x) either writes x as an integer or a list of integers. It also refuses to print the Q vector.
f(srt,Qz(1)0) f(uni,Qz(1)0) F(Cut,Qz(1)0) F(Drp,Qz(1)0)
I figured out what nyi means! It means “Not yet implemented”, as we can see from these function definitions.
_i(m,s a=malloc(1+x);*a++=x;a)
And we find our previously-used function s m(c x), which allocates our buffer and returns a fat pointer (with the size at x[-1], hence the 1+x and a++). x is the length we’re allocating here, which means our vectors are limited to 255 bytes. The repo suggests upgrading capacity as an exercise to the reader, which could be fun.
#define A(c) ((s)memchr(a,c,na)?:a+na)-a
This macro finds the first occurence of the character c in our vector a as an index into the string (hence the -a, since memchr returns a pointer). If the result is null, it just returns the length of the string (a+na - a). We see another fun bit of non-standard syntax, ?:, which I had to look up. a ?: b is equivalent to a ? a : b without evaluating a twice. Pretty snazzy!
#define g(a,v) ax?255&a:r(nx,v)
Strange little operation, I’ll have to see it in action. If x is an atom, it clamps a to be an atom with a simple mask (255&a), otherwise it creates a new vector the same size as x filled with the result from v.
f(not,g(!ix,!xi)) f(sub,g(-ix,-xi)) F(At,Qr(aa)g(a[ix],a[xi])) F(_A,Qr(aa)g(A(ix),A(xi)))
Ah, I see now. g(a, v) lets us define functions that work on both atoms and vectors. If x is an atom, it returns the atom result clamped within the correct bounds. Otherwise it allocates a new vector and computes the other expression. All the above functions work either on x as an integer (ix), or on every element of x (xi).
* s At(s a, s x) indexes into a, either to get one value or to shuffle them into a new vector. a has to be a vector.
* s _A(s a, s x) searches a vector a for the value of x and gives us the index, either one value or every value in the vector.
This is a lot of functionality in such a small bit of code.
f(ind,Qr(!ax)0>ix?r(-ix,-ix-1-i):r(ix,i))
F(Ind,Qr(!aa)Qd(1>ia)g(ix%ia,xi%ia))
These are some atom-only functions.
* s ind(s x) creates a vector of length |x| containing 0, 1… x-1 if x is positive, otherwise it contains -x-1, -x-2… 0.
...
Read the original on needleful.net »
The diode might be the most neglected component in the electronics curriculum today. Pages upon pages have been written about the mechanics of resistors, capacitors, and inductors; on this blog alone, we covered the components’ fundamental equations, the model of complex impedance, the behavior of R-C filters, and more. As for semiconductors, the diode’s more useful sibling — the transistor — hogs the limelight.
The diode is given neither the mathematical rigor of linear circuits nor the red-carpet treatment of the transistor. To the extent that the component is marveled at all, it’s usually in the context of exotic inventions such as the Gunn diode or the tunnel diode — both of which are almost never encountered in real life.
If you’re rusty on concepts such as voltage, current, or impedance, I suggest reviewing this article first.
In an earlier post about the physics of semiconductors, I noted that pure silicon is a poor conductor of electricity. This is because the material lacks long-lived, mobile charge carriers. Some conduction is still possible due to the short-lived thermal excitation of valence electrons that briefly pop into a higher-energy state, but these electrons can’t travel far before returning to a lower-energy level, so the effect is more or less negligible.
The conductivity of the material is improved by the addition of dopants. Some dopants contribute long-lived electrons that occupy higher energy levels with no lower-energy vacancies to return to; this is what’s called an n-type semiconductor. Other additives create easily-accessible valence band vacancies (“holes”); in such a p-type material, lower-energy electrons can slither around from atom to atom without needing to be knocked into a higher-energy state.
When an n-type material is brought into contact with a p-type semiconductor, higher-energy electrons from the n-side randomly diffuse to the p-side and then promptly fall into the abundant lower-energy holes. This produces a thermodynamic equilibrium with an internal electric field across the junction. There is a positive charge on the n-side and a negative charge on the p-side:
The field pushes any mobile electrons that wander into the depletion region back to the n-side. The result is a thin, poorly conductive depletion region at the boundary.
The field of a p-n junction can be offset by an externally-applied voltage; if we make the p-side sufficiently more positive than the n-side, some current will flow. In the case of silicon, the junction becomes markedly conductive when the forward voltage reaches about 600 mV, although microamp-range currents will be flowing sooner than that.
A conventional diode is just a p-n junction. The component can be thought of as a rudimentary voltage-controlled gate: when the voltage is below a certain threshold, it presents itself as a very high resistance — typically in excess of 100 kΩ — so virtually no current can flow. When the threshold is cleared, the diode admits current that’s roughly proportional to the “excess” applied voltage, an ohmic behavior that’s a consequence of the resistance of the material itself:
So far, we discussed a condition known as forward bias. If the diode is reverse-biased — that is, if the p-side is more negative than the n-side — the component notionally remains nonconductive. Well… up to a point.
One of the possible reverse-bias scenarios is that if the reverse voltage becomes high enough, the electric field can accelerate the odd charge carrier in the depletion region to a point where the particle knocks other electrons into conduction band, producing an avalanche-like effect. The abundance of these kinetically-generated charge carriers makes the junction unexpectedly conductive again.
Most diodes are designed to keep this reverse breakdown voltage well outside the device’s intended operating range. A special category of components — known as Zener diodes — is engineered to exhibit reverse breakdown at lower, carefully calibrated voltages. Either way, once the threshold is exceeded, a reverse-biased diode starts conducting just fine:
Now that we have the basic theory laid out, we can have a look at some of the common uses of diodes.
About the simplest application of diodes is circuit protection. Let’s start with the arrangement shown on the left:
In the first circuit, a Zener-type diode is placed in reverse bias between a protected line and the ground. The diode remains non-conductive under normal operating conditions, but experiences electrical breakdown — and thus temporarily starts conducting — when the input voltage exceeds a safe limit. In effect, the diode acts as a crowbar that dissipates energy and protects more delicate components downstream. Diodes designed for this purpose are often marketed as transient voltage suppressors (TVS) and are particularly important for protecting semiconductors against static discharge. Another application is the suppression of voltage spikes that happen when we abruptly cut the current supplied to motors and other inductive loads.
A single diode can only be used to protect inputs where the input signal has a defined polarity — that is, where one rail is always more positive than the other. To provide overvoltage protection for AC signals with alternating polarity, we instead rely a two-diode arrangement shown on the right in the illustration above. This arrangement of components is also available in a single package known as a bidirectional TVS.
In the latter circuit, regardless of the polarity of the applied voltage, the “crowbar” path always consists of a forward-biased diode in series with a reverse-biased one. It follows that positive and negative conduction thresholds are the same: they’re equal to the diode’s reverse-bias breakdown voltage, plus roughly 600 mV.
Yet another protection technique is shown in the bottom panel. A regular forward-biased diode with a high reverse breakdown voltage is placed in series with the supply; this arrangement prevents damage to sensitive components if the polarity of the supply is accidentally reversed, for example if the batteries are inserted the wrong way. The trade-off is the inevitable voltage drop across the p-n junction, along with resistive heating if the current is high, so a transistor-based solution is typically preferred, especially in low-voltage circuits.
As mentioned earlier, most diodes are designed to withstand very high reverse-bias voltages, often in excess of -100 V; that said, a special category of products — Zener diodes — is designed to start conducting earlier than that.
When forward-biased, such a diode behaves the same as its conventional counterpart, becoming markedly conductive around 600 mV. When reverse-biased, it starts conducting at a low voltage of the manufacturer’s choice, with common low-voltage options ranging from 1.8 V to 30 V.
The V-I plots shown earlier in the article tell us that once reverse breakdown begins, a small change in the applied voltage can produce a comparatively large swing in the current flowing through. We can also look at it another way: if the current through the diode is limited in some way, fluctuations in that current will have a comparatively minor effect on the voltage that develops across the diode’s terminals.
This observation lends itself to the use of diodes as voltage references. We take an unregulated power supply — for example, a battery — and in the simplest variant, use a resistor to roughly limit the current flowing through the diode. Depending on the voltage you want, you can use one or more forward-biased diodes, a Zener diode, or some combination thereof.
From Ohm’s law, the current admitted by the resistor will change linearly with the supply voltage (I = V/R), but these current fluctuations affect the diode voltage to a much lower extent. Here’s an experimental plot for the circuit constructed with a 1N4733 diode and a 100 Ω resistor:
The swing of the output voltage is under 5% of the fluctuations of the input signal: 45 mV versus 1 V. This figure might not sound particularly impressive, but the circuit can be cascaded: the output of one resistor-diode voltage reference can be used as the supply voltage for a second one. The effects stack up: 5% of 5% is equal to 0.25%.
Of course, the Zener voltage of the first diode should be higher than the second one. Further, for the cascaded layout to behave correctly, we need to make sure that the current siphoned off by the second stage is much lower than the current flowing through the intended resistor-diode path. One way to ensure this property is to choose R1 ≪ R2. Another solution is to separate the stages with a transistor circuit that mirrors the output voltage of stage 1 for use by stage 2; such voltage follower circuits are discussed here.
Nowadays, more complex transistor-based circuits with temperature compensation are more favored for precision applications. Nevertheless, a Zener diode still offers a viable a solution in a pinch.
Let’s consider the circuit shown below:
This circuit is called a half-wave rectifier. The analysis is the easiest if we reference all circuit voltages to the bottom output leg marked as B, and then evaluate the positive half-cycle of the input AC waveform separately from the negative half-cycle:
During the positive half-cycle of a sine wave — when the upper terminal of the supply is more positive — the diode is initially forward-biased. Assuming a low-impedance signal source, this allows the capacitor to charge to a voltage equal to the peak amplitude of the input signal, minus some diode voltage drop.
When the polarity of the signal is reversed — making the upper supply terminal more negative — the diode becomes reverse-biased and doesn’t conduct, so the capacitor holds charge. The following is a discrete-time simulation of the process; I added a modest resistive load across the output terminals to discharge the capacitor slightly in between each positive peak:
If the load resistor is made a permanent part of the circuit and if it’s chosen so that the capacitor discharges quickly enough to keep up with the amplitude modulation of a carrier wave, we get a circuit known as the envelope follower. The circuit is a simple way to extract the approximate modulating waveform from the carrier signal in AM radio circuits:
The same principle can be used if we want to build a circuit that measures the approximate loudness of an audio signal, or more generally, hones in on the slow-changing component of any composite waveform.
The drawback of the half-wave rectifier is that the capacitor is only charged by the positive half-cycle of the sine wave; this is wasteful if the goal is to maximize the power delivered to a load. This deficiency can be addressed by constructing a full-wave rectifier, shown below:
Once again, the analysis of the circuit is the simplest if we consider output B to be the reference point:
During the positive half-cycle, diodes D1 and D2 are initially forward-biased; this allows the capacitor to charge to the AC peak voltage (minus the summed voltage drop of two diodes). During the negative half-cycle, diodes D3 and D4 become forward-biased, which connects the output B to the upper supply terminal. Meanwhile, the bottom supply terminal, which is currently at a higher voltage, is connected to point A. This allows the capacitor to continue charging in the same polarity as before.
A simulation of the process is shown below:
The rectifier circuits outlined in the preceding section use diodes as voltage-controlled switches. Another application of the same principle is a circuit known as the voltage doubler.
There are many flavors of voltage doublers, but one particularly clean design is shown below. The circuit outputs a DC voltage that is equal to twice the peak amplitude of the zero-centered input waveform, minus the usual diode voltage drops. This in contrast to the rectifier circuits discussed earlier on, which only produce DC voltages in the vicinity of the peak amplitude:
This time, let’s use use the midpoint between the two capacitors as the reference point for voltage measurements. During the positive half-cycle of the AC signal (panel on the left), the upper diode (D1) can conduct to charge the top capacitor. This puts the output terminal A at a positive voltage in relation to the midpoint.
Next, let’s have a look at the negative half-cycle (right). In this scenario, the top diode is always reverse-biased, so it doesn’t conduct; C1 retains charge. At the same time, conduction is possible for the lower diode D2, which charges C2 so that the output terminal B ends up at a negative voltage in relation to the midpoint. In effect, we store the positive peak voltage of the input waveform in C1 and the negative maximum in C2. The total voltage between B and A is V· 2 (once again, minus the expected diode voltage drops).
This method of multiplying voltages with switched capacitors lives on, although modern circuits typically use digitally-controlled transistors instead of diodes; this avoids voltage drops and eliminates the need for an AC voltage supply. If you’re interested in such circuits, I have a separate article here.
Most of the time, alternating waveforms that are centered around zero volts are inconvenient to work with; in particular, it’s more challenging to build circuits that run off a single voltage supply but that are able to discern, amplify, or generate signals that extend below the negative supply rail.
This brings us to a somewhat mind-bending alternative approach. The circuit is known as a clamper — or, less cryptically, as a DC restorer. It takes an AC waveform and shifts it so that the negative peaks are at roughly zero volts, with no appreciable impact on signal amplitude:
For now, let’s ignore the optional resistor. We start with the first positive half-cycle of the input sine wave (top left):
Initially, the capacitor is not charged (V = 0 V); further, there’s no current path via the diode, so charging is not possible. To elaborate: for energy to be stored in a capacitor, there must be a symmetry in the motion of charges flowing onto and off the plates. This way, the resulting electrostatic fields — increasingly positive on one plate and increasingly negative on another — largely cancel out, allowing a non-trivial charge to be moved with the help of a modest voltage.
If one of the capacitor’s is left floating, the device can’t be charged or discharged; instead, its previous charge state persists as a voltage across its terminals. If we take a capacitor charged to 1 V and connect one of its legs to a 10 V supply, the other leg will read 11 V in reference to the ground. If we connect it to a -5 V supply, we’ll get a reading of -4 V. It’s no different from putting a battery in series with another voltage source. In our circuit, the initial V = 0 V, so in the positive half-cycle, the capacitor adds nothing, and the voltage on the output leg A simply follows the input waveform.
In the following negative half-cycle, once the voltage at point A reaches about -600 mV, the diode starts to conduct (top right). This clamps the voltage at point A while simultaneously allowing the capacitor to charge so that its left terminal becomes negative in relation to the right terminal. If we measure V left to right, the resulting voltage is positive and is equal to the peak amplitude of the supply signal (minus the diode voltage drop).
In the subsequent positive cycle, the diode becomes reverse-biased again, so the capacitor must hold its previous charge; this means that V remains unchanged and that the voltage at point A is necessarily offset from the input waveform by that amount. If the input waveform runs -V to +V, the output will be now moving from roughly -600 mV to V· 2 — 600 mV.
The role of the optional load resistor is that it controls the circuit’s ability to respond to gradual shifts in signal amplitude. Without it, the circuit would theoretically be stuck forever at a voltage offset dictated by the largest encountered single-cycle swing in the input waveform. With a resistor, the capacitor can discharge over time, so the offset can change if the envelope of the waveform changes in some way.
In practice, the diode’s leakage current and the capacitor’s self-discharge rate are typically enough to make the circuit behave reasonably even without an output resistance. If you wish to play around with this layout, I recommend using a 10-100 µF capacitor and either skipping the resistor or using a large one (1 MΩ).
An OR gate is a circuit with two or more inputs that produces a positive voltage when any of the inputs is positive. An AND gate, in contrast, outputs a positive signal only if all the inputs are positive. Many readers are probably familiar with the application of this concept in computing, but more simply: a practical application of an OR gate might be a circuit that raises alarm if any of the door or window sensors are triggered. An application of an AND gate might be a system that illuminates a “PARKING FULL” sign when all the spots are occupied.
There are simple ways to implement this logic with diodes:
In the case of an OR circuit (left), if the positive supply rail is connected to any of the input terminals, this forward-biases the corresponding diode and causes a current to flow through a resistor. Because the impedance of a forward-biased diode is much lower than that of a 10 kΩ resistor, the output voltage shoots up very close to the upper supply rail.
The AND circuit (right) essentially works in reverse: if any of the inputs is connected to the ground, this pulls the output voltage close to 0 V, so the output is positive only if both inputs are high (or are left floating).
The reason I put “gate” in scare quotes in the illustration is that the circuits are not readily composable to implement more complex digital logic; each of the gates requires current to flow through the input terminals, but it can’t necessarily deliver such currents on its output leg. A particularly troublesome situation is shown below:
With the input signals as indicated in the drawing, three out of four diodes are reverse-biased; the only current path is the series resistor-diode-resistor connection between the positive supply rail and the ground. The circuit is essentially a resistor-based voltage divider; instead of providing a binary output, it produces an ambiguous intermediate voltage.
In other words, the solution works for single-step logic; to build real computers, we’d need gates that can deliver output currents higher than what they demand as input of the gates upstream.
👉 For a write-up on photodiodes, click here. For more articles about electronics, math, and geek life, check out this page. And you enjoy the content, please subscribe. I don’t sell anything; it’s just a good way to stay in touch with the authors you like.
...
Read the original on lcamtuf.substack.com »
The morning went well. The mornings always go well. Everybody knows what they’re doing. We’re professionals, equals. Same pay. Same benefits. All working together toward retirement. We look out for each other. Whoever has the hardest task in this crew today could be the foreman tomorrow, and vice versa. Nobody wants to be the boss, so our bosses are the best kind.
See, the truck nobody else wanted had been my office. I’d built a portable desk inside it. My truck desk, I called it. A couple of planks screwed together, our union sticker slapped on, the whole deal sealed with shellac. I’d built the desk so it slid into the bottom of the steering wheel and sat across the armrests. I used to hang back at the job and sneak in some creative work while the rest of the crew went to break. My desk—which I’d taken far too long to build and perfect through many prototypes—had been stowed behind the driver’s seat when the truck was hauled off by the wrecker.
Back at the break trailer, I took my old seat and joined in on the jokes, insults, tall tales. That trailer was, to me, the best place for storytelling in the world—but, as always, it was too loud, too raucous, too fun to do any writing or reading, which is all I ever want to do on break. At lunch, I retreated into the relative quiet of the machine shop. I sat down by the drill press and took out my cell phone and started writing. Just like I used to do.
For nearly two decades I’ve worked off and on at this petrochemical plant as a mechanic and welder. The union dispatched me here: When it gets slow, I get laid off; when work picks up, I boomerang back. And the whole time, I’ve written stories and parts of my novels during breaks—fifteen minutes for coffee and then half an hour for lunch. I’ve also made use of the heaven-sent delays brought on by lightning, severe rainstorms, evacuations, permitting problems, equipment issues, and so on. I’m thankful for each and every delay that happens on this construction site, and, believe me, there are many.
One day I walked into the payroll trailer where the secretaries and site manager sat. There wasn’t an explicit sign that said , but it was an unspoken rule. The trailer had a few unused old cubicles tucked to the side. I sat down in one and happily pecked away with my thumbs. Every break for a week I went in and worked on my writing. After a few days I started to feel like I should hang pictures of my mom and dad and my wife inside it. But I didn’t dare.
Then things really heated up. I brought in a Bluetooth keyboard and wrote a whole story that day on my breaks. There was no going back. My heart soared. I thought I should adopt a brown dog with a bandanna around his neck just so I could thumbtack his picture to the cubicle wall. I hadn’t interacted with any of the office staff, but they’d seen me. They’d followed my oily bootprints down the hallway and begun to leer. Who is this diesel-stinking contractor? He’s probably the one who’s been eating Janelle’s Oreos. He raided the mango-kiwi yogurt from the fridge. He glommed all the sporks. I knew my cubicle dreams were over the morning I found the site manager waiting in “my” cubicle.
In all my years working at that place, I’d never seen the site manager out on the site. I’m not sure he knew what it was or where it was. You went to him to order tools; he was the one who said no. I’d only ever seen him at a urinal or buying bacon and eggs off the lunch truck. But if I had ever seen him out on the site, it would have never occurred to me to ask him what he was doing there. He was wearing a blue polo shirt and khakis, and I was in his world—and he was asking.
I started writing in the machine shop again. It wasn’t the same. Once I’d been infected by the cubicle virus, there was no going back. Out of scrap lumber I gathered from various dumpsters, I built a proper desk for myself in the northeast corner of the shop. That desk was a huge leap forward in possibility and productivity. In the evenings, if I wrote something by hand or on my typewriter at home, I could now use my time at work to retype it at my shop desk.
It was made of three boards cut at twenty-four inches. Light and compact. Sealed with shellac. It slid into the bottom of the steering wheel, one side supported by a curved rebar I welded into a nut that fit exactly in a recess on the driver’s door. The center console supported the other side of the desk. I kept it stored behind the seat. Whenever break time came and the crew drove back to the trailer compound, I stayed parked on the unit and got at least ten extra minutes to write.
Every morning, when I find out what crew I’m in, I bring that plank with me. I stick it on the dashboard and climb into the driver’s seat. I drive us all out to the job and at break time I take them to the trailer. I clean my hands with pumice wipes and sit alone in whoever’s truck it is that day, pulling the plank off the dashboard and setting it across the armrests. Within a minute or so, I’ve got the laptop out and I’m working. If somebody from the crew is still in the back seat, bandanna over their eyes, snoozing, I do my best to keep extra quiet. And if they begin to snore, I don’t let that bother me at all.
Bud Smith is the author of the novel Teenager and the story collection Double Bird, among other books. Mighty, a novel, is forthcoming from Knopf in spring 2027. His story “Skyhawks” appears in the new Fall issue of The Paris Review.
...
Read the original on www.theparisreview.org »
Welcome! This is another Sunday edition of the Animation Obsessive newsletter, and here’s our slate:
A quick note before we start. The newsletter recently passed 60,000 subscribers — a number we can’t believe. Huge thanks to everyone who’s chosen to come along as we look into animation from all over the world.
With that, let’s go!
Before YouTube, TikTok or social media as a whole, there was Flash.
It changed the internet. The Shockwave Flash (.SWF) file format allowed animation and even games to run on dial-up connections. It’s all been retired now — but, in its heyday, web designers everywhere used Flash to make sites feel slick.
There was another group that took to Flash, too: amateur animators. The program was easy to use, and creations with it were easy to share. This caused the first online animation boom. A solo artist with only a home computer could reach millions.
That was a big deal in the United States — but it was, in some ways, a bigger deal in China. Flash arrived there in the late ’90s, and it became era-defining. The so-called “Flashers” (闪客) spoke with the bold, new voice of the younger generation. Their work fascinated the press and public alike.
“Chinese underground films and rock ‘n’ roll music were once the expression of rebellious passions in the pursuit of … new cultural dimensions,” scholar Weihua Wu once wrote, “but today these passions are expressed through the channels of Flash.”
China’s internet cafes were packed with Flash-watchers by the early 2000s. And one of their favorites was Xiao Xiao (2000–2002), a violent action series about stick figures. It was simple, utterly of its time and copied to infinity. Quickly, it outgrew China and became a phenomenon around the world.
For people of a certain age, who grew up online, Xiao Xiao and its clones were part of life. The series isn’t deep and has little to say: it’s just kung fu, firefights, blood and chaos. But it was the height of cool to its (mostly young) audience. It was also a gateway to Flash animation for many.
That was true inside and outside China. Xiao Xiao was a hit on Western sites like Newgrounds and Albino Blacksheep, which hosted Flash files. It did numbers across Taiwan, Korea, Japan and beyond. These brutal little stick figures — and their moves reminiscent of Hong Kong action movies and The Matrix — connected worldwide.
Still, the series is Chinese. Its creator, Zhu Zhiqiang, was a man in his mid-20s. And he was an unlikely star.
Zhu wasn’t trained in animation. Before he discovered Flash, he eked out a living as a graphic designer. He wasn’t tech-y, either. Zhu first encountered computers only in 1997, after his move from Jilin City (in the Northeast) to Beijing.
Those were hard years. Zhu had dropped out after junior high, and his first Beijing job paid 800 yuan per month — something like $181 after inflation. He was clocking endless overtime to make up the difference. In fact, for him, getting work at all could mean telling lies. He landed one job by claiming he’d graduated from a “technical secondary school” but hadn’t brought his diploma.
Still, Zhu had a passion. He loved stick figures. He’d started animating them in 1989, at age 14 — drawing in the corners of book after book, flipping the pages to make his characters move. His inspirations were partly Jackie Chan films, partly his childhood love of Dragon Ball.
Around the turn of the century, Zhu revisited that passion through software.
A lot was happening when he made his first virtual stick-figure fight, Dugu Qiubai, in April 2000. The Flash scene was just taking off in China through sites like Flash Empire. A few months earlier, a violent Flash called Gangster’s Paradise got popular, launching a new era of ambition for Flashers. Its creator became Zhu’s “idol.”
Zhu animated Dugu Qiubai with Corel Painter, but he quickly switched to Flash. He basically started from zero. Not long before, he said, “I had no computer skills, my English was not good, I couldn’t program and my drawing [ability] was average.” He learned Flash mostly alone, using a mouse to create each frame. That became his process. In mid-2000, Zhu made a sequel to Dugu Qiubai called Xiao Xiao No. 2.
These early projects were popular, and they got Zhu a web design job at Sohu, the Beijing company that hosted his work. As 2000 went on, the press noticed China’s Flash scene, and he was one of the artists they profiled. But all of this was only a tee-up for Xiao Xiao No. 3 — the project that made Zhu’s stick figures world-famous.
Zhu put seven months into Xiao Xiao No. 3. It was a hobby project, made in his spare time. The film is simply drawn, and there’s no plot or acting here: just a giant brawl, as a lone stickman takes down a small army. The cool factor was unprecedented for a Flash animation back then, though. It counted for a lot. There’s something a little mesmerizing even today about the movement of Zhu’s fighters.
When Xiao Xiao No. 3 appeared in April 2001, the reaction was immediate, even in the States. Forum users were calling it “mind blowing,” and getting their threads locked because so many people had already posted about it. A Nintendo fansite went off-script to show this “l33t animation” to its readers. Later in the year, it hit the Detroit Free Press:
Just when you thought you’d seen the most Flash animations could do online, along comes Xiao Xiao No. 3. Put simply, it’s a Jackie Chan-style gang-against-one martial arts fight among stick figures. If that sounds silly, the choreography is truly Chan-worthy, with figures running up walls, doing 360-degree kicks and generally showing off the best that martial arts offer. … Even the cinematography is inspiring: 3D shots, slow-motion and a Matrix-style camera wraparound that’ll have you asking for more.
Zhu could tell that he’d hit upon something. He’d burned his email address into the video, and viewers used it to contact him. “The part that made the deepest impression,” Zhu recalled, “was on the third day, I received 1,200 emails in one day. There was no junk in them, and 80% of them were not written by Chinese people, but by people from all over the world.”
Even though the internet was small at the time, Xiao Xiao No. 3’s numbers remain impressive. By late 2001, it had 800,000-plus views on Flash Empire and more than half a million on Newgrounds, not counting the (many) other sites that hosted it. Over the years, the Newgrounds upload alone would climb upward of 5 million. A writer for Flash Empire noted, “I don’t know how the author made such a good work.”
Without warning, Zhu had turned into an early e-celebrity. The Xiao Xiao series blew up just as Flash was taking over the mainland. Some called 2001 “the year of Chinese Flash,” and one magazine named Zhu the “Internet Person of the Year.”
Hearing all the buzz, Zhu’s father went to an internet cafe to see Xiao Xiao for himself. He was shocked. It was the same stuff, he realized, that Zhu had drawn in the corners of those books.
Zhu soon became a freelance animator — and he started to make money. Major brands (like Cityplaza in Hong Kong) wanted his stick figures in their ads. Just three months after Xiao Xiao No. 3, he made a deal with the company Barunson to host the series in Korea.
By the end of 2001, Zhu was on TV with his fellow Flashers, and the press was visiting his home. Again, Zhu was an unlikely star. Reporters found that he slept on a couch, rarely went outside and woke up close to the afternoon. His limit as a cook was a simple potato-and-egg dish, so he ate out a lot — but only cheaply. Asked how long he worked each day, he said, “More than 8 hours.” Besides that, he mainly watched TV.
… is a quiet young man, easygoing and a little shy; he spoke very slowly and it takes him longer than others to put his ideas into words. But when it comes to design and Flash he resolutely sticks to his own ideas. … He stays at home most of the time and seldom goes out, except for some Flashmaker get-togethers and activities. All of his time is devoted to animation.
Zhu didn’t invent violent stickman animations. In the ’90s, the Western site Stick Figure Death Theatre hosted exactly what its name implied. But Xiao Xiao, and its mix of Jackie Chan with Jet Li with The Matrix, perfected the idea. (Also, Zhu denied having seen the foreign stickman work beforehand — after all, he’d done these himself since age 14.)
Either way, it was Xiao Xiao that made “stick fights” massive online. Clones were rampant — even Stick Figure Death Theatre had them. As one paper reported in 2002:
The Web’s legions of part-time Flash animators have begun producing their own copies of Xiao Xiao — so many, in fact, that there’s a whole portal dedicated to them. Stick Figure Death Theatre … has so many stick man knockoffs, you have to wonder why Zhu doesn’t just give up.
The competition didn’t shrink Xiao Xiao, though. As Zhu made new episodes through 2001 and 2002 (a shooting game here, a kung fu film there), his work still towered. And he was getting more ambitious. His code was better, and episodes seven and eight are full of 3D camerawork — done with the help of 3ds Max. Xiao Xiao remained totally style-over-substance, but that style continued to excite the internet.
A question hung over the Flashers, though. Where was all of this headed?
The Flash scene in China was defined by self-expression. As Zhu said, “TV is made for everyone to watch; Flash is made for oneself to watch.” That ethos made the scene bigger and bigger — by 2003, Flash Empire had its own show on television. Yet these artists needed to make money, too. Otherwise, it could only be a hobby.
Money was the hard problem. Getting hired to do Flash animation wasn’t a guarantee, and the rates for this work weren’t always the best. Zhu noted that “most Flashers have very difficult lives.” There was the problem of ownership, too. A lot of Flashers freely swiped copyrighted sound, music and characters. How could they ever charge?
Zhu tried to answer those questions. His “matchstick man,” the pitch-black stick figure that leads Xiao Xiao, was a recognizable character. Brands wanted to associate with it, and Zhu wanted to profit from it. He kept his work as original as possible, copyrighted his films and, in 2003, submitted a trademark application for the stickman.
By then, though, the Nike ads were already airing abroad.
In early 2003, Nike rolled out the “Stickman” campaign. It stars an animated stick figure much like the one in Xiao Xiao, and its flashy moves are, at times, suspiciously similar to Zhu’s ideas. When this campaign hit China, he contacted Nike about it. That went nowhere, so he sued.
Nike was defiant when the story hit the papers. “It is obvious that the plaintiff intended to promote himself and his Flash works by accusing a famous multi-national company,” said one Nike lawyer.
Meanwhile, Zhu said that the Stickman character was so similar to his own, people assumed he’d done the ads himself. Plus, he called stick figures like these a “perfect” fit for sports advertising — which meant trouble for him. “Once Nike uses [these characters], how is anyone going to come to me to make them?” he asked. Already, a publisher had backed out of his book project thanks to Nike’s ads, Zhu claimed.
Although Zhu kept releasing a little Xiao Xiao-branded commercial work, there were no new episodes in 2003. “I’ll resume after the lawsuit is over,” he said. The case turned into a yearslong ordeal. He saw its outcome as critical to his future.
Zhu Zhiqiang told reporters that he has already drawn up a bright “career blueprint” for “Matchstick Man,” but the most important thing right now is to win the lawsuit. After all, these bright prospects are all based on the confirmation of the copyright to “Matchstick Man.”
Zhu initially won in court. Then the appeals process ran until 2006, when he finally lost. The stick figures were too different, according to the judges, and the imagery was too simple to copyright. Nike was in the clear. Zhu faced thousands of dollars in court fees.
After this, he didn’t animate much. Motorola hired him to do another Xiao Xiao-inspired ad in 2007, but the series never returned. By 2008, Zhu worked as a coder. He and James Gao, the creator of Flash Empire, joined the creative agency VML and got involved in mobile games. Xiao Xiao was done.
In many ways, Zhu’s art career was a casualty of the early internet. If the roadmap from viral success to solid income is faint today, it didn’t exist at all in 2003. Getting a Xiao Xiao-sized hit now would, most likely, give someone a shot at starting a business. Zhu had none of the tools necessary to do so.
The Stickman campaign was just another layer of the problem. It was the era when a major company could brush off the bad PR that comes with copying a major online artist. Is it believable that no one involved in the Nike ads had seen Xiao Xiao? Not really — it was popular with young people worldwide. Yet Zhu was new media at a time when old media ruled. What could he do?
All that said, the Xiao Xiao story isn’t one of failure, first and foremost. It has to be emphasized: this series was huge. It inspired people around the world. That happened in China (Bu Hua, the creator of Cat, was a big Xiao Xiao fan) and abroad.
Xiao Xiao is definitely shallow, and its look isn’t adventurous. But that simplicity made it approachable. Any young person could watch it, get it and copy it. Other defining hits from China’s Flash scene — Big Fish & Chinese Flowering Crab Apple, The Black Bird and so on — could be too complex or specific to China for the world to imitate. Xiao Xiao wasn’t. Back then, anyone could understand a stick-figure fight.
Zhu may not have reaped the benefits of this series himself, but he absolutely paved the way for the Flash scene — which paved the way for what came next.
Chinese Flash, which Xiao Xiao helped to pioneer, trained a new generation of animators and filmmakers. Lots of key people started there, including Zhang Ping, whose Legend of Hei II made a serious dent in the box office this year. Flash artists abroad were no less impacted by the success of Zhu’s work.
A couple of years ago, an archivist named Ben Latimore put out an ebook. Since Adobe began the retirement of Flash in 2017, he’s been preserving .SWF files and the history around them. His book is a chronicle of the Flash era, which he sees as a lost golden age. On the final page, he wrote this about that time:
… intense creativity, easy-to-access software, notable but not crippling limitations, almost universal compatibility across the entire technological space of its time, widespread adoption by encouraging free consumption and sharing in an age where “going viral” actually meant something, all combining to influence the entire entertainment industry with one strike after another? That’s something that we’ll never be able to recreate, only remember fondly. All driven by a bunch of guys sitting in their bedrooms who watched too much Xiao Xiao.
...
Read the original on animationobsessive.substack.com »
Police in Israel have arrested and detained the military’s top legal officer after she admitted leaking footage of soldiers allegedly attacking a Palestinian detainee and then in effect lying about her actions to Israel’s high court.
The military advocate general, Yifat Tomer-Yerushalmi, said in a resignation letter last week that she had authorised publication of the video to defuse attacks on military investigators and prosecutors working on the case.
Rightwing politicians and pundits championed soldiers detained over the case as “heroes”, attacked military investigators as traitors, and called for the case against the soldiers to be dropped.
Tomer-Yerushalmi has now been arrested on suspicion of fraud and breach of trust, abuse of office, obstruction of justice, and disclosure of official information by a public servant, Israeli media reported.
Her arrest and detention raises serious questions about the rule of law in Israel, accountability for abuse and killing of Palestinians during what a UN commission has called a genocidal war, and the country’s ability to defend itself in international courts.
In July 2024 prosecutors raided the Sde Teiman military detention centre, which has become notorious for torture, and detained 11 soldiers for interrogation.
They were suspects in a violent assault on a Palestinian from Gaza, including anal rape. The victim was hospitalised with injuries including broken ribs, a punctured lung and rectal damage, according to the indictment, and Tomer-Yerushalmi launched an investigation.
The government and far-right politicians and pundits have accused her of damaging Israel’s global standing by pursing the case and releasing the video, in effect casting her efforts to prosecute extreme violence as a project to undermine the state.
“The incident in Sde Teiman caused immense damage to the image of the state of Israel and the IDF [Israel Defense Forces],” the Israeli prime minister, Benjamin Netanyahu, said in a statement on Sunday. “This is perhaps the most severe public relations attack that the state of Israel has experienced since its establishment.”
After the first detentions of soldiers in the case in summer 2024, a far-right mob gathered outside Sde Teiman calling for the investigation to be dropped. Some of the protesters — including a minister and two members of the Knesset — broke into the base.
Tomer-Yerushalmi leaked the video in August 2024 after the protests, saying in her resignation letter that it was “an attempt to debunk false propaganda against army law enforcement bodies”.
Days later, five soldiers were charged with aggravated abuse and causing serious bodily harm. They have not been named and are currently not in custody or under any legal restrictions, Israeli media reported.
Tomer-Yerushalemi subsequently refused to open or advance investigations into other cases of possible war crimes by the Israeli military, because of the pressure of public attacks over the case, Haaretz reported.
There has been only one conviction of an Israeli soldier for assaulting Palestinians in detention during the war, although widespread torture and abuse have been documented in Israel’s jail system, and dozens of Palestinians have died in captivity.
No soldiers have been charged for killing civilians in Gaza, even after high-profile attacks that prompted international outrage, including the killing of paramedics and strikes on a team from the World Central Kitchen charity. Tens of thousands of Palestinian civilians in Gaza have been killed in attacks and airstrikes over two years.
Attacks on Tomer-Yerushalemi over the Sde Teiman affair intensified in recent days amid reports that she was responsible for leaking the video. There were official demands for her to step down and personal threats online, even after she announced her resignation.
The campaign briefly halted on Sunday afternoon amid fears for her life, after her partner reported her missing to the police and her car was found empty at a beach in the Tel Aviv area with a note inside, Israeli media reported.
Then she was found, and within minutes the attacks resumed. The far-right commentator Yinon Magal posted on X, “we can proceed with the lynching”, adding a winking emoji.
Soon after, protesters had gathered outside her house, Israeli media reported, shouting slogans including “we will give you no peace”. The defence minister, Israel Katz, later accused her of “spreading blood libels”.
Traditionally Israel’s government and military have considered the existence of an independent judiciary a crucial barrier to international legal tribunals investigating Israel for alleged abuses against Palestinians.
Where there is a robust national legal system willing and able to investigate and prosecute crimes, international courts are less likely to have jurisdiction to intervene.
“Don’t they understand we had no choice? That the only way to address the wave of international legal proceedings is by proving we can investigate ourselves?” the investigative reporter Ronen Bergman quoted the advocate general telling colleagues six weeks ago, in a report for Yedioth Ahronoth newspaper.
In recent decades many Israelis have seen the role of the military advocate general “as protecting soldiers from prosecution abroad”, said Prof Yagil Levy, head of the Institute for the Study of Civil-Military Relations at Israel’s Open University.
“In other words, the law is not upheld as a value in itself, but as a defence against international tribunals.”
Now even such legal pragmatism is under attack by the political right, whose influence can be seen in the lack of legal accountability for soldiers’ conduct in Gaza over the past two years, Levy added.
“During the war, the advocate general gave the army a free hand in Gaza, for example, regarding the unprecedented collateral damage from airstrikes,” he said.
“This reflects a far weaker commitment to international law, with some on the right claiming that Israel is exempt from respecting it, and even providing religious justifications for this view.”
...
Read the original on www.theguardian.com »
Skip to main contentThe Case That A. I. Is ThinkingChatGPT does not have an inner life. Yet it seems to know what it’s talking about.How convincing does the illusion of understanding have to be before you stop calling it an illusion?Dario Amodei, the C.E.O. of the artificial-intelligence company Anthropic, has been predicting that an A.I. “smarter than a Nobel Prize winner” in such fields as biology, math, engineering, and writing might come online by 2027. He envisions millions of copies of a model whirring away, each conducting its own research: a “country of geniuses in a datacenter.” In June, Sam Altman, of OpenAI, wrote that the industry was on the cusp of building “digital superintelligence.” “The 2030s are likely going to be wildly different from any time that has come before,” he asserted. Meanwhile, the A.I. tools that most people currently interact with on a day-to-day basis are reminiscent of Clippy, the onetime Microsoft Office “assistant” that was actually more of a gadfly. A Zoom A.I. tool suggests that you ask it “What are some meeting icebreakers?” or instruct it to “Write a short message to share gratitude.” Siri is good at setting reminders but not much else. A friend of mine saw a button in Gmail that said “Thank and tell anecdote.” When he clicked it, Google’s A.I. invented a funny story about a trip to Turkey that he never took.The rushed and uneven rollout of A.I. has created a fog in which it is tempting to conclude that there is nothing to see here—that it’s all hype. There is, to be sure, plenty of hype: Amodei’s timeline is science-fictional. (A.I. models aren’t improving that fast.) But it is another kind of wishful thinking to suppose that large language models are just shuffling words around. I used to be sympathetic to that view. I sought comfort in the idea that A.I. had little to do with real intelligence or understanding. I even celebrated its shortcomings—rooting for the home team. Then I began using A.I. in my work as a programmer, fearing that if I didn’t I would fall behind. (My employer, a trading firm, has several investments in and partnerships with A.I. companies, including Anthropic.) Writing code is, by many accounts, the thing that A.I. is best at; code has more structure than prose does, and it’s often possible to automatically validate that a given program works. My conversion was swift. At first, I consulted A.I. models in lieu of looking something up. Then I gave them small, self-contained problems. Eventually, I gave them real work—the kind I’d trained my whole career to do. I saw these models digest, in seconds, the intricate details of thousands of lines of code. They could spot subtle bugs and orchestrate complex new features. Finally, I was transferred to a fast-growing team that aims to make better use of A.I. tools, and to create our own.The science-fiction author William Gibson is said to have observed that the future is already here, just not evenly distributed—which might explain why A.I. seems to have minted two cultures, one dismissive and the other enthralled. In our daily lives, A.I. “agents” that can book vacations or file taxes are a flop, but I have colleagues who compose much of their code using A.I. and sometimes run multiple coding agents at a time. Models sometimes make amateur mistakes or get caught in inane loops, but, as I’ve learned to use them effectively, they have allowed me to accomplish in an evening what used to take a month. Not too long ago, I made two iOS apps without knowing how to make an iOS app.“O.K., we’re good on bread crumbs. Now we’re looking for a pound of ground beef and a pound of veal.”I once had a boss who said that a job interview should probe for strengths, not for the absence of weaknesses. Large language models have many weaknesses: they famously hallucinate reasonable-sounding falsehoods; they can be servile even when you’re wrong; they are fooled by simple puzzles. But I remember a time when the obvious strengths of today’s A.I. models—fluency, fluidity, an ability to “get” what someone is talking about—were considered holy grails. When you experience these strengths firsthand, you wonder: How convincing does the illusion of understanding have to be before you stop calling it an illusion?On a brutally hot day this summer, my friend Max met up with his family at a playground. For some reason, a sprinkler for kids was switched off, and Max’s wife had promised everyone that her husband would fix it. Confronted by red-faced six- and seven-year-olds, Max entered a utility shed hoping to find a big, fat “On” switch. Instead, he found a maze of ancient pipes and valves. He was about to give up when, on a whim, he pulled out his phone and fed a photo into ChatGPT-4o, along with a description of his problem. The A.I. thought for a second, or maybe didn’t think, but all the same it said that he was looking at a backflow-preventer system typical of irrigation setups. Did he see that yellow ball valve toward the bottom? That probably controlled the flow. Max went for it, and cheers rang out across the playground as the water turned on.Was ChatGPT mindlessly stringing words together, or did it understand the problem? The answer could teach us something important about understanding itself. “Neuroscientists have to confront this humbling truth,” Doris Tsao, a neuroscience professor at the University of California, Berkeley, told me. “The advances in machine learning have taught us more about the essence of intelligence than anything that neuroscience has discovered in the past hundred years.” Tsao is best known for decoding how macaque monkeys perceive faces. Her team learned to predict which neurons would fire when a monkey saw a specific face; even more strikingly, given a pattern of neurons firing, Tsao’s team could render the face. Their work built on research into how faces are represented inside A.I. models. These days, her favorite question to ask people is “What is the deepest insight you have gained from ChatGPT?” “My own answer,” she said, “is that I think it radically demystifies thinking.”The most basic account of how we got here goes something like this. In the nineteen-eighties, a small team of cognitive psychologists and computer scientists tried to simulate thinking in a machine. Among the more famous of them were David Rumelhart, Geoffrey Hinton, and James McClelland, who went on to form a research group at U.C. San Diego. They saw the brain as a vast network in which neurons fire in patterns, causing other sets of neurons to fire, and so on; this dance of patterns is thinking. The brain learns by changing the strength of the connections between neurons. Crucially, the scientists mimicked this process by creating an artificial neural network, and by applying a simple algorithm called gradient descent to increase the accuracy of its predictions. (The algorithm could be compared to a hiker navigating from a mountaintop to a valley; a simple strategy for eventually finding one’s way is to insure that every step moves downhill.) The use of such algorithms in large networks is known as deep learning.Other people in A.I. were skeptical that neural networks were sophisticated enough for real-world tasks, but, as the networks got bigger, they began to solve previously unsolvable problems. People would devote entire dissertations to developing techniques for distinguishing handwritten digits or for recognizing faces in images; then a deep-learning algorithm would digest the underlying data, discover the subtleties of the problem, and make those projects seem obsolete. Deep learning soon conquered speech recognition, translation, image captioning, board games, and even the problem of predicting how proteins will fold.Today’s leading A.I. models are trained on a large portion of the internet, using a technique called next-token prediction. A model learns by making guesses about what it will read next, then comparing those guesses to whatever actually appears. Wrong guesses inspire changes in the connection strength between the neurons; this is gradient descent. Eventually, the model becomes so good at predicting text that it appears to know things and make sense. So that is something to think about. A group of people sought the secret of how the brain works. As their model grew toward a brain-like size, it started doing things that were thought to require brain-like intelligence. Is it possible that they found what they were looking for?There is understandable resistance to such a simplistic and triumphant account of A.I. The case against it was well argued by Ted Chiang, who wrote an article for this magazine in early 2023 titled “ChatGPT Is a Blurry JPEG of the Web.” He meant it in a more or less deflationary way: that’s all ChatGPT is. You feed the whole internet to a program and it regurgitates it back to you imperfectly, like a copy of a copy of a photograph—but with just enough facility to fool you into believing that the program is intelligent. This spring, a similar argument was made in a book, “The AI Con,” by Emily M. Bender, a linguist, and Alex Hanna, a sociologist. Bender is perhaps best known for describing L.L.M.s as “stochastic parrots.” “Large language models do not, cannot, and will not ‘understand’ anything at all,” the writer Tyler Austin Harper declared in a book review in The Atlantic. Models “produce writing not by thinking but by making statistically informed guesses about which lexical item is likely to follow another.” Harper buttressed these technical arguments with moral ones. A.I. enriches the powerful, consumes enough energy to accelerate climate change, and marginalizes workers. He concluded that “the foundation of the AI industry is a scam.”But the moral case against A.I. may ultimately be stronger than the technical one. “The ‘stochastic parrot’ thing has to be dead at some point,” Samuel J. Gershman, a Harvard cognitive scientist who is no A.I. hype man, told me. “Only the most hardcore skeptics can deny these systems are doing things many of us didn’t think were going to be achieved.” Jonathan Cohen, a cognitive neuroscientist at Princeton, emphasized the limitations of A.I., but argued that, in some cases, L.L.M.s seem to mirror one of the largest and most important parts of the human brain. “To a first approximation, your neocortex is your deep-learning mechanism,” Cohen said. Humans have a much larger neocortex than other animals, relative to body size, and the species with the largest neocortices—elephants, dolphins, gorillas, chimpanzees, dogs—are among the most intelligent.In 2003, the machine-learning researcher Eric B. Baum published a book called “What Is Thought?” (I stumbled upon it in my college’s library stacks, drawn by the title.) The gist of Baum’s argument is that understanding is compression, and compression is understanding. In statistics, when you want to make sense of points on a graph, you can use a technique called linear regression to draw a “line of best fit” through them. If there’s an underlying regularity in the data—maybe you’re plotting shoe size against height—the line of best fit will efficiently express it, predicting where new points could fall. The neocortex can be understood as distilling a sea of raw experience—sounds, sights, and other sensations—into “lines of best fit,” which it can use to make predictions. A baby exploring the world tries to guess how a toy will taste or where food will go when it hits the floor. When a prediction is wrong, the connections between neurons are adjusted. Over time, those connections begin to capture regularities in the data. They form a compressed model of the world.Artificial neural networks compress experience just like real neural networks do. One of the best open-source A.I. models, DeepSeek, is capable of writing novels, suggesting medical diagnoses, and sounding like a native speaker in dozens of languages. It was trained using next-token prediction on many terabytes of data. But when you download the model it is one six-hundredth of that. A distillation of the internet, compressed to fit on your laptop. Ted Chiang was right to call an early version of ChatGPT a blurry JPEG of the web—but, in my view, this is the very reason these models have become increasingly intelligent. Chiang noted in his piece that, to compress a text file filled with millions of examples of arithmetic, you wouldn’t create a zip file. You’d write a calculator program. “The greatest degree of compression can be achieved by understanding the text,” he wrote. Perhaps L.L.M.s are starting to do that.It can seem unnatural, even repulsive, to imagine that a computer program actually understands, actually thinks. We usually conceptualize thinking as something conscious, like a Joycean inner monologue or the flow of sense memories in a Proustian daydream. Or we might mean reasoning: working through a problem step by step. In our conversations about A.I., we often conflate these different kinds of thinking, and it makes our judgments pat. ChatGPT is obviously not thinking, goes one argument, because it is obviously not having a Proustian reverie; ChatGPT clearly is thinking, goes another, because it can work through logic puzzles better than you can.Something more subtle is going on. I do not believe that ChatGPT has an inner life, and yet it seems to know what it’s talking about. Understanding—having a grasp of what’s going on—is an underappreciated kind of thinking, because it’s mostly unconscious. Douglas Hofstadter, a professor of cognitive science and comparative literature at Indiana University, likes to say that cognition is recognition. Hofstadter became famous for a book about the mind and consciousness called “Gödel, Escher, Bach: An Eternal Golden Braid,” which won a Pulitzer Prize in 1980. Hofstadter’s theory, developed through decades of research, is that “seeing as” is the essence of thinking. You see one patch of color as a car and another as a key chain; you recognize the letter “A” no matter what font it is written in or how bad the handwriting might be. Hofstadter argued that the same process underlies more abstract kinds of perception. When a grand master examines a chess board, years of practice are channelled into a way of seeing: white’s bishop is weak; that endgame is probably a draw. You see an eddy in a river as a sign that it’s dangerous to cross. You see a meeting you’re in as an emperor-has-no-clothes situation. My nearly two-year-old son recognizes that late-morning stroller walks might be an opportunity for a croissant and makes demands accordingly. For Hofstadter, that’s intelligence in a nutshell.Hofstadter was one of the original A.I. deflationists, and my own skepticism was rooted in his. He wrote that most A.I. research had little to do with real thinking, and when I was in college, in the two-thousands, I agreed with him. There were exceptions. He found the U.C.S.D. group interesting. And he admired the work of a lesser-known Finnish American cognitive scientist, Pentti Kanerva, who noticed some unusual properties in the mathematics of high-dimensional spaces. In a high-dimensional space, any two random points may be extremely far apart. But, counterintuitively, each point also has a large cloud of neighbors around it, so you can easily find your way to it if you get “close enough.” That reminded Kanerva of the way that memory works. In a 1988 book called “Sparse Distributed Memory,” Kanerva argued that thoughts, sensations, and recollections could be represented as coördinates in high-dimensional space. The brain seemed like the perfect piece of hardware for storing such things. Every memory has a sort of address, defined by the neurons that are active when you recall it. New experiences cause new sets of neurons to fire, representing new addresses. Two addresses can be different in many ways but similar in others; one perception or memory triggers other memories nearby. The scent of hay recalls a memory of summer camp. The first three notes of Beethoven’s Fifth beget the fourth. A chess position that you’ve never seen reminds you of old games—not all of them, just the ones in the right neighborhood.“Bye, sweetie—have a day filled with social drama, drastically shifting friendships, and academic milestones, which you’ll describe to me later as ‘fine.’ ”Hofstadter realized that Kanerva was describing something like a “seeing as” machine. “Pentti Kanerva’s memory model was a revelation for me,” he wrote in a foreword to Kanerva’s book. “It was the very first piece of research I had ever run across that made me feel I could glimpse the distant goal of understanding how the brain works as a whole.” Every kind of thinking—whether Joycean, Proustian, or logical—depends on the relevant thing coming to mind at the right time. It’s how we figure out what situation we’re in.Kanerva’s book receded from view, and Hofstadter’s own star faded—except when he occasionally poked up his head to criticize a new A.I. system. In 2018, he wrote of Google Translate and similar technologies: “There is still something deeply lacking in the approach, which is conveyed by a single word: understanding.” But GPT-4, which was released in 2023, produced Hofstadter’s conversion moment. “I’m mind-boggled by some of the things that the systems do,” he told me recently. “It would have been inconceivable even only ten years ago.” The staunchest deflationist could deflate no longer. Here was a program that could translate as well as an expert, make analogies, extemporize, generalize. Who were we to say that it didn’t understand? “They do things that are very much like thinking,” he said. “You could say they are thinking, just in a somewhat alien way.”L.L.M.s appear to have a “seeing as” machine at their core. They represent each word with a series of numbers denoting its coördinates—its vector—in a high-dimensional space. In GPT-4, a word vector has thousands of dimensions, which describe its shades of similarity to and difference from every other word. During training, a large language model tweaks a word’s coördinates whenever it makes a prediction error; words that appear in texts together are nudged closer in space. This produces an incredibly dense representation of usages and meanings, in which analogy becomes a matter of geometry. In a classic example, if you take the word vector for “Paris,” subtract “France,” and then add “Italy,” the nearest other vector will be “Rome.” L.L.M.s can “vectorize” an image by encoding what’s in it, its mood, even the expressions on people’s faces, with enough detail to redraw it in a particular style or to write a paragraph about it. When Max asked ChatGPT to help him out with the sprinkler at the park, the model wasn’t just spewing text. The photograph of the plumbing was compressed, along with Max’s prompt, into a vector that captured its most important features. That vector served as an address for calling up nearby words and concepts. Those ideas, in turn, called up others as the model built up a sense of the situation. It composed its response with those ideas “in mind.”A few months ago, I was reading an interview with an Anthropic researcher, Trenton Bricken, who has worked with colleagues to probe the insides of Claude, the company’s series of A.I. models. (Their research has not been peer-reviewed or published in a scientific journal.) His team has identified ensembles of artificial neurons, or “features,” that activate when Claude is about to say one thing or another. Features turn out to be like volume knobs for concepts; turn them up and the model will talk about little else. (In a sort of thought-control experiment, the feature representing the Golden Gate Bridge was turned up; when one user asked Claude for a chocolate-cake recipe, its suggested ingredients included “1/4 cup dry fog” and “1 cup warm seawater.”) In the interview, Bricken mentioned Google’s Transformer architecture, a recipe for constructing neural networks that underlies leading A.I. models. (The “T” in ChatGPT stands for “Transformer.”) He argued that the mathematics at the heart of the Transformer architecture closely approximated a model proposed decades earlier—by Pentti Kanerva, in “Sparse Distributed Memory.”Should we be surprised by the correspondence between A.I. and our own brains? L.L.M.s are, after all, artificial neural networks that psychologists and neuroscientists helped develop. What’s more surprising is that when models practiced something rote—predicting words—they began to behave in such a brain-like way. These days, the fields of neuroscience and artificial intelligence are becoming entangled; brain experts are using A.I. as a kind of model organism. Evelina Fedorenko, a neuroscientist at M.I.T., has used L.L.M.s to study how brains process language. “I never thought I would be able to think about these kinds of things in my lifetime,” she told me. “I never thought we’d have models that are good enough.”It has become commonplace to say that A.I. is a black box, but the opposite is arguably true: a scientist can probe the activity of individual artificial neurons and even alter them. “Having a working system that instantiates a theory of human intelligence—it’s the dream of cognitive neuroscience,” Kenneth Norman, a Princeton neuroscientist, told me. Norman has created computer models of the hippocampus, the brain region where episodic memories are stored, but in the past they were so simple that he could only feed them crude approximations of what might enter a human mind. “Now you can give memory models the exact stimuli you give to a person,” he said.The Wright brothers studied birds during their early efforts to build an airplane. They noted that birds take off into the wind, even though a reasonable person might have assumed they’d want the wind at their backs, and that they warp the tips of their wings for balance. These findings influenced their rudimentary glider designs. Then they built a six-foot-long wind tunnel, which allowed them to test a set of artificial wings under precisely controlled conditions. Their next round of glider flights was far more successful. Strangely, it was only well after they’d made a working flying machine that it became possible to understand exactly how the birds do it.A.I. enables scientists to place thinking itself in a wind tunnel. For a paper provocatively titled “On the Biology of a Large Language Model,” Anthropic researchers observed Claude responding to queries and described “circuits”—cascades of features that, together, perform complex computations. (Calling up the right memories is one step toward thinking; combining and manipulating them in circuits is arguably another.) One longstanding criticism of L.L.M.s has been that, because they must generate one token of their response at a time, they can’t plan or reason. But, when you ask Claude to finish a rhyming couplet in a poem, a circuit begins considering the last word of the new line, to insure that it will rhyme. It then works backward to compose the line as a whole. Anthropic researchers counted this as evidence that their models do engage in planning. Squint a little and you might feel, for the first time, that the inner workings of a mind are in view.You really do have to squint, though. “The worry I have is that people flipped the bit from ‘I’m really skeptical of this’ to totally dropping their shields,” Norman, the Princeton neuroscientist, told me. “Many things still have to get figured out.” I’m one of the people that Norman is talking about. (Perhaps I am too easily moved by the seeming convergence of “Sparse Distributed Memory” and an Anthropic model.) In the past year or two, I started to believe what Geoffrey Hinton, who recently won a Nobel Prize for his A.I. research, told the journalist Karen Hao in 2020: “Deep learning is going to be able to do everything.” But we have also seen that larger models aren’t always better models. Curves plotting model performance against size have begun flattening out. It’s becoming difficult to find high-quality data that the models haven’t already digested, and computing power is increasingly expensive. When GPT-5 came out, in August, it was a merely incremental improvement—and so profound a disappointment that it threatened to pop the A.I. investment bubble. The moment demands a middle kind of skepticism: one that takes today’s A.I. models seriously without believing that there are no hard problems left.Perhaps the most consequential of these problems is how to design a model that learns as efficiently as humans do. It is estimated that GPT-4 was exposed to trillions of words in training; children need only a few million to become fluent. Cognitive scientists tell us that a newborn’s brain has certain “inductive biases” that accelerate learning. (Of course, the brain is the result of millions of years of evolution—itself a sort of training data.) For instance, human babies have the expectation that the world is made of objects, and that other beings have beliefs and intentions. When Mama says “banana,” an infant connects that word to the entire yellow object she’s looking at—not just its tip or its peel. Infants perform little experiments: Can I eat this? How far can I throw that? They are motivated by emotions such as desire, curiosity, and frustration. Children are always trying to do something just beyond their ability. Their learning is efficient because it’s embodied, adaptive, deliberate, and continuous. Maybe truly understanding the world requires participating in it.An A.I.’s experience, in comparison, is so impoverished that it can’t really be called “experience.” Large language models are trained on data that is already extraordinarily refined. “I think the reason they work is that they’re piggybacking on language,” Tsao, the U.C. Berkeley neuroscientist, told me. Language is like experience pre-chewed; other kinds of data are less dense with meaning. “Why is it that we haven’t had a comparable revolution in terms of reasoning about video data?” Gershman, the Harvard cognitive scientist, asked. “The kinds of vision models that we have still struggle with common-sense reasoning about physics.” A recent model from DeepMind can generate videos in which paints are mixed correctly and mazes are solved—but they also depict a glass bouncing, instead of shattering, and ropes defying physics by being smooshed into a knot. Ida Momennejad, a cognitive neuroscientist who now works for Microsoft Research, has done experiments in which an L.L.M. is given a virtual walk-through of a building and then asked questions about routes and shortcuts—spatial inferences that come easily to humans. With all but the most basic setups, the A.I.s tend to fail or hallucinate nonexistent paths. “Do they really do planning?” she said. “Not really.”In my conversations with neuroscientists, I sensed a concern that the A.I. industry is racing ahead somewhat thoughtlessly. If the goal is to make artificial minds as capable as human minds are, then “we’re not training the systems in the right way,” Brenden M. Lake, a cognitive scientist at Princeton, told me. When an A.I. is done training, the neural network’s “brain” is frozen. If you tell the model some facts about yourself, it doesn’t rewire its neurons. Instead, it uses a crude substitute: it writes down a bit of text—“The user has a toddler and is studying French”—and considers that before other instructions you give. The human brain updates itself continuously, and there’s a beautiful theory about one of its ways of doing so: when you sleep, selected snapshots from your episodic memory are replayed for your neocortex in order to train it. Your high-dimensional thought space gets dimpled by the replayed memories; you wake up with a slightly new way of seeing.The A.I. community has become so addicted to—and so financially invested in—breakneck progress that it sometimes pretends that advancement is inevitable and there’s no science left to do. Science has the inconvenient property of sometimes stalling out. Silicon Valley may call A.I. companies “labs,” and some employees there “researchers,” but fundamentally it has an engineering culture that does whatever works. “It’s just so remarkable how little the machine-learning community bothers looking at, let alone respects, the history and cognitive science that precedes it,” Cohen said.Today’s A.I. models owe their success to decades-old discoveries about the brain, but they are still deeply unlike brains. Which differences are incidental and which are fundamental? Every group of neuroscientists has its pet theory. These theories can be put to the test in a way that wasn’t possible before. Still, no one expects easy answers. The problems that continue to plague A.I. models “are solved by carefully identifying ways in which the models don’t behave as intelligently as we want them to and then addressing them,” Norman said. “That is still a human-scientist-in-the-loop process.”In the nineties, billions of dollars poured into the Human Genome Project on the assumption that sequencing DNA might solve medicine’s most vexing problems: cancer, hereditary conditions, even aging. It was a time of bluster and confidence—the era of Dolly the cloned sheep and “Jurassic Park”—when biotech was ascendant and the commentariat reckoned with whether humans should be playing God. Biologists soon found that the reality was more complicated. We didn’t cure cancer or discover the causes of Alzheimer’s or autism. We learned that DNA tells just one part of the story of life. In fact, one could argue that biology got swept up in a kind of gene fever, fixating on DNA because we had the means to study and understand it.Still, nobody would claim that Francis Crick was wrong when, on the day in 1953 that he helped confirm the structure of DNA, he walked into a Cambridge pub talking about having discovered the secret of life. He and his colleagues did more to demystify life than almost anyone, ever. The decades following their discovery were among the most productive and exciting in the history of science. DNA became a household term; every high schooler learns about the double helix.With A.I., we once again find ourselves in a moment of bluster and confidence. Sam Altman talks about raising half a trillion dollars to build Stargate, a new cluster of A.I. data centers, in the U.S. People discuss the race for superintelligence with a gravitas and an urgency that can seem ungrounded, even silly. But I suspect the reason that the Amodeis and Altmans of the world are making messianic pronouncements is that they believe that the basic picture of intelligence has been worked out; the rest is just details.Even some neuroscientists believe that a crucial threshold has been crossed. “I really think it could be the right model for cognition,” Uri Hasson, a colleague of Cohen’s, Norman’s, and Lake’s at Princeton, said of neural networks. This upsets him as much as it excites him. “I have the opposite worry of most people,” he said. “My worry is not that these models are similar to us. It’s that we are similar to these models.” If simple training techniques can enable a program to behave like a human, maybe humans aren’t as special as we thought. Could it also mean that A.I. will surpass us not only in knowledge but also in judgment, ingenuity, cunning—and, as a result, power? To my surprise, Hasson told me that he is “worried these days that we might succeed in understanding how the brain works. Pursuing this question may have been a colossal mistake for humanity.” He likened A.I. researchers to nuclear scientists in the nineteen-thirties: “This is the most interesting time in the life of these people. And, at the same time, they know that what they are working on has grave implications for humanity. But they cannot stop because of the curiosity to learn.”One of my favorite books by Hofstadter is a nerdy volume called “Fluid Concepts and Creative Analogies: Computer Models of the Fundamental Mechanisms of Thought.” When I was in college, it electrified me. The premise was that a question such as “What is thinking?” was not merely philosophical but, rather, had a real answer. In 1995, when the book was published, Hofstadter and his research group could only gesture at what the answer might be. Thinking back on the book, I wondered whether Hofstadter would feel excited that A.I. researchers may have attained what he had yearned for: a mechanical account of the rudiments of thinking. When we spoke, however, he sounded profoundly disappointed—and frightened. Current A.I. research “confirms a lot of my ideas, but it also takes away from the beauty of what humanity is,” he told me. “When I was younger, much younger, I wanted to know what underlay creativity, the mechanisms of creativity. That was a holy grail for me. But now I want it to remain a mystery.” Perhaps the secrets of thinking are simpler than anyone expected—the kind of thing that a high schooler, or even a machine, could understand. ♦
...
Read the original on www.newyorker.com »
We just did something crazy: we completely rewrote our backend from Python to Node just one week after our launch.
We did this so we can scale. Yes, scale. A week in.
In some ways, it’s a good time right? The codebase is still small and we don’t have too many users.
But on the other hand, it goes completely against the advice given to early-stage startups which is to just ship and sell, and worry about scale once you’ve hit product-market-fit. “Do things that don’t scale”, as PG put it.
You see, we didn’t have a magical launch week that flooded us with users and force us to scale. And generally you can expect that any stack you pick should be able to scale reasonably well for a long time until you actually get to the point where you should consider changing frameworks or rewriting your backend in a different language (read: Rust).
So why do it?
I’m a big fan of Django. I was introduced to it at PostHog and it’s become my go-to backend for most projects since. It gets you off the ground really fast, has great tooling and abstractions, and is still flexible enough to tweak to your needs.
So naturally, when I started writing our backend at Skald, I started us off with Django too.
Now, we make a lot of calls to LLM and embedding APIs at Skald, so we’re generally doing a lot of network I/O that we’d like to be async. Not only that, we often want to fire a lot of requests concurrently, such as when need to generate vector embeddings for the various chunks of a document.
And things quickly got really messy in Django.
I’ll preface this by saying that neither of us has a lot of experience writing Python async code (I’ve mostly worked on async-heavy services in Node) but I think this is partly the point here: it’s really hard and unintuitive to write solid and performant Python async code. You need to go deep into the foundations of everything in order to be able to do so.
I’m actually really interested in spending proper time in becoming more knowledgeable with Python async, but in our context you a) lose precious time that you need to use to ship as an early-stage startup and b) can shoot yourself in the foot very easily in the process.
Nevertheless, I thought I was to blame. “Bad programmer! Bad programmer!” was what I was hearing in my head as I tried to grasp everything. But while more knowledgeable folks would certainly have a better time, we discovered that the foundations of Python async are actually a bit shaky too.
Unlike JavaScript, which had the event loop from the beginning, and Go, that created the concept of goroutines (both concurrency models that I quite like and have used in production), Python async support was patched on later, and that’s where the difficulty lies.
Two blog posts that cover this really well are “Python has had async for 10 years — why isn’t it more popular?” and “Python concurrency: gevent had it right”, both conveniently published not long before I started digging into all this.
As for us, we learned a few things:
* Django still doesn’t have full async support. Async in the ORM is not done yet and the colored functions problem really shines here. You can technically use Django with async, but their docs on this have so many caveats that it should scare anyone.
* You gotta write sync_to_async and async_to_sync everywhere.
* All sorts of models have emerged to bring better async support to different parts of the Python ecosystem, but as they’re not native they have their own caveats. For instance, aiofiles brings async API-compatible file operations but uses a thread pool under the hood, and Gevent with its greenlets is pretty cool but it literally patches the stdlib in order to work.
* Due to a lot of async support in Python relying on layers that sit on top of the language rather than being native, you need to be careful about the async code you write as it will have different implications depending on e.g. the Gunicorn worker type you run (good luck learning much about those from the Gunicorn docs, btw).
Overall, just getting an equivalent of Promise.all to work, while understanding all of its gotchas was not simple at all.
Faced with this, I went into the PostHog codebase.
I worked at PostHog for three years and we had no async in the Django codebase back then but they’re a massive company and they have AI features now so they must have figured this out!
And what I realized was that they’re still running WSGI (not ASGI) with Gunicorn Gthread workers (where the max concurrent requests you’re able to handle is usually max 4x CPU cores), thus not getting much benefit from running things async. The codebase also has a lot of utils to make async work properly, like their own implementation of async_to_sync. So I guess way they’re handling a lot of load is probably just horizontal scaling.
There’s simply no great way to run async in Django.
We essentially concluded that Django was going to hurt us really soon, not just when we started to have a lot of load.
Without too many users we’d already need to start running multiple machines in order to not have terrible latency, plus we’d be writing clunky code that would be hard to maintain.
We could of course just “do things that don’t scale” for now and just solve the problem with money (or AWS credits), but it didn’t feel right. And being so early would make the migration to another framework much easier.
At this point, some people are probably screaming at their screens going: “just use FastAPI!” — and we did indeed consider it.
FastAPI does have proper async support and is quite a loved framework said to be performant. And if you want an ORM with it you could use SQLAlchemy which also supports async.
Migrating to FastAPI would have probably saved us a day or two (our migration took 3 days) due to being able to reuse a lot of code without translating it, but at this point we weren’t feeling great about the Python async ecosystem overall, and we had actually already written our background worker service in Node, so we thought it would be a good opportunity to go all-in on one ecosystem.
And so migrate to Node we did. We took a little time picking the framework + ORM combo but settled on Express + MikroORM.
Yeah sure Express is old but it’s battle-tested and feels familiar. Coming over to the JS event loop was the main point of all this anyway.
Our initial benchmarks show we’ve gained ~3x throughput out of the box and that’s just with us running what is mostly sequential code in an async context. Being over on Node now, we’re planning on doing a lot concurrent processing when chunking, embedding, reranking, and so on. This means this change should have an even greater payoff over time.
Losing Django hurts, and we’ve already found ourselves building a lot more middleware and utilities ourselves on the Express side. Adonis exists, which is a more fully-featured Node framework, but moving to a whole new ecosystem felt like more work to us than just using something minimal.
What I’m missing the most is the ORM, which in my opinion is really ergonomic. And while you always have to be careful with ORMs when looking to extract the best possible performance, the Django ORM does do some nice things under the hood in order to make it performant enough to write queries in Python, and I learned a bit more about this when migrating our Django models over to MikroORM entities.
MikroORM was a consolation prize in this whole migration. I still much prefer the Django ORM but at the same time different ecosystems call for different tooling.
I’d never used it before and was positively surprised to find Django-like lazy loading, a migrations setup that felt much better than Prisma’s, as well as a reasonably ergonomic API (once you manually set up the foundations right).
Overall, we’re early into this change, but currently happy to have picked MikroORM over the incumbent Prisma.
I think this is pretty self-explanatory. While most tools for building RAGs and agents have Python and TypeScript SDKs, Python still takes priority, and we’re just talking about API wrappers here.
Once you want to actually get into ML stuff yourself, there’s just no competition. I suspect that as we get more sophisticated we’ll end up having a Python service, but for now we’re ok.
We’d always realized that migrating to Node would mean we’d have two Node services instead of a Python one and a Node one, but it didn’t occur to us until a day in that we could actually merge the codebases and that that would be extremely helpful.
There was a lot of duplicate logic across the Node worker and the Django server, and now we’ve unified the Express server and background worker into one codebase, which feels so much better. They can both use the ORM now (previously the worker was running raw SQL) and share a bunch of utils.
This is not a pytest vs jest thing, it’s just that in order to make sure everything was working as expected after migrating, we just wrote a ton more tests. This and some refactoring were welcome side benefits.
I think it’s about time to wrap this post up, but here are some quick notes about the actual migration process.
* It took us three days.
* We barely used AI code generation at all until the final bits — it felt important to us to understand the foundations of our new setup really well, particularly the inner workings of the new ORM. Once we had the foundations of everything down Claude Code was quite helpful in generating code for some less important endpoints, and also helped us in scanning the codebase for issues.
* We almost quit multiple times. We were getting customer requests for new features and had some bugs in the Django code and it felt like we were wasting time migrating instead of serving customers.
Honestly, we’re quite happy with our decision and would 100% do it again. Not only will this pay off in the long term but it’s already paying off today.
We learned a lot of stuff in the process too, and if the whole point of this whole post is that someone comes to tell me that we’re dumb and we should just have done X or Y, or comes to teach me about how Python async works, then that will honestly be great. For my part, I gladly recognize my inexperience with Python async and if I can learn more about it, that’s a win.
And if you’re interested in actually seeing the code, check out the following PRs:
Skald is an MIT-licensed RAG API platform, so if you have any thoughts or concerns, you can come yell at us on GitHub, or open a PR to rewrite the backend to your framework of choice :D
...
Read the original on blog.yakkomajuri.com »
To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".
10HN is also available as an iOS App
If you visit 10HN only rarely, check out the the best articles from the past week.
If you like 10HN please leave feedback and share
Visit pancik.com for more.