Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove label annotations from NIP 32 #872

Merged
merged 1 commit into from
Nov 10, 2023

Conversation

staab
Copy link
Member

@staab staab commented Nov 9, 2023

I added label annotations to NIP 32 in order to support reviews as a use case. This was a mistake for the following reasons:

  • It adds a 4th positional argument, which is too many
  • That argument is json-encoded and therefore way too open-ended
  • The suggested keys for the json object were poorly defined (especially context)

Most importantly, giving labels a value field transforms labels into a key-value store. This makes this NIP applicable to many more use cases (like reviews), but is a very poor fit for them. Adding a regular tag to the even can cover many of them orthogonal to NIP 32. For the rest, a different data structure should be used.

For those of you wondering why I left the L tag in and mandatory, they're important for the following reasons:

  • L tags make it possible to query only the l tags with the meaning you want, and all labels within the namespace without knowing them in advance.
  • L is required, with ugc being the default namespace so that ugc-only labels can still be queried. If we ever get REQ functionality for "doesn't have tag", we can make L optional.

@Gruruya @s3x-jay @rabble

32.md Outdated Show resolved Hide resolved
@@ -83,8 +73,9 @@ A review of a relay.
"kind": 1985,
"tags": [
["L", "com.example.ontology"],
["l", "relay/review", "com.example.ontology", "{\"quality\": 0.1}"],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree the example isn't a lucky one, but I think it is powerful to have the fourth component for formulating RDF triples like: ["l", "name", "http://xmlns.com/foaf/0.1/", "Bob"]. I can imagine some use cases using this possibility.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't it be ["l", "Bob", "http://xmlns.com/foaf/0.1/name"] ?

  • ["l", "VI-hum", "com.example.ontology"] - Violence toward a human being as defined by ontology.example.com.

Looking at this example I think @staab intends the value to be in index 1 position.

Copy link

@sroertgen sroertgen Nov 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that could maybe also be more clearer formulated in the NIP. Sth like: the value is placed at index position 1 the namespace is positioned at index position 2. Right now it has to be guessed from the examples.
But then the use of the L tag does not make too much sense. So I would wish for some more clarification on this.
Example:
http://example.org/Bob https://schema.org/name "Bob", how would this translate to a NIP-32 label?

["L", "https://schema.org/name"]
["l", "Bob", "https://schema.org/name"]
["r", "http://example.org/Bob"]

?

My use case is decentral annotation of web resources using NIP-32 labels.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we need clarification. I saw originally at position 1 the property, at 2th the vocabulary/onto, and at 3th the value, but your example above is neat specifying first the ontology with L then triples and finally the resource URI with the r tag.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is powerful to have the fourth component for formulating RDF triples

This is exactly why I'm removing the value argument, RDF triples are fundamentally different from labels, and aren't supported well by this NIP. I think RDF triples are an awesome idea for nostr, but they should be handled in a different way. The main problem is that triple values should probably be searchable, but only single-letter tags are searchable, and only by the first positional argument. So there's no way to search arbitrary key/value combinations.

Right now it has to be guessed from the examples.

The first paragraph under "Label Tag" says:

A label MUST include a mark matching an L tag

This should be enough, a "mark" is a final positional element. But a lot of people have expressed confusion so I've tried to clarify the language a bit more in the most recent commit.

32.md Show resolved Hide resolved
@fiatjaf fiatjaf merged commit c945d8b into nostr-protocol:master Nov 10, 2023
@sroertgen
Copy link

@staab
though already merged, I would still like to hear your opinions.
I built https://labelmachine.org/ to experiment with labels and would of course like to do it the right way. But the current NIP and the changes confuse me more than that they clarify. Especially if want to use namespaces.

To use the example I already brought up:
http://example.org/Bob https://schema.org/name "Bob" which translates to:

A resource http://example.org/Bob has the attribute https://schema.org/name with a value of "Bob".

How would you translate this to NIP-32?
Like this?

["L", "https://schema.org/"],
["l", "name", "https://schema.org/"],
["r", "http://example.org/Bob"],
["name", "Bob"]

Because then I think it is incosistent with assigning other labels like, e.g. topics:

["L", "#t"],
["l", "permies", "#t"],

Here you set the value of the label in second position. But using namespaces you seem to set the labelnamespace in the second position (name or relay/review). And then the value is found somewhere in the tags (["rating", "0.1"])

@s3x-jay
Copy link

s3x-jay commented Nov 10, 2023

I'm disappointed this PR was merged so quickly. I think labels, while very optional, are rather essential to things like a robust content moderation scheme that incorporates the input of automated tools / bots. IMHO, it would have been better to clarify their use and scope.

@fiatjaf
Copy link
Member

fiatjaf commented Nov 10, 2023

We can use other PRs and I think we can have other annotations.

This one was just for removing the JSON object, which to me was horrible and most people seemed to agree -- nothing prevents you from still using it, but if we want compatibility across clients that wouldn't be it.

What is a good concrete use case served by the annotations and what are the options available to solve it?

@rodant
Copy link

rodant commented Nov 10, 2023

@s3x-jay I also think so, although now I have a better understanding of the NIP and don't see any big issues. Do you have a specific concern?

@staab staab mentioned this pull request Nov 10, 2023
@staab
Copy link
Member Author

staab commented Nov 10, 2023

Opened another PR in an attempt to clarify things a bit more: #874

@sroertgen your use case is somewhere in between key/value pairs and labels, so I'm not sure it's a good fit for this NIP. If I were to shoehorn it in (meaning "bob" would be a "label", which would be weird for attributes like "age" or something):

["L", "https://schema.org/name"],
["l", "Bob", "https://schema.org/name"],
["l", "1991-03-12", "https://schema.org/dob"],
["r", "http://example.org/Bob"],

This makes the fully qualified schema attribute the namespace, and the value the label. But I think this is an abuse of labels — the value of a label should not be unique, but should be shared by multiple labeling events. If I were to come up with an RDF triple format off the top of my head, it might look something like this:

["L", "https://schema.org"],
["https://schema.org/name", "Bob"],
["https://schema.org/dob", "1991-03-12"],
["r", "http://example.org/Bob"],

To avoid confusion, this should go on a different event kind and be defined by a different NIP. And of course it has the drawback of not being able to index the value, which I'm not sure how to solve.

@s3x-jay
Copy link

s3x-jay commented Nov 10, 2023

What is a good concrete use case served by the annotations and what are the options available to solve it?

Prior to NIP-32 being proposed there was NIP-69, and then NIP-68 which were proposed. I believe the json-encoded 4th parameter came from them. Here's how it was described initially:


Accommodating bots & advanced users

It is expected that bots will, in time, contribute to the labeling process, as will advanced users (e.g. scientists, moderators). These groups will require additional relevant information not required by regular users. Some features they will need supported are:

  • quality is a real number between 0 and 1 which expresses how good of an example the item being labeled is of that label.
  • degree is a real number between 0 and 1 which expresses where the item falls on a range if the label refers to a range.
  • confidence is a real number between 0 and 1 which expresses how certain the entity publishing the label is that the label is accurate. It will mostly be used by bots.
  • support is an array of URLs and/or Nostr ids with information to justify the labeling.
  • appliesto is an array of element names and is used when content is a JSON encoded string and the labeling applies to only certain elements in content.

The features above are optional. With the possible exception of appliesto it is not expected that client apps aimed at regular users will make use of these features.


The 4th parameter was json-encoded because it couldn't be definitively defined. The parameters needed varied based on context. While there was no expectation they would be queried, but they were essential for certain use cases.


A scientist comes across a post on Ebola and they want to label it to make it easier for others to find…

{
  "kind": 1985,
  "pubkey": "<pubkey of labeler>",
  "tags": [
    ["e", "<eventid of event being labeled>", "<recommended relay URL>"],
    ["p", "<pubkey of event being labeled>", "<recommended relay URL>"],
    ["a", "<sharable identifer for event with extra metadata>"],
    ["l", "MeSH>D019142", "{\"confidence\":1,\"quality\":0.8}"],
    ["l", "GeoNames>203312", "{\"confidence\":1,\"support\":[\"https://www.cdc.gov/vhf/ebola/history/chronology.html\"]}"]
  ],
  "content": "Post discusses paper on the origins of Ebola.",
  "id": "<event-id>"
}

Example: A nudity detection bot reporting it's finding about a post...

{
  "kind": 1985,
  "pubkey": "<pubkey of bot (labeler)>",
  "tags": [
    ["e", "<eventid of event being labeled>", "<recommended relay URL>"],
    ["p", "<pubkey of event being labeled>"],
    ["a", "<`nevent`, `nprofile` with list of all known relays where event can be found>"],
    ["L", "MOD"],
    ["l", "MOD>warn-public", "MOD" ],
    ["l", "MOD>NS", "MOD", "{\"confidence\":0.62}"]
  ],
  "content": "Nudity detected (62% confidence)",
  "id": "<event-id>"
}

Example: A bot reporting results after it compared a file from a NIP-94 event to a database of known CSAM.

{
  "kind": 1985,
  "pubkey": "<pubkey of bot (labeler)>",
  "tags": [
    ["e", "<eventid of event being labeled>", "<recommended relay URL>"],
    ["a", "<`nevent`, `nprofile` with list of all known relays where event can be found>"],
    ["p", "<pubkey of event being labeled>"],
    ["L", "MOD"],
    ["l", "MOD>delete", "MOD"],
    ["l", "MOD>IL-csa", "MOD", "{\"confidence\":1,\"degree\":1,\"support\":\"https://domain.com/csam-verifier?dbid=123\"}"]
  ],
  "content": "It is recommended that all relay owners delete this event immediately and block all future NIP-94 events with the same hash.",
  "id": "<event-id>"
}

@fiatjaf
Copy link
Member

fiatjaf commented Nov 10, 2023

I see. It makes sense but I think in that case I think we should be fine to allow the fourth parameter in the l tag to be dependent on the ontology.

We could change the NIP to say that.

@mplorentz
Copy link
Collaborator

I'm not a fan of stringified JSON or positional arguments in tags, but this removes some functionality from labels that we are using at Nos.social without specifying a better alternative, so that feels bad.

We have a bot hooked up to OpenAI that is publishing 1984 reports with labels mapping them to our moderation ontology (ontology from NIP-69 which @s3x-jay referenced above) and we are using the 4th positional argument to pass through the confidence value from the AI. If you're curious you can query wss://relay.nos.social for events from d981591e0ea6153b8687b2aed670ab7d9b6c3ad018a360b2820b3cf0f7c0ae37. They look like this:

{
  "content": "Content that expresses, incites, or promotes harassing language towards any target.",
  "created_at": 1699609369,
  "id": "aec864d6d2cf9659a5ae1a27ea52785e1abeb9f2bb735ef9b6932e06df828cb0",
  "kind": 1984,
  "pubkey": "add5190be4673768546c18b565da3a699241f0e06a75e2dbc03f18663d1b7b27",
  "sig": "87ba73e3fdba1ac6c851e5cfa6b36bde590fee31636f618e6c974d964dfd69268883f81cc8328c1e0f5d7712a34c43995e79b0dfeec4c7ec1e66094238275830",
  "tags": [
    [
      "e",
      "9ec5c3db0f2291abe3f22cbefb2344aaf574d9f06b1c9894c6295a02c3f53375",
      "profanity"
    ],
    [
      "L",
      "MOD"
    ],
    [
      "l",
      "IL-har",
      "MOD",
      "{\"confidence\":0.9668398499488831}"
    ]
  ]
}

I don't particularly care whether the confidence is in stringified JSON, a new confidence tag (with a stringified float as its value), or somewhere else. But I did like that there was a place to include metadata in the NIP, and putting stringified JSON in places that aren't going to be indexed by relays is pretty standard Nostr practice.

I'd like to see this is reverted. Or if people hate the stringified JSON too much lets agree on a new place for parameters like confidence and not just axe them, because AI classifiers are one of the prime use cases for "labeling".

@staab
Copy link
Member Author

staab commented Nov 10, 2023

this removes some functionality from labels that we are using at Nos.social without specifying a better alternative, so that feels bad.

I feel this for sure. I'm breaking my own relay reviews feature as well. But we're early enough with nip 32 that I think a little bit of breaking changes is ok — labels are getting a lot more use as actual labels rather than as key/value pairs. Like fiatjaf said, people can keep using the legacy format without the nip specifying it, or we can move to confidence tags, which probably could be an entirely separate NIP applicable to events other than kind 1985. Feel free to open up a new PR to specify how that should be done, even if it's just a reversion of this PR 😉.

@fiatjaf
Copy link
Member

fiatjaf commented Nov 10, 2023

Yes. Well, to me IL-har is completely meaningless and I don't know where to get information about it if I see it in the wild, so what you're doing is already not defined by the NIP, so I don't see what has changed.

I'm not saying this is a problem or that these things should be defined in the NIP at all, much to the contrary. I imagine that once someone gets to understand what IL-har means and notice that events with that label often have the {"confidence":0.96} thing in them will be able to write code that uses it, and that will become a standard.

@fiatjaf
Copy link
Member

fiatjaf commented Nov 10, 2023

On the other hand I think it would be good to have a table at the end of the NIP-32 text defining some common idioms that are being used in the wild, like IL-har + {confidence}, so future implementors can make use of them if they want.

@s3x-jay
Copy link

s3x-jay commented Nov 10, 2023

I see. It makes sense but I think in that case I think we should be fine to allow the fourth parameter in the l tag to be dependent on the ontology.

We could change the NIP to say that.

Agreed. That was always how I envisioned it working. While there may be syntax overlap between vocabularies/ontologies, the data in the 4th parameter are part of the vocabulary/ontology being referenced.

On the other hand I think it would be good to have a table at the end of the NIP-32 text defining some common idioms that are being used in the wild, like IL-har + {confidence}, so future implementors can make use of them if they want.

The PR for NIP-69 was closed prematurely. It was what was supposed to define the MOD (content moderation) vocabulary (which defines IL-har, etc.) There was strong opposition to any moderation vocabulary being defined anywhere. So we wanted it used by more than NOS before we fought that battle again. (Plus my life was disrupted by a stroke 6 months ago - just now kinda getting back into the swing of things.)

In the coming month (+/-) we’ll reintroduce NIP-69. (Stay tuned)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants