1# Chapter 8: llm, the eloquent one on a short leash 2 3Sometimes a question needs writing before Jev can judge it. "What is the 4best pizza topping?" is a pick, and a pick needs options; Jev cannot make 5them up. "How hot is the sun?" needs a scale in kelvin, not "Slightly" to 6"Extremely". "Is Rust fast and is it hard to learn?" is two questions 7wearing one coat. For these, and only these, an LLM is called. 8 9It is told plainly what it is for. This is the start of its system prompt: 10 11> You sit between a person and Jev. Jev is a model that cannot write text. 12> It only judges, in three ways [...] Turn the person's input into the tool 13> call that answers it. Always call a tool. Never answer the question 14> yourself, and write no other text. 15 16It gets three tools, one per Jev type, and it answers by calling them: 17 18| Tool | Jev type | What the LLM writes | 19| --- | --- | --- | 20| `jev_noul` | Noul | A yes-or-no question, with what yes and no mean. | 21| `jev_choice` | Choice | 2 to 8 real, specific options, each with a one-line description. | 22| `jev_score` | Score | 3 to 7 levels, lowest first (Jev takes 2 to 10). | 23 24At most 4 calls per input. What it writes is then judged by Jev, and only 25Jev's answer is ever shown as the answer: never the LLM's own words. 26 27> **Aside: the leash.** When the rules have already worked out what kind of 28> question it is (say, a pick), the LLM is told so and given *only* that 29> tool. Otherwise it might helpfully also write a yes-or-no version, Jev 30> would answer that too, and the page would show two answers that disagree. 31> That happened once (2026-10-02), which is why `takes` now refuses any 32> call of a kind the rules did not ask for. 33 34> **Try it.** Ask <https://lmjtfy.fun/?q=what+is+the+best+pizza+topping> 35> and open the LLM's panel under the answer: the request it was sent, and 36> the tool call it wrote back, byte for byte. 37 38Which model is the LLM? The cheapest Workers AI model that gets every test 39case right, with Claude Haiku's price as the ceiling. Chapter 14 is how that 40is decided; today it is `@cf/qwen/qwen3-30b-a3b-fp8`. 41 42## For the people who maintain it 43 44- `request(input, wants)` is the Workers AI request body as JSON text: the 45 system prompt, the input, and the tools. `wants` is what the rules want 46 written (`rules::Network::wants`); when it settles the kind, only those 47 tools are given and the prompt says so. 48- `takes(wants, draft)` says whether a tool call is of a kind that was asked 49 for. One that is not is not sent. 50- `parse(body)` reads a chat-completion reply into `ToolCall`s. Each carries 51 the arguments as the model wrote them and a `Draft` (the question for Jev) 52 or the reason the arguments do not make one. It repairs exactly one thing: 53 arguments encoded as JSON twice. 54- `CANDIDATES` is the price list of the models that could do the job, and 55 `Model` turns usage into neurons and a request into its worst case. 56 `FREE_NEURONS_PER_DAY` is Workers AI's free daily allocation. 57 58The Worker sends the request through the AI binding and the eval sends it 59over REST. Both read the reply with `parse`. 60 61## In this folder 62 63| Path | What | 64| --- | --- | 65| [src/](src/) | The prompt, the tools, the parser, the price list. | 66| [Cargo.toml](Cargo.toml) | The crate: `rules`, `serde` and `serde_json`. | 67 68← Previous: [Chapter 7½, ask/src/](../ask/src/) · Up: [packages](../) · Next: [Chapter 8½, llm/src/](src/) →