11.5.3. Demo: Recommend Users to Follow#

Choose Social Media Platform: Reddit | Discord | Bluesky | No Coding

Now let’s look at a recommendation algorithm for new users to follow. Our algorithm will be

For a given user:

  1. Look at the people this user follows

  2. For each of those follows, look at who they follow

  3. While doing this, keep track of what accounts showed up most

  4. Recommend the accounts that showed up the most (the users most followed by people followed by our given user)

Normal Bluesky Setup#

# Load some code called "Client" from the "atproto" library that will help us work with Bluesky
from atproto import Client

(Optional) Step 1b: Make a fake Bluesky connection with the fake_atproto library

%run ../../fake_apis/fake_atproto.ipynb
Fake atproto (bsky.app) is replacing the atproto.blue library. Fake atproto doesn't need real passwords, and prevents you from accessing real Bluesky

Login to Bluesky

# Login to Bluesky
# TODO: put your account name and password below

client = Client(base_url="https://bsky.social")
client.login("your_account_name.bsky.social", "m#5@_fake_bsky_password_$%Ds")
Fake atproto is pretending to set up a client connection to: https://bsky.social
Fake atproto is pretending log into your account: your_account_name.bsky.social

Make a function to get follow suggestions#

Now we make a function that will generate follow suggestions.

The function takes a username (who we are making suggestions for), and a num_followers_to_check, which limits how many follows of our user we check (to limit how many requests to Bluesky we make at a time)

We then get a list of the follows for our user, and we create a dictionary counter (possible_suggestion_counts).

For each of our user’s follows, we get a list of who they follow (the follow-follows). Then for each of the follow_follows, we see if that user is in the possible_suggestion_counts dictionary, and add it if it wasn’t there (starting with 1), or add 1 to it if it was already there.

After the for loop we have counts for our possible suggestions (how often the follow-follows appeared). So we sort the list to put the most common ones at the top, and we return the results.client.get_follows(username, limit=num_followers_to_check)

def get_follow_suggestions(username, num_followers_to_check=3):

    # find the people that user currently follows
    follow_users = client.get_follows(username, limit=num_followers_to_check).follows

    # dictionary to track who my follow follows are, as possible suggestions
    # The keys will be the username, and the values will be how often they
    # appeared as follow follows
    possible_suggestion_counts = {}

    # for each of those people, see who they follow
    for follow_user in follow_users:
        print("looking for followings of user: " + follow_user.handle)
        # Get followers of the follow_user (note: 100 is the max follows you can get at a time)
        follow_follow_users = client.get_follows(follow_user.handle, limit=100).follows
        
        # print out the follow-follows (using some python tricks to make it display nicer)
        print("  the follow-follows are: " + str(list(map(lambda x: x.handle, follow_follow_users))))

        for follow_follow_user in follow_follow_users:
            possible_suggestion = follow_follow_user.handle

            # If this possible suggestion is not yet in the dictionary,
            # add it with a count of one
            if possible_suggestion not in possible_suggestion_counts:
                possible_suggestion_counts[possible_suggestion] = 1
            else: #otherwise, update the count in the dictionary
                possible_suggestion_counts[possible_suggestion] += 1

        print()

    # sort the suggestions by who appeared the most
    ordered_suggestions = sorted(possible_suggestion_counts.items(), key=lambda x: -x[1])
    # recommend that I follow the people who those people follow most
    return ordered_suggestions

Test our function (suggest follows)#

Now that our function is ready, we can test it out and see who we suggest our “fake_user” should follow (if you skip fake_atproto and log into real Bluesky, you can do this for real users)

suggestions = get_follow_suggestions("fake_user", num_followers_to_check=5)

display(suggestions)
fake_user
looking for followings of user: unreal_user
unreal_user
  the follow-follows are: ['great_user', 'awesome_user']

looking for followings of user: imaginary_user
imaginary_user
  the follow-follows are: ['ok_user', 'awesome_user']

looking for followings of user: false_user
false_user
  the follow-follows are: ['great_user', 'awesome_user', 'mediocre_user', 'another_user']
[('awesome_user', 3),
 ('great_user', 2),
 ('ok_user', 1),
 ('mediocre_user', 1),
 ('another_user', 1)]

Try it youself!#

If you skip the fake_atproto step and run this on real Discord, you might see some issues with the suggestions that we haven’t accounted for, such as:

  • it might suggest the user follow themself, or someone they already follow

  • the follow lists can be very long and you might not be getting the whole list in the client.get_follows() function call (you could use track a cursor value and repeat calls to the client.get_follows() to get more)

We could of course add more code to deal with those issues, but hopefully you can at least get the idea of how this recommendation algorithm works :)