From 67e950a2009e81df1b8c91b0a2ade0596e83f168 Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Mon, 3 Jul 2023 14:21:13 +0200
Subject: [PATCH 001/217] wip
---
vending-machine.md | 163 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 163 insertions(+)
create mode 100644 vending-machine.md
diff --git a/vending-machine.md b/vending-machine.md
new file mode 100644
index 00000000..273aa28f
--- /dev/null
+++ b/vending-machine.md
@@ -0,0 +1,163 @@
+# NIP-XX: Data Vending Machine
+Money in, data out.
+
+## Rationale
+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"), but where they don't necessarily care about "who" processes the data.
+
+This NIP is not to be confused with a 1:1 marketplace; but rather, a flow where user announces a desired output, willigness to pay, and service providers compete to fulfill the job requirement in the best way possible.
+
+### Actors
+There are two actors to the workflow described in this NIP:
+* Customers (npubs who request a job)
+* Service providers (npubs who fulfill jobs)
+
+## User flow
+* User publishes a job request
+`{ "kind": 68001, "tags": [ [ "j", "speech-to-text" ], ... ] }`
+
+* Service providers listen for the type of jobs they can perform
+`{"kinds":[68001], "#j": ["speech-to-text", "image-generation", ... ]}`
+
+* When a job comes in, the service providers who opt to attempt to fulfill the request begin processing it
+* Upon completion, the service provider publishes the result of the job with a `job-result` event.
+* Upon acceptance, the user zaps the service provider, tagging the job request
+
+## Kinds
+
+This NIP introduces two new kinds:
+
+* `kind:68001`: Job request -- a request to have a job be processed
+* `kind:68002`: Job result -- a proposal of the resulting job
+
+### Job request
+A request to have data processed -- published by a user
+
+```json
+{
+ "kind": 68001,
+ "content": "",
+ "tags": [
+ // The type data processing the user wants to be performed
+ // on the
+ [ "j", "", "" ],
+ [ "input", "", "", "" ],
+ [ "relays", "wss://..."],
+
+ // stringified sat amount that the user is offering to pay
+ // for this request
+ // should this include an optional max price or is it too
+ // ambiguous?
+ [ "bid", "", [""] ],
+
+ // max timestamp at which the job is no longer to be processed
+ [ "expiration", "" ]
+
+ // p tags
+ [ "p", "service-provider-1" ],
+ [ "p", "service-provider-2" ],
+
+ // NIP-33 d-tag
+ [ "d", ""]
+ ]
+}
+```
+
+#### `content` field
+An optional, human-readable description of what this job is for.
+
+#### `j` tag
+Specifies the job to be executed. A job request MUST have exactly one `j` tag.
+
+A `j` tag MIGHT name a specific model to be used for the computed with.
+
+#### `input` tag
+Specified the input that the job should be executed with.
+
+* ``: The argument for the input
+* ``: The way this argument should be interpreted
+ * Possible values:
+ * `url`: a URL to be fetched
+ * `event`: a different event ID
+ * `job`: the output of a previous job
+* ``:
+
+#### `relays` tag
+A list of relays the service provider should publish its job result to.
+
+#### `p` tags (optional)
+A user might want to explicitly request this job to be processed by specific service provider(s). Other service providers might still choose to compete for this job.
+
+#### `expiration` (optional)
+A user might specify that they will not be interested in results past a certain time (e.g. a time-sensitive job whos value is no longer relevant after some time, like a live transcription service)
+
+### Job result
+The output of processing the data -- published by the
+```json
+{
+ "pubkey": "service-provider",
+
+ // result
+ "content": "",
+ "tags" [
+ // stringified JSON request event
+ [ "request", "<2xxx1-event>" ],
+ [ "e", ],
+ [ "p", "" ],
+ [ "status", "success", ""],
+ [ "payment", "requested-payment-amount" ]
+ ]
+}
+```
+
+### `status` tag
+The service provider might want to return an error to the user in case the job could not be processed correctly
+
+### `payment`
+
+## Job types
+
+This NIP defines some job types, clients SHOULD specify these types for maximum compatibility with service providers. Other job types might be added to this NIP.
+
+### `speech-to-text`
+#### params
+| param | req? | description
+|--------------------------------|------|--------
+| `range` | opt | timestamp range (in seconds) of desired text to be transcribed
+
+### `summarization`
+| param | req? | description
+|--------------------------------|------|--------
+| `length` | opt | desired length
+
+### `translation` -- Translate text to a specific language
+#### params
+| param | req? | description
+|--------------------------------|------|--------
+| `language` | req | desired language in BCP 47 format.
+
+## Job chaining
+A customer CAN request multiple jobs to be chained, 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.
+
+Service providers might opt to start processing a subsequent job the moment they see the prior job's result, or they might choose to wait for a zap to have been published. This introduces the 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.
+
+## Job feedback
+> **Warning**
+> Is this hijacking/modifying the meaning of NIP-25 reactions too much?
+
+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, either
+in the form of
+
+
+## Explicitly not addressed in this NIP
+
+### 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.
+
+## Notes
+
+### Multitple job acceptance
+* Nothing prevents a user from accepting multiple job results.
+
From 71803c21a6bdd2413244a47752c129e3c64eaec6 Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Mon, 3 Jul 2023 14:33:17 +0200
Subject: [PATCH 002/217] Add examples
---
vending-machine.md | 84 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 82 insertions(+), 2 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index 273aa28f..a94cd332 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -77,8 +77,8 @@ Specified the input that the job should be executed with.
* ``: The way this argument should be interpreted
* Possible values:
* `url`: a URL to be fetched
- * `event`: a different event ID
- * `job`: the output of a previous job
+ * `event`: a nostr event ID
+ * `job`: the output of a previous job with the specified event ID
* ``:
#### `relays` tag
@@ -161,3 +161,83 @@ It's out of scope (and undesirable) to have this NIP address this issue; the mar
### Multitple job acceptance
* Nothing prevents a user from accepting multiple job results.
+# Appendix 1: Examples
+
+## Customer wants to get a transcript of a podcast from second 900 to 930.
+
+### `kind:68001`: Job Request
+```json
+{
+ "id": "12345",
+ "pubkey": "abcdef",
+ "content": "I need a transcript of Bitcoin.review",
+ "tags": [
+ [ "j", "speech-to-text" ],
+ [ "params", "range", "900", "930" ],
+ [ "input", "https://bitcoin.review/episode1.mp3", "url" ],
+ [ "bid", "5000", "9000" ]
+ ]
+}
+```
+
+### `kind:1021`: Job fulfillment
+```json
+{
+ "content": "Person 1: blah blah blah",
+ "tags": [
+ ["e", "12345"],
+ ["p", "abcdef"],
+ ["status", "success"]
+ ]
+}
+```
+
+## Customer wants to get a summarization of a podcast
+
+User publishes two job requests at the same time in the order they should be executed.
+
+### `kind:68001`: Job Request #1
+```json
+{
+ "id": "12345",
+ "pubkey": "abcdef",
+ "content": "I need a transcript of Bitcoin.review from second 900 to 930",
+ "tags": [
+ [ "j", "speech-to-text" ],
+ [ "params", "range", "900", "930" ],
+ [ "input", "https://bitcoin.review/episode1.mp3", "url" ],
+ [ "bid", "5000", "9000" ]
+ ]
+}
+```
+
+### `kind:68001`: Job Request #2
+```json
+{
+ "id": "12346",
+ "pubkey": "abcdef",
+ "content": "I need a summarization",
+ "tags": [
+ [ "j", "summarization" ],
+ [ "params", "length", "3 paragraphs" ],
+ [ "input", "12346", "job" ],
+ [ "bid", "300", "900" ]
+ ]
+}
+```
+
+## Customer wants a translation of a note
+### `kind:68001`: Job Request #1
+```json
+{
+ "id": "12346",
+ "pubkey": "abcdef",
+ "content": "",
+ "tags": [
+ [ "j", "translation" ],
+ [ "input", "", "event" ]
+ [ "params", "language", "es_AR" ],
+ [ "bid", "100", "500" ]
+ ]
+}
+```
\ No newline at end of file
From b5a7b67d78ad2b8ea52d81704be6b71a9cc80dac Mon Sep 17 00:00:00 2001
From: Semisol <45574030+Semisol@users.noreply.github.com>
Date: Mon, 3 Jul 2023 18:02:15 +0300
Subject: [PATCH 003/217] Clarify JSON serialization for the `id` field
---
01.md | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/01.md b/01.md
index 2ff81ebf..9258d2f7 100644
--- a/01.md
+++ b/01.md
@@ -30,7 +30,7 @@ The only object type that exists is the `event`, which has the following format
}
```
-To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (with no white space or line breaks) of the following structure:
+To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (which is described below) of the following structure:
```json
[
@@ -43,6 +43,14 @@ To obtain the `event.id`, we `sha256` the serialized event. The serialization is
]
```
+To prevent implementation differences from creating a different event ID for the same event, the following rules MUST be followed while serializing:
+- No whitespace, line breaks or other unnecessary formatting should be included in the output JSON.
+- No characters except the following should be escaped, and instead should be included verbatim:
+ - The line break, `0x0A`, as `\n`
+ - A double quote, `0x22`, as `\"`
+ - A backspace, `0x5C`, as `\\`
+- UTF-8 should be used for encoding.
+
## Communication between clients and relays
Relays expose a websocket endpoint to which clients can connect.
From 3f8658ecc11e593f85a6a8d7de109d0b8f3254df Mon Sep 17 00:00:00 2001
From: Semisol <45574030+Semisol@users.noreply.github.com>
Date: Tue, 4 Jul 2023 13:49:52 +0300
Subject: [PATCH 004/217] Fix typo
---
01.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/01.md b/01.md
index 9258d2f7..70aae443 100644
--- a/01.md
+++ b/01.md
@@ -48,7 +48,7 @@ To prevent implementation differences from creating a different event ID for the
- No characters except the following should be escaped, and instead should be included verbatim:
- The line break, `0x0A`, as `\n`
- A double quote, `0x22`, as `\"`
- - A backspace, `0x5C`, as `\\`
+ - A backslash, `0x5C`, as `\\`
- UTF-8 should be used for encoding.
## Communication between clients and relays
From 21d71791c89f41fb93f84b69d6db253bb7b403c4 Mon Sep 17 00:00:00 2001
From: Semisol <45574030+Semisol@users.noreply.github.com>
Date: Tue, 4 Jul 2023 13:55:15 +0300
Subject: [PATCH 005/217] Add carriage returns and tab characters since those
may be in some events
---
01.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/01.md b/01.md
index 70aae443..f5673b38 100644
--- a/01.md
+++ b/01.md
@@ -49,6 +49,8 @@ To prevent implementation differences from creating a different event ID for the
- The line break, `0x0A`, as `\n`
- A double quote, `0x22`, as `\"`
- A backslash, `0x5C`, as `\\`
+ - A carriage return, `0x0D`, as `\r`
+ - A tab character, `0x09`, as `\t`
- UTF-8 should be used for encoding.
## Communication between clients and relays
From ce552554a08bb5b9878621abfdde3207d54cae62 Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Wed, 5 Jul 2023 11:14:50 +0200
Subject: [PATCH 006/217] wip, part 2
---
vending-machine.md | 208 ++++++++++++++++++++++++++++++---------------
1 file changed, 139 insertions(+), 69 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index a94cd332..eb26688d 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -1,8 +1,15 @@
-# NIP-XX: Data Vending Machine
-Money in, data out.
+NIP-XX
+======
+
+Data Vending Machine
+--------------------
+
+`draft` `optional` `author:pablof7z`
+
+This NIP defines the interaction between customers and Service Providers to perform on-demand computation.
## Rationale
-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"), but where they don't necessarily care about "who" processes the data.
+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.
This NIP is not to be confused with a 1:1 marketplace; but rather, a flow where user announces a desired output, willigness to pay, and service providers compete to fulfill the job requirement in the best way possible.
@@ -11,26 +18,9 @@ There are two actors to the workflow described in this NIP:
* Customers (npubs who request a job)
* Service providers (npubs who fulfill jobs)
-## User flow
-* User publishes a job request
-`{ "kind": 68001, "tags": [ [ "j", "speech-to-text" ], ... ] }`
-
-* Service providers listen for the type of jobs they can perform
-`{"kinds":[68001], "#j": ["speech-to-text", "image-generation", ... ]}`
-
-* When a job comes in, the service providers who opt to attempt to fulfill the request begin processing it
-* Upon completion, the service provider publishes the result of the job with a `job-result` event.
-* Upon acceptance, the user zaps the service provider, tagging the job request
-
-## Kinds
-
-This NIP introduces two new kinds:
-
-* `kind:68001`: Job request -- a request to have a job be processed
-* `kind:68002`: Job result -- a proposal of the resulting job
-
-### Job request
-A request to have data processed -- published by a user
+# Event Kinds
+## Job request
+A request to have data processed -- published by a customer
```json
{
@@ -38,40 +28,35 @@ A request to have data processed -- published by a user
"content": "",
"tags": [
// The type data processing the user wants to be performed
- // on the
- [ "j", "", "" ],
- [ "input", "", "", "" ],
+ [ "j", "", "" ],
+
+ // input(s) for the job request
+ [ "i", "", "", "" ],
+
+ // relays where the job result should be published
[ "relays", "wss://..."],
- // stringified sat amount that the user is offering to pay
- // for this request
- // should this include an optional max price or is it too
- // ambiguous?
- [ "bid", "", [""] ],
-
- // max timestamp at which the job is no longer to be processed
- [ "expiration", "" ]
-
- // p tags
+ // millisats amount that the user is offering to pay
+ [ "bid", "", "" ],
+ [ "exp", "" ],
[ "p", "service-provider-1" ],
[ "p", "service-provider-2" ],
-
- // NIP-33 d-tag
- [ "d", ""]
]
}
```
-#### `content` field
+### `content` field
An optional, human-readable description of what this job is for.
-#### `j` tag
+### `j` tag
Specifies the job to be executed. A job request MUST have exactly one `j` tag.
-A `j` tag MIGHT name a specific model to be used for the computed with.
+A `j` tag MIGHT name a specific model to be used for the computed with as the second value.
-#### `input` tag
-Specified the input that the job should be executed with.
+### `i` (input) tag
+Specifies the input that the job should be executed with. The input is relay-indexable so that clients interested in the exact same job can find it it's result if it's already fulfilled.
+
+A job request CAN have zero or more inputs.
* ``: The argument for the input
* ``: The way this argument should be interpreted
@@ -81,17 +66,20 @@ Specified the input that the job should be executed with.
* `job`: the output of a previous job with the specified event ID
* ``:
-#### `relays` tag
+### `bid` tag
+The user MIGHT specify an amount of millisats they are willing to pay for the job to be processed. The user MIGHT also specify a maximum amount of millisats they are willing to pay.
+
+### `relays` tag
A list of relays the service provider should publish its job result to.
-#### `p` tags (optional)
-A user might want to explicitly request this job to be processed by specific service provider(s). Other service providers might still choose to compete for this job.
+### `p` tags
+A user MIGHT want to explicitly request this job to be processed by specific service provider(s). Other service providers might still choose to compete for this job.
-#### `expiration` (optional)
+### `exp`
A user might specify that they will not be interested in results past a certain time (e.g. a time-sensitive job whos value is no longer relevant after some time, like a live transcription service)
-### Job result
-The output of processing the data -- published by the
+## Job result
+The output of processing the data -- published by the service provider.
```json
{
"pubkey": "service-provider",
@@ -100,19 +88,22 @@ The output of processing the data -- published by the
"content": "",
"tags" [
// stringified JSON request event
- [ "request", "<2xxx1-event>" ],
- [ "e", ],
+ [ "request", "<68001-event>" ],
+ [ "e", ],
[ "p", "" ],
[ "status", "success", ""],
- [ "payment", "requested-payment-amount" ]
+ [ "amount", "requested-payment-amount" ]
]
}
```
-### `status` tag
+The result of the job should be in the `content`. If the output is not text, the `content` field should be empty and an `output` tag should be used instead as described below.
+
+#### `status` tag
The service provider might want to return an error to the user in case the job could not be processed correctly
-### `payment`
+#### `amount`
+The amount of millisats the service provider is requesting to be paid. This amount MIGHT be different than the amount specified by the user in the `bid` tag. The amount SHOULD be less than the maximum amount specified by the user in the `bid` tag.
## Job types
@@ -133,21 +124,52 @@ This NIP defines some job types, clients SHOULD specify these types for maximum
#### params
| param | req? | description
|--------------------------------|------|--------
-| `language` | req | desired language in BCP 47 format.
+| `language` | req | requested language in BCP 47 format.
-## Job chaining
+# Protocol Flow
+* User publishes a job request
+`{ "kind": 68001, "tags": [ [ "j", "speech-to-text" ], ... ] }`
+
+* Service providers listen for the type of jobs they can perform
+`{"kinds":[68001], "#j": ["speech-to-text", "image-generation", ... ]}`
+
+* When a job comes in, the service providers who opt to attempt to fulfill the request begin processing it, or they can react to it with feedback for the user (e.g. _payment required_, _unprocessable entity_, etc.)
+* Upon completion, the service provider publishes the result of the job with a `job-result` event.
+* Upon acceptance, the user zaps the service provider, tagging the job result event.
+
+# Payment
+Customers SHOULD pay service providers whose job results they accept. Users should zap the service provider, tagging the `kind:68002` job result.
+
+
+# Job chaining
A customer CAN request multiple jobs to be chained, 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.
Service providers might opt to start processing a subsequent job the moment they see the prior job's result, or they might choose to wait for a zap to have been published. This introduces the 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.
-## Job feedback
+# Reactions
> **Warning**
> Is this hijacking/modifying the meaning of NIP-25 reactions too much?
-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, either
-in the form of
+## Job request reactions
+Service Providers might opt to give feedback about a job.
+### E.g. Payment required
+```json
+{
+ "kind": 7,
+ "content": "Please pay 7 sats for job xxxx",
+ "tags": [
+ [ "e", ],
+ [ "status", "payment-required" ],
+ [ "amount", "7000" ],
+ ]
+}
+```
+
+## 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.
## Explicitly not addressed in this NIP
@@ -163,7 +185,7 @@ It's out of scope (and undesirable) to have this NIP address this issue; the mar
# Appendix 1: Examples
-## Customer wants to get a transcript of a podcast from second 900 to 930.
+## Transcript of a podcast from second `900` to `930`.
### `kind:68001`: Job Request
```json
@@ -174,7 +196,7 @@ It's out of scope (and undesirable) to have this NIP address this issue; the mar
"tags": [
[ "j", "speech-to-text" ],
[ "params", "range", "900", "930" ],
- [ "input", "https://bitcoin.review/episode1.mp3", "url" ],
+ [ "i", "https://bitcoin.review/episode1.mp3", "url" ],
[ "bid", "5000", "9000" ]
]
}
@@ -192,7 +214,7 @@ It's out of scope (and undesirable) to have this NIP address this issue; the mar
}
```
-## Customer wants to get a summarization of a podcast
+## Summarization of a podcast
User publishes two job requests at the same time in the order they should be executed.
@@ -205,7 +227,7 @@ User publishes two job requests at the same time in the order they should be exe
"tags": [
[ "j", "speech-to-text" ],
[ "params", "range", "900", "930" ],
- [ "input", "https://bitcoin.review/episode1.mp3", "url" ],
+ [ "i", "https://bitcoin.review/episode1.mp3", "url" ],
[ "bid", "5000", "9000" ]
]
}
@@ -220,13 +242,13 @@ User publishes two job requests at the same time in the order they should be exe
"tags": [
[ "j", "summarization" ],
[ "params", "length", "3 paragraphs" ],
- [ "input", "12346", "job" ],
+ [ "i", "12346", "job" ],
[ "bid", "300", "900" ]
]
}
```
-## Customer wants a translation of a note
+## Translation of a note
### `kind:68001`: Job Request #1
```json
{
@@ -235,9 +257,57 @@ User publishes two job requests at the same time in the order they should be exe
"content": "",
"tags": [
[ "j", "translation" ],
- [ "input", "", "event" ]
+ [ "i", "", "event" ]
[ "params", "language", "es_AR" ],
[ "bid", "100", "500" ]
]
}
-```
\ No newline at end of file
+```
+
+## AI-image of the summarization of 2 podcasts
+
+### `kind:68001`: Job request #1 (transcribe podcast #1)
+```json
+{
+ "id": "123",
+ "tags": [
+ [ "j", "speech-to-text" ],
+ [ "i", "https://example.com/episode1.mp3", "url" ],
+ [ "bid", "100", "500" ]
+ ]
+}
+```
+
+### `kind:68001`: Job request #2 (transcribe podcast #2)
+```json
+{
+ "id": "124",
+ "tags": [
+ [ "j", "speech-to-text" ],
+ [ "i", "https://example.com/episode2.mp3", "url" ],
+ [ "bid", "100", "500" ]
+ ]
+}
+```
+
+### `kind:68001`: Job request #3 (summarize both podcasts into one podcast)
+```json
+{
+ "id": "125",
+ "tags": [
+ [ "j", "summarize" ],
+ [ "param", "length", "1 paragraph" ],
+ [ "i", "123", "job" ],
+ [ "i", "124", "job" ],
+ [ "bid", "100", "500" ]
+ ]
+}
+```
+
+# Notes
+
+* Should there be a possibility of getting the job result delivered encrypted? I don't like it but maybe it should be supported.
+
+* Ambiguity on job acceptance, particularly for job-chaining circumstances is deliberately ambiguous: 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.
+
+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).
From 667c700c1cab5106655df2de528e960b4875db0d Mon Sep 17 00:00:00 2001
From: gsovereignty
Date: Sat, 8 Jul 2023 18:51:30 +0800
Subject: [PATCH 007/217] Problem: some of the language is inconsistent
---
vending-machine.md | 53 +++++++++++++++++++++++-----------------------
1 file changed, 27 insertions(+), 26 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index eb26688d..2f9c0649 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -27,7 +27,7 @@ A request to have data processed -- published by a customer
"kind": 68001,
"content": "",
"tags": [
- // The type data processing the user wants to be performed
+ // The type of data processing the user wants to be performed
[ "j", "", "" ],
// input(s) for the job request
@@ -49,12 +49,12 @@ A request to have data processed -- published by a customer
An optional, human-readable description of what this job is for.
### `j` tag
-Specifies the job to be executed. A job request MUST have exactly one `j` tag.
+Specifies the job to be executed. A job request MUST have exactly one (1) `j` tag.
-A `j` tag MIGHT name a specific model to be used for the computed with as the second value.
+A `j` tag MAY include a second value specifying the name of a model to be used when computing the result.
### `i` (input) tag
-Specifies the input that the job should be executed with. The input is relay-indexable so that clients interested in the exact same job can find it it's result if it's already fulfilled.
+Specifies the input data that the job is to be executed against. The input is relay-indexable so that clients interested in the exact same job can find the input data and the result result (if it's already fulfilled).
A job request CAN have zero or more inputs.
@@ -64,50 +64,51 @@ A job request CAN have zero or more inputs.
* `url`: a URL to be fetched
* `event`: a nostr event ID
* `job`: the output of a previous job with the specified event ID
-* ``:
+* ``: an optional field indicating where the data can be found if it is a subset of the provided values, for example the name of the key(s) in a key/value set, or the start and end positions of the data if it's a bytestream.
### `bid` tag
-The user MIGHT specify an amount of millisats they are willing to pay for the job to be processed. The user MIGHT also specify a maximum amount of millisats they are willing to pay.
+The Customer MAY specify a maximum amount (in millisats) they are willing to pay for the job to be processed.
### `relays` tag
-A list of relays the service provider should publish its job result to.
+The Service Provider SHOULD publish job results to the relays specified in this this tag.
### `p` tags
-A user MIGHT want to explicitly request this job to be processed by specific service provider(s). Other service providers might still choose to compete for this job.
+If a Customer has a preference for specific Service Provider(s) to process this job, they SHOULD indicate this by including the Service Provider(s) pubkey in a `p` tag. This is NOT intended to exclude other Service Providers and they MAY still choose to compete for jobs that have not tagged them.
### `exp`
-A user might specify that they will not be interested in results past a certain time (e.g. a time-sensitive job whos value is no longer relevant after some time, like a live transcription service)
+A Customer MAY indicate that they will not pay for results produced after a specific Block height or Unix Timestamp. This is intended for time-sensitive jobs where the result is not relevant unless produced within a certain timeframe, e.g. a live transcription service.
## Job result
-The output of processing the data -- published by the service provider.
+The output of processing the data -- published by the Service Provider.
```json
{
- "pubkey": "service-provider",
+ "pubkey": "service-provider pubkey in hex",
// result
- "content": "",
+ "content": "string: ",
+ "kind": 68002,
"tags" [
// stringified JSON request event
- [ "request", "<68001-event>" ],
- [ "e", ],
- [ "p", "" ],
- [ "status", "success", ""],
+ [ "request", "" ],
+ [ "e", "" ],
+ [ "p", "" ],
+ [ "status", "success", "" ],
[ "amount", "requested-payment-amount" ]
]
}
```
-The result of the job should be in the `content`. If the output is not text, the `content` field should be empty and an `output` tag should be used instead as described below.
+The result of the job SHOULD be included in the `content` field. If the output is not text, the `content` field SHOULD be empty and an `output` tag should be used instead as described below.
#### `status` tag
-The service provider might want to return an error to the user in case the job could not be processed correctly
+The Service Provider MAY indicate errors during processing by including them in the `status` tag, these errors are intended to be consumed by the Customer.
#### `amount`
-The amount of millisats the service provider is requesting to be paid. This amount MIGHT be different than the amount specified by the user in the `bid` tag. The amount SHOULD be less than the maximum amount specified by the user in the `bid` tag.
+The amount (in millisats) that the Service Provider is requesting to be paid. This amount MAY differ to the amount specified by the Customer in the `bid` tag. The amount SHOULD be less than the maximum amount specified by the user in the `bid` tag.
## Job types
-This NIP defines some job types, clients SHOULD specify these types for maximum compatibility with service providers. Other job types might be added to this NIP.
+This NIP defines some example job types, Customers SHOULD specify these types for maximum compatibility with Service Providers. Other job types MAY be added to this NIP after being observed in the wild.
### `speech-to-text`
#### params
@@ -127,24 +128,24 @@ This NIP defines some job types, clients SHOULD specify these types for maximum
| `language` | req | requested language in BCP 47 format.
# Protocol Flow
-* User publishes a job request
+* Customer publishes a job request
`{ "kind": 68001, "tags": [ [ "j", "speech-to-text" ], ... ] }`
-* Service providers listen for the type of jobs they can perform
+* Service Providers subsribe to the type of jobs they can perform
`{"kinds":[68001], "#j": ["speech-to-text", "image-generation", ... ]}`
-* When a job comes in, the service providers who opt to attempt to fulfill the request begin processing it, or they can react to it with feedback for the user (e.g. _payment required_, _unprocessable entity_, etc.)
+* When a job comes in, the Service Providers who opt to attempt to fulfill the request begin processing it, or they can react to it with feedback for the user (e.g. _payment required_, _unprocessable entity_, etc.)
* Upon completion, the service provider publishes the result of the job with a `job-result` event.
* Upon acceptance, the user zaps the service provider, tagging the job result event.
# Payment
-Customers SHOULD pay service providers whose job results they accept. Users should zap the service provider, tagging the `kind:68002` job result.
+Customers SHOULD pay service providers whose job results they accept by zapping the Service Provider and tagging the `kind:68002` job result.
# Job chaining
-A customer CAN request multiple jobs to be chained, 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.
+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.
-Service providers might opt to start processing a subsequent job the moment they see the prior job's result, or they might choose to wait for a zap to have been published. This introduces the 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.
+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.
# Reactions
> **Warning**
From 5f27121c98efe01f756ee8d316051913277b33c5 Mon Sep 17 00:00:00 2001
From: Believethehype
Date: Sun, 9 Jul 2023 12:08:28 +0200
Subject: [PATCH 008/217] Update vending-machine.md
---
vending-machine.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/vending-machine.md b/vending-machine.md
index 2f9c0649..e64a667c 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -89,7 +89,7 @@ The output of processing the data -- published by the Service Provider.
"kind": 68002,
"tags" [
// stringified JSON request event
- [ "request", "" ],
+ [ "request", "<68001-event-as-stringified JSON>" ],
[ "e", "" ],
[ "p", "" ],
[ "status", "success", "" ],
@@ -115,6 +115,7 @@ This NIP defines some example job types, Customers SHOULD specify these types fo
| param | req? | description
|--------------------------------|------|--------
| `range` | opt | timestamp range (in seconds) of desired text to be transcribed
+| `alignment` | opt | word, segment, raw : word-level, segment-level or raw outputs
### `summarization`
| param | req? | description
From a9dd5574531229df065eb9df2212bb7510db1f61 Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Tue, 11 Jul 2023 15:22:30 +0200
Subject: [PATCH 009/217] get rid of the kind:7 stuff
---
vending-machine.md | 131 +++++++++++++++++++++------------------------
1 file changed, 61 insertions(+), 70 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index e64a667c..0f0b0031 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -33,6 +33,9 @@ A request to have data processed -- published by a customer
// input(s) for the job request
[ "i", "", "", "" ],
+ // expected output format
+ [ "output", "mimetype" ],
+
// relays where the job result should be published
[ "relays", "wss://..."],
@@ -45,51 +48,36 @@ A request to have data processed -- published by a customer
}
```
-### `content` field
-An optional, human-readable description of what this job is for.
+* `content` field: An optional, human-readable description of what this job is for.
+* `j` tag: Job-type to be executed.
+ * A job request MUST have exactly one `j` tag.
+ * It MAY include a second value specifying the name of a model to be used when computing the result.
-### `j` tag
-Specifies the job to be executed. A job request MUST have exactly one (1) `j` tag.
-
-A `j` tag MAY include a second value specifying the name of a model to be used when computing the result.
-
-### `i` (input) tag
-Specifies the input data that the job is to be executed against. The input is relay-indexable so that clients interested in the exact same job can find the input data and the result result (if it's already fulfilled).
-
-A job request CAN have zero or more inputs.
-
-* ``: The argument for the input
-* ``: The way this argument should be interpreted
- * Possible values:
+* `i` tag: Input data for the job.
+ * A job request CAN have zero or more inputs.
+ * Positional arguments: `["i", "", "", "", ""]`
+ * ``: The argument for the input
+ * ``: The way this argument should be interpreted, one of:
* `url`: a URL to be fetched
- * `event`: a nostr event ID
+ * `event`: a nostr event ID, include an optional relay-url extra param
* `job`: the output of a previous job with the specified event ID
-* ``: an optional field indicating where the data can be found if it is a subset of the provided values, for example the name of the key(s) in a key/value set, or the start and end positions of the data if it's a bytestream.
-
-### `bid` tag
-The Customer MAY specify a maximum amount (in millisats) they are willing to pay for the job to be processed.
-
-### `relays` tag
-The Service Provider SHOULD publish job results to the relays specified in this this tag.
-
-### `p` tags
-If a Customer has a preference for specific Service Provider(s) to process this job, they SHOULD indicate this by including the Service Provider(s) pubkey in a `p` tag. This is NOT intended to exclude other Service Providers and they MAY still choose to compete for jobs that have not tagged them.
-
-### `exp`
-A Customer MAY indicate that they will not pay for results produced after a specific Block height or Unix Timestamp. This is intended for time-sensitive jobs where the result is not relevant unless produced within a certain timeframe, e.g. a live transcription service.
+ * ``: if `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string.
+ * ``: an optional field indicating how this input should be used.
+* `output` tag: MIME type. Expected output format. Service Providers SHOULD publish the result of the job in this format.
+* `bid` tag: Customer MAY specify a maximum amount (in millisats) they are willing to pay.
+* `relays` tag: relays where Service Providers SHOULD publish responses to.
+* `p` tags: Service Providers the customer is interested in having process this job. Other SP MIGHT still choose to process the job.
+* `exp`: Optional expiration timestamp. Service Providers SHOULD not send results after this timestamp.
## Job result
The output of processing the data -- published by the Service Provider.
```json
{
"pubkey": "service-provider pubkey in hex",
-
- // result
- "content": "string: ",
+ "content": "",
"kind": 68002,
"tags" [
- // stringified JSON request event
- [ "request", "<68001-event-as-stringified JSON>" ],
+ [ "request", "<68001-event>" ],
[ "e", "" ],
[ "p", "" ],
[ "status", "success", "" ],
@@ -98,36 +86,15 @@ The output of processing the data -- published by the Service Provider.
}
```
+## Job feedback
+Both customers and service providers can give feedback about a job.
+
The result of the job SHOULD be included in the `content` field. If the output is not text, the `content` field SHOULD be empty and an `output` tag should be used instead as described below.
-#### `status` tag
-The Service Provider MAY indicate errors during processing by including them in the `status` tag, these errors are intended to be consumed by the Customer.
-
-#### `amount`
-The amount (in millisats) that the Service Provider is requesting to be paid. This amount MAY differ to the amount specified by the Customer in the `bid` tag. The amount SHOULD be less than the maximum amount specified by the user in the `bid` tag.
-
-## Job types
-
-This NIP defines some example job types, Customers SHOULD specify these types for maximum compatibility with Service Providers. Other job types MAY be added to this NIP after being observed in the wild.
-
-### `speech-to-text`
-#### params
-| param | req? | description
-|--------------------------------|------|--------
-| `range` | opt | timestamp range (in seconds) of desired text to be transcribed
-| `alignment` | opt | word, segment, raw : word-level, segment-level or raw outputs
-
-### `summarization`
-| param | req? | description
-|--------------------------------|------|--------
-| `length` | opt | desired length
-
-### `translation` -- Translate text to a specific language
-#### params
-| param | req? | description
-|--------------------------------|------|--------
-| `language` | req | requested language in BCP 47 format.
+* `status` tag: Service Providers MAY indicate errors or extra info about the results by including them in the `status` tag.
+* `amount`: millisats that the Service Provider is requesting to be paid.
+##
# Protocol Flow
* Customer publishes a job request
`{ "kind": 68001, "tags": [ [ "j", "speech-to-text" ], ... ] }`
@@ -142,15 +109,17 @@ This NIP defines some example job types, Customers SHOULD specify these types fo
# Payment
Customers SHOULD pay service providers whose job results they accept by zapping the Service Provider and tagging the `kind:68002` job result.
+Additionally, if a service provider requests full or partial prepayment via a `kind:68003` job-feedback event, the customer SHOULD zap that event to pay the service provider.
+
+# Cancellation
+A `kind:68001` job request might be cancelled by publishing a `kind:5` delete request event tagging the job request event.
# Job chaining
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.
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.
-# Reactions
-> **Warning**
-> Is this hijacking/modifying the meaning of NIP-25 reactions too much?
+# Job Feedback
## Job request reactions
Service Providers might opt to give feedback about a job.
@@ -169,7 +138,6 @@ Service Providers might opt to give feedback about a job.
```
## 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.
@@ -197,21 +165,21 @@ It's out of scope (and undesirable) to have this NIP address this issue; the mar
"content": "I need a transcript of Bitcoin.review",
"tags": [
[ "j", "speech-to-text" ],
- [ "params", "range", "900", "930" ],
[ "i", "https://bitcoin.review/episode1.mp3", "url" ],
- [ "bid", "5000", "9000" ]
+ [ "params", "range", "900", "930" ],
+ [ "bid", "5000", "9000" ],
+ [ "output", "text/plain" ]
]
}
```
-### `kind:1021`: Job fulfillment
+### `kind:68002`: Job fulfillment
```json
{
- "content": "Person 1: blah blah blah",
+ "content": "blah blah blah",
"tags": [
["e", "12345"],
["p", "abcdef"],
- ["status", "success"]
]
}
```
@@ -306,6 +274,29 @@ User publishes two job requests at the same time in the order they should be exe
}
```
+# Appendix 2: Job types
+
+This NIP defines some example job types, Customers SHOULD specify these types for maximum compatibility with Service Providers. Other job types MAY be added to this NIP after being observed in the wild.
+
+### `speech-to-text`
+#### params
+| param | req? | description
+|--------------------------------|------|--------
+| `range` | opt | timestamp range (in seconds) of desired text to be transcribed
+| `alignment` | opt | word, segment, raw : word-level, segment-level or raw outputs
+
+### `summarization`
+| param | req? | description
+|--------------------------------|------|--------
+| `length` | opt | desired length
+
+### `translation` -- Translate text to a specific language
+#### params
+| param | req? | description
+|--------------------------------|------|--------
+| `language` | req | requested language in BCP 47 format.
+
+
# Notes
* Should there be a possibility of getting the job result delivered encrypted? I don't like it but maybe it should be supported.
From def620e1ce4417a4e78b5012c3a43adbe105f43e Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Tue, 11 Jul 2023 22:25:54 +0200
Subject: [PATCH 010/217] more cleanup
---
vending-machine.md | 57 +++++++++++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 21 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index 0f0b0031..8121ffc0 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -27,19 +27,10 @@ A request to have data processed -- published by a customer
"kind": 68001,
"content": "",
"tags": [
- // The type of data processing the user wants to be performed
[ "j", "", "" ],
-
- // input(s) for the job request
[ "i", "", "", "" ],
-
- // expected output format
- [ "output", "mimetype" ],
-
- // relays where the job result should be published
+ [ "output", "" ],
[ "relays", "wss://..."],
-
- // millisats amount that the user is offering to pay
[ "bid", "", "" ],
[ "exp", "" ],
[ "p", "service-provider-1" ],
@@ -94,7 +85,6 @@ The result of the job SHOULD be included in the `content` field. If the output i
* `status` tag: Service Providers MAY indicate errors or extra info about the results by including them in the `status` tag.
* `amount`: millisats that the Service Provider is requesting to be paid.
-##
# Protocol Flow
* Customer publishes a job request
`{ "kind": 68001, "tags": [ [ "j", "speech-to-text" ], ... ] }`
@@ -127,7 +117,7 @@ Service Providers might opt to give feedback about a job.
### E.g. Payment required
```json
{
- "kind": 7,
+ "kind": 68003,
"content": "Please pay 7 sats for job xxxx",
"tags": [
[ "e", ],
@@ -148,11 +138,6 @@ Service providers are at obvious risk of having their results not compensated. M
It's out of scope (and undesirable) to have this NIP address this issue; the market should.
-## Notes
-
-### Multitple job acceptance
-* Nothing prevents a user from accepting multiple job results.
-
# Appendix 1: Examples
## Transcript of a podcast from second `900` to `930`.
@@ -162,7 +147,7 @@ It's out of scope (and undesirable) to have this NIP address this issue; the mar
{
"id": "12345",
"pubkey": "abcdef",
- "content": "I need a transcript of Bitcoin.review",
+ "content": "",
"tags": [
[ "j", "speech-to-text" ],
[ "i", "https://bitcoin.review/episode1.mp3", "url" ],
@@ -173,13 +158,30 @@ It's out of scope (and undesirable) to have this NIP address this issue; the mar
}
```
-### `kind:68002`: Job fulfillment
+### `kind:68003`: Job Feedback: request for (partial) payment
+```json
+{
+ "kind": 68003,
+ "content": "",
+ "tags": [
+ ["e", "12345"],
+ ["p", "abcdef"],
+ ["status", "payment-required"],
+ ["amount", "1000"]
+ ]
+}
+```
+
+* User zaps 1000 sats to event kind:68003.
+
+### `kind:68002`: Job fulfillment + request for remaining payment
```json
{
"content": "blah blah blah",
"tags": [
["e", "12345"],
["p", "abcdef"],
+ ["amount", "6000"]
]
}
```
@@ -208,7 +210,7 @@ User publishes two job requests at the same time in the order they should be exe
{
"id": "12346",
"pubkey": "abcdef",
- "content": "I need a summarization",
+ "content": "",
"tags": [
[ "j", "summarization" ],
[ "params", "length", "3 paragraphs" ],
@@ -227,13 +229,26 @@ User publishes two job requests at the same time in the order they should be exe
"content": "",
"tags": [
[ "j", "translation" ],
- [ "i", "", "event" ]
+ [ "i", "", "event", "wss://relay.nostr.com" ]
[ "params", "language", "es_AR" ],
[ "bid", "100", "500" ]
]
}
```
+### `kind:68003`: Job respomse
+```json
+{
+ "kind": 68003,
+ "content": "Che, que copado, boludo!",
+ "tags": [
+ ["e", "12346"],
+ ["p", "abcdef"],
+ ["amount", "1000"]
+ ]
+}
+```
+
## AI-image of the summarization of 2 podcasts
### `kind:68001`: Job request #1 (transcribe podcast #1)
From e9924bdcde2dc516a891c027bd023f487b73a674 Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Sat, 15 Jul 2023 12:24:32 +0200
Subject: [PATCH 011/217] add optional bolt11
---
vending-machine.md | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index 8121ffc0..1d08bd23 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -72,7 +72,7 @@ The output of processing the data -- published by the Service Provider.
[ "e", "" ],
[ "p", "" ],
[ "status", "success", "" ],
- [ "amount", "requested-payment-amount" ]
+ [ "amount", "requested-payment-amount", "" ]
]
}
```
@@ -80,21 +80,27 @@ The output of processing the data -- published by the Service Provider.
## Job feedback
Both customers and service providers can give feedback about a job.
-The result of the job SHOULD be included in the `content` field. If the output is not text, the `content` field SHOULD be empty and an `output` tag should be used instead as described below.
+The result of the job SHOULD be included in the `content` field.
* `status` tag: Service Providers MAY indicate errors or extra info about the results by including them in the `status` tag.
-* `amount`: millisats that the Service Provider is requesting to be paid.
+* `amount`: millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice.
# Protocol Flow
* Customer publishes a job request
`{ "kind": 68001, "tags": [ [ "j", "speech-to-text" ], ... ] }`
+* Service Prpvoders can submit `kind:68003` job-feedback events (e.g. `payment-required`, `processing`, `unprocessable-entity`, etc.).
+* Upon completion, the service provider publishes the result of the job with a `kind:68002` job-result event.
+* Upon acceptance, the user zaps the service provider, tagging the job result event with a `kind:7` 👍 reaction.
-* Service Providers subsribe to the type of jobs they can perform
-`{"kinds":[68001], "#j": ["speech-to-text", "image-generation", ... ]}`
+`kind:68002` and `kind:68003` 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 must be done before moving on to the next step.
-* When a job comes in, the Service Providers who opt to attempt to fulfill the request begin processing it, or they can react to it with feedback for the user (e.g. _payment required_, _unprocessable entity_, etc.)
-* Upon completion, the service provider publishes the result of the job with a `job-result` event.
-* Upon acceptance, the user zaps the service provider, tagging the job result event.
+## Notes about the protocol flow
+The flow is deliverately left 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:68002` 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.
# Payment
Customers SHOULD pay service providers whose job results they accept by zapping the Service Provider and tagging the `kind:68002` job result.
@@ -131,7 +137,7 @@ Service Providers might opt to give feedback about a job.
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.
-## Explicitly not addressed in this NIP
+## Not addressed in this NIP
### 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).
From 53bd97373b5442445f5c387945cf5685ac39ab80 Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Sun, 23 Jul 2023 21:28:59 +0200
Subject: [PATCH 012/217] use different kinds per job request type
---
vending-machine.md | 217 ++++++++++++++++++++++++++-------------------
1 file changed, 127 insertions(+), 90 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index 1d08bd23..4dbc5a3a 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -8,10 +8,19 @@ Data Vending Machine
This NIP defines the interaction between customers and Service Providers to perform on-demand computation.
+## Kinds
+This NIP reserves the range `65000-69999` for data vending machine use.
+
+| Kind | Description |
+| ---- | ----------- |
+| 65000 | Job feedback |
+| 65001 | Job result |
+| 65002-69999 | Job request kinds |
+
## Rationale
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.
-This NIP is not to be confused with a 1:1 marketplace; but rather, a flow where user announces a desired output, willigness to pay, and service providers compete to fulfill the job requirement in the best way possible.
+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.
### Actors
There are two actors to the workflow described in this NIP:
@@ -24,52 +33,44 @@ A request to have data processed -- published by a customer
```json
{
- "kind": 68001,
+ "kind": 6xxxx,
"content": "",
"tags": [
- [ "j", "", "" ],
- [ "i", "", "", "" ],
+ [ "i", "", "", "", "" ],
[ "output", "" ],
[ "relays", "wss://..."],
- [ "bid", "", "" ],
+ [ "bid", "" ],
[ "exp", "" ],
- [ "p", "service-provider-1" ],
- [ "p", "service-provider-2" ],
+ [ "t", "bitcoin" ]
]
}
```
-* `content` field: An optional, human-readable description of what this job is for.
-* `j` tag: Job-type to be executed.
- * A job request MUST have exactly one `j` tag.
- * It MAY include a second value specifying the name of a model to be used when computing the result.
-
-* `i` tag: Input data for the job.
- * A job request CAN have zero or more inputs.
- * Positional arguments: `["i", "", "", "", ""]`
+* `i` tag: Input data for the job, (zero or more inputs may exist)
* ``: The argument for the input
- * ``: The way this argument should be interpreted, one of:
+ * ``: The way this argument should be interpreted, MUST be one of:
* `url`: a URL to be fetched
* `event`: a nostr event ID, include an optional relay-url extra param
* `job`: the output of a previous job with the specified event ID
- * ``: if `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string.
+ * `content`:
* ``: an optional field indicating how this input should be used.
-* `output` tag: MIME type. Expected output format. Service Providers SHOULD publish the result of the job in this format.
-* `bid` tag: Customer MAY specify a maximum amount (in millisats) they are willing to pay.
+ * ``: if `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string.
+* `output` tag (opt): MIME type. Expected output format. Service Providers SHOULD publish the result of the job in this format if it has been specified.
+* `bid` tag (opt): Customer MAY specify a maximum amount (in millisats) they are willing to pay.
* `relays` tag: relays where Service Providers SHOULD publish responses to.
-* `p` tags: Service Providers the customer is interested in having process this job. Other SP MIGHT still choose to process the job.
-* `exp`: Optional expiration timestamp. Service Providers SHOULD not send results after this timestamp.
+* `p` tags (opt): Service Providers the customer is interested in having process this job. Other SP MIGHT still choose to process the job.
+* `exp` (opt): expiration timestamp. Service Providers SHOULD not send results after this timestamp.
## Job result
The output of processing the data -- published by the Service Provider.
```json
{
- "pubkey": "service-provider pubkey in hex",
+ "pubkey": "",
"content": "",
- "kind": 68002,
+ "kind": 65001,
"tags" [
- [ "request", "<68001-event>" ],
- [ "e", "" ],
+ [ "request", "" ],
+ [ "e", "", "" ],
[ "p", "" ],
[ "status", "success", "" ],
[ "amount", "requested-payment-amount", "" ]
@@ -77,6 +78,9 @@ The output of processing the data -- published by the Service Provider.
}
```
+* `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.
+
## Job feedback
Both customers and service providers can give feedback about a job.
@@ -86,29 +90,25 @@ The result of the job SHOULD be included in the `content` field.
* `amount`: millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice.
# Protocol Flow
-* Customer publishes a job request
-`{ "kind": 68001, "tags": [ [ "j", "speech-to-text" ], ... ] }`
-* Service Prpvoders can submit `kind:68003` job-feedback events (e.g. `payment-required`, `processing`, `unprocessable-entity`, etc.).
-* Upon completion, the service provider publishes the result of the job with a `kind:68002` job-result event.
-* Upon acceptance, the user zaps the service provider, tagging the job result event with a `kind:7` 👍 reaction.
+* 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.
-`kind:68002` and `kind:68003` 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 must be done before moving on to the next step.
+`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. Custeroms 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.
## Notes about the protocol flow
-The flow is deliverately left 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:68002` 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.
+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.
# Payment
-Customers SHOULD pay service providers whose job results they accept by zapping the Service Provider and tagging the `kind:68002` job result.
+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.
-Additionally, if a service provider requests full or partial prepayment via a `kind:68003` job-feedback event, the customer SHOULD zap that event to pay the service provider.
+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.
# Cancellation
-A `kind:68001` job request might be cancelled by publishing a `kind:5` delete request event tagging the job request event.
+A job request might be cancelled by publishing a `kind:5` delete request event tagging the job request event.
# Job chaining
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.
@@ -116,17 +116,31 @@ A Customer MAY request multiple jobs to be processed in a chained form, so that
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.
# Job Feedback
+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.
-## Job request reactions
-Service Providers might opt to give feedback about a job.
+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.
-### E.g. Payment required
+| 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)
```json
{
- "kind": 68003,
- "content": "Please pay 7 sats for job xxxx",
+ "kind": 65000,
+ "content": "This is the transcription service that you",
"tags": [
- [ "e", ],
+ [ "e", , ],
+ [ "p", ],
[ "status", "payment-required" ],
[ "amount", "7000" ],
]
@@ -144,153 +158,160 @@ Service providers are at obvious risk of having their results not compensated. M
It's out of scope (and undesirable) to have this NIP address this issue; the market should.
+### 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.
+
# Appendix 1: Examples
## Transcript of a podcast from second `900` to `930`.
-### `kind:68001`: Job Request
+### `kind:65002`: Speech-to-text job request
```json
{
"id": "12345",
"pubkey": "abcdef",
"content": "",
+ "kind": 65002,
"tags": [
- [ "j", "speech-to-text" ],
[ "i", "https://bitcoin.review/episode1.mp3", "url" ],
[ "params", "range", "900", "930" ],
- [ "bid", "5000", "9000" ],
+ [ "output", "text/vtt" ],
+ [ "bid", "50000" ],
[ "output", "text/plain" ]
]
}
```
-### `kind:68003`: Job Feedback: request for (partial) payment
+### `kind:65001`: Job Feedback: request for (partial) payment
+* The SP is signaling here that it won't start processing until 100 sats are paid
```json
{
- "kind": 68003,
+ "kind": 65000,
"content": "",
"tags": [
["e", "12345"],
["p", "abcdef"],
["status", "payment-required"],
- ["amount", "1000"]
+ ["amount", "100000"]
]
}
```
-* User zaps 1000 sats to event kind:68003.
+* User zaps 100 sats to the `kind:65000` job-feedback
-### `kind:68002`: Job fulfillment + request for remaining payment
+### `kind:65001`: Job result + request for remaining payment
```json
{
"content": "blah blah blah",
"tags": [
["e", "12345"],
["p", "abcdef"],
- ["amount", "6000"]
+ ["amount", "400000"]
]
}
```
## Summarization of a podcast
+User publishes two job requests at the same time.
-User publishes two job requests at the same time in the order they should be executed.
-
-### `kind:68001`: Job Request #1
+### `kind:65002`: Job Request #1: speech-to-text
```json
{
"id": "12345",
"pubkey": "abcdef",
+ "kinds" 65002,
"content": "I need a transcript of Bitcoin.review from second 900 to 930",
"tags": [
- [ "j", "speech-to-text" ],
- [ "params", "range", "900", "930" ],
[ "i", "https://bitcoin.review/episode1.mp3", "url" ],
- [ "bid", "5000", "9000" ]
+ [ "output", "text/plain" ],
+ [ "params", "range", "900", "930" ],
+ [ "bid", "100000" ]
]
}
```
-### `kind:68001`: Job Request #2
+### `kind:65003`: Job Request #2: summarization of job #1's result
```json
{
"id": "12346",
"pubkey": "abcdef",
+ "kinds": 65003,
"content": "",
"tags": [
- [ "j", "summarization" ],
- [ "params", "length", "3 paragraphs" ],
[ "i", "12346", "job" ],
- [ "bid", "300", "900" ]
+ [ "output", "text/plain" ],
+ [ "params", "length", "3 paragraphs" ],
+ [ "bid", "10000" ]
]
}
```
## Translation of a note
-### `kind:68001`: Job Request #1
+### `kind:65004`: Job Request #1: translation of an existing note
```json
{
"id": "12346",
"pubkey": "abcdef",
"content": "",
+ "kinds": 65004,
"tags": [
- [ "j", "translation" ],
[ "i", "", "event", "wss://relay.nostr.com" ]
- [ "params", "language", "es_AR" ],
- [ "bid", "100", "500" ]
+ [ "params", "lang", "es_AR" ],
+ [ "bid", "5000" ]
]
}
```
-### `kind:68003`: Job respomse
+### `kind:65001`: Job respomse
```json
{
- "kind": 68003,
+ "kind": 65001,
"content": "Che, que copado, boludo!",
"tags": [
["e", "12346"],
["p", "abcdef"],
- ["amount", "1000"]
+ ["amount", "4000"]
]
}
```
## AI-image of the summarization of 2 podcasts
-### `kind:68001`: Job request #1 (transcribe podcast #1)
+### `kind:65002`: Job request #1 (transcribe podcast #1)
```json
{
"id": "123",
+ "kind" 65002,
"tags": [
- [ "j", "speech-to-text" ],
[ "i", "https://example.com/episode1.mp3", "url" ],
- [ "bid", "100", "500" ]
+ [ "bid", "100000" ]
]
}
```
-### `kind:68001`: Job request #2 (transcribe podcast #2)
+### `kind:65002`: Job request #2 (transcribe podcast #2)
```json
{
"id": "124",
+ "kind" 65002,
"tags": [
- [ "j", "speech-to-text" ],
[ "i", "https://example.com/episode2.mp3", "url" ],
- [ "bid", "100", "500" ]
+ [ "bid", "100000" ]
]
}
```
-### `kind:68001`: Job request #3 (summarize both podcasts into one podcast)
+### `kind:65003`: Job request #3 (summarize both podcasts into one paragraph)
```json
{
"id": "125",
+ "kind": 65003,
"tags": [
- [ "j", "summarize" ],
[ "param", "length", "1 paragraph" ],
[ "i", "123", "job" ],
[ "i", "124", "job" ],
- [ "bid", "100", "500" ]
+ [ "bid", "100000" ]
]
}
```
@@ -299,29 +320,45 @@ User publishes two job requests at the same time in the order they should be exe
This NIP defines some example job types, Customers SHOULD specify these types for maximum compatibility with Service Providers. Other job types MAY be added to this NIP after being observed in the wild.
-### `speech-to-text`
+### speech-to-text: `kind:65002`
#### params
| param | req? | description
|--------------------------------|------|--------
| `range` | opt | timestamp range (in seconds) of desired text to be transcribed
-| `alignment` | opt | word, segment, raw : word-level, segment-level or raw outputs
+| `alignment` | opt | word, segment, raw: word-level, segment-level or raw outputs
-### `summarization`
+### summarization: `kind:65003`
| param | req? | description
|--------------------------------|------|--------
| `length` | opt | desired length
-### `translation` -- Translate text to a specific language
-#### params
+### translation: `kind:65004`
| param | req? | description
|--------------------------------|------|--------
-| `language` | req | requested language in BCP 47 format.
+| `lang` | req | desired language in BCP 47 format.
+### image generation: `kind:65005`
+* `input`
# Notes
-* Should there be a possibility of getting the job result delivered encrypted? I don't like it but maybe it should be supported.
-
-* Ambiguity on job acceptance, particularly for job-chaining circumstances is deliberately ambiguous: 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.
+* 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.
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).
+
+# Appendix 3: Service provider discoverability
+
+Service Providers can use NIP-89 announcements to advertise their support for job kinds:
+
+```json
+{
+ "kind": 31990,
+ "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.
\ No newline at end of file
From d8b0e7d757206098f65b8ff868e8c59a9ac92ea6 Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Sun, 23 Jul 2023 23:37:20 +0300
Subject: [PATCH 013/217] wip
---
vending-machine.md | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index 4dbc5a3a..4934d4c3 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -9,13 +9,13 @@ Data Vending Machine
This NIP defines the interaction between customers and Service Providers to perform on-demand computation.
## Kinds
-This NIP reserves the range `65000-69999` for data vending machine use.
+This NIP reserves the range `65000-66000` for data vending machine use.
| Kind | Description |
| ---- | ----------- |
| 65000 | Job feedback |
| 65001 | Job result |
-| 65002-69999 | Job request kinds |
+| 65002-66000 | Job request kinds |
## Rationale
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.
@@ -33,7 +33,7 @@ A request to have data processed -- published by a customer
```json
{
- "kind": 6xxxx,
+ "kind": <65002-66000>,
"content": "",
"tags": [
[ "i", "", "", "", "" ],
@@ -46,6 +46,8 @@ A request to have data processed -- published by a customer
}
```
+All tags are optional.
+
* `i` tag: Input data for the job, (zero or more inputs may exist)
* ``: The argument for the input
* ``: The way this argument should be interpreted, MUST be one of:
@@ -55,11 +57,11 @@ A request to have data processed -- published by a customer
* `content`:
* ``: an optional field indicating how this input should be used.
* ``: if `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string.
-* `output` tag (opt): MIME type. Expected output format. Service Providers SHOULD publish the result of the job in this format if it has been specified.
-* `bid` tag (opt): Customer MAY specify a maximum amount (in millisats) they are willing to pay.
-* `relays` tag: relays where Service Providers SHOULD publish responses to.
-* `p` tags (opt): Service Providers the customer is interested in having process this job. Other SP MIGHT still choose to process the job.
-* `exp` (opt): expiration timestamp. Service Providers SHOULD not send results after this timestamp.
+* `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.
## Job result
The output of processing the data -- published by the Service Provider.
From 280483adc5b2299886e1e15e369557001e8807af Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Sun, 23 Jul 2023 23:58:12 +0300
Subject: [PATCH 014/217] more clarifications
---
vending-machine.md | 68 +++++++++++++++++++++++++++++++++++-----------
1 file changed, 52 insertions(+), 16 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index 4934d4c3..c4fdc18c 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -17,6 +17,8 @@ This NIP reserves the range `65000-66000` for data vending machine use.
| 65001 | Job result |
| 65002-66000 | Job request kinds |
+[Appendix 2](#appendix-2-job-types) defines the job types.
+
## Rationale
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.
@@ -33,7 +35,7 @@ A request to have data processed -- published by a customer
```json
{
- "kind": <65002-66000>,
+ "kind": xxx, // kind in 65002-66000 range
"content": "",
"tags": [
[ "i", "", "", "", "" ],
@@ -54,8 +56,8 @@ All tags are optional.
* `url`: a URL to be fetched
* `event`: a nostr event ID, include an optional relay-url extra param
* `job`: the output of a previous job with the specified event ID
- * `content`:
- * ``: an optional field indicating how this input should be used.
+ * `text`: `` is the value of the input, no resolution is needed
+ * ``: an optional field indicating how this input should be used within the context of the job.
* ``: if `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string.
* `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.
@@ -97,7 +99,7 @@ The result of the job SHOULD be included in the `content` field.
* 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.
-`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. Custeroms 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.
+`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.
## Notes about the protocol flow
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.
@@ -117,6 +119,8 @@ A Customer MAY request multiple jobs to be processed in a chained form, so that
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.
+Consult [Appendix 1: Example](#appendix-1-examples)'s [Summarization of a podcast](#summarization-of-a-podcast)
+
# Job Feedback
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.
@@ -215,7 +219,9 @@ Not to be included in the first draft of this NIP, but encrypted job requests sh
```
## Summarization of a podcast
-User publishes two job requests at the same time.
+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.
### `kind:65002`: Job Request #1: speech-to-text
```json
@@ -223,7 +229,7 @@ User publishes two job requests at the same time.
"id": "12345",
"pubkey": "abcdef",
"kinds" 65002,
- "content": "I need a transcript of Bitcoin.review from second 900 to 930",
+ "content": "",
"tags": [
[ "i", "https://bitcoin.review/episode1.mp3", "url" ],
[ "output", "text/plain" ],
@@ -233,7 +239,7 @@ User publishes two job requests at the same time.
}
```
-### `kind:65003`: Job Request #2: summarization of job #1's result
+### `kind:65002`: Job Request #2: summarization of job #1's result
```json
{
"id": "12346",
@@ -241,7 +247,7 @@ User publishes two job requests at the same time.
"kinds": 65003,
"content": "",
"tags": [
- [ "i", "12346", "job" ],
+ [ "i", "12345", "job" ], // input is the output of job with id 12345
[ "output", "text/plain" ],
[ "params", "length", "3 paragraphs" ],
[ "bid", "10000" ]
@@ -317,30 +323,60 @@ User publishes two job requests at the same time.
]
}
```
+## AI-image of embedded input
+
+### `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" ]
+ ]
+}
+```
+
+### `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
-This NIP defines some example job types, Customers SHOULD specify these types for maximum compatibility with Service Providers. Other job types MAY be added to this NIP after being observed in the wild.
-
-### speech-to-text: `kind:65002`
-#### params
+This is a list of all the supported job requests
+.
+## speech-to-text: `kind:65002`
+### params
| param | req? | description
|--------------------------------|------|--------
| `range` | opt | timestamp range (in seconds) of desired text to be transcribed
| `alignment` | opt | word, segment, raw: word-level, segment-level or raw outputs
-### summarization: `kind:65003`
+## summarization: `kind:65003`
| param | req? | description
|--------------------------------|------|--------
| `length` | opt | desired length
-### translation: `kind:65004`
+## translation: `kind:65004`
| param | req? | description
|--------------------------------|------|--------
| `lang` | req | desired language in BCP 47 format.
-### image generation: `kind:65005`
-* `input`
+## 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
# Notes
From 4cb3ac871f1c54d2e845ec8655bf564072377a46 Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Mon, 24 Jul 2023 00:38:47 +0300
Subject: [PATCH 015/217] clarifications, hopefully
---
vending-machine.md | 192 ++++++++++++++++++++++-----------------------
1 file changed, 93 insertions(+), 99 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index c4fdc18c..276132df 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -1,4 +1,4 @@
-NIP-XX
+NIP-90
======
Data Vending Machine
@@ -6,7 +6,9 @@ Data Vending Machine
`draft` `optional` `author:pablof7z`
-This NIP defines the interaction between customers and Service Providers to perform on-demand computation.
+This NIP defines the interaction between customers and Service Providers for performing on-demand computation.
+
+Money in, data out.
## Kinds
This NIP reserves the range `65000-66000` for data vending machine use.
@@ -20,18 +22,18 @@ This NIP reserves the range `65000-66000` for data vending machine use.
[Appendix 2](#appendix-2-job-types) defines the job types.
## Rationale
-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.
+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.
-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.
+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.
### Actors
-There are two actors to the workflow described in this NIP:
+There are two actors in the workflow described in this NIP:
* Customers (npubs who request a job)
* Service providers (npubs who fulfill jobs)
# Event Kinds
## Job request
-A request to have data processed -- published by a customer
+A request to have data processed, published by a customer
```json
{
@@ -50,33 +52,34 @@ A request to have data processed -- published by a customer
All tags are optional.
-* `i` tag: Input data for the job, (zero or more inputs may exist)
+* `i` tag: Input data for the job (zero or more inputs may exist)
* ``: The argument for the input
* ``: The way this argument should be interpreted, MUST be one of:
- * `url`: a URL to be fetched
- * `event`: a nostr event ID, include an optional relay-url extra param
- * `job`: the output of a previous job with the specified event ID
+ * `url`: A URL to be fetched
+ * `event`: A Nostr event ID, include an optional relay-url extra param
+ * `job`: The output of a previous job with the specified event ID
* `text`: `` is the value of the input, no resolution is needed
- * ``: an optional field indicating how this input should be used within the context of the job.
- * ``: if `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string.
-* `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.
+ * ``: An optional field indicating how this input should be used within the context of the job
+ * ``: If `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string
+* `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 SPs MIGHT still choose to process the job
+* `exp`: Expiration timestamp. Service Providers SHOULD not send results after this timestamp
## Job result
+
The output of processing the data -- published by the Service Provider.
+
```json
{
"pubkey": "",
"content": "",
"kind": 65001,
- "tags" [
+ "tags": [
[ "request", "" ],
[ "e", "", "" ],
[ "p", "" ],
- [ "status", "success", "" ],
[ "amount", "requested-payment-amount", "" ]
]
}
@@ -91,54 +94,35 @@ Both customers and service providers can give feedback about a job.
The result of the job SHOULD be included in the `content` field.
* `status` tag: Service Providers MAY indicate errors or extra info about the results by including them in the `status` tag.
-* `amount`: millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice.
+* `amount`: as defined in the [Job Result](#job-result) section.
# Protocol Flow
* 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.).
+* Service Providers 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.
-`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.
+`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.
## Notes about the protocol flow
-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.
+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.
+
+Some 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.
It's not up to this NIP to define how individual vending machines should choose to run their business.
-# Payment
-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.
-
-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.
-
# Cancellation
A job request might be cancelled by publishing a `kind:5` delete request event tagging the job request event.
# Job chaining
-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.
+A 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.
-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.
+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.
+
+This gives a higher level of flexibility to service providers (which sophisticated service providers would take anyway).
Consult [Appendix 1: Example](#appendix-1-examples)'s [Summarization of a podcast](#summarization-of-a-podcast)
-# Job Feedback
-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.
-
-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.
-
-| 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)
```json
{
@@ -153,20 +137,15 @@ Any job feedback event MIGHT include results in the `.content` field, as describ
}
```
-## 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.
-
## Not addressed in this NIP
### 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.
+Service providers are at an 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.). It's out of scope (and undesirable) to have this NIP address this issue; the market should.
### 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.
+ * 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.
+
# Appendix 1: Examples
@@ -189,7 +168,7 @@ Not to be included in the first draft of this NIP, but encrypted job requests sh
}
```
-### `kind:65001`: Job Feedback: request for (partial) payment
+### `kind:65000`: Job Feedback: request for (partial) payment
* The SP is signaling here that it won't start processing until 100 sats are paid
```json
{
@@ -228,7 +207,7 @@ User publishes event #1 and #2 together.
{
"id": "12345",
"pubkey": "abcdef",
- "kinds" 65002,
+ "kind": 65002,
"content": "",
"tags": [
[ "i", "https://bitcoin.review/episode1.mp3", "url" ],
@@ -244,7 +223,7 @@ User publishes event #1 and #2 together.
{
"id": "12346",
"pubkey": "abcdef",
- "kinds": 65003,
+ "kind": 65003,
"content": "",
"tags": [
[ "i", "12345", "job" ], // input is the output of job with id 12345
@@ -262,16 +241,17 @@ User publishes event #1 and #2 together.
"id": "12346",
"pubkey": "abcdef",
"content": "",
- "kinds": 65004,
+ "kind": 65004,
"tags": [
[ "i", "", "event", "wss://relay.nostr.com" ]
+ [ "output", "text/plain" ],
[ "params", "lang", "es_AR" ],
[ "bid", "5000" ]
]
}
```
-### `kind:65001`: Job respomse
+### `kind:65001`: Job result
```json
{
"kind": 65001,
@@ -290,7 +270,7 @@ User publishes event #1 and #2 together.
```json
{
"id": "123",
- "kind" 65002,
+ "kind": 65002,
"tags": [
[ "i", "https://example.com/episode1.mp3", "url" ],
[ "bid", "100000" ]
@@ -302,7 +282,7 @@ User publishes event #1 and #2 together.
```json
{
"id": "124",
- "kind" 65002,
+ "kind": 65002,
"tags": [
[ "i", "https://example.com/episode2.mp3", "url" ],
[ "bid", "100000" ]
@@ -310,7 +290,7 @@ User publishes event #1 and #2 together.
}
```
-### `kind:65003`: Job request #3 (summarize both podcasts into one paragraph)
+### `kind:65003`: Job request #3 (summarize the two job's outputs into one paragraph)
```json
{
"id": "125",
@@ -323,6 +303,21 @@ User publishes event #1 and #2 together.
]
}
```
+
+### `kind:65005`: 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" ]
+ ]
+}
+``
+
## AI-image of embedded input
### `kind:65005`: Job request
@@ -337,61 +332,60 @@ User publishes event #1 and #2 together.
}
```
-### `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
-This is a list of all the supported job requests
-.
+This is a list of all the supported job requests.
+
## speech-to-text: `kind:65002`
+
### params
-| param | req? | description
-|--------------------------------|------|--------
-| `range` | opt | timestamp range (in seconds) of desired text to be transcribed
-| `alignment` | opt | word, segment, raw: word-level, segment-level or raw outputs
+
+| param | req? | description |
+|------------|------|-----------------------------------------------------------|
+| `range` | opt | timestamp range (in seconds) of desired text to be transcribed |
+| `alignment`| opt | word, segment, raw: word-level, segment-level, or raw outputs |
## summarization: `kind:65003`
-| param | req? | description
-|--------------------------------|------|--------
-| `length` | opt | desired length
+
+| param | req? | description |
+|-----------|------|---------------|
+| `length` | opt | desired length |
## translation: `kind:65004`
-| param | req? | description
-|--------------------------------|------|--------
-| `lang` | req | desired language in BCP 47 format.
+
+| param | req? | description |
+|-----------|------|--------------------------------------------|
+| `lang` | req | desired language in BCP 47 format. |
## 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
-# Notes
+| param | req? | description |
+|-----------|------|-------------------------------------------------------|
+| `prompt` | opt | extra prompt to be used for the image generation |
+| `size` | opt | desired size of the image |
-* 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.
-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).
+# Appendix 3: Job feedback status
-# Appendix 3: Service provider discoverability
+| 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 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.
+
+# Appendix 4: 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"
From 723103506030749fc2bba9d5b4ddaf607dd24da3 Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Tue, 25 Jul 2023 01:29:02 +0300
Subject: [PATCH 016/217] feed-generation kind and some more stuff
---
vending-machine.md | 104 ++++++++++++++++++++++++++++++++-------------
1 file changed, 74 insertions(+), 30 deletions(-)
diff --git a/vending-machine.md b/vending-machine.md
index 276132df..c41ccceb 100644
--- a/vending-machine.md
+++ b/vending-machine.md
@@ -19,7 +19,7 @@ This NIP reserves the range `65000-66000` for data vending machine use.
| 65001 | Job result |
| 65002-66000 | Job request kinds |
-[Appendix 2](#appendix-2-job-types) defines the job types.
+[Appendix 2](#appendix-2-job-types) defines the job request types.
## Rationale
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.
@@ -32,19 +32,23 @@ There are two actors in the workflow described in this NIP:
* Service providers (npubs who fulfill jobs)
# Event Kinds
+
+* `kind:65000`: job feedback
+* `kind:65001`: job result
+* `kind:65002`-`kind:66000`: job requests
+
## Job request
-A request to have data processed, published by a customer
+A 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.
```json
{
- "kind": xxx, // kind in 65002-66000 range
+ "kind": 65xxx, // kind in 65002-66000 range
"content": "",
"tags": [
[ "i", "", "", "", "" ],
[ "output", "" ],
[ "relays", "wss://..."],
[ "bid", "" ],
- [ "exp", "" ],
[ "t", "bitcoin" ]
]
}
@@ -52,24 +56,25 @@ A request to have data processed, published by a customer
All tags are optional.
-* `i` tag: Input data for the job (zero or more inputs may exist)
+* `i` tag: Input data for the job (zero or more inputs)
* ``: The argument for the input
- * ``: The way this argument should be interpreted, MUST be one of:
+ * ``: The way this argument should be interpreted. MUST be one of:
* `url`: A URL to be fetched
- * `event`: A Nostr event ID, include an optional relay-url extra param
+ * `event`: A Nostr event ID.
* `job`: The output of a previous job with the specified event ID
* `text`: `` is the value of the input, no resolution is needed
* ``: An optional field indicating how this input should be used within the context of the job
* ``: If `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string
-* `output`: MIME type. Expected output format. Service Providers SHOULD publish the result of the job in this format if it has been specified
+* `output`: Expected output format. (e.g. MIME type)
+ * Service Providers MUST publish the result of the job in this format if it has been specified.
+ * Each job-type ([Appendix 2](#appendix-2-job-types)) might define the output format more narrowly.
* `bid`: Customer MAY specify a maximum amount (in millisats) they are willing to pay
-* `relays`: Relays where Service Providers SHOULD publish responses to
+* `relays`: List of relays where Service Providers SHOULD publish responses to
* `p`: Service Providers the customer is interested in. Other SPs MIGHT still choose to process the job
-* `exp`: Expiration timestamp. Service Providers SHOULD not send results after this timestamp
## Job result
-The output of processing the data -- published by the Service Provider.
+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.
```json
{
@@ -79,28 +84,40 @@ The output of processing the data -- published by the Service Provider.
"tags": [
[ "request", "" ],
[ "e", "", "" ],
- [ "p", "" ],
+ [ "p", "" ],
[ "amount", "requested-payment-amount", "" ]
]
}
```
-* `request` tag: The job request event ID.
+* `request`: The job request event stringified-JSON.
* `amount`: millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice.
## Job feedback
-Both customers and service providers can give feedback about a job.
+Service providers can give feedback about a job back to the customer.
-The result of the job SHOULD be included in the `content` field.
+```json
+{
+ "kind": 65000,
+ "content": "",
+ "tags": [
+ [ "status", "", "" ],
+ [ "amount", "requested-payment-amount", "" ],
+ [ "e", "", "" ],
+ [ "p", "" ],
+ ]
+}
+```
-* `status` tag: Service Providers MAY indicate errors or extra info about the results by including them in the `status` tag.
-* `amount`: as defined in the [Job Result](#job-result) section.
+* `content`: Either empty or a job-result (e.g. for partial-result samples)
+* `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.
+* `amount` tag: as defined in the [Job Result](#job-result) section.
# Protocol Flow
-* Customer publishes a job request (e.g. `kind:65002`).
+* Customer publishes a job request (e.g. `kind:65002` speech-to-text).
* Service Providers 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.
+* 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
`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.
@@ -137,16 +154,6 @@ Consult [Appendix 1: Example](#appendix-1-examples)'s [Summarization of a podcas
}
```
-## Not addressed in this NIP
-
-### Reputation system
-Service providers are at an 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.). It's out of scope (and undesirable) to have this NIP address this issue; the market should.
-
-### 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.
-
-
# Appendix 1: Examples
## Transcript of a podcast from second `900` to `930`.
@@ -316,7 +323,7 @@ User publishes event #1 and #2 together.
[ "bid", "500000" ]
]
}
-``
+```
## AI-image of embedded input
@@ -364,6 +371,43 @@ This is a list of all the supported job requests.
| `prompt` | opt | extra prompt to be used for the image generation |
| `size` | opt | desired size of the image |
+## event list generation: `kind:65006`
+
+Generates a list of event ids, (e.g. algorithmic feeds, spam-free notifications, trending topics)
+
+Output should be a stringified array of elements usually find in a nostr event' `tags`, e.g.:
+
+```json
+{ "content": "[
+ [\"e\", \"\"],
+ [\"a\", \"30023:pubkey:id\"],
+ [\"t\", \"tag\"],
+ [\"p\", \"pubkey\"],
+]" }
+```
+
+| param | req? | description |
+|-----------|------|-------------------------------------------------------|
+| `filter` | opt | JSON-stringified `REQ`-like filter
+| `prompt` | opt | A human-readable description of the desired results. Which might be used with e.g. an LLM to tune the results.
+| `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.
+
+### example job-request
+
+Generate an algorithmic feed of the most interesting `kind:1`s related to the topic "bitcoin", tagging service providers specializing in safe-for-work content
+that would interest pubkey `pubkey1`.
+
+```json
+{
+ "kind": 65006,
+ "tags": [
+ [ "param", "filter", "{ \"kinds\": [1], \"#t\": [\"bitcoin\"] }" ],
+ [ "param", "p", "[\"pubkey1\"]"]
+ [ "bid", "5000" ],
+ [ "t", "sfw" ]
+ ]
+}
+```
# Appendix 3: Job feedback status
From 948ee24775fe89e779efe7680ca6a27dc5a6207f Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Tue, 25 Jul 2023 17:20:24 +0300
Subject: [PATCH 017/217] rename file
---
vending-machine.md => 90.md | 1 -
README.md | 4 ++++
2 files changed, 4 insertions(+), 1 deletion(-)
rename vending-machine.md => 90.md (99%)
diff --git a/vending-machine.md b/90.md
similarity index 99%
rename from vending-machine.md
rename to 90.md
index c41ccceb..99f313d4 100644
--- a/vending-machine.md
+++ b/90.md
@@ -417,7 +417,6 @@ that would interest pubkey `pubkey1`.
| `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 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.
diff --git a/README.md b/README.md
index 9893ffcf..ebfd3596 100644
--- a/README.md
+++ b/README.md
@@ -64,6 +64,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [NIP-65: Relay List Metadata](65.md)
- [NIP-78: Application-specific data](78.md)
- [NIP-89: Recommended Application Handlers](89.md)
+- [NIP-90: Data Vending Machines](90.md)
- [NIP-94: File Metadata](94.md)
- [NIP-98: HTTP Auth](98.md)
@@ -110,6 +111,8 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `30078` | Application-specific Data | [78](78.md) |
| `31989` | Handler recommendation | [89](89.md) |
| `31990` | Handler information | [89](89.md) |
+| `65000` | Job Feedback | [90](90.md) |
+| `65001` | Job Result | [90](90.md) |
### Event Kind Ranges
@@ -119,6 +122,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `10000`--`19999` | Replaceable Events | [16](16.md) |
| `20000`--`29999` | Ephemeral Events | [16](16.md) |
| `30000`--`39999` | Parameterized Replaceable Events | [33](33.md) |
+| `65002`--`66000` | Job Requests | [90](90.md) |
## Message types
From 9fa9045d19b93f4cbac231bff39558108a6e82ae Mon Sep 17 00:00:00 2001
From: pablof7z
Date: Tue, 25 Jul 2023 17:31:31 +0300
Subject: [PATCH 018/217] remove duplicated output
---
90.md | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/90.md b/90.md
index 99f313d4..51c49cf2 100644
--- a/90.md
+++ b/90.md
@@ -168,9 +168,8 @@ Consult [Appendix 1: Example](#appendix-1-examples)'s [Summarization of a podcas
"tags": [
[ "i", "https://bitcoin.review/episode1.mp3", "url" ],
[ "params", "range", "900", "930" ],
- [ "output", "text/vtt" ],
+ [ "output", "text/plain" ],
[ "bid", "50000" ],
- [ "output", "text/plain" ]
]
}
```
@@ -388,7 +387,7 @@ Output should be a stringified array of elements usually find in a nostr event'
| param | req? | description |
|-----------|------|-------------------------------------------------------|
-| `filter` | opt | JSON-stringified `REQ`-like filter
+| `filter` | opt | Stringified JSON `REQ` filter. Used to scope the desired results (e.g. specify the desired kinds)
| `prompt` | opt | A human-readable description of the desired results. Which might be used with e.g. an LLM to tune the results.
| `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.
From e9f8bc27b7f14355a3c4a321e4368046125a3dc0 Mon Sep 17 00:00:00 2001
From: "Nostr.Band" <124499563+nostrband@users.noreply.github.com>
Date: Tue, 10 Oct 2023 20:12:21 +0300
Subject: [PATCH 019/217] add spring.site to nip-07 (#810)
Add Spring.site as NIP07 implementation
---
07.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/07.md b/07.md
index ee4e3722..0c8c4027 100644
--- a/07.md
+++ b/07.md
@@ -33,3 +33,4 @@ async window.nostr.nip04.decrypt(pubkey, ciphertext): string // takes ciphertext
- [AKA Profiles](https://github.com/neilck/aka-extension) (Chrome, stores multiple keys)
- [TokenPocket](https://www.tokenpocket.pro/) (Android, IOS, Chrome and derivatives)
- [Nostrmo](https://github.com/haorendashu/nostrmo_faq#download) (Android, IOS)
+- [Spring Browser](https://spring.site) (Android)
From 21c6c12c524cb71f18e068c9bcf223cda0214b5f Mon Sep 17 00:00:00 2001
From: Vic <88121568+vicariousdrama@users.noreply.github.com>
Date: Wed, 11 Oct 2023 00:57:12 -0400
Subject: [PATCH 020/217] Update 57.md (#808)
Clarify how multiple relays should be included in the zap request event
---
57.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/57.md b/57.md
index 8e2be1b2..849c8696 100644
--- a/57.md
+++ b/57.md
@@ -45,7 +45,7 @@ Example:
"kind": 9734,
"content": "Zap!",
"tags": [
- ["relays", "wss://nostr-pub.wellorder.com"],
+ ["relays", "wss://nostr-pub.wellorder.com", "wss://anotherrelay.example.com"],
["amount", "21000"],
["lnurl", "lnurl1dp68gurn8ghj7um5v93kketj9ehx2amn9uh8wetvdskkkmn0wahz7mrww4excup0dajx2mrv92x9xp"],
["p", "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9"],
@@ -66,7 +66,7 @@ A signed `zap request` event is not published, but is instead sent using a HTTP
- `nostr` is the `9734` `zap request` event, JSON encoded then URI encoded
- `lnurl` is the lnurl pay url of the recipient, encoded using bech32 with the prefix `lnurl`
-This request should return a JSON response with a `pr` key, which is the invoice the sender must pay to finalize his zap. Here is an example flow:
+This request should return a JSON response with a `pr` key, which is the invoice the sender must pay to finalize his zap. Here is an example flow in javascript:
```javascript
const senderPubkey // The sender's pubkey
From 324c7aafdcd316fb971c1f26b964d2b53c939a10 Mon Sep 17 00:00:00 2001
From: Don
Date: Wed, 11 Oct 2023 20:55:27 +0900
Subject: [PATCH 021/217] Change wording to imply that reactions can target any
event (#815)
* kind:17 generic reactions.
* `kind 7` is available for all kind events.
* `k` tag is not required.
---
25.md | 6 +++-
README.md | 82 +++++++++++++++++++++++++++----------------------------
2 files changed, 46 insertions(+), 42 deletions(-)
diff --git a/25.md b/25.md
index 63c07a73..7b29140a 100644
--- a/25.md
+++ b/25.md
@@ -7,7 +7,7 @@ Reactions
`draft` `optional` `author:jb55`
-A reaction is a `kind 7` note that is used to react to other notes.
+A reaction is a `kind 7` event that is used to react to other events.
The generic reaction, represented by the `content` set to a `+` string, SHOULD
be interpreted as a "like" or "upvote".
@@ -34,6 +34,9 @@ The last `e` tag MUST be the `id` of the note that is being reacted to.
The last `p` tag MUST be the `pubkey` of the event being reacted to.
+The reaction event MAY include a `k` tag with the stringified kind number
+of the reacted event as its value.
+
Example code
```swift
@@ -43,6 +46,7 @@ func make_like_event(pubkey: String, privkey: String, liked: NostrEvent) -> Nost
}
tags.append(["e", liked.id])
tags.append(["p", liked.pubkey])
+ tags.append(["k", liked.kind])
let ev = NostrEvent(content: "+", pubkey: pubkey, kind: 7, tags: tags)
ev.calculate_id()
ev.sign(privkey: privkey)
diff --git a/README.md b/README.md
index 1097bc55..dc708873 100644
--- a/README.md
+++ b/README.md
@@ -156,47 +156,47 @@ Please update these lists when proposing NIPs introducing new event kinds.
## Standardized Tags
-| name | value | other parameters | NIP |
-| ----------------- | ------------------------------------ | -------------------- | ------------------------ |
-| `e` | event id (hex) | relay URL, marker | [01](01.md), [10](10.md) |
-| `p` | pubkey (hex) | relay URL, petname | [01](01.md), [02](02.md) |
-| `a` | coordinates to an event | relay URL | [01](01.md) |
-| `d` | identifier | -- | [01](01.md) |
-| `alt` | summary | -- | [31](31.md) |
-| `g` | geohash | -- | [52](52.md) |
-| `i` | identity | proof | [39](39.md) |
-| `k` | kind number (string) | -- | [18](18.md), [72](72.md) |
-| `l` | label, label namespace | annotations | [32](32.md) |
-| `L` | label namespace | -- | [32](32.md) |
-| `m` | MIME type | -- | [94](94.md) |
-| `r` | a reference (URL, etc) | petname | |
-| `r` | relay url | marker | [65](65.md) |
-| `t` | hashtag | -- | |
-| `amount` | millisatoshis, stringified | -- | [57](57.md) |
-| `bolt11` | `bolt11` invoice | -- | [57](57.md) |
-| `challenge` | challenge string | -- | [42](42.md) |
-| `content-warning` | reason | -- | [36](36.md) |
-| `delegation` | pubkey, conditions, delegation token | -- | [26](26.md) |
-| `description` | invoice/badge description | -- | [57](57.md), [58](58.md) |
-| `emoji` | shortcode, image URL | -- | [30](30.md) |
-| `expiration` | unix timestamp (string) | -- | [40](40.md) |
-| `goal` | event id (hex) | relay URL | [75](75.md) |
-| `image` | image URL | dimensions in pixels | [23](23.md), [58](58.md) |
-| `lnurl` | `bech32` encoded `lnurl` | -- | [57](57.md) |
-| `location` | location string | -- | [52](52.md), [99](99.md) |
-| `name` | badge name | -- | [58](58.md) |
-| `nonce` | random | -- | [13](13.md) |
-| `preimage` | hash of `bolt11` invoice | -- | [57](57.md) |
-| `price` | price | currency, frequency | [99](99.md) |
-| `proxy` | external ID | protocol | [48](48.md) |
-| `published_at` | unix timestamp (string) | -- | [23](23.md) |
-| `relay` | relay url | -- | [42](42.md) |
-| `relays` | relay list | -- | [57](57.md) |
-| `subject` | subject | -- | [14](14.md) |
-| `summary` | article summary | -- | [23](23.md) |
-| `thumb` | badge thumbnail | dimensions in pixels | [58](58.md) |
-| `title` | article title | -- | [23](23.md) |
-| `zap` | pubkey (hex), relay URL | weight | [57](57.md) |
+| name | value | other parameters | NIP |
+| ----------------- | ------------------------------------ | -------------------- | ------------------------------------- |
+| `e` | event id (hex) | relay URL, marker | [01](01.md), [10](10.md) |
+| `p` | pubkey (hex) | relay URL, petname | [01](01.md), [02](02.md) |
+| `a` | coordinates to an event | relay URL | [01](01.md) |
+| `d` | identifier | -- | [01](01.md) |
+| `alt` | summary | -- | [31](31.md) |
+| `g` | geohash | -- | [52](52.md) |
+| `i` | identity | proof | [39](39.md) |
+| `k` | kind number (string) | -- | [18](18.md), [25](25.md), [72](72.md) |
+| `l` | label, label namespace | annotations | [32](32.md) |
+| `L` | label namespace | -- | [32](32.md) |
+| `m` | MIME type | -- | [94](94.md) |
+| `r` | a reference (URL, etc) | petname | |
+| `r` | relay url | marker | [65](65.md) |
+| `t` | hashtag | -- | |
+| `amount` | millisatoshis, stringified | -- | [57](57.md) |
+| `bolt11` | `bolt11` invoice | -- | [57](57.md) |
+| `challenge` | challenge string | -- | [42](42.md) |
+| `content-warning` | reason | -- | [36](36.md) |
+| `delegation` | pubkey, conditions, delegation token | -- | [26](26.md) |
+| `description` | invoice/badge description | -- | [57](57.md), [58](58.md) |
+| `emoji` | shortcode, image URL | -- | [30](30.md) |
+| `expiration` | unix timestamp (string) | -- | [40](40.md) |
+| `goal` | event id (hex) | relay URL | [75](75.md) |
+| `image` | image URL | dimensions in pixels | [23](23.md), [58](58.md) |
+| `lnurl` | `bech32` encoded `lnurl` | -- | [57](57.md) |
+| `location` | location string | -- | [52](52.md), [99](99.md) |
+| `name` | badge name | -- | [58](58.md) |
+| `nonce` | random | -- | [13](13.md) |
+| `preimage` | hash of `bolt11` invoice | -- | [57](57.md) |
+| `price` | price | currency, frequency | [99](99.md) |
+| `proxy` | external ID | protocol | [48](48.md) |
+| `published_at` | unix timestamp (string) | -- | [23](23.md) |
+| `relay` | relay url | -- | [42](42.md) |
+| `relays` | relay list | -- | [57](57.md) |
+| `subject` | subject | -- | [14](14.md) |
+| `summary` | article summary | -- | [23](23.md) |
+| `thumb` | badge thumbnail | dimensions in pixels | [58](58.md) |
+| `title` | article title | -- | [23](23.md) |
+| `zap` | pubkey (hex), relay URL | weight | [57](57.md) |
## Criteria for acceptance of NIPs
From 09ffb951c69343312486aaff2726dca04bc42f6e Mon Sep 17 00:00:00 2001
From: fiatjaf_
Date: Wed, 11 Oct 2023 10:17:43 -0300
Subject: [PATCH 022/217] rework NIP-03 so it is actually usable (#804)
* rework nip-03 to be actually useful and usable.
* fixes.
* add ots verification flow.
---
03.md | 33 +++++++++++++++++++++++----------
README.md | 1 +
2 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/03.md b/03.md
index 3c5d764e..4faf3f15 100644
--- a/03.md
+++ b/03.md
@@ -4,20 +4,33 @@ NIP-03
OpenTimestamps Attestations for Events
--------------------------------------
-`draft` `optional` `author:fiatjaf`
+`draft` `optional` `author:fiatjaf` `author:constant`
-When there is an OTS available it MAY be included in the existing event body under the `ots` key:
+This NIP defines an event with `kind:1040` that can contain an [OpenTimestamps](https://opentimestamps.org/) proof for any other event:
-```
+```json
{
- "id": ...,
- "kind": ...,
- ...,
- ...,
- "ots":
+ "kind": 1040
+ "tags": [
+ ["e", , ],
+ ["block", , ],
+ ["alt", "opentimestamps attestation"]
+ ],
+ "content":
}
```
-The _event id_ MUST be used as the raw hash to be included in the OpenTimestamps merkle tree.
+- The OpenTimestamps proof MUST prove the referenced `e` event id as its digest.
+- The `block` tag is optional, it exists to establish a minimum date since which the given event has existed.
+- The `content` MUST be the full content of an `.ots` file containing at least one Bitcoin attestation. This file SHOULD contain a **single** Bitcoin attestation and no reference to "pending" attestations since they are useless in this context.
-The attestation can be either provided by relays automatically (and the OTS binary contents just appended to the events it receives) or by clients themselves when they first upload the event to relays — and used by clients to show that an event is really "at least as old as [OTS date]".
+### Example OpenTimestamps proof verification flow
+
+Using [`nak`](https://github.com/fiatjaf/nak), [`jq`](https://jqlang.github.io/jq/) and [`ots`](https://github.com/fiatjaf/ots):
+
+```bash
+~> nak req -i e71c6ea722987debdb60f81f9ea4f604b5ac0664120dd64fb9d23abc4ec7c323 wss://nostr-pub.wellorder.net | jq -r .content | ots verify
+> using an esplora server at https://blockstream.info/api
+- sequence ending on block 810391 is valid
+timestamp validated at block [810391]
+```
diff --git a/README.md b/README.md
index dc708873..e9f08bdb 100644
--- a/README.md
+++ b/README.md
@@ -92,6 +92,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `44` | Channel Mute User | [28](28.md) |
| `1063` | File Metadata | [94](94.md) |
| `1311` | Live Chat Message | [53](53.md) |
+| `1040` | OpenTimestamps | [03](03.md) |
| `1984` | Reporting | [56](56.md) |
| `1985` | Label | [32](32.md) |
| `4550` | Community Post Approval | [72](72.md) |
From 202e18f2b256646148805880ed58731c1c8b2b9b Mon Sep 17 00:00:00 2001
From: Mike O'Bank <111360219+mikeobank@users.noreply.github.com>
Date: Thu, 12 Oct 2023 15:31:58 +0200
Subject: [PATCH 023/217] Nip 06 test vectors (#819)
---
06.md | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/06.md b/06.md
index 4ae571f7..a0b4a01b 100644
--- a/06.md
+++ b/06.md
@@ -13,3 +13,19 @@ Basic key derivation from mnemonic seed phrase
A basic client can simply use an `account` of `0` to derive a single key. For more advanced use-cases you can increment `account`, allowing generation of practically infinite keys from the 5-level path with hardened derivation.
Other types of clients can still get fancy and use other derivation paths for their own other purposes.
+
+### Test vectors
+
+mnemonic: leader monkey parrot ring guide accident before fence cannon height naive bean\
+private key (hex): 7f7ff03d123792d6ac594bfa67bf6d0c0ab55b6b1fdb6249303fe861f1ccba9a\
+nsec: nsec10allq0gjx7fddtzef0ax00mdps9t2kmtrldkyjfs8l5xruwvh2dq0lhhkp\
+public key (hex): 17162c921dc4d2518f9a101db33695df1afb56ab82f5ff3e5da6eec3ca5cd917\
+npub: npub1zutzeysacnf9rru6zqwmxd54mud0k44tst6l70ja5mhv8jjumytsd2x7nu
+
+---
+
+mnemonic: what bleak badge arrange retreat wolf trade produce cricket blur garlic valid proud rude strong choose busy staff weather area salt hollow arm fade\
+private key (hex): c15d739894c81a2fcfd3a2df85a0d2c0dbc47a280d092799f144d73d7ae78add\
+nsec: nsec1c9wh8xy5eqdzln7n5t0ctgxjcrdug73gp5yj0x03gntn67h83twssdfhel\
+public key (hex): d41b22899549e1f3d335a31002cfd382174006e166d3e658e3a5eecdb6463573\
+npub: npub16sdj9zv4f8sl85e45vgq9n7nsgt5qphpvmf7vk8r5hhvmdjxx4es8rq74h
From d9400e1e7b08225aedb6c78b522c5ad07b5198b4 Mon Sep 17 00:00:00 2001
From: Pablo Fernandez
Date: Sat, 14 Oct 2023 16:14:24 +0300
Subject: [PATCH 024/217] big refactor
* use different kinds per response type
* remove examples
* remove specific job request definitions, moved to a separate repo for clarity
---
90.md | 383 +++++++++-------------------------------------------------
1 file changed, 58 insertions(+), 325 deletions(-)
diff --git a/90.md b/90.md
index 51c49cf2..4c0eff6a 100644
--- a/90.md
+++ b/90.md
@@ -4,22 +4,24 @@ NIP-90
Data Vending Machine
--------------------
-`draft` `optional` `author:pablof7z`
+`draft` `optional` `author:pablof7z` `author:dontbelievethehype`
This NIP defines the interaction between customers and Service Providers for performing on-demand computation.
Money in, data out.
## Kinds
-This NIP reserves the range `65000-66000` for data vending machine use.
+This NIP reserves the range `5000-7000` for data vending machine use.
| Kind | Description |
| ---- | ----------- |
-| 65000 | Job feedback |
-| 65001 | Job result |
-| 65002-66000 | Job request kinds |
+| 5000-5999 | Job request kinds |
+| 6000-6999 | Job result |
+| 7000 | Job feedback |
-[Appendix 2](#appendix-2-job-types) defines the job request types.
+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`).
+
+Job request types are defined [separately](https://github.com/nostr-protocol/data-vending-machines/tree/master/kinds).
## Rationale
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.
@@ -31,21 +33,15 @@ There are two actors in the workflow described in this NIP:
* Customers (npubs who request a job)
* Service providers (npubs who fulfill jobs)
-# Event Kinds
-
-* `kind:65000`: job feedback
-* `kind:65001`: job result
-* `kind:65002`-`kind:66000`: job requests
-
-## Job request
-A 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.
+## Job request (`kind:5000-5999`)
+A 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.
```json
{
- "kind": 65xxx, // kind in 65002-66000 range
+ "kind": 5xxx, // kind in 5000-5999 range
"content": "",
"tags": [
- [ "i", "", "", "", "" ],
+ [ "i", "", "", "", "" ],
[ "output", "" ],
[ "relays", "wss://..."],
[ "bid", "" ],
@@ -59,20 +55,19 @@ All tags are optional.
* `i` tag: Input data for the job (zero or more inputs)
* ``: The argument for the input
* ``: The way this argument should be interpreted. MUST be one of:
- * `url`: A URL to be fetched
+ * `url`: A URL to be fetched of the data that should be processed.
* `event`: A Nostr event ID.
- * `job`: The output of a previous job with the specified event ID
+ * `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.)
* `text`: `` is the value of the input, no resolution is needed
- * ``: An optional field indicating how this input should be used within the context of the job
* ``: If `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string
-* `output`: Expected output format. (e.g. MIME type)
- * Service Providers MUST publish the result of the job in this format if it has been specified.
- * Each job-type ([Appendix 2](#appendix-2-job-types)) might define the output format more narrowly.
+ * ``: An optional field indicating how this input should be used within the context of the job
+* `output`: Expected output format. Different job request `kind` defines this more precisely.
+* `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" ]`)
* `bid`: Customer MAY specify a maximum amount (in millisats) they are willing to pay
* `relays`: List of relays where Service Providers SHOULD publish responses to
* `p`: Service Providers the customer is interested in. Other SPs MIGHT still choose to process the job
-## Job result
+## Job result (`kind:6000-6999`)
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.
@@ -80,10 +75,11 @@ Service providers publish job results, providing the output of the job result. T
{
"pubkey": "",
"content": "",
- "kind": 65001,
+ "kind": 6xxx,
"tags": [
[ "request", "" ],
[ "e", "", "" ],
+ [ "i", "" ],
[ "p", "" ],
[ "amount", "requested-payment-amount", "" ]
]
@@ -92,13 +88,14 @@ Service providers publish job results, providing the output of the job result. T
* `request`: The job request event stringified-JSON.
* `amount`: millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice.
+* `i`: The original input(s) specified in the request.
## Job feedback
Service providers can give feedback about a job back to the customer.
```json
{
- "kind": 65000,
+ "kind": 7000,
"content": "",
"tags": [
[ "status", "", "" ],
@@ -110,305 +107,10 @@ Service providers can give feedback about a job back to the customer.
```
* `content`: Either empty or a job-result (e.g. for partial-result samples)
-* `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.
* `amount` tag: as defined in the [Job Result](#job-result) section.
+* `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.
-# Protocol Flow
-* Customer publishes a job request (e.g. `kind:65002` speech-to-text).
-* Service Providers 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, 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
-
-`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.
-
-## Notes about the protocol flow
-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.
-
-Some 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.
-
-It's not up to this NIP to define how individual vending machines should choose to run their business.
-
-# Cancellation
-A job request might be cancelled by publishing a `kind:5` delete request event tagging the job request event.
-
-# Job chaining
-A 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.
-
-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.
-
-This gives a higher level of flexibility to service providers (which sophisticated service providers would take anyway).
-
-Consult [Appendix 1: Example](#appendix-1-examples)'s [Summarization of a podcast](#summarization-of-a-podcast)
-
-### E.g. Payment required (with sample content)
-```json
-{
- "kind": 65000,
- "content": "This is the transcription service that you",
- "tags": [
- [ "e", , ],
- [ "p", ],
- [ "status", "payment-required" ],
- [ "amount", "7000" ],
- ]
-}
-```
-
-# Appendix 1: Examples
-
-## Transcript of a podcast from second `900` to `930`.
-
-### `kind:65002`: Speech-to-text job request
-```json
-{
- "id": "12345",
- "pubkey": "abcdef",
- "content": "",
- "kind": 65002,
- "tags": [
- [ "i", "https://bitcoin.review/episode1.mp3", "url" ],
- [ "params", "range", "900", "930" ],
- [ "output", "text/plain" ],
- [ "bid", "50000" ],
- ]
-}
-```
-
-### `kind:65000`: Job Feedback: request for (partial) payment
-* The SP is signaling here that it won't start processing until 100 sats are paid
-```json
-{
- "kind": 65000,
- "content": "",
- "tags": [
- ["e", "12345"],
- ["p", "abcdef"],
- ["status", "payment-required"],
- ["amount", "100000"]
- ]
-}
-```
-
-* User zaps 100 sats to the `kind:65000` job-feedback
-
-### `kind:65001`: Job result + request for remaining payment
-```json
-{
- "content": "blah blah blah",
- "tags": [
- ["e", "12345"],
- ["p", "abcdef"],
- ["amount", "400000"]
- ]
-}
-```
-
-## Summarization of a podcast
-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.
-
-### `kind:65002`: Job Request #1: speech-to-text
-```json
-{
- "id": "12345",
- "pubkey": "abcdef",
- "kind": 65002,
- "content": "",
- "tags": [
- [ "i", "https://bitcoin.review/episode1.mp3", "url" ],
- [ "output", "text/plain" ],
- [ "params", "range", "900", "930" ],
- [ "bid", "100000" ]
- ]
-}
-```
-
-### `kind:65002`: Job Request #2: summarization of job #1's result
-```json
-{
- "id": "12346",
- "pubkey": "abcdef",
- "kind": 65003,
- "content": "",
- "tags": [
- [ "i", "12345", "job" ], // input is the output of job with id 12345
- [ "output", "text/plain" ],
- [ "params", "length", "3 paragraphs" ],
- [ "bid", "10000" ]
- ]
-}
-```
-
-## Translation of a note
-### `kind:65004`: Job Request #1: translation of an existing note
-```json
-{
- "id": "12346",
- "pubkey": "abcdef",
- "content": "",
- "kind": 65004,
- "tags": [
- [ "i", "", "event", "wss://relay.nostr.com" ]
- [ "output", "text/plain" ],
- [ "params", "lang", "es_AR" ],
- [ "bid", "5000" ]
- ]
-}
-```
-
-### `kind:65001`: Job result
-```json
-{
- "kind": 65001,
- "content": "Che, que copado, boludo!",
- "tags": [
- ["e", "12346"],
- ["p", "abcdef"],
- ["amount", "4000"]
- ]
-}
-```
-
-## AI-image of the summarization of 2 podcasts
-
-### `kind:65002`: Job request #1 (transcribe podcast #1)
-```json
-{
- "id": "123",
- "kind": 65002,
- "tags": [
- [ "i", "https://example.com/episode1.mp3", "url" ],
- [ "bid", "100000" ]
- ]
-}
-```
-
-### `kind:65002`: Job request #2 (transcribe podcast #2)
-```json
-{
- "id": "124",
- "kind": 65002,
- "tags": [
- [ "i", "https://example.com/episode2.mp3", "url" ],
- [ "bid", "100000" ]
- ]
-}
-```
-
-### `kind:65003`: Job request #3 (summarize the two job's outputs into one paragraph)
-```json
-{
- "id": "125",
- "kind": 65003,
- "tags": [
- [ "param", "length", "1 paragraph" ],
- [ "i", "123", "job" ],
- [ "i", "124", "job" ],
- [ "bid", "100000" ]
- ]
-}
-```
-
-### `kind:65005`: 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" ]
- ]
-}
-```
-
-## AI-image of embedded input
-
-### `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" ]
- ]
-}
-```
-
-# Appendix 2: Job types
-
-This is a list of all the supported job requests.
-
-## speech-to-text: `kind:65002`
-
-### params
-
-| param | req? | description |
-|------------|------|-----------------------------------------------------------|
-| `range` | opt | timestamp range (in seconds) of desired text to be transcribed |
-| `alignment`| opt | word, segment, raw: word-level, segment-level, or raw outputs |
-
-## summarization: `kind:65003`
-
-| param | req? | description |
-|-----------|------|---------------|
-| `length` | opt | desired length |
-
-## translation: `kind:65004`
-
-| param | req? | description |
-|-----------|------|--------------------------------------------|
-| `lang` | req | desired language in BCP 47 format. |
-
-## 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 |
-
-## event list generation: `kind:65006`
-
-Generates a list of event ids, (e.g. algorithmic feeds, spam-free notifications, trending topics)
-
-Output should be a stringified array of elements usually find in a nostr event' `tags`, e.g.:
-
-```json
-{ "content": "[
- [\"e\", \"