Skip to content

Commit e80dcdd

Browse files
author
Jon Staab
committed
New DVM spec
1 parent cddab6d commit e80dcdd

File tree

1 file changed

+60
-199
lines changed

1 file changed

+60
-199
lines changed

90.md

Lines changed: 60 additions & 199 deletions
Original file line numberDiff line numberDiff line change
@@ -1,230 +1,91 @@
11
NIP-90
22
======
33

4-
Data Vending Machine
5-
--------------------
4+
Service Providers
5+
-----------------
66

77
`draft` `optional`
88

9-
This NIP defines the interaction between customers and Service Providers for performing on-demand computation.
9+
This NIP defines listings for service providers.
1010

11-
Money in, data out.
11+
## Flows
1212

13-
## Kinds
14-
This NIP reserves the range `5000-7000` for data vending machine use.
13+
A flow is an independently-defined specification for how users ineract with a given service. The flow may be identified using any one of the following:
1514

16-
| Kind | Description |
17-
| ---- | ----------- |
18-
| 5000-5999 | Job request kinds |
19-
| 6000-6999 | Job result |
20-
| 7000 | Job feedback |
15+
- A `SP-XX` number, referring to a specification contained in this document.
16+
- A url pointing to a web page containing a flow specification.
17+
- A nostr event address pointing to any event which contains a flow specification.
2118

