upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/90.md
diff options
context:
space:
mode:
authorPablo Fernandez <p@f7z.io>2023-10-14 16:14:24 +0300
committerPablo Fernandez <p@f7z.io>2023-10-14 16:15:00 +0300
commitd9400e1e7b08225aedb6c78b522c5ad07b5198b4 (patch)
tree95e66329f674eaad3e6c59acd953591ef3664373 /90.md
parent5026747008c0a84c14079c39807296eebd409c36 (diff)
big refactor
* use different kinds per response type * remove examples * remove specific job request definitions, moved to a separate repo for clarity
Diffstat (limited to '90.md')
-rw-r--r--90.md371
1 files changed, 52 insertions, 319 deletions
diff --git a/90.md b/90.md
index 51c49cf..4c0eff6 100644
--- a/90.md
+++ b/90.md
@@ -4,22 +4,24 @@ NIP-90
4Data Vending Machine 4Data Vending Machine
5-------------------- 5--------------------
6 6
7`draft` `optional` `author:pablof7z` 7`draft` `optional` `author:pablof7z` `author:dontbelievethehype`
8 8
9This NIP defines the interaction between customers and Service Providers for performing on-demand computation. 9This NIP defines the interaction between customers and Service Providers for performing on-demand computation.
10 10
11Money in, data out. 11Money in, data out.
12 12
13## Kinds 13## Kinds
14This NIP reserves the range `65000-66000` for data vending machine use. 14This NIP reserves the range `5000-7000` for data vending machine use.
15 15
16| Kind | Description | 16| Kind | Description |
17| ---- | ----------- | 17| ---- | ----------- |
18| 65000 | Job feedback | 18| 5000-5999 | Job request kinds |
19| 65001 | Job result | 19| 6000-6999 | Job result |
20| 65002-66000 | Job request kinds | 20| 7000 | Job feedback |
21 21
22[Appendix 2](#appendix-2-job-types) defines the job request types. 22Job results always use a kind number that is `1000` higher than the job request kind. (e.g. request: `kind:5001` gets a result: `kind:6001`).
23
24Job request types are defined [separately](https://github.com/nostr-protocol/data-vending-machines/tree/master/kinds).
23 25
24## Rationale 26## Rationale
25Nostr can act as a marketplace for data processing, where users request jobs to be processed in certain ways (e.g., "speech-to-text", "summarization", etc.), but they don't necessarily care about "who" processes the data. 27Nostr can act as a marketplace for data processing, where users request jobs to be processed in certain ways (e.g., "speech-to-text", "summarization", etc.), but they don't necessarily care about "who" processes the data.
@@ -31,21 +33,15 @@ There are two actors in the workflow described in this NIP:
31* Customers (npubs who request a job) 33* Customers (npubs who request a job)
32* Service providers (npubs who fulfill jobs) 34* Service providers (npubs who fulfill jobs)
33 35
34# Event Kinds 36## Job request (`kind:5000-5999`)
35 37A request to process data, published by a customer. This event signals that an customer is interested in receiving the result of some kind of compute.
36* `kind:65000`: job feedback
37* `kind:65001`: job result
38* `kind:65002`-`kind:66000`: job requests
39
40## Job request
41A request to have data processed, published by a customer. This event signals that an npub is interested in receiving the result of some kind of compute.
42 38
43```json 39```json
44{ 40{
45 "kind": 65xxx, // kind in 65002-66000 range 41 "kind": 5xxx, // kind in 5000-5999 range
46 "content": "", 42 "content": "",
47 "tags": [ 43 "tags": [
48 [ "i", "<data>", "<input-type>", "<marker>", "<relay>" ], 44 [ "i", "<data>", "<input-type>", "<relay>", "<marker>" ],
49 [ "output", "<mime-type>" ], 45 [ "output", "<mime-type>" ],
50 [ "relays", "wss://..."], 46 [ "relays", "wss://..."],
51 [ "bid", "<msat-amount>" ], 47 [ "bid", "<msat-amount>" ],
@@ -59,20 +55,19 @@ All tags are optional.
59* `i` tag: Input data for the job (zero or more inputs) 55* `i` tag: Input data for the job (zero or more inputs)
60 * `<data>`: The argument for the input 56 * `<data>`: The argument for the input
61 * `<input-type>`: The way this argument should be interpreted. MUST be one of: 57 * `<input-type>`: The way this argument should be interpreted. MUST be one of:
62 * `url`: A URL to be fetched 58 * `url`: A URL to be fetched of the data that should be processed.
63 * `event`: A Nostr event ID. 59 * `event`: A Nostr event ID.
64 * `job`: The output of a previous job with the specified event ID 60 * `job`: The output of a previous job with the specified event ID. The dermination of which output to build upon is up to the service provider to decide (e.g. waiting for a signaling from the customer, waiting for a payment, etc.)
65 * `text`: `<data>` is the value of the input, no resolution is needed 61 * `text`: `<data>` is the value of the input, no resolution is needed
66 * `<marker>`: An optional field indicating how this input should be used within the context of the job
67 * `<relay>`: If `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string 62 * `<relay>`: If `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string
68* `output`: Expected output format. (e.g. MIME type) 63 * `<marker>`: An optional field indicating how this input should be used within the context of the job
69 * Service Providers MUST publish the result of the job in this format if it has been specified. 64* `output`: Expected output format. Different job request `kind` defines this more precisely.
70 * Each job-type ([Appendix 2](#appendix-2-job-types)) might define the output format more narrowly. 65* `param`: Optional parameters for the job as key (first argument)/value (second argument). Different job request `kind` defines this more precisely. (e.g. `[ "param", "lang", "es" ]`)
71* `bid`: Customer MAY specify a maximum amount (in millisats) they are willing to pay 66* `bid`: Customer MAY specify a maximum amount (in millisats) they are willing to pay
72* `relays`: List of relays where Service Providers SHOULD publish responses to 67* `relays`: List of relays where Service Providers SHOULD publish responses to
73* `p`: Service Providers the customer is interested in. Other SPs MIGHT still choose to process the job 68* `p`: Service Providers the customer is interested in. Other SPs MIGHT still choose to process the job
74 69
75## Job result 70## Job result (`kind:6000-6999`)
76 71
77Service providers publish job results, providing the output of the job result. They should tag the original job request event id as well as the customer's pubkey. 72Service providers publish job results, providing the output of the job result. They should tag the original job request event id as well as the customer's pubkey.
78 73
@@ -80,10 +75,11 @@ Service providers publish job results, providing the output of the job result. T
80{ 75{
81 "pubkey": "<service-provider pubkey>", 76 "pubkey": "<service-provider pubkey>",
82 "content": "<payload>", 77 "content": "<payload>",
83 "kind": 65001, 78 "kind": 6xxx,
84 "tags": [ 79 "tags": [
85 [ "request", "<job-request>" ], 80 [ "request", "<job-request>" ],
86 [ "e", "<job-request-id>", "<relay-hint>" ], 81 [ "e", "<job-request-id>", "<relay-hint>" ],
82 [ "i", "<input-data>" ],
87 [ "p", "<customer's-pubkey>" ], 83 [ "p", "<customer's-pubkey>" ],
88 [ "amount", "requested-payment-amount", "<optional-bolt11>" ] 84 [ "amount", "requested-payment-amount", "<optional-bolt11>" ]
89 ] 85 ]
@@ -92,13 +88,14 @@ Service providers publish job results, providing the output of the job result. T
92 88
93* `request`: The job request event stringified-JSON. 89* `request`: The job request event stringified-JSON.
94* `amount`: millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice. 90* `amount`: millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice.
91* `i`: The original input(s) specified in the request.
95 92
96## Job feedback 93## Job feedback
97Service providers can give feedback about a job back to the customer. 94Service providers can give feedback about a job back to the customer.
98 95
99```json 96```json
100{ 97{
101 "kind": 65000, 98 "kind": 7000,
102 "content": "<empty-or-payload>", 99 "content": "<empty-or-payload>",
103 "tags": [ 100 "tags": [
104 [ "status", "<status>", "<extra-info>" ], 101 [ "status", "<status>", "<extra-info>" ],
@@ -110,326 +107,62 @@ Service providers can give feedback about a job back to the customer.
110``` 107```
111 108
112* `content`: Either empty or a job-result (e.g. for partial-result samples) 109* `content`: Either empty or a job-result (e.g. for partial-result samples)
113* `status` tag: Service Providers SHOULD indicate what this feedback status refers to. [Appendix 3](#appendix-3-job-feedback-status) defines status. Extra human-readable information can be added as an extra argument.
114* `amount` tag: as defined in the [Job Result](#job-result) section. 110* `amount` tag: as defined in the [Job Result](#job-result) section.
111* `status` tag: Service Providers SHOULD indicate what this feedback status refers to. [Appendix 1](#appendix-1-job-feedback-status) defines status. Extra human-readable information can be added as an extra argument.
112
113### Job feedback status
114
115| status | description |
116|--------|-------------|
117| `payment-required` | Service Provider requires payment before continuing. |
118| `processing` | Service Provider is processing the job. |
119| `error` | Service Provider was unable to process the job. |
120| `success` | Service Provider successfully processed the job. |
121| `partial` | Service Provider partially processed the job. The `.content` might include a sample of the partial results. |
122
123Any job feedback event MIGHT include results in the `.content` field, as described in the [Job Result](#job-result) section. This is useful for service providers to provide a sample of the results that have been processed so far.
124
115 125
116# Protocol Flow 126# Protocol Flow
117* Customer publishes a job request (e.g. `kind:65002` speech-to-text). 127* Customer publishes a job request (e.g. `kind:5000` speech-to-text).
118* Service Providers can submit `kind:65000` job-feedback events (e.g. `payment-required`, `processing`, `error`, etc.). 128* Service Providers MAY submit `kind:7000` job-feedback events (e.g. `payment-required`, `processing`, `error`, etc.).
119* Upon completion, the service provider publishes the result of the job with a `kind:65001` job-result event. 129* Upon completion, the service provider publishes the result of the job with a `kind:6000` job-result event.
120* At any point, if there is an `amount` pending to be paid as instructed by the service provider, the user can pay the included `bolt11` or zap the job result event the service provider has sent to the user 130* At any point, if there is an `amount` pending to be paid as instructed by the service provider, the user can pay the included `bolt11` or zap the job result event the service provider has sent to the user
121 131
122`kind:65000` and `kind:65001` events MAY include an `amount` tag, this can be interpreted as a suggestion to pay. Service Providers SHOULD use the `payment-required` feedback event to signal that a payment is required and no further actions will be performed until the payment is sent. Customers can always either pay the included `bolt11` invoice or zap the event requesting the payment and service providers should monitor for both if they choose to include a bolt11 invoice. 132Job feedback (`kind:7000`) and Job Results (`kind:6000-6999`) events MAY include an `amount` tag, this can be interpreted as a suggestion to pay. Service Providers MUST use the `payment-required` feedback event to signal that a payment is required and no further actions will be performed until the payment is sent.
133
134Customers can always either pay the included `bolt11` invoice or zap the event requesting the payment and service providers should monitor for both if they choose to include a bolt11 invoice.
123 135
124## Notes about the protocol flow 136## Notes about the protocol flow
125The flow is deliberately ambiguous, allowing vast flexibility for the interaction between customers and service providers so that service providers can model their behavior based on their own decisions/perceptions of risk. 137The flow is deliberately ambiguous, allowing vast flexibility for the interaction between customers and service providers so that service providers can model their behavior based on their own decisions/perceptions of risk.
126 138
127Some service providers might choose to submit a `payment-required` as the first reaction before sending a `processing` or before delivering `kind:65001` results, some might choose to serve partial results for the job (e.g. as a sample), send a `payment-required` to deliver the rest of the results, and some service providers might choose to assess likelihood of payment based on an npub's past behavior and thus serve the job results before requesting payment for the best possible UX. 139Some service providers might choose to submit a `payment-required` as the first reaction before sending a `processing` or before delivering results, some might choose to serve partial results for the job (e.g. a sample), send a `payment-required` to deliver the rest of the results, and some service providers might choose to assess likelihood of payment based on an npub's past behavior and thus serve the job results before requesting payment for the best possible UX.
128 140
129It's not up to this NIP to define how individual vending machines should choose to run their business. 141It's not up to this NIP to define how individual vending machines should choose to run their business.
130 142
131# Cancellation 143# Cancellation
132A job request might be cancelled by publishing a `kind:5` delete request event tagging the job request event. 144A job request might be cancelled by publishing a `kind:5` delete request event tagging the job request event.
133 145
134# Job chaining 146# Appendix 1: Job chaining
135A Customer MAY request multiple jobs to be processed as a chain, where the output of a job can be the input of another job. (e.g. podcast transcription -> summarization of the transcription). This is done by specifying as input an event id of a different job with the `job` type. 147A Customer MAY request multiple jobs to be processed as a chain, where the output of a job is the input of another job. (e.g. podcast transcription -> summarization of the transcription). This is done by specifying as input an event id of a different job with the `job` type.
136 148
137Service Providers MAY begin processing a subsequent job the moment they see the prior job's result, but they will likely wait for a zap to be published first. This introduces a risk that Service Provider of job #1 might delay publishing the zap event in order to have an advantage. This risk is up to Service Providers to mitigate or to decide whether the service provider of job #1 tends to have good-enough results so as to not wait for an explicit zap to assume the job was accepted. 149Service Providers MAY begin processing a subsequent job the moment they see the prior job's result, but they will likely wait for a zap to be published first. This introduces a risk that Service Provider of job #1 might delay publishing the zap event in order to have an advantage. This risk is up to Service Providers to mitigate or to decide whether the service provider of job #1 tends to have good-enough results so as to not wait for an explicit zap to assume the job was accepted.
138 150
139This gives a higher level of flexibility to service providers (which sophisticated service providers would take anyway). 151This gives a higher level of flexibility to service providers (which sophisticated service providers would take anyway).
140 152
141Consult [Appendix 1: Example](#appendix-1-examples)'s [Summarization of a podcast](#summarization-of-a-podcast) 153# Appendix 2: Service provider discoverability
142 154Service Providers MAY use NIP-89 announcements to advertise their support for job kinds:
143### E.g. Payment required (with sample content)
144```json
145{
146 "kind": 65000,
147 "content": "This is the transcription service that you",
148 "tags": [
149 [ "e", <job-request-id>, <relay-hint> ],
150 [ "p", <customer-pubkey> ],
151 [ "status", "payment-required" ],
152 [ "amount", "7000" ],
153 ]
154}
155```
156
157# Appendix 1: Examples
158
159## Transcript of a podcast from second `900` to `930`.
160
161### `kind:65002`: Speech-to-text job request
162```json
163{
164 "id": "12345",
165 "pubkey": "abcdef",
166 "content": "",
167 "kind": 65002,
168 "tags": [
169 [ "i", "https://bitcoin.review/episode1.mp3", "url" ],
170 [ "params", "range", "900", "930" ],
171 [ "output", "text/plain" ],
172 [ "bid", "50000" ],
173 ]
174}
175```
176
177### `kind:65000`: Job Feedback: request for (partial) payment
178* The SP is signaling here that it won't start processing until 100 sats are paid
179```json
180{
181 "kind": 65000,
182 "content": "",
183 "tags": [
184 ["e", "12345"],
185 ["p", "abcdef"],
186 ["status", "payment-required"],
187 ["amount", "100000"]
188 ]
189}
190```
191
192* User zaps 100 sats to the `kind:65000` job-feedback
193
194### `kind:65001`: Job result + request for remaining payment
195```json
196{
197 "content": "blah blah blah",
198 "tags": [
199 ["e", "12345"],
200 ["p", "abcdef"],
201 ["amount", "400000"]
202 ]
203}
204```
205
206## Summarization of a podcast
207User publishes two job requests at the same time. A job that transcribes an audio and a job that summarizes the transcription (output of job #1).
208
209User publishes event #1 and #2 together.
210
211### `kind:65002`: Job Request #1: speech-to-text
212```json
213{
214 "id": "12345",
215 "pubkey": "abcdef",
216 "kind": 65002,
217 "content": "",
218 "tags": [
219 [ "i", "https://bitcoin.review/episode1.mp3", "url" ],
220 [ "output", "text/plain" ],
221 [ "params", "range", "900", "930" ],
222 [ "bid", "100000" ]
223 ]
224}
225```
226
227### `kind:65002`: Job Request #2: summarization of job #1's result
228```json
229{
230 "id": "12346",
231 "pubkey": "abcdef",
232 "kind": 65003,
233 "content": "",
234 "tags": [
235 [ "i", "12345", "job" ], // input is the output of job with id 12345
236 [ "output", "text/plain" ],
237 [ "params", "length", "3 paragraphs" ],
238 [ "bid", "10000" ]
239 ]
240}
241```
242
243## Translation of a note
244### `kind:65004`: Job Request #1: translation of an existing note
245```json
246{
247 "id": "12346",
248 "pubkey": "abcdef",
249 "content": "",
250 "kind": 65004,
251 "tags": [
252 [ "i", "<hexid>", "event", "wss://relay.nostr.com" ]
253 [ "output", "text/plain" ],
254 [ "params", "lang", "es_AR" ],
255 [ "bid", "5000" ]
256 ]
257}
258```
259
260### `kind:65001`: Job result
261```json
262{
263 "kind": 65001,
264 "content": "Che, que copado, boludo!",
265 "tags": [
266 ["e", "12346"],
267 ["p", "abcdef"],
268 ["amount", "4000"]
269 ]
270}
271```
272
273## AI-image of the summarization of 2 podcasts
274
275### `kind:65002`: Job request #1 (transcribe podcast #1)
276```json
277{
278 "id": "123",
279 "kind": 65002,
280 "tags": [
281 [ "i", "https://example.com/episode1.mp3", "url" ],
282 [ "bid", "100000" ]
283 ]
284}
285```
286
287### `kind:65002`: Job request #2 (transcribe podcast #2)
288```json
289{
290 "id": "124",
291 "kind": 65002,
292 "tags": [
293 [ "i", "https://example.com/episode2.mp3", "url" ],
294 [ "bid", "100000" ]
295 ]
296}
297```
298
299### `kind:65003`: Job request #3 (summarize the two job's outputs into one paragraph)
300```json
301{
302 "id": "125",
303 "kind": 65003,
304 "tags": [
305 [ "param", "length", "1 paragraph" ],
306 [ "i", "123", "job" ],
307 [ "i", "124", "job" ],
308 [ "bid", "100000" ]
309 ]
310}
311```
312
313### `kind:65005`: Job request #4 (generate image based on the summary)
314```json
315{
316 "id": "126",
317 "kind": 65004,
318 "tags": [
319 [ "i", "125", "job" ],
320 [ "param", "prompt", "photorealistic" ],
321 [ "param", "size", "4000x4000" ],
322 [ "bid", "500000" ]
323 ]
324}
325```
326
327## AI-image of embedded input
328
329### `kind:65005`: Job request
330```json
331{
332 "kind": 65004,
333 "tags": [
334 [ "i", "Millions of vending machines, interconnected with tubes with eah other", "text" ],
335 [ "param", "prompt", "photorealistic" ],
336 [ "bid", "500000" ]
337 ]
338}
339```
340
341# Appendix 2: Job types
342
343This is a list of all the supported job requests.
344
345## speech-to-text: `kind:65002`
346
347### params
348
349| param | req? | description |
350|------------|------|-----------------------------------------------------------|
351| `range` | opt | timestamp range (in seconds) of desired text to be transcribed |
352| `alignment`| opt | word, segment, raw: word-level, segment-level, or raw outputs |
353
354## summarization: `kind:65003`
355
356| param | req? | description |
357|-----------|------|---------------|
358| `length` | opt | desired length |
359
360## translation: `kind:65004`
361
362| param | req? | description |
363|-----------|------|--------------------------------------------|
364| `lang` | req | desired language in BCP 47 format. |
365
366## image generation: `kind:65005`
367
368| param | req? | description |
369|-----------|------|-------------------------------------------------------|
370| `prompt` | opt | extra prompt to be used for the image generation |
371| `size` | opt | desired size of the image |
372
373## event list generation: `kind:65006`
374
375Generates a list of event ids, (e.g. algorithmic feeds, spam-free notifications, trending topics)
376
377Output should be a stringified array of elements usually find in a nostr event' `tags`, e.g.:
378
379```json
380{ "content": "[
381 [\"e\", \"<id>\"],
382 [\"a\", \"30023:pubkey:id\"],
383 [\"t\", \"tag\"],
384 [\"p\", \"pubkey\"],
385]" }
386```
387
388| param | req? | description |
389|-----------|------|-------------------------------------------------------|
390| `filter` | opt | Stringified JSON `REQ` filter. Used to scope the desired results (e.g. specify the desired kinds)
391| `prompt` | opt | A human-readable description of the desired results. Which might be used with e.g. an LLM to tune the results.
392| `p` | opt | Array of pubkeys to generate a feed from someone else's point-of-view. This param allows for a client to choose to generate the feeds and incur the costs of its users.
393
394### example job-request
395
396Generate an algorithmic feed of the most interesting `kind:1`s related to the topic "bitcoin", tagging service providers specializing in safe-for-work content
397that would interest pubkey `pubkey1`.
398
399```json
400{
401 "kind": 65006,
402 "tags": [
403 [ "param", "filter", "{ \"kinds\": [1], \"#t\": [\"bitcoin\"] }" ],
404 [ "param", "p", "[\"pubkey1\"]"]
405 [ "bid", "5000" ],
406 [ "t", "sfw" ]
407 ]
408}
409```
410
411# Appendix 3: Job feedback status
412
413| status | description |
414|--------|-------------|
415| `payment-required` | Service Provider requires payment before continuing. |
416| `processing` | Service Provider is processing the job. |
417| `error` | Service Provider was unable to process the job. |
418| `success` | Service Provider successfully processed the job. |
419| `partial` | Service Provider partially processed the job. The `.content` might include a sample of the partial results. |
420
421Any job feedback event MIGHT include results in the `.content` field, as described in the [Job Result](#job-result) section. This is useful for service providers to provide a sample of the results that have been processed so far.
422
423# Appendix 4: Service provider discoverability
424
425Service Providers can use NIP-89 announcements to advertise their support for job kinds:
426 155
427```json 156```json
428{ 157{
429 "kind": 31990, 158 "kind": 31990,
430 "pubkey": "<pubkey>", 159 "pubkey": "<pubkey>",
160 "content": "{
161 \"name\": \"Translating DVM\",
162 \"about\": \"I'm a DVM specialized in translating Bitcoin content.\"
163 }",
431 "tags": [ 164 "tags": [
432 [ "k", 65002 ], // e.g. speech-to-text 165 [ "k", 5005 ], // e.g. translation
433 [ "t", "bitcoin" ] // e.g. optionally advertises it specializes in bitcoin audio transcription that won't confuse "Drivechains" with "Ridechains" 166 [ "t", "bitcoin" ] // e.g. optionally advertises it specializes in bitcoin audio transcription that won't confuse "Drivechains" with "Ridechains"
434 ] 167 ]
435} 168}