2023-07-05 09:14:50 +00:00
NIP-XX
======
Data Vending Machine
--------------------
`draft` `optional` `author:pablof7z`
This NIP defines the interaction between customers and Service Providers to perform on-demand computation.
2023-07-03 12:21:13 +00:00
2023-07-23 19:28:59 +00:00
## Kinds
2023-07-23 20:37:20 +00:00
This NIP reserves the range `65000-66000` for data vending machine use.
2023-07-23 19:28:59 +00:00
| Kind | Description |
| ---- | ----------- |
| 65000 | Job feedback |
| 65001 | Job result |
2023-07-23 20:37:20 +00:00
| 65002-66000 | Job request kinds |
2023-07-23 19:28:59 +00:00
2023-07-23 20:58:12 +00:00
[Appendix 2 ](#appendix-2-job-types ) defines the job types.
2023-07-03 12:21:13 +00:00
## Rationale
2023-07-05 09:14:50 +00:00
Nostr 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 where they don't necessarily care about "who" processes the data.
2023-07-03 12:21:13 +00:00
2023-07-23 19:28:59 +00:00
This NIP is not to be confused with a 1:1 marketplace; but rather, a flow where user announces a desired output, willingness to pay, and service providers compete to fulfill the job requirement in the best way possible.
2023-07-03 12:21:13 +00:00
### Actors
There are two actors to the workflow described in this NIP:
* Customers (npubs who request a job)
* Service providers (npubs who fulfill jobs)
2023-07-05 09:14:50 +00:00
# Event Kinds
## Job request
A request to have data processed -- published by a customer
2023-07-03 12:21:13 +00:00
```json
{
2023-07-23 20:58:12 +00:00
"kind": xxx, // kind in 65002-66000 range
2023-07-03 12:21:13 +00:00
"content": "",
"tags": [
2023-07-23 19:28:59 +00:00
[ "i", "< data > ", "< input-type > ", "< marker > ", "< relay > " ],
2023-07-11 20:25:54 +00:00
[ "output", "< mime-type > " ],
2023-07-05 09:14:50 +00:00
[ "relays", "wss://..."],
2023-07-23 19:28:59 +00:00
[ "bid", "< msat-amount > " ],
2023-07-05 09:14:50 +00:00
[ "exp", "< timestamp > " ],
2023-07-23 19:28:59 +00:00
[ "t", "bitcoin" ]
2023-07-03 12:21:13 +00:00
]
}
```
2023-07-23 20:37:20 +00:00
All tags are optional.
2023-07-23 19:28:59 +00:00
* `i` tag: Input data for the job, (zero or more inputs may exist)
2023-07-11 13:22:30 +00:00
* `<data>` : The argument for the input
2023-07-23 19:28:59 +00:00
* `<input-type>` : The way this argument should be interpreted, MUST be one of:
2023-07-03 12:21:13 +00:00
* `url` : a URL to be fetched
2023-07-11 13:22:30 +00:00
* `event` : a nostr event ID, include an optional relay-url extra param
2023-07-03 12:33:17 +00:00
* `job` : the output of a previous job with the specified event ID
2023-07-23 20:58:12 +00:00
* `text` : `<data>` is the value of the input, no resolution is needed
* `<marker>` : an optional field indicating how this input should be used within the context of the job.
2023-07-23 19:28:59 +00:00
* `<relay>` : if `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string.
2023-07-23 20:37:20 +00:00
* `output` : MIME type. Expected output format. Service Providers SHOULD publish the result of the job in this format if it has been specified.
* `bid` : Customer MAY specify a maximum amount (in millisats) they are willing to pay.
* `relays` : relays where Service Providers SHOULD publish responses to.
* `p` : Service Providers the customer is interested in. Other SP MIGHT still choose to process the job.
* `exp` : expiration timestamp. Service Providers SHOULD not send results after this timestamp.
2023-07-03 12:21:13 +00:00
2023-07-05 09:14:50 +00:00
## Job result
2023-07-08 10:51:30 +00:00
The output of processing the data -- published by the Service Provider.
2023-07-03 12:21:13 +00:00
```json
{
2023-07-23 19:28:59 +00:00
"pubkey": "< service-provider pubkey > ",
2023-07-11 13:22:30 +00:00
"content": "< payload > ",
2023-07-23 19:28:59 +00:00
"kind": 65001,
2023-07-03 12:21:13 +00:00
"tags" [
2023-07-23 19:28:59 +00:00
[ "request", "< job-request > " ],
[ "e", "< job-request-id > ", "< relay-hint > " ],
2023-07-08 10:51:30 +00:00
[ "p", "< Customer ' s pubkey > " ],
[ "status", "success", "< more-info > " ],
2023-07-15 10:24:32 +00:00
[ "amount", "requested-payment-amount", "< optional-bolt11 > " ]
2023-07-03 12:21:13 +00:00
]
}
```
2023-07-23 19:28:59 +00:00
* `request` tag: The job request event ID.
* `amount` : millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice.
2023-07-11 13:22:30 +00:00
## Job feedback
Both customers and service providers can give feedback about a job.
2023-07-03 12:21:13 +00:00
2023-07-15 10:24:32 +00:00
The result of the job SHOULD be included in the `content` field.
2023-07-03 12:21:13 +00:00
2023-07-11 13:22:30 +00:00
* `status` tag: Service Providers MAY indicate errors or extra info about the results by including them in the `status` tag.
2023-07-15 10:24:32 +00:00
* `amount` : millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice.
2023-07-05 09:14:50 +00:00
# Protocol Flow
2023-07-23 19:28:59 +00:00
* Customer publishes a job request (e.g. `kind:65002` ).
* Service Prpvoders can submit `kind:65000` job-feedback events (e.g. `payment-required` , `processing` , `error` , etc.).
* Upon completion, the service provider publishes the result of the job with a `kind:65001` job-result event.
* At any point, the user can pay the included `bolt11` or zap any of the events the service provider has sent to the user.
2023-07-05 09:14:50 +00:00
2023-07-23 20:58:12 +00:00
`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 are 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.
2023-07-05 09:14:50 +00:00
2023-07-15 10:24:32 +00:00
## Notes about the protocol flow
2023-07-23 19:28:59 +00:00
The flow is deliverately ambiguos, allowing vast flexibility for the interaction between customers and service providers so that service providers can model their behavior based on their own decisions. Some service providers might choose to submit a `payment-required` as the first reaction before sending an `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 likelyhood of payment based on an npub's past behavior and thus serve the job results before requesting payment for the best possible UX.
It's not up to this NIP to define how individual vending machines should choose to run their business.
2023-07-03 12:21:13 +00:00
2023-07-05 09:14:50 +00:00
# Payment
2023-07-23 19:28:59 +00:00
Customers SHOULD pay service providers whose job results they accept by either zapping the Service Provider and tagging the `kind:65001` job result or, if included, paying the bolt11 invoice.
2023-07-05 09:14:50 +00:00
2023-07-23 19:28:59 +00:00
Additionally, if a service provider requests full or partial prepayment via a `kind:65000` job-feedback event, the customer SHOULD zap that event to pay the service provider.
2023-07-11 13:22:30 +00:00
# Cancellation
2023-07-23 19:28:59 +00:00
A job request might be cancelled by publishing a `kind:5` delete request event tagging the job request event.
2023-07-05 09:14:50 +00:00
# Job chaining
2023-07-08 10:51:30 +00:00
A Customer MAY request multiple jobs to be processed in a chained form, so that the output of a job can be the input of the next job. (e.g. summarization of a podcast's transcription). This is done by specifying as `input` an eventID of a different job with the `job` marker.
2023-07-03 12:21:13 +00:00
2023-07-08 10:51:30 +00:00
Service 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 a explicit zap to assume the job was accepted.
2023-07-03 12:21:13 +00:00
2023-07-23 20:58:12 +00:00
Consult [Appendix 1: Example ](#appendix-1-examples )'s [Summarization of a podcast ](#summarization-of-a-podcast )
2023-07-11 13:22:30 +00:00
# Job Feedback
2023-07-23 19:28:59 +00:00
The parties to a job request can use `kind:65000` to provide feedback about the job, using a `status` tag to indicate the type of feedback.
2023-07-03 12:21:13 +00:00
2023-07-23 19:28:59 +00:00
Any job feedback event MIGHT include an `amount` tag, indicating the amount of millisats the party is requesting to be paid. An optional third value can be a bolt11 invoice.
2023-07-05 09:14:50 +00:00
2023-07-23 19:28:59 +00:00
| status | description |
|--------|-------------|
| `payment-required` | Service Provider requires payment before continuing. |
| `processing` | Service Provider is processing the job. |
| `error` | Service Provider was unable to process the job. |
| `success` | Service Provider successfully processed the job. |
| `failure` | Service Provider failed to process the job. |
| `partial` | Service Provider partially processed the job. The `.content` might include a sample of the partial results. |
Any job feedback event MIGHT include an `amount` tag, as described in the [Job Result ](#job-result ) section.
Any job feedback event MIGHT include results in the `.content` field, as described in the [Job Result ](#job-result ) section.
### E.g. Payment required (with sample content)
2023-07-05 09:14:50 +00:00
```json
{
2023-07-23 19:28:59 +00:00
"kind": 65000,
"content": "This is the transcription service that you",
2023-07-05 09:14:50 +00:00
"tags": [
2023-07-23 19:28:59 +00:00
[ "e", < job-request-id > , < relay-hint > ],
[ "p", < customer-pubkey > ],
2023-07-05 09:14:50 +00:00
[ "status", "payment-required" ],
[ "amount", "7000" ],
]
}
```
2023-07-03 12:21:13 +00:00
2023-07-05 09:14:50 +00:00
## Job feedback
A user might choose to not accept a job result for any reason. A user can provide feedback via NIP-25 reactions.
The `content` of the `kind:7` event SHOULD include a description of how the user reacted to the job result.
2023-07-03 12:21:13 +00:00
2023-07-15 10:24:32 +00:00
## Not addressed in this NIP
2023-07-03 12:21:13 +00:00
### Reputation system
Service providers are at obvious risk of having their results not compensated. Mitigation of this risk is up to service providers to figure out (i.e. building reputation systems, requiring npub "balances", etc, etc).
It's out of scope (and undesirable) to have this NIP address this issue; the market should.
2023-07-23 19:28:59 +00:00
### Encrypted job requests
Not to be included in the first draft of this NIP, but encrypted job requests should be added. A few ways:
* publish job requests with some useful metadata of the job "e.g. length of audio to be transcribed", service providers offer to do the job, the customer replies with a NIP-04-like encrypted job requested encrypted with the service provider's pubkey.
2023-07-03 12:33:17 +00:00
# Appendix 1: Examples
2023-07-05 09:14:50 +00:00
## Transcript of a podcast from second `900` to `930`.
2023-07-03 12:33:17 +00:00
2023-07-23 19:28:59 +00:00
### `kind:65002`: Speech-to-text job request
2023-07-03 12:33:17 +00:00
```json
{
"id": "12345",
"pubkey": "abcdef",
2023-07-11 20:25:54 +00:00
"content": "",
2023-07-23 19:28:59 +00:00
"kind": 65002,
2023-07-03 12:33:17 +00:00
"tags": [
2023-07-05 09:14:50 +00:00
[ "i", "https://bitcoin.review/episode1.mp3", "url" ],
2023-07-11 13:22:30 +00:00
[ "params", "range", "900", "930" ],
2023-07-23 19:28:59 +00:00
[ "output", "text/vtt" ],
[ "bid", "50000" ],
2023-07-11 13:22:30 +00:00
[ "output", "text/plain" ]
2023-07-03 12:33:17 +00:00
]
}
```
2023-07-23 19:28:59 +00:00
### `kind:65001`: Job Feedback: request for (partial) payment
* The SP is signaling here that it won't start processing until 100 sats are paid
2023-07-11 20:25:54 +00:00
```json
{
2023-07-23 19:28:59 +00:00
"kind": 65000,
2023-07-11 20:25:54 +00:00
"content": "",
"tags": [
["e", "12345"],
["p", "abcdef"],
["status", "payment-required"],
2023-07-23 19:28:59 +00:00
["amount", "100000"]
2023-07-11 20:25:54 +00:00
]
}
```
2023-07-23 19:28:59 +00:00
* User zaps 100 sats to the `kind:65000` job-feedback
2023-07-11 20:25:54 +00:00
2023-07-23 19:28:59 +00:00
### `kind:65001`: Job result + request for remaining payment
2023-07-03 12:33:17 +00:00
```json
{
2023-07-11 13:22:30 +00:00
"content": "blah blah blah",
2023-07-03 12:33:17 +00:00
"tags": [
["e", "12345"],
["p", "abcdef"],
2023-07-23 19:28:59 +00:00
["amount", "400000"]
2023-07-03 12:33:17 +00:00
]
}
```
2023-07-05 09:14:50 +00:00
## Summarization of a podcast
2023-07-23 20:58:12 +00:00
User 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 ).
User publishes event #1 and #2 together.
2023-07-03 12:33:17 +00:00
2023-07-23 19:28:59 +00:00
### `kind:65002`: Job Request #1: speech-to-text
2023-07-03 12:33:17 +00:00
```json
{
"id": "12345",
"pubkey": "abcdef",
2023-07-23 19:28:59 +00:00
"kinds" 65002,
2023-07-23 20:58:12 +00:00
"content": "",
2023-07-03 12:33:17 +00:00
"tags": [
2023-07-05 09:14:50 +00:00
[ "i", "https://bitcoin.review/episode1.mp3", "url" ],
2023-07-23 19:28:59 +00:00
[ "output", "text/plain" ],
[ "params", "range", "900", "930" ],
[ "bid", "100000" ]
2023-07-03 12:33:17 +00:00
]
}
```
2023-07-23 20:58:12 +00:00
### `kind:65002`: Job Request #2: summarization of job #1's result
2023-07-03 12:33:17 +00:00
```json
{
"id": "12346",
"pubkey": "abcdef",
2023-07-23 19:28:59 +00:00
"kinds": 65003,
2023-07-11 20:25:54 +00:00
"content": "",
2023-07-03 12:33:17 +00:00
"tags": [
2023-07-23 20:58:12 +00:00
[ "i", "12345", "job" ], // input is the output of job with id 12345
2023-07-23 19:28:59 +00:00
[ "output", "text/plain" ],
[ "params", "length", "3 paragraphs" ],
[ "bid", "10000" ]
2023-07-03 12:33:17 +00:00
]
}
```
2023-07-05 09:14:50 +00:00
## Translation of a note
2023-07-23 19:28:59 +00:00
### `kind:65004`: Job Request #1: translation of an existing note
2023-07-03 12:33:17 +00:00
```json
{
"id": "12346",
"pubkey": "abcdef",
"content": "",
2023-07-23 19:28:59 +00:00
"kinds": 65004,
2023-07-03 12:33:17 +00:00
"tags": [
2023-07-11 20:25:54 +00:00
[ "i", "< hexid > ", "event", "wss://relay.nostr.com" ]
2023-07-23 19:28:59 +00:00
[ "params", "lang", "es_AR" ],
[ "bid", "5000" ]
2023-07-03 12:33:17 +00:00
]
}
2023-07-05 09:14:50 +00:00
```
2023-07-23 19:28:59 +00:00
### `kind:65001`: Job respomse
2023-07-11 20:25:54 +00:00
```json
{
2023-07-23 19:28:59 +00:00
"kind": 65001,
2023-07-11 20:25:54 +00:00
"content": "Che, que copado, boludo!",
"tags": [
["e", "12346"],
["p", "abcdef"],
2023-07-23 19:28:59 +00:00
["amount", "4000"]
2023-07-11 20:25:54 +00:00
]
}
```
2023-07-05 09:14:50 +00:00
## AI-image of the summarization of 2 podcasts
2023-07-23 19:28:59 +00:00
### `kind:65002`: Job request #1 (transcribe podcast #1)
2023-07-05 09:14:50 +00:00
```json
{
"id": "123",
2023-07-23 19:28:59 +00:00
"kind" 65002,
2023-07-05 09:14:50 +00:00
"tags": [
[ "i", "https://example.com/episode1.mp3", "url" ],
2023-07-23 19:28:59 +00:00
[ "bid", "100000" ]
2023-07-05 09:14:50 +00:00
]
}
```
2023-07-23 19:28:59 +00:00
### `kind:65002`: Job request #2 (transcribe podcast #2)
2023-07-05 09:14:50 +00:00
```json
{
"id": "124",
2023-07-23 19:28:59 +00:00
"kind" 65002,
2023-07-05 09:14:50 +00:00
"tags": [
[ "i", "https://example.com/episode2.mp3", "url" ],
2023-07-23 19:28:59 +00:00
[ "bid", "100000" ]
2023-07-05 09:14:50 +00:00
]
}
```
2023-07-23 19:28:59 +00:00
### `kind:65003`: Job request #3 (summarize both podcasts into one paragraph)
2023-07-05 09:14:50 +00:00
```json
{
"id": "125",
2023-07-23 19:28:59 +00:00
"kind": 65003,
2023-07-05 09:14:50 +00:00
"tags": [
[ "param", "length", "1 paragraph" ],
[ "i", "123", "job" ],
[ "i", "124", "job" ],
2023-07-23 19:28:59 +00:00
[ "bid", "100000" ]
2023-07-05 09:14:50 +00:00
]
}
```
2023-07-23 20:58:12 +00:00
## AI-image of embedded input
2023-07-05 09:14:50 +00:00
2023-07-23 20:58:12 +00:00
### `kind:65005`: Job request
```json
{
"kind": 65004,
"tags": [
[ "i", "Millions of vending machines, interconnected with tubes with eah other", "text" ],
[ "param", "prompt", "photorealistic" ],
[ "bid", "500000" ]
]
}
```
2023-07-11 13:22:30 +00:00
2023-07-23 20:58:12 +00:00
### `kind:65006`: Job request #4 (generate image based on the summary)
```json
{
"id": "126",
"kind": 65004,
"tags": [
[ "i", "125", "job" ],
[ "param", "prompt", "photorealistic" ],
[ "param", "size", "4000x4000" ],
[ "bid", "500000" ]
]
}
```
# Appendix 2: Job types
2023-07-11 13:22:30 +00:00
2023-07-23 20:58:12 +00:00
This is a list of all the supported job requests
.
## speech-to-text: `kind:65002`
### params
2023-07-11 13:22:30 +00:00
| param | req? | description
|--------------------------------|------|--------
| `range` | opt | timestamp range (in seconds) of desired text to be transcribed
2023-07-23 19:28:59 +00:00
| `alignment` | opt | word, segment, raw: word-level, segment-level or raw outputs
2023-07-11 13:22:30 +00:00
2023-07-23 20:58:12 +00:00
## summarization: `kind:65003`
2023-07-11 13:22:30 +00:00
| param | req? | description
|--------------------------------|------|--------
| `length` | opt | desired length
2023-07-23 20:58:12 +00:00
## translation: `kind:65004`
2023-07-11 13:22:30 +00:00
| param | req? | description
|--------------------------------|------|--------
2023-07-23 19:28:59 +00:00
| `lang` | req | desired language in BCP 47 format.
2023-07-11 13:22:30 +00:00
2023-07-23 20:58:12 +00:00
## image generation: `kind:65005`
| param | req? | description
|--------------------------------|------|--------
| `prompt` | opt | extra prompt to be used for the image generation
| `size` | opt | desired size of the image
2023-07-11 13:22:30 +00:00
2023-07-05 09:14:50 +00:00
# Notes
2023-07-23 19:28:59 +00:00
* Job acceptance ambiguity, particularly for job-chaining circumstances is deliberate: service providers could wait until explicit job result acceptance / payment to start working on the next item on the chain, or they could start working as soon as they see a result of the previous job computed.
2023-07-05 09:14:50 +00:00
That's up to each service provider to choose how to behave depending on the circumstances. This gives a higher level of flexibility to service providers (which sophisticated service providers would take anyway).
2023-07-23 19:28:59 +00:00
# Appendix 3: Service provider discoverability
Service Providers can use NIP-89 announcements to advertise their support for job kinds:
```json
{
"kind": 31990,
"pubkey": < pubkey > ,
"tags": [
[ "k", 65002 ], // e.g. speech-to-text
[ "t", "bitcoin" ] // e.g. optionally advertises it specializes in bitcoin audio transcription that won't confuse "Drivechains" with "Ridechains"
]
}
```
Customers can use NIP-89 to see what service providers their follows use.