22-
Job 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`).
19+
Flow specifications MAY describe ANY flow, but SHOULD use nostr events as the primary means of communication between parties. Nostr events SHOULD specify the address of the `kind 31999` service announcement event when relevant, rather than the serivce provider's pubkey.
2320

24-
Job request types are defined [separately](https://github.com/nostr-protocol/data-vending-machines/tree/master/kinds).
21+
## Discovery
2522

26-
## Rationale
27-
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 they don't necessarily care about "who" processes the data.
23+
Service Providers MAY use a `kind 31999` service announcement event to advertise their support for a given flow:
2824

29-
This NIP is not to be confused with a 1:1 marketplace; instead, it describes a flow where a user announces a desired output, willingness to pay, and service providers compete to fulfill the job requirement in the best way possible.
30-
31-
### Actors
32-
There are two actors in the workflow described in this NIP:
33-
* Customers (npubs who request a job)
34-
* Service providers (npubs who fulfill jobs)
35-
36-
## Job request (`kind:5000-5999`)
37-
A request to process data, published by a customer. This event signals that a customer is interested in receiving the result of some kind of compute.
38-
39-
```jsonc
40-
{
41-
"kind": 5xxx, // kind in 5000-5999 range
42-
"content": "",
43-
"tags": [
44-
[ "i", "<data>", "<input-type>", "<relay>", "<marker>" ],
45-
[ "output", "<mime-type>" ],
46-
[ "relays", "wss://..." ],
47-
[ "bid", "<msat-amount>" ],
48-
[ "t", "bitcoin" ]
49-
],
50-
// other fields...
51-
}
52-
```
53-
54-
All tags are optional.
55-
56-
* `i` tag: Input data for the job (zero or more inputs)
57-
* `<data>`: The argument for the input
58-
* `<input-type>`: The way this argument should be interpreted. MUST be one of:
59-
* `url`: A URL to be fetched of the data that should be processed.
60-
* `event`: A Nostr event ID.
61-
* `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.)
62-
* `text`: `<data>` is the value of the input, no resolution is needed
63-
* `<relay>`: If `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string
64-
* `<marker>`: An optional field indicating how this input should be used within the context of the job
65-
* `output`: Expected output format. Different job request `kind` defines this more precisely.
66-
* `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" ]`)
67-
* `bid`: Customer MAY specify a maximum amount (in millisats) they are willing to pay
68-
* `relays`: List of relays where Service Providers SHOULD publish responses to
69-
* `p`: Service Providers the customer is interested in. Other SPs MIGHT still choose to process the job
70-
71-
## Encrypted Params
72-
73-
If the user wants to keep the input parameters a secret, they can encrypt the `i` and `param` tags with the service provider's 'p' tag and add it to the content field. Add a tag `encrypted` as tags. Encryption for private tags will use [NIP-04 - Encrypted Direct Message encryption](04.md), using the user's private and service provider's public key for the shared secret
74-
75-
```json
76-
[
77-
["i", "what is the capital of France? ", "text"],
78-
["param", "model", "LLaMA-2"],
79-
["param", "max_tokens", "512"],
80-
["param", "temperature", "0.5"],
81-
["param", "top-k", "50"],
82-
["param", "top-p", "0.7"],
83-
["param", "frequency_penalty", "1"]
84-
]
85-
```
86-
87-
This param data will be encrypted and added to the `content` field and `p` tag should be present
88-
89-
```jsonc
25+
```yaml
9026
{
91-
"content": "BE2Y4xvS6HIY7TozIgbEl3sAHkdZoXyLRRkZv4fLPh3R7LtviLKAJM5qpkC7D6VtMbgIt4iNcMpLtpo...",
27+
"kind": 31999,
28+
"pubkey": "<provider_pubkey>",
29+
"created_at": 1000000000,
30+
"content": "",
9231
"tags": [
93-
["p", "04f74530a6ede6b24731b976b8e78fb449ea61f40ff10e3d869a3030c4edc91f"],
94-
["encrypted"]
95-
],
96-
// other fields...
32+
["d", "<dvm-identifier>"],
33+
["n", "<nostr event naddr (decoded) or url describing the flow>"],
34+
["name", "<dvm_name>"],
35+
["about", "<dvm_description>"],
36+
["picture", "<dvm_logo_url>"],
37+
]
9738
}
9839
```
9940

41+
## Flow Specifications
10042

101-
## Job result (`kind:6000-6999`)
102-
103-
Service 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.
104-
105-
```jsonc
106-
{
107-
"pubkey": "<service-provider pubkey>",
108-
"content": "<payload>",
109-
"kind": 6xxx,
110-
"tags": [
111-
["request", "<job-request>"],
112-
["e", "<job-request-id>", "<relay-hint>"],
113-
["i", "<input-data>"],
114-
["p", "<customer's-pubkey>"],
115-
["amount", "requested-payment-amount", "<optional-bolt11>"]
116-
],
117-
// other fields...
118-
}
119-
```
120-
121-
* `request`: The job request event stringified-JSON.
122-
* `amount`: millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice.
123-
* `i`: The original input(s) specified in the request.
124-
125-
## Encrypted Output
126-
127-
If the request has encrypted params, then output should be encrypted and placed in `content` field. If the output is encrypted, then avoid including `i` tag with input-data as clear text.
128-
Add a tag encrypted to mark the output content as `encrypted`
129-
130-
```jsonc
131-
{
132-
"pubkey": "<service-provider pubkey>",
133-
"content": "<encrypted payload>",
134-
"kind": 6xxx,
135-
"tags": [
136-
["request", "<job-request>"],
137-
["e", "<job-request-id>", "<relay-hint>"],
138-
["p", "<customer's-pubkey>"],
139-
["amount", "requested-payment-amount", "<optional-bolt11>"],
140-
["encrypted"]
141-
],
142-
// other fields...
143-
}
144-
```
43+
### SP-01 - Content Discovery
14544

146-
## Job feedback
45+
User publishes a `kind 5300` request for recommended content, including the following tags:
14746

148-
Service providers can give feedback about a job back to the customer.
47+
- `param, max_results` with the max number of requested recommendations
48+
- `param, user` with the pubkey of the user making the request
49+
- `relays` with one or more relays on which the service provider should respond
50+
- `p` the pubkey of the service provider (for backwards compatibility)
14951

150-
```jsonc
52+
```yaml
15153
{
152-
"kind": 7000,
153-
"content": "<empty-or-payload>",
154-
"tags": [
155-
["status", "<status>", "<extra-info>"],
156-
["amount", "requested-payment-amount", "<bolt11>"],
157-
["e", "<job-request-id>", "<relay-hint>"],
158-
["p", "<customer's-pubkey>"],
159-
],
160-
// other fields...
54+
"id": "3706c9b6d150a8dd81596bbb7af2c7483b12b3342abea789365812426500057d",
55+
"pubkey": "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322",
56+
"created_at": 1748535017,
57+
"kind": 5300,
58+
"tags": [
59+
["param", "max_results", "200"],
60+
["param", "user", "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322"],
61+
["relays", "wss://relay.nostrdvm.com", "wss://nostr.mom", "wss://nostr.oxtr.dev"],
62+
["p", "96945c769ef9e91be05570fef1003633f5bb9d072ba2453781b5140013ab35b3"]
63+
],
64+
"content": "NIP 90 Content Discovery request",
16165
}
16266
```
16367

