Writer's context, reader's context
I’ve been toying with two things for the last week: (1) a thing that uses semantic distance/similarity to build a short outline from prose, and (2) a thing that just regurgitates the original text but with a "heatmap" highlighting key/summary sentences. I've been using it to read almost everything I can use it on. My takeaways so far:
- The outline is rarely what I want, by itself. Because I often want to see "where did this sentence come from?" and see the surrounding in-document context of sentences, and taking sentences out-of-context makes them hard to read except for a certain class of writing like news reports where each sentence is a pretty stand-alone reporting of facts.
- The heatmap is distinctly easier to read, because my eyes can sort of scan for highlighted sentences and adjust in real time how much detail I want to take in about a certain section, using highlights as cues. If I read a highlighted sentence and I feel like I’m missing context it’s also trivial to rewind visually to the start of the paragraph.
- I also made a thing so that I can click on a sentence in the heatmap and see sentences that are most close to it semantically, which usually ends up being like "supporting reasoning" or "what else the author said about this" which is surprisingly useful. But I have to scroll around to see all of them which is annoying. I'll keep iterating on the design of this bit.
My high level conclusion so far is that there are two kinds of "contexts" when you’re exploring any text or collection of texts, and both matter equally. There’s original context/situated context which comes from the original source, and semantic context/reader context which is all the things that sentence/note is related to in the reader’s personal universe of ideas.
Whether I’m reading or taking notes, I want to quickly get a gist of key ideas and see them placed in both kind of contexts. So I think the interface challenge (in my view) boils down to: Can we have a reading/writing interface or notation that allows easily seeing excerpts from a large collection of texts/ideas in both the original/writer’s context and the reader/semantic context?
Science fiction/short story ideas
- A budding human settlement on Mars, quickly maturing through shipments of industrial/manufacturing/agricultural equipment from Earth, gets cut off from the last few critical shipments for a self-sustained future due to a world war on the home world. The Martian settlement must now figure out how to ensure a sustainable future for themselves by either inventing and building the lost equipment (like semiconductor fabricators, radio communications equipment, Earth-based fertilizers, and rocket fuel) themselves, or navigating the complex task of acquiring what they need from a world mired in conflict and fog of war.
- Humans experience reality and consciousness in a continuous way (at least, it seems this way to me). If the current path of development for powerful AI continues on its path, future AI agents and artificially conscious beings may experience reality as a discrete sequence of computations/inferences instead. How might a story narratively explore the difference between these two kinds of conscious entities and how they experience time and life?
Very excited for a time when products built on large language/image models become something more than thin boring UI wrappers around raw inference APIs. Why are you showing end users dials for top-k and temperature? They don't care!
I found a startlingly simple and pretty efficient algorithm to approximate π today, on a web demo for Tabby. It was so interesting that I tried it myself. Here's the script:
n := 1000000
k := 1
x := 0
with std.loop(n) fn {
x <- x + 1 / (k * k)
k <- k + 2
}
fmt.printf('Almost π: {{0}}\t(at n = {{1}})', math.sqrt(x * 8), n)Looks deceptively simple, right? Just a few additions and multiplications. For various values of n, here's the output:
Almost π: 2.8284271247461903 (at n = 1)
Almost π: 3.1096254579886478 (at n = 10)
Almost π: 3.1384079670670912 (at n = 100)
Almost π: 3.14127432760274 (at n = 1000)
Almost π: 3.1415608224399487 (at n = 10000)
Almost π: 3.141589470489344 (at n = 100000)
Almost π: 3.1415923352799697 (at n = 1000000)
Almost π: 3.1415926217577352 (at n = 10000000)It looks like the formula is a variant of a Taylor series-like approximation of π, but written iteratively/imperatively rather than as a sum per se, and it comes out really clean. I like it.
The anticipation of knowing that something you're capable of building can solve a problem you've been struggling with for a long time, but you can't actually see it work until you build it.
A full file/object storage service in ~30 lines of Oak!
with server.route('/blob/:fileName') fn(params) fn(req, end) if req.method {
'GET' -> with fs.readFile(path.join(BlobDir, params.fileName)) fn(file) if file {
? -> end(http.NotFound)
_ -> end({
status: 200
headers: { 'Content-Type': http.mimeForPath(params.fileName) }
body: file
})
}
'POST' -> if ext := params.fileName |> str.split('.') |> std.last() |> str.lower() {
'jpg', 'jpeg', 'png', 'svg', 'gif', 'gifv' -> {
blobPath := crypto.uuid() + '.' + ext
with fs.writeFile(path.join(BlobDir, blobPath), req.body) fn(res) if res {
? -> end({
status: 500
headers: { 'Content-Type': http.MimeTypes.txt }
body: 'could not save blob'
})
_ -> end({
status: 201
headers: { 'Content-Type': http.MimeTypes.txt }
body: blobPath
})
}
}
_ -> end({
status: 400
headers: { 'Content-Type': http.MimeTypes.txt }
body: 'unsupported file type'
})
}
_ -> end(http.MethodNotAllowed)
}I wrote this as a part of my work to add file upload/attachment support to Lig3, but I might pull this out as a separate cross-app service for my personal infrastructure because it's so simple and it's something every app needs at some point.
Doing some brainstorming today by:
- Having GPT-3 come up with creative inspirations/solutions to problem statements
- Feeding them into text-to-image models to visualize them in different styles and worlds
- Reading articles in an app that highlights key ideas and how they connect to each other within the page
- Collecting my notes in a document that highlights missed connections between my ideas old and new
Still a long road to go, but I'm optimistic we're still at the very beginning of how computers can change the way we read and write.
Today I learned while digging through my /usr/include that my local Fedora install comes with a whopping 1.2M lines of C headers in /usr/include. That seems like a lot? Yeah?
$ cat /usr/include/**/*.h | wc
1208974 4871654 4411060644MB of source text!
Sorting in Lisp
As I've been porting Klisp to Oak for fun this week, I wrote a couple of sorting algorithms that I think came out very elegant in Lisp:
(defn quicksort (xs)
(if (< (size xs) 2)
xs
(let (pivot (nth xs (int (/ (dec (size xs)) 2)))) ; heuristic: pick midpoint
(-> (quicksort (filter xs (partial (< ? pivot))))
(append (filter xs (is pivot)))
(append (quicksort (filter xs (partial (> ? pivot)))))))))(defn merge (left right)
(cond ((empty? left) right)
((empty? right) left)
((do
(def l (first left))
(def r (first right))
(if (<= l r)
(conj l (merge (rest left) right))
(conj r (merge left (rest right))))))))
(defn mergesort (xs)
(if (< (size xs) 2)
xs
(let (split-at (int (/ (size xs) 2)))
(merge (mergesort (take xs split-at))
(mergesort (drop xs split-at))))))Code is a poor interface for interactivity
As I was building Oak Notebook, I thought a lot about interactive documents and what makes me excited about improving their state of the art.
An often-cited category of interactive documents is programming notebooks like Jupyter, Observable, and Nextjournal. They're very, very cool, and they've inspired me in my own work. But I think they share one big flaw in their underlying document model: code is a poor interface for interactivity.
What I mean is that programming notebooks like those use writing and executing code in a general-purpose language as the main way for the reader to control visualizations and data displays. This excludes non-programmers from being able to really understand and work with these documents, and more important, even for programmers, reading and understanding code takes effort. Code is poor notation for things that aren't software, and code as interface hides what's really going on.
Oak Notebook, despite its many flaws, uses well-known and simple interactive input widgets and avoids this pitfall, at least for the simplest 20% of needs that cover 80% of use cases. Kevin Kwok's Carbide is another workaround for this pitfall that I'm excited about — making code as notation easier to interact with by augmenting it with interactive widgets and autodiff.