251 lines
9.0 KiB
Python
251 lines
9.0 KiB
Python
import io
|
|
from django.contrib import admin
|
|
from django.contrib import messages
|
|
from django.core.management import call_command
|
|
from django.http import HttpResponseRedirect
|
|
from django.urls import path, reverse
|
|
from django.utils.html import format_html
|
|
from .models import TrainingJob, NameVocab, GeneratedPerson
|
|
|
|
|
|
class GeneratedPersonInline(admin.TabularInline):
|
|
model = GeneratedPerson
|
|
extra = 0
|
|
fields = (
|
|
'first_name', 'last_name', 'username', 'username_locked',
|
|
'birth_date', 'gender', 'confidence', 'generated_at'
|
|
)
|
|
readonly_fields = (
|
|
'first_name', 'last_name', 'username', 'username_locked',
|
|
'birth_date', 'gender', 'confidence', 'generated_at'
|
|
)
|
|
can_delete = False
|
|
show_change_link = True
|
|
|
|
|
|
@admin.register(TrainingJob)
|
|
class TrainingJobAdmin(admin.ModelAdmin):
|
|
list_display = (
|
|
'id',
|
|
'task_id',
|
|
'status',
|
|
'model_type',
|
|
'model_file_exists',
|
|
'generated_person_count',
|
|
'accuracy',
|
|
'created_at',
|
|
'completed_at',
|
|
)
|
|
list_filter = ('status', 'model_type', 'created_at')
|
|
search_fields = ('task_id', 'error_message')
|
|
readonly_fields = (
|
|
'task_id',
|
|
'created_at',
|
|
'started_at',
|
|
'completed_at',
|
|
'model_version',
|
|
'model_file_exists',
|
|
'generated_person_count',
|
|
)
|
|
actions = (
|
|
'generate_100_statistical_action',
|
|
'generate_100_llm_action',
|
|
'generate_1000_statistical_action',
|
|
'generate_1000_llm_action',
|
|
)
|
|
inlines = (GeneratedPersonInline,)
|
|
|
|
fieldsets = (
|
|
('Görev Bilgisi', {
|
|
'fields': ('task_id', 'status', 'created_at', 'started_at', 'completed_at')
|
|
}),
|
|
('Model', {
|
|
'fields': ('model_type', 'model_version', 'model_path', 'model_file_exists')
|
|
}),
|
|
('Uretilen Kayitlar', {
|
|
'fields': ('generated_person_count',)
|
|
}),
|
|
('Metrikler', {
|
|
'fields': ('accuracy', 'precision', 'recall', 'f1_score')
|
|
}),
|
|
('Go Servisi', {
|
|
'fields': ('go_service_notified',)
|
|
}),
|
|
('Hata', {
|
|
'fields': ('error_message',),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
def model_file_exists(self, obj):
|
|
return bool(obj.model_path and __import__('os').path.exists(obj.model_path))
|
|
|
|
model_file_exists.boolean = True
|
|
model_file_exists.short_description = 'Model dosyasi var'
|
|
|
|
def generated_person_count(self, obj):
|
|
return obj.generated_persons.count()
|
|
|
|
generated_person_count.short_description = 'Uretilen kisi sayisi'
|
|
|
|
def _run_generate_persons(self, request, queryset, count, use_llm):
|
|
total_jobs = queryset.count()
|
|
ok_jobs = 0
|
|
|
|
for job in queryset:
|
|
try:
|
|
out = io.StringIO()
|
|
kwargs = {
|
|
'count': count,
|
|
'job_id': job.pk,
|
|
'stdout': out,
|
|
}
|
|
if use_llm:
|
|
kwargs['use_llm'] = True
|
|
else:
|
|
kwargs['no_llm'] = True
|
|
|
|
call_command('generate_persons', **kwargs)
|
|
ok_jobs += 1
|
|
except Exception as exc:
|
|
self.message_user(
|
|
request,
|
|
f'Job id={job.pk} icin uretim hatasi: {exc}',
|
|
level=messages.ERROR,
|
|
)
|
|
|
|
mode = 'LLM (fallback ile)' if use_llm else 'Istatistiksel'
|
|
self.message_user(
|
|
request,
|
|
f'Uretim tamamlandi. Mod: {mode}. Basarili job: {ok_jobs}/{total_jobs}. Her job icin {count} kayit.',
|
|
level=messages.SUCCESS,
|
|
)
|
|
|
|
@admin.action(description='Secili job(lar) icin 100 kisi uret (Istatistiksel)')
|
|
def generate_100_statistical_action(self, request, queryset):
|
|
self._run_generate_persons(request, queryset, count=100, use_llm=False)
|
|
|
|
@admin.action(description='Secili job(lar) icin 100 kisi uret (LLM + fallback)')
|
|
def generate_100_llm_action(self, request, queryset):
|
|
self._run_generate_persons(request, queryset, count=100, use_llm=True)
|
|
|
|
@admin.action(description='Secili job(lar) icin 1000 kisi uret (Istatistiksel)')
|
|
def generate_1000_statistical_action(self, request, queryset):
|
|
self._run_generate_persons(request, queryset, count=1000, use_llm=False)
|
|
|
|
@admin.action(description='Secili job(lar) icin 1000 kisi uret (LLM + fallback)')
|
|
def generate_1000_llm_action(self, request, queryset):
|
|
self._run_generate_persons(request, queryset, count=1000, use_llm=True)
|
|
|
|
|
|
@admin.register(NameVocab)
|
|
class NameVocabAdmin(admin.ModelAdmin):
|
|
list_display = ('name', 'name_type', 'gender', 'origin', 'frequency')
|
|
list_filter = ('origin', 'name_type', 'gender')
|
|
search_fields = ('name',)
|
|
ordering = ('origin', '-frequency')
|
|
|
|
|
|
@admin.register(GeneratedPerson)
|
|
class GeneratedPersonAdmin(admin.ModelAdmin):
|
|
list_display = (
|
|
'first_name', 'last_name', 'username', 'username_locked',
|
|
'birth_date', 'gender', 'confidence', 'generated_at', 'username_ops'
|
|
)
|
|
list_filter = ('gender', 'username_locked', 'generated_at')
|
|
search_fields = ('first_name', 'last_name', 'username')
|
|
readonly_fields = ('generated_at',)
|
|
actions = ('regenerate_username_action', 'lock_username_action', 'unlock_username_action')
|
|
|
|
def get_urls(self):
|
|
urls = super().get_urls()
|
|
custom_urls = [
|
|
path(
|
|
'<int:person_id>/regenerate-username/',
|
|
self.admin_site.admin_view(self.regenerate_username_view),
|
|
name='namecreate_generatedperson_regenerate_username',
|
|
),
|
|
path(
|
|
'<int:person_id>/toggle-username-lock/',
|
|
self.admin_site.admin_view(self.toggle_username_lock_view),
|
|
name='namecreate_generatedperson_toggle_username_lock',
|
|
),
|
|
]
|
|
return custom_urls + urls
|
|
|
|
def regenerate_username_view(self, request, person_id):
|
|
person = self.get_object(request, person_id)
|
|
if person is None:
|
|
self.message_user(request, 'Kayit bulunamadi.', level=messages.ERROR)
|
|
return HttpResponseRedirect('../')
|
|
|
|
if person.username_locked:
|
|
self.message_user(request, 'Username kilitli. Once kilidi acin.', level=messages.WARNING)
|
|
return HttpResponseRedirect('../../')
|
|
|
|
old_username = person.username
|
|
person.regenerate_username(save=True)
|
|
self.message_user(
|
|
request,
|
|
f'Username guncellendi: {old_username} -> {person.username}',
|
|
level=messages.SUCCESS,
|
|
)
|
|
return HttpResponseRedirect('../../')
|
|
|
|
def toggle_username_lock_view(self, request, person_id):
|
|
person = self.get_object(request, person_id)
|
|
if person is None:
|
|
self.message_user(request, 'Kayit bulunamadi.', level=messages.ERROR)
|
|
return HttpResponseRedirect('../')
|
|
|
|
person.username_locked = not person.username_locked
|
|
person.save(update_fields=['username_locked'])
|
|
state = 'kilitlendi' if person.username_locked else 'kilidi acildi'
|
|
self.message_user(request, f'Username {state}.', level=messages.SUCCESS)
|
|
return HttpResponseRedirect('../../')
|
|
|
|
def username_ops(self, obj):
|
|
regen_url = reverse('admin:namecreate_generatedperson_regenerate_username', args=[obj.pk])
|
|
lock_url = reverse('admin:namecreate_generatedperson_toggle_username_lock', args=[obj.pk])
|
|
lock_label = 'Kilidi ac' if obj.username_locked else 'Kilitle'
|
|
return format_html(
|
|
'<a class="button" href="{}">Yeniden uret</a> '
|
|
'<a class="button" href="{}">{}</a>',
|
|
regen_url,
|
|
lock_url,
|
|
lock_label,
|
|
)
|
|
|
|
username_ops.short_description = 'Islemler'
|
|
|
|
@admin.action(description='Secili kayitlarda username yeniden uret')
|
|
def regenerate_username_action(self, request, queryset):
|
|
used_usernames = set(
|
|
GeneratedPerson.objects.exclude(username='').values_list('username', flat=True)
|
|
)
|
|
updated = 0
|
|
skipped = 0
|
|
for person in queryset:
|
|
if person.username_locked:
|
|
skipped += 1
|
|
continue
|
|
|
|
used_usernames.discard(person.username)
|
|
person.regenerate_username(used_usernames=used_usernames, force=True, save=True)
|
|
updated += 1
|
|
|
|
self.message_user(
|
|
request,
|
|
f'{updated} kayitta username yeniden uretildi. Kilitli oldugu icin atlanan: {skipped}.'
|
|
)
|
|
|
|
@admin.action(description='Secili kayitlarda username kilitle')
|
|
def lock_username_action(self, request, queryset):
|
|
count = queryset.update(username_locked=True)
|
|
self.message_user(request, f'{count} kayitta username kilitlendi.')
|
|
|
|
@admin.action(description='Secili kayitlarda username kilidini ac')
|
|
def unlock_username_action(self, request, queryset):
|
|
count = queryset.update(username_locked=False)
|
|
self.message_user(request, f'{count} kayitta username kilidi acildi.')
|