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

NIP-34 - Algorithmic Filter #579

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

arthurfranca
Copy link
Contributor

@arthurfranca arthurfranca commented Jun 2, 2023

Before going on with NIP text, I would like feedback on the concept below. It is simple but hard to explain. It is a way to enable algo decentralization by making algos work in any dumb relay instead of Google algo that works only on Google relays. Please tell me your questions if any.

From NIP-01: When limit: n is present it is assumed that the events returned in the initial query will be the latest n events.

With the above quote in mind, we could turn this:
["REQ", <sub_id>, { kinds: [1], ..., limit: 5 }]

Into this:
["REQ", <sub_id>, { kinds: [1], ..., limit: 5, nip34: 'algorithm_a' }]

Then, non-supporting relays will (probably) just ignore the nip34 field and sort by created_at in descending order, as usual (this detail is important because it is what makes it backward-compatible).
While supporting relays (that not only support nip34 but also algorithm_a) will just swap the created_at field in their internal query with a nip34_algorithm_a field.

I want it to be a simple swap of fields. For example, if a relay implementation uses a SQL DB, the above filter would turn this:
SELECT * FROM events WHERE kind in (1) ORDER BY created_at DESC LIMIT 5

Into this:
SELECT * FROM events WHERE kind in (1) ORDER BY nip34_algorithm_a DESC LIMIT 5

So:

  1. Each NIP-34 algo supported by the relay will in practice add a field on relay DB for each event. The field works like created_at, meaning the event with highest value in said field will be the first retrieved on queries;
  2. Each specific algo section explains how and when to update the corresponding field. For example, the field is always set on event creation but may be updated every time the event was "liked"

If the concept is acknowledged, I will kick start the NIP with a simple algo that will enable us to sort events in ascending order. Such feature is useful for instance on github-like PR discussions that have older messages at top.

Original discussion

@arthurfranca
Copy link
Contributor Author

Should each algorithm be a new nip like NIP-3401 (instead of just "algorithm_name" inside a NIP-34 section) so that relays can advertise support on Relay Information Document using "supported_nips" array field?

I see there's also a "supported_nip_extensions": ["11a"] field example, so maybe "supported_nip_extensions": ["34algorithm_name"] or just "supported_nip_extensions": ["34a"]?

@fiatjaf
Copy link
Member

fiatjaf commented Jun 9, 2023

I like this.

@huumn
Copy link
Contributor

huumn commented Jun 9, 2023

Joy!

Would it be extra to make nip34 take an array? Some algorithms might take arguments that clients might want to expose. It could be best to keep it simple though and add some other nipXX field later for args.

@arthurfranca
Copy link
Contributor Author

@huumn What kind of args you anticipate? This NIP seems incompatible with args cause the score field isn't calculated on each client query but previously set on event creation but may be updated every time the event was "liked" etc. So it is not a different score for each user.

However, the good thing of being a REQ extension is that the client can be smart by keeping track of pubkeys from whom the user is consuming content, also hashtags, and use such pubkeys/hashtags as a way to tailor the query to that specific user like this:

["REQ", <sub_id>, { kinds: [1], limit: 5, nip34: 'featured', authors: ["p1 user follows", "p2 user has read content recently", "p3 user has liked content recently"] }, { kinds: [1], limit: 5, nip34: 'featured', '#t': ['cats', 'bitcoin'] }]

@huumn
Copy link
Contributor

huumn commented Jun 9, 2023

This NIP seems incompatible with args cause the score field isn't calculated on each client query but previously set on event creation but may be updated every time the event was "liked" etc.

Sorry I missed that. Should we be telling relays how they should be computing keeping scores? It makes sense to suggest these things though I guess.

So it is not a different score for each user.

In the case of ranking by likes I guess this would mean my feed could be influenced by anyone, so long as other filter conditions are met, ie there's no way for me to filter out the influence of likes by people I've muted for instance.

I do really enjoy how simple this is. Nice work.

What kind of args you anticipate?

One example is whose likes we want to take into account. The simplest version is just a boolean flag, e.g. true if I only want my follows considered, false for global.

@arthurfranca
Copy link
Contributor Author

Each algo section on the NIP describes how relays should compute the score. It's a global score so can't avoid muted ppl weight. Relays should atleast rate limit likes and such by ip to avoid gaming the score.

@rabble
Copy link
Collaborator

rabble commented Jun 12, 2023

This seems really similar to the atproto solution. That's one of the few areas where they're farther along than nostr.

https://github.com/bluesky-social/feed-generator

