1# Chapter 9: archive, never pay for the same answer twice 2 3Here is the rule, in the owner's own words: never send the same exact shape 4to the same model, ever. If a request has been answered before (the same 5bytes, to the same model) it is not sent again, by anyone, unless someone 6presses ↻ on it (below). The kept response comes back instead. Nothing is 7spent, nothing waits on the network, and the page says "not sent" and when 8it was answered. 9 10This matters more than it sounds. Jev is calibrated and deterministic 11enough that the same question really does deserve the same answer. And the 12way people use a site like this is to drop a link in a chat, where a dozen 13people click it within a minute. Without the archive that is a dozen 14identical calls. With it, it is one. 15 16```mermaid 17sequenceDiagram 18 participant A as Visitor A 19 participant B as Visitor B 20 participant R as Archive 21 participant J as Jev 22 A->>R: this request, please 23 R->>R: kept? no. On the wire? no. 24 R->>J: send it (once) 25 B->>R: the same request, please 26 R->>R: on the wire: wait for it 27 J-->>R: the response 28 R->>R: keep it 29 R-->>A: the response (sent now) 30 R-->>B: the same response (kept) 31``` 32 33The archive is a Durable Object (chapter 2), so there is exactly one of it, 34and every visitor's request goes through the same one. It does not just look 35things up: it makes the calls itself. That is what lets two visitors asking 36the same new thing at once share one call, and why a call finishes and is 37kept even if the visitor who started it closes the tab. A call that got no 38response (an error, a timeout) keeps nothing, so it can be tried again. 39 40> **Aside.** Why key on the whole request body and not a hash of it? Because 41> a hash can collide, and the rule is absolute. Two different requests can 42> never be taken for one if what is compared is the requests themselves. 43 44> **Try it.** Open 45> <https://lmjtfy.fun/?q=Is+a+slot+machine+a+good+retirement+plan%3F>, 46> scroll to the calls under the answer, and look for "not sent". Then look at 47> "So far" on the home page: how many requests were never sent because the 48> same one had been answered before. 49 50## Asking again, and every answer kept 51 52Jev is calibrated, but a model can change, and the LLM in front of it is not 53deterministic at all. So every call panel has ↻: it sends that request for 54real, and keeps the response as its newest version. Whatever comes after is 55worked out again from the new answer. A later request that comes out the same 56is served from the archive; one that changes (the LLM wrote different 57questions, say) is new, and is sent. 58 59Every response a request ever got is kept, numbered from 1. A panel with more 60than one shows ◀ answer 2 of 3 ▶, and the newest is the default. Stepping 61back is only looking: it sends nothing, and neither does anything after it. 62If an old answer leads to a request nobody has asked yet, the page says so 63and offers ↻ for it rather than sending it. 64 65```mermaid 66flowchart LR 67 P["the page's $pins: 3f2a9c01be44:2"] --> W["the Worker: what does each call want?"] 68 W -->|"pinned: Version(2)"| A["archive: version 2 of that request"] 69 W -->|"after a pinned one: KeptOnly"| B["archive: the newest kept, or NotKept"] 70 W -->|"↻: Fresh"| C["archive: send now, keep as newest"] 71 W -->|"anything else: Latest"| D["archive: the newest kept, or send"] 72``` 73 74> **Aside: the page names calls by a hash, the archive does not.** A panel 75> needs a short name for its buttons, so `call_id` is twelve hex digits of the 76> SHA-256 of where the request went and what it said. The archive still looks 77> responses up by the request itself. 78 79## The feed 80 81The same store keeps the questions people asked, and the home page shows 82them: **asked lately** and **most asked**, with Jev's answer beside each and 83how many times it was asked. Each line is a link that asks it again, for 84free. The feed shows nothing about who asked. (What the site keeps for 85its owner is another matter: chapter 2, 86[What is kept about visitors](../../apps/lmjtfy/#what-is-kept-about-visitors).) A 87question goes on the list only if the rule "list it" holds (chapter 6), 88which needs Jev's `fit` fact: Jev moderates its own feed, and the owner can 89overrule it either way. An unfit question is still answered for whoever 90asked it, and still kept. Asked lately goes back as far as 91the feed does: scroll it to its end and the next fifty load. **So far** counts the questions, the 92share Jev answered with no LLM, the requests sent and not sent, and clones 93and pulls of the code. 94 95## For the people who maintain it 96 97This package is the messages between the Worker and the archive object, with 98no I/O and no clock; the object is `apps/lmjtfy/src/archive.rs`, and its 99storage is drawn in chapter 2. 100 101| Message | What | 102| --- | --- | 103| `Ask::Jev`, `Ask::Llm` | "The response to this request, please", with a `Pick`: the newest (`Latest`), sent again (`Fresh`), a `Version`, or only if kept (`KeptOnly`). Answered with a `Called`: a `Record` (the response, when it was answered, whether this ask sent it, and which version of how many), a failure, a refusal by the day's budget, or `NotKept`. | 104| `Ask::Asked` | A question was answered: its text, Jev's answers, whether an LLM was needed, whether it may be listed, and the asking browser for this question (`Asker`), which counts once. | 105| `Ask::Rate`, `Ask::Rating` | A browser's 👍 or 👎 on Jev's answer as kept (`Vote`), pressed again to take it back; the votes after it (`Rating`). | 106| `Ask::Fetched` | Someone cloned or pulled the code (`Fetch::Clone` or `Fetch::Pull`). | 107| `Ask::Home` | What the home page shows: the questions asked lately and most asked (`Entry`: the text, Jev's answers, how many times, and nothing about who asked), and the archive in numbers (`Stats`). | 108| `Ask::Older` | The next page of asked lately, after a `Cursor`: the last line shown, by when it was asked and then its text, so no line is shown twice or skipped. | 109| `Ask::Answer` | What Jev said to one question, if it was ever asked. For link previews; it sends nothing. | 110| `Ask::Event` | Something happened, to be kept whole: an `Event` (`event.rs`), one row of `events`. | 111 112`Admin` is the other set of messages, for the owner's admin backend, sent 113to the object's `/admin` path by a Worker of its own: `Select` (one 114statement that only reads, checked by `reads_only`) and `Moderate` (the 115owner's say on a question's place in the feed). `Answered` is the reply. 116 117`Live` is what the archive pushes to open pages over `/live`: `Online`, 118`Toast`, `Patch` and `Build`. `Pins` reads the page's `$pins` and says what 119each call should `Pick`; `call_id` names a call for it. `Place` and `Seen` 120are where an open page is, kept on its socket. 121 122An `Answer` is what is kept of what Jev said: the few words the page prints 123large, and the numbers behind them (`Detail`: the probability, or the 124confidence with every option or level and its probability). The feed prints 125the words; a link preview prints and draws the numbers too. Answers kept 126before the numbers were are read as words alone (`stored`). `when` writes a 127moment the way the page shows it. 128 129## In this folder 130 131| Path | What | 132| --- | --- | 133| [src/](src/) | The messages, answers and stats. | 134| [Cargo.toml](Cargo.toml) | The crate: `ask`, `budget`, `http` (for reading a request's headers), `serde`, `serde_json`, `sha2`. | 135 136← Previous: [Chapter 8½, llm/src/](../llm/src/) · Up: [packages](../) · Next: [Chapter 9½, archive/src/](src/) →