Added models and admin for agents
This commit is contained in:
parent
44ad993b55
commit
3a680c76d4
7 changed files with 249 additions and 0 deletions
0
apps/mlstore/__init__.py
Normal file
0
apps/mlstore/__init__.py
Normal file
57
apps/mlstore/admin.py
Normal file
57
apps/mlstore/admin.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
from django.contrib import admin
|
||||
from django.contrib.admin import ModelAdmin, TabularInline
|
||||
from apps.mlstore.models import AgentModel, AgentRun, Agent, AgentEvent
|
||||
|
||||
|
||||
class AgentInline(TabularInline):
|
||||
model = Agent
|
||||
extra = 0
|
||||
raw_id_fields = ('model',)
|
||||
|
||||
|
||||
class AgentRunInline(TabularInline):
|
||||
model = AgentRun
|
||||
extra = 0
|
||||
raw_id_fields = ('agent', 'user')
|
||||
|
||||
|
||||
class AgentEventInline(TabularInline):
|
||||
model = AgentEvent
|
||||
extra = 0
|
||||
raw_id_fields = ('execution',)
|
||||
|
||||
|
||||
@admin.register(AgentModel)
|
||||
class AgentModelAdmin(ModelAdmin):
|
||||
list_display = ('id', 'uuid', 'name', 'version')
|
||||
search_fields = ('name', 'version')
|
||||
inlines = (AgentInline,)
|
||||
readonly_fields = ('uuid',)
|
||||
|
||||
|
||||
@admin.register(Agent)
|
||||
class AgentAdmin(ModelAdmin):
|
||||
list_display = ('id', 'uuid', 'model', 'status', 'started_at', 'completed_at')
|
||||
search_fields = ('model__name', 'uuid')
|
||||
list_filter = ('status',)
|
||||
inlines = (AgentRunInline,)
|
||||
raw_id_fields = ('model',)
|
||||
readonly_fields = ('uuid', 'started_at', 'completed_at')
|
||||
|
||||
|
||||
@admin.register(AgentRun)
|
||||
class AgentRunAdmin(ModelAdmin):
|
||||
list_display = ('id', 'uuid', 'agent', 'user', 'status', 'started_at', 'completed_at')
|
||||
search_fields = ('uuid', 'agent__model__name', 'user__email_address')
|
||||
list_filter = ('status',)
|
||||
inlines = (AgentEventInline,)
|
||||
raw_id_fields = ('agent', 'user')
|
||||
readonly_fields = ('uuid', 'started_at', 'completed_at')
|
||||
|
||||
|
||||
@admin.register(AgentEvent)
|
||||
class AgentEventAdmin(ModelAdmin):
|
||||
list_display = ('id', 'event_type', 'execution', 'timestamp')
|
||||
search_fields = ('event_type', 'execution__uuid', 'execution__agent__model__name')
|
||||
list_filter = ('event_type',)
|
||||
raw_id_fields = ('execution',)
|
||||
6
apps/mlstore/apps.py
Normal file
6
apps/mlstore/apps.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MlstoreConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'apps.mlstore'
|
||||
86
apps/mlstore/migrations/0001_initial.py
Normal file
86
apps/mlstore/migrations/0001_initial.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# Generated by Django 5.2.10 on 2026-01-17 16:12
|
||||
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AgentModel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(primary_key=True, serialize=False)),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
||||
('name', models.CharField(max_length=255)),
|
||||
('version', models.CharField(max_length=50)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Model',
|
||||
'verbose_name_plural': 'Models',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Agent',
|
||||
fields=[
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
|
||||
('id', models.BigAutoField(primary_key=True, serialize=False)),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
||||
('status', models.CharField(choices=[('idle', 'Idle'), ('running', 'Running'), ('paused', 'Paused'), ('completed', 'Completed'), ('failed', 'Failed')], default='idle', max_length=20)),
|
||||
('description', models.TextField(blank=True, default='')),
|
||||
('started_at', models.DateTimeField(blank=True, null=True)),
|
||||
('completed_at', models.DateTimeField(blank=True, null=True)),
|
||||
('model', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='agents', to='mlstore.agentmodel')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Agent Instance',
|
||||
'verbose_name_plural': 'Agent Instances',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AgentRun',
|
||||
fields=[
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
|
||||
('id', models.BigAutoField(primary_key=True, serialize=False)),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
||||
('status', models.CharField(choices=[('queued', 'Queued'), ('running', 'Running'), ('completed', 'Completed'), ('failed', 'Failed')], default='queued', max_length=20)),
|
||||
('input_data', models.JSONField(default=dict)),
|
||||
('output_data', models.JSONField(blank=True, default=dict)),
|
||||
('error_message', models.TextField(blank=True, default='')),
|
||||
('started_at', models.DateTimeField(blank=True, null=True)),
|
||||
('completed_at', models.DateTimeField(blank=True, null=True)),
|
||||
('agent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='runs', to='mlstore.agent')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='agent_runs', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Agent Run',
|
||||
'verbose_name_plural': 'Agent Runs',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AgentEvent',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
||||
('event_type', models.CharField(choices=[('started', 'Started'), ('message', 'Message'), ('progress', 'Progress'), ('completed', 'Completed'), ('error', 'Error'), ('step', 'Step')], max_length=20)),
|
||||
('content', models.JSONField()),
|
||||
('timestamp', models.DateTimeField(auto_now_add=True)),
|
||||
('execution', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='events', to='mlstore.agentrun')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Agent Event',
|
||||
'verbose_name_plural': 'Agent Events',
|
||||
'ordering': ['timestamp'],
|
||||
},
|
||||
),
|
||||
]
|
||||
0
apps/mlstore/migrations/__init__.py
Normal file
0
apps/mlstore/migrations/__init__.py
Normal file
99
apps/mlstore/models.py
Normal file
99
apps/mlstore/models.py
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
from django.db.models import BigAutoField, CASCADE, CharField, DateTimeField, ForeignKey, JSONField, Model, TextField, UUIDField
|
||||
from apps.users.mixins import TimeStampMixin
|
||||
from apps.users.models import User
|
||||
from uuid import uuid4
|
||||
|
||||
class AgentModel(Model):
|
||||
|
||||
id = BigAutoField(primary_key=True)
|
||||
uuid = UUIDField(default=uuid4, unique=True, editable=False)
|
||||
name = CharField(max_length=255)
|
||||
version = CharField(max_length=50)
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'Model'
|
||||
verbose_name_plural = 'Models'
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Agent(TimeStampMixin, Model):
|
||||
|
||||
STATUS_CHOICES = [
|
||||
('idle', 'Idle'),
|
||||
('running', 'Running'),
|
||||
('paused', 'Paused'),
|
||||
('completed', 'Completed'),
|
||||
('failed', 'Failed'),
|
||||
]
|
||||
|
||||
id = BigAutoField(primary_key = True)
|
||||
uuid = UUIDField(default = uuid4, unique = True, editable = False)
|
||||
|
||||
model = ForeignKey(AgentModel, on_delete = CASCADE, related_name='agents')
|
||||
status = CharField(max_length=20, choices=STATUS_CHOICES, default='idle')
|
||||
|
||||
description = TextField(blank=True, default='')
|
||||
|
||||
started_at = DateTimeField(null=True, blank=True)
|
||||
completed_at = DateTimeField(null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'Agent Instance'
|
||||
verbose_name_plural = 'Agent Instances'
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.model.name} - {self.uuid}'
|
||||
|
||||
class AgentRun(TimeStampMixin, Model):
|
||||
|
||||
RUN_CHOICES = [
|
||||
('queued', 'Queued'),
|
||||
('running', 'Running'),
|
||||
('completed', 'Completed'),
|
||||
('failed', 'Failed'),
|
||||
]
|
||||
|
||||
id = BigAutoField(primary_key=True)
|
||||
uuid = UUIDField(default=uuid4, editable=False, unique=True)
|
||||
agent = ForeignKey(Agent, on_delete=CASCADE, related_name='runs')
|
||||
user = ForeignKey(User, on_delete=CASCADE, related_name='agent_runs')
|
||||
status = CharField(max_length=20, choices=RUN_CHOICES, default='queued')
|
||||
|
||||
input_data = JSONField(default=dict)
|
||||
output_data = JSONField(default=dict, blank=True)
|
||||
error_message = TextField(blank=True, default="")
|
||||
started_at = DateTimeField(null=True, blank=True)
|
||||
completed_at = DateTimeField(null=True, blank=True)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Execution {self.uuid} - {self.agent.name} ({self.status})"
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Agent Run"
|
||||
verbose_name_plural = "Agent Runs"
|
||||
|
||||
class AgentEvent(Model):
|
||||
EVENT_TYPES = [
|
||||
('started', 'Started'),
|
||||
('message', 'Message'),
|
||||
('progress', 'Progress'),
|
||||
('completed', 'Completed'),
|
||||
('error', 'Error'),
|
||||
('step', 'Step'),
|
||||
]
|
||||
|
||||
uuid = UUIDField(default = uuid4, editable=False, unique=True)
|
||||
execution = ForeignKey(AgentRun, on_delete=CASCADE, related_name='events')
|
||||
event_type = CharField(max_length=20, choices=EVENT_TYPES)
|
||||
|
||||
content = JSONField()
|
||||
timestamp = DateTimeField(auto_now_add=True)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.id} - {self.event_type} - {self.execution.agent.name}"
|
||||
|
||||
class Meta:
|
||||
ordering = ['timestamp']
|
||||
verbose_name = "Agent Event"
|
||||
verbose_name_plural = "Agent Events"
|
||||
|
|
@ -66,6 +66,7 @@ THIRD_PARTY_APPS = [
|
|||
LOCAL_APPS = [
|
||||
'apps.users',
|
||||
'apps.orgs',
|
||||
'apps.mlstore',
|
||||
]
|
||||
INSTALLED_APPS = OVERRIDE_APPS + DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue