More from John Wiseman
I have a collection of prompts and tools that I give to LLMs to generate daily aviation briefings. The briefings are supposed to be a summary of everything interesting that’s happened in the air in the past several hours, either globally or in a region of interest. The model should contextualize aircraft activity in terms of behavioral analysis, historical patterns, geography, and current events: The fire west of Piñon Hills stood at roughly 2,700 acres and 0% containment in the latest reports, with cooler overnight conditions helping crews strengthen lines. This morning’s air picture is recon and rotary rather than Saturday’s tanker parade: N8PQ, the Aero Commander 690A, is back overhead at 8,000 ft, K-MAX N107MW is working the fire at 4,200 ft, Bell 205 N33HX is staging at Fox Field, and Tanker 104, an Erickson Aero Tanker MD-87, sits on the ramp at San Bernardino International. Writing a worthwhile briefing is a challenging task. It’s agentic, with models using 15-20 tools including querying databases, searching the web, and writing and executing scripts to process data. It also requires judgment from a model on what to include in the briefing and how to put together separate pieces of data to tell a story without overstating a conclusion. The agents filter through a large amount of data looking for interesting items, find corroborating sources, take screenshots, and edit it all into a short (less than 6000 characters) report. I’ve tried Claude Opus 4.8, Fable 5, OpenAI GPT-5.6-Sol, and Kimi K3 on this task. The tl;dr if you’re paying retail API token prices: Opus 4.8 is cheap, fast, and its output is good. Kimi K3 costs about the same as Opus 4.8 and its output is of similar quality (it’s saved by the fact-checker) but it takes 5-6x as long as Opus 4.8. Fable 5 costs 2-5x as much as Opus 4.8 or Kimi K3. I like the feel of its output best, but it needs to be reined in by the fact-checker almost as much as Kimi K3. GPT-5.6-Sol is cheap and fast and makes few mistakes, but its briefings are too short and boring. I think GPT-5.6-Sol is the smartest model available at the moment, but for this task Fable 5 does better, and Opus 4.8 does almost as well for far cheaper. Some numbers The initial prompt for the task is about 25 K - 30 K tokens, depending on whether the briefing is for the world or just Southern California. (All token calculations are done with the OpenAI tokenizer; others may be different.) Runbook Tokens briefing-runbook-common 16,516 briefing-runbook-world 13,635 briefing-runbook-socal 8,039 The custom tools to give the models access to aircraft and geospatial data, and the guides on how to best use them consume another 50 K tokens. Custom MCP Tokens MCP Description 433 Tool Descriptions (10 tools) 3533 Resources (13 documents) 45713 I’ve done six briefings with Fable 5 and two briefings with each of the other models. The following table lists time and cost for a single briefing, for each model. Time includes the total time for research, review, corrections and posting. Costs are API-equivalent estimates based on current pricing with token caching included. Model # Briefings Median time (minutes) Median cost Opus 4.8 2 24.8 $10.06 Fable 5 6 31.5 $30.33 Kimi K3 2 132.4 $10.43 GPT-5.6-Sol 2 40.0 $15.63 After a model writes the first draft of a briefing it sends it and the supporting material to an adversarial fact-checker powered by GPT-5.6-Sol. The model then rewrites the report based on the fact-checker’s findings. For each briefing I classified the fact-checker’s findings into “major”, more substantive corrections, and “minor”, softer issues. The table below shows the median number of writer tool calls and the mean number of corrections per report for each model. Model # Tool calls Major corrections Minor corrections Opus 4.8 66 0.0 4.0 Fable 5 93.5 2.5 7.0 Kimi K3 125 2.5 7.5 GPT-5.6-Sol 116 1.0 2.0 The GPT-5.6-Sol reports used separate GPT-5.6-Sol reviewer sessions, following the same adversarial process as the other models. The review step added a median $1.95 worth of GPT-5.6-Sol tokens to the cost of a report, and review costs are already included in the costs listed above. Report quality Opus 4.8 Opus 4.8 did a good job of creating rich reports with strong themes, and it showed good editorial judgment by removing weak leads not supported by further research. As an example, it might lead with a developing emergency: N969WR … was cruising at FL450 across the Oklahoma/Texas panhandle when it squawked 7700 at ~2204Z and began a continuous descent, averaging around 2,300 ft/min. It combined that lead with a large firefighting mobilisation, an EA-37B, an E-6B, allied tanker movements and forward-looking airspace notices. This was varied and interesting without feeling like a list of unrelated aircraft. The fact-checker didn’t refute any of Opus 4.8’s conclusions, and didn’t find any unsupported claims. Corrections were mostly wording changes to avoid implying unwarranted precision. Fable 5 Fable 5 produced the most detailed and ambitious reports. It was strongest when it could connect several observations into a larger story. For example, the 15 July world report described a shared GPS spoofing pattern near Smolensk: Three airliners (Turkish, Belavia, Air Serbia) each plotted flying an impossible 1.2-nm, 55-kt circle around the same fixed point southwest of Smolensk while MLAT put the real aircraft 400 km away. The 14 July SoCal report turned an anonymous military track into a strong lead: A silent visitor working W-291 — ae685e, a US military hex with no callsign, came down from Oregon overnight at FL270 and has flown a broad 21,000-ft circuit off the San Diego/northern Baja coast for hours. Fable 5 also followed stories across several days. It tracked tanker relays, airlift movements, range activity and unusual aircraft between reports. Fable 5’s reports were detailed, visual, and interesting. They also needed significant corrections, an average of 2.5 substantive and 7 minor problems per report. Its main weakness was overprecision. Codex regularly corrected: exact start and end times track boundaries aircraft counts claims about every member of a group statements that joined events across an anchor time mission interpretations that went beyond the observed movement An example of a significant error (that GPT-5.6-Sol let pass but that I found on review) was its report on a Russian Be-200 amphibious aircraft. Its published heading said: A Russian EMERCOM Be-200ChS scooping the Donbas. The report described the aircraft as working “a 300-km chain of fire sites”, but when I saw the map that seemed implausible. I asked Fable 5 about it, and eventually it posted an update: The evidence now says ‘repeated brief landings at unmapped sites, purpose unknown’. I still don’t know what that aircraft was doing, but it’s an example of Fable 5 going significantly off course. Kimi K3 Kimi K3 is really slow, and the fact-checker had to correct it more than any other model, but the quality of its (corrected) output once it was finally done was excellent–as good as Opus 4.8. KC-135 declares an emergency over the Irish Sea, home safe at Mildenhall. Fox Field staged and scattered — seven fire aircraft on the ramp on the fire squawk all morning; the 737 Fireliner and RJ-85 launched ~10am and ferried north without a drop run. There’s just no reason to use Kimi K3 since it costs as much as Opus 4.8, is about as good, but much slower. GPT-5.6-Sol GPT-5.6-Sol shows so much restraint that its briefings are boring: dry, no flavor, and not particularly interesting. LATTE18 / N650RX, a trustee-registered Global 6500, flew roughly 4 broad clockwise circuits at FL360 from 01:28 to 02:14Z, then departed southwest. The direct ADS-B track measured about 38 by 16 nautical miles. Public aviation reporting associates this tail with SNC’s Army ATHENA-S fleet; SNC confirms its 2 ATHENA aircraft support US Army airborne ISR, but SNC does not name the tails. The same offshore block appears repeatedly in the recent archive. I generally like GPT-5.6-Sol but its briefings were just too dull.
More in technology
Google told K-12 schools they could turn off AI, but only if they gave up search too. That isn’t integration. It’s holding education for ransom.
A Pika author was editing the same post in two browsers. They added six images in Browser A, then later they referenced an old tab editing the post in Browser B. That copy of the editor did not include those images. Browser B saved and removed all six images from Active Storage. A short time later, Browser A saved its newer copy of the post and put the image references back, but at that point the originally uploaded files were gone due to Browser B saving the post without the images. This exposed two separate problems: Missing images produced uncached 404 responses that the editor requested repeatedly. Action Text purged an image as soon as one save removed it from the body. Here’s how we fixed those problems. Why Action Text deleted the images Action Text keeps a rich text record’s embeds synchronized with the attachments in its body. When a submitted body no longer contains an image, Action Text removes its ActiveStorage::Attachment. Active Storage then purges the dependent blob, deleting both its database record and its file. That behavior makes sense when there is only one current copy of a document. It is unsafe when the same post can be open in multiple tabs, browsers, or devices. One stale save can delete an image that another editor is still using. Why the missing images flooded the server Browser A still had the six images in its editor, each pointing at an Active Storage redirect URL: /rails/active_storage/blobs/redirect/:signed_id/:filename Pika uses the ProseMirror-based Rhino editor. Rhino rebuilt an image’s DOM node when its caption or selection changed. Each new <img> element requested its URL again. Healthy images did not cause trouble since Active Storage makes its redirect cacheable. For a purged blob, Rails returned a 404 without Cache-Control, so the browser kept sending the request to Rails instead of reusing the failure. In a gallery, typing could re-request several missing images per keystroke. In these scenarios, this issue led to hundreds of requests hitting our servers. Fix 1: Cache permanent Active Storage 404s A purged blob’s redirect URL can never start working again. Blob IDs are not reused, and uploading the image again creates a new blob with a new signed URL. Sinc there is no concern of a 404 becoming stale, we made a specific 404 cacheable for the same period as a successful redirect: # app/controllers/concerns/active_storage_missing_blob_cache.rb module ActiveStorageMissingBlobCache extend ActiveSupport::Concern included do rescue_from ActiveRecord::RecordNotFound, with: :render_cacheable_not_found end private def render_cacheable_not_found expires_in ActiveStorage.service_urls_expire_in render file: Rails.public_path.join("404.html"), layout: false, status: :not_found end end We included the concern only in the controller serving these blob redirects: # config/initializers/active_storage_missing_blob_cache.rb Rails.application.config.to_prepare do ActiveStorage::Blobs::RedirectController.include(ActiveStorageMissingBlobCache) end (We also offered an update to Rhino that avoids it being so aggressive re-requesting images.) Fix 2: Detach dropped images instead of purging them When a save removes an image from an Action Text body, we now remove the attachment while temporarily keeping its blob. Another browser can save the image again and reattach that same blob. If nothing brings it back, a cleanup job purges it later. First, we added a timestamp for when the image was dropped: class AddDetachedAtToActiveStorageBlobs < ActiveRecord::Migration[8.1] def change add_column :active_storage_blobs, :detached_at, :datetime end end We then intercepted the private callback Active Storage uses to purge a dependent blob: # config/initializers/detach_dropped_embeds.rb module DetachDroppedEmbeds private def purge_dependent_blob if dropped_from_rich_text? blob&.update_columns(detached_at: Time.now) else super end end def dropped_from_rich_text? record.is_a?(ActionText::RichText) && !destroyed_by_association end end ActiveSupport.on_load(:active_storage_attachment) do prepend DetachDroppedEmbeds end The destroyed_by_association check preserves intentional deletion. Removing an image from a saved body detaches it, but deleting the post and its rich text still purges its images normally. Purge detached blobs after a grace period The cleanup query considers both when the blob was created and when it was detached: ActiveSupport.on_load(:active_storage_blob) do scope :unattached_since, ->(time) { unattached.where( created_at: ..time, detached_at: [nil, ..time] ) } end That scope handles both kinds of unattached blobs: A new upload that has never been attached becomes eligible based on created_at. An image removed from an old post becomes eligible based on detached_at. Pika gives both a 30-day grace period: class PurgeUnattachedUploadsJob < ApplicationJob GRACE_PERIOD = 30.days def perform ActiveStorage::Blob.unattached_since(GRACE_PERIOD.ago).find_each do |blob| blob.purge_later end end end If another browser saves the image during that period, it is attached again and the unattached scope excludes it from cleanup. The result Replaying the original two-browser edit now works safely: Browser B saves a body without the six images. The attachments are removed, but their blobs are only marked as detached. Browser A saves its newer body and reattaches the existing blobs. The images remain available and do not need to be uploaded again. If no editor brings a detached image back, the cleanup job eventually purges it. Much better! Reply by email
Yesterday, a group of MIT researchers released an article titled “Sparks of Weight-Space Programming: LLMs can natively read & write neural network weights”. The piece describes a set of experiments which convincingly show OpenAI’s latest Astra model is able to understand and successfully alter raw weight data. Wowzers! It’s a rough analogy, but an LLM’s weights are sort of like its brain. A set of weights is a large pile of numbers generated during training, and an LLM’s output is derived by running input through the weights using some matrix multiplication and a bit of randomization. While the steps to generate weights are well understood, the weights themselves are extremely opaque. There’s ongoing work to try and explain how weights work, but researchers currently have a limited understanding of what these numbers do. Based on this, I was quite surprised to learn that LLMs are able to act on raw weight data — even if it’s still just in limited cases. It’s unclear if OpenAI’s model was trained on weight data. Even if it was, I still find these results surprising. The article shows the model accurately predicting what a never-before-seen set of weights was built to do, fixing another model by updating its weights, and creating new sets of weights that performed simple tasks. I would not have guessed any of that would be possible a couple of days ago. This whole thing is slightly unnerving. The whole “weights as a black box” thing has always felt a bit sketchy to me, even when I was working with much simpler machine learning models. Now these experiments hint at a future where LLMs could be self-improving in ways that aren’t human-verifiable. Machines building machines, and we can only hope that they’re not doing anything weird. I don’t know if this strategy is scalable, but I’d guess that it’s something more people will be exploring very soon. More and more often these days, I wish we were living in less interesting times.
Harry threw me off course in episode 48 of Traction Heroes. At first, I thought was reading from a book about mind mapping. Soon, it became clear it was about something else: how to define a clear vision for a team or organization. Visions are notoriously hard to articulate. Drawing a picture — especially a picture of the whole forest, plus the trees — can help. The passage Harry read from Cameron Herold’s Vivid Vision explores this idea: So to visualize something a little more tangible, think about a tree trunk in the earth, inner core with its branches stretching out into the sky. Each of those branches contains twigs extend further out. The mind map works in a similar way, a core that branches out into smaller components. Now, apply this to the world of business. As the leader of an organization, you’re firmly planted at the center, and the various areas that contribute to the business branch out: marketing, sales, engineering, and so forth. With that in place, build off that by describing those branches in about three or four bullet points each. In other words, describe what your marketing looks like and sales and so on until you’ve captured every idea. Remember too that among the branches of your business, you want to consider every aspect of the organization: the vibe, informal codes of conduct, the fiscal environment, the scenery, all of that. Deliberately leave out numbers and data. Get a feel for the place. When you step out of your time machine three years from now and walk around the office, what’s happening? What can you say that is typical of the business three years from now? The mind map is an initial foray into the vivid vision and will act as an outline for the rough draft that you, the leader, will then write. I’ve sketched diagrams before when outlining articles, workshops, and presentations, never in service of aligning around a company’s vision. Harry’s done it several times and found it easier than trying to write it out. Seems useful — check out our conversation for more: Traction Heroes episode 48: Visions
Sharing a few data points because some people did not expect these drives to last that long.