-
Notifications
You must be signed in to change notification settings - Fork 90
Add AI preference options #1911
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
base: master
Are you sure you want to change the base?
Changes from all commits
db6d7bb
c2ed870
5b28ea4
218a95d
e310ec7
312992e
8a443af
d6a2bfa
cc29f5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Generated by Django 4.2.19 on 2025-05-23 15:39 | ||
|
||
from django.conf import settings | ||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
('accounts', '0041_alter_profile_options'), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='AIPreference', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('date_updated', models.DateTimeField(auto_now=True)), | ||
('preference', models.CharField(choices=[('fr', "My sounds are used following Freesound's recommendations for interpreting Creative Commons licenses in a generative AI training context"), ('o', 'My sounds are used to train open models that are freely available to the public'), ('on', 'My sounds are used to train open models that are freely available to the public and that do not allow a commercial use')], default='fr', max_length=2)), | ||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='ai_preference', to=settings.AUTH_USER_MODEL)), | ||
], | ||
), | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -641,7 +641,19 @@ def get_stats_for_profile_page(self): | |
cache.set(settings.USER_STATS_CACHE_KEY.format(self.user_id), stats_from_cache, 60*60*24) | ||
stats_from_db.update(stats_from_cache) | ||
return stats_from_db | ||
|
||
|
||
def get_ai_preference(self): | ||
try: | ||
return self.user.ai_preference.preference | ||
except AIPreference.DoesNotExist: | ||
# If no preference is set, return the default one | ||
return AIPreference.DEFAULT_AI_PREFERENCE | ||
|
||
def set_ai_preference(self, preference_value): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isn't this just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm you might be right, although I think it is strange that I did not test that. Anyway, I still need to add unit tests so I'll make sure this is covered and consider the reimplementation. Thanks! |
||
num_updated = AIPreference.objects.update(user=self.user, preference=preference_value) | ||
if num_updated == 0: | ||
# If no AIPreference object was updated, it means no AIPreference object exister for that user. Create a new one. | ||
AIPreference.objects.create(user=self.user, preference=preference_value) | ||
|
||
class Meta: | ||
ordering = ('-user__date_joined', ) | ||
|
@@ -657,6 +669,18 @@ class GdprAcceptance(models.Model): | |
date_accepted = models.DateTimeField(auto_now_add=True) | ||
|
||
|
||
class AIPreference(models.Model): | ||
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="ai_preference") | ||
date_updated = models.DateTimeField(auto_now=True) | ||
AI_PREFERENCE_CHOICES = ( | ||
("fr", "My sounds are used following Freesound's recommendations for interpreting Creative Commons licenses in a generative AI training context"), | ||
Comment on lines
+675
to
+676
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a new way that we can do this is models.TextChoices: https://docs.djangoproject.com/en/5.2/ref/models/fields/#enumeration-types Let's use descriptive names too, instead of these small 1-2 letter codes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestion, I'll look into that! The short cryptic names are because of DB char column length, but maybe the new field type already does some "translation", or maybe my assumption that limiting the chars would be more optimal is just not valid as PG will use some enum internally instead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note that TextChoices isn't a new field type, it's just a data type that makes it a bit easier to handle choices for a CharField, much more similar to a python enum. Additionally, I was suggesting to not have a short column. In postgres there's no difference between a length 2, length 100, or unlimited length text field. Especially in our case where we only ever read the value. Let's make things easier on ourselves and make it readable when it's in the database. There is a library which allows us to use a postgres |
||
("o", "My sounds are used to train open models that are freely available to the public"), | ||
("on", "My sounds are used to train open models that are freely available to the public and that do not allow a commercial use") | ||
) | ||
DEFAULT_AI_PREFERENCE = "fr" | ||
preference = models.CharField(max_length=2, choices=AI_PREFERENCE_CHOICES, default=DEFAULT_AI_PREFERENCE) | ||
|
||
|
||
class UserFlag(models.Model): | ||
user = models.ForeignKey(User, related_name="flags", on_delete=models.CASCADE) | ||
reporting_user = models.ForeignKey(User, null=True, blank=True, default=None, on_delete=models.CASCADE) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this mean that the process for a user to change their preference means that they first need to upload a sound and then go back to their profile? Can we make it clearer somehow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far yes, but maybe we could think of redirecting users to the setting. Well, maybe not redirecting because I don't like that, but we could add a banner in the "manage sounds" page for users that have sounds and have no preference set explicitly. In this way, users that already have sounds will see the banner, and also right after describing a sound, when redirected to the manage sounds page, the banner will appear as well. Also I could move the AI preference to a new tab in the account settings page for more clarity and discoverability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aaaaand we could email uploaders about that. It will be ~38k emails, so should be doable...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's a good place to also verify that our email bounce code is working and use it to verify uploader accounts!