@arthurfranca arthurfranca force-pushed the nip-34 branch 2 times, most recently from eb49042 to 3430c36 Compare June 12, 2023 18:03
@arthurfranca arthurfranca marked this pull request as ready for review June 12, 2023 18:36
@arthurfranca
Copy link
Contributor Author

Took the route of adding NIP extensions for each algo to use "supported_nip_extensions": ["34a", "34b", ...] etc from NIP-11.
Added NIP-34a Oldest First algo.

@arthurfranca
Copy link
Contributor Author

I have added a new simple algo to address issue #78

@fiatjaf
Copy link
Member

fiatjaf commented Jun 27, 2023

This sounds like a good solution, but before this is tried I think we need a more developed client ecosystem first, in which clients are more prepared to differentiate between relays.

@fiatjaf
Copy link
Member

fiatjaf commented Jun 27, 2023

On the other hand, if clients get to that point, it would be easier for a relay to just offer different endpoints which users can specify manually by using URL paths. This would ensure maximum compatibility with clients that do not explicitly support algorithms.

@arthurfranca
Copy link
Contributor Author

it would be easier for a client to just offer different endpoints which users can specify manually by using URL paths.

The client? Or you meant a relay besides supporting { "nip34": "algox" } filter field could make available wss://relay.url/nip34algox in addition to regular wss://relay.url for users to add to relay list on unsupporting clients?

@fiatjaf
Copy link
Member

fiatjaf commented Jun 27, 2023

Yes, that's what I mean. I fixed my comment to say "relay" instead.

@arthurfranca
Copy link
Contributor Author

@fiatjaf I've added it as a requirement.
Instead of a new endpoint, ended up using a ?nip34=algo query param on connection string cause there is already things like wss://filter.nostr.wine/npub1...?broadcast=true in the wild and I think requiring query param support is less complicated than appending /nip34a to the path like wss://filter.nostr.wine/npub1.../nip34a?broadcast=true .

@arthurfranca
Copy link
Contributor Author

arthurfranca commented Jul 18, 2023

It ocurred to me that the algos don't need to return a string because DBs that can only index strings already have to deal with integer for the created_at field.
So they store string but turn it into integer before replying to the request, or index the string but store both versions.
I will edit it.

@arthurfranca
Copy link
Contributor Author

Now Ascending and Seen At fields are integers.

@fiatjaf
Copy link
Member

fiatjaf commented Jul 19, 2023

Wherever we're heading with this, I think the entire thing should be in a single file.

@arthurfranca
Copy link
Contributor Author

Ive put everything in one file and simplified text a lot

@mikedilger
Copy link
Contributor

related: #78

@arthurfranca
Copy link
Contributor Author

I'm biased but if this gets merged and relays start supporting this, the protocol gets both a simple way to do client-relay event sync (seen_at) and to reverse sort events (asc). Huge win for clients that keep a local DB so would appreciate sync or to those that don't have a local DB and would like to reverse sort events relay-side.

More involved algorithms can be added in the future as an extension. Like NIP-11 "supported_nip_extensions":["34-extra-algo-xyz"]. Regular NIP-34 support would be achieved just by implementing seen_at and asc.

@fiatjaf
Copy link
Member

fiatjaf commented Oct 23, 2023

Why do this with an extra parameter in the filter instead of a subdomain or a path in the relay URL? I think the later is better, more flexible, more transparent and easier to grasp.

i.e. instead of sending ["REQ", "_", {"nip34": "crazy"}] to wss://relay.com you could send ["REQ", "_", {}] to wss://crazy.relay.com or wss://relay.com/crazy then it is immediately obvious to anyone what is happening and no one has to code new parsers or anything like that. Also it works immediately on all clients that allow users to select relays to query from, they can just paste a new URL there.

@vitorpamplona
Copy link
Collaborator

I'm biased but if this gets merged and relays start supporting this...

Not to be annoying, but the order is: relays start supporting it and then it gets merged. :)

@arthurfranca
Copy link
Contributor Author

@fiatjaf because the same connection can be kept open and reused for subscriptions that use or don't use NIP-34 (side note: the field name is now "algo" instead of "nip34" cause don't know if gonna have to change nip number).

I already added the Relay Connection URL Query Parameter section with what you said, to be able to manually add relay urls on clients that don't support this nip.

@vitorpamplona fair T_T I haven't seem many relay implementers on NIP discussions lately

Copy link
Collaborator

@Semisol Semisol left a comment

Choose a reason for hiding this comment

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

I think it is better we do a DVM-style thing instead of this.

@arthurfranca arthurfranca marked this pull request as draft May 9, 2024 16:08
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.

7 participants