164-
* `content`: Either empty or a job-result (e.g. for partial-result samples)
165-
* `amount` tag: as defined in the [Job Result](#job-result-kind6000-6999) section.
166-
* `status` tag: Service Providers SHOULD indicate what this feedback status refers to. [Job Feedback Status](#job-feedback-status) defines status. Extra human-readable information can be added as an extra argument.
167-
168-
* NOTE: If the input params requires input to be encrypted, then `content` field will have encrypted payload with `p` tag as key.
169-
170-
### Job feedback status
171-
172-
| status | description |
173-
| -------- | ------------- |
174-
| `payment-required` | Service Provider requires payment before continuing. |
175-
| `processing` | Service Provider is processing the job. |
176-
| `error` | Service Provider was unable to process the job. |
177-
| `success` | Service Provider successfully processed the job. |
178-
| `partial` | Service Provider partially processed the job. The `.content` might include a sample of the partial results. |
179-
180-
Any job feedback event MIGHT include results in the `.content` field, as described in the [Job Result](#job-result-kind6000-6999) section. This is useful for service providers to provide a sample of the results that have been processed so far.
181-
182-
183-
# Protocol Flow
184-
185-
* Customer publishes a job request (e.g. `kind:5000` speech-to-text).
186-
* Service Providers MAY submit `kind:7000` job-feedback events (e.g. `payment-required`, `processing`, `error`, etc.).
187-
* Upon completion, the service provider publishes the result of the job with a `kind:6000` job-result event.
188-
* 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.
68+
The service then responds with a `kind 6300` with the `content` set to a stringified tag list of e-tagged events. These are the recommendations. In addition, the response SHOULD include the following tags:
18969

190-
Job 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.
70+
- `status` - `success` if successful
71+
- `request` - the stringified `kind 5300` request event JSON
72+
- `e` - the `kind 5300` request event id
73+
- `p` - the author of the `kind 5300` event
19174

192-
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.
193-
194-
## Notes about the protocol flow
195-
The 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.
196-
197-
Some 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.
198-
199-
It's not up to this NIP to define how individual vending machines should choose to run their business.
200-
201-
# Cancellation
202-
A job request might be canceled by publishing a `kind:5` delete request event tagging the job request event.
203-
204-
# Appendix 1: Job chaining
205-
A 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.
206-
207-
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 an explicit zap to assume the job was accepted.
208-
209-
This gives a higher level of flexibility to service providers (which sophisticated service providers would take anyway).
210-
211-
# Appendix 2: Service provider discoverability
212-
Service Providers MAY use NIP-89 announcements to advertise their support for job kinds:
213-
214-
```jsonc
75+
```yaml
21576
{
216-
"kind": 31990,
217-
"pubkey": "<pubkey>",
218-
"content": "{
219-
\"name\": \"Translating DVM\",
220-
\"about\": \"I'm a DVM specialized in translating Bitcoin content.\"
221-
}",
222-
"tags": [
223-
["k", "5005"], // e.g. translation
224-
["t", "bitcoin"] // e.g. optionally advertises it specializes in bitcoin audio transcription that won't confuse "Drivechains" with "Ridechains"
225-
],
226-
// other fields...
77+
"content": "[[\"e\", \"5614552b203ed72011d52afe03aa022491fbc0aa7dc7b51fc72d132f1f4e58d5\"]]",
78+
"created_at": 1748535020,
79+
"id": "66c83248e174bfeef852f80278290700627bf12e00aec3afe3785c8d607443d7",
80+
"kind": 6300,
81+
"pubkey": "96945c769ef9e91be05570fef1003633f5bb9d072ba2453781b5140013ab35b3",
82+
"tags": [
83+
["request", "<stringified 5300 request event>"],
84+
["e", "3706c9b6d150a8dd81596bbb7af2c7483b12b3342abea789365812426500057d"],
85+
["p", "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322"],
86+
["alt", "This is the result of a NIP90 DVM task with kind 5300"],
87+
["status", "success"],
88+
["relays", "wss://relay.nostrdvm.com", "wss://nostr.mom", "wss://nostr.oxtr.dev"]
89+
]
22790
}
22891
```
229-
230-
Customers can use NIP-89 to see what service providers their follows use.

0 commit comments

Comments
 (0)