Add vision model support to LLM Manager admin and rename index for clarity
This commit is contained in:
@@ -166,6 +166,8 @@ Titania provides TLS termination and reverse proxy for all services.
|
||||
| `peitho.ouranos.helu.ca` | puck.incus:22981 | Peitho (Django) |
|
||||
| `pgadmin.ouranos.helu.ca` | prospero.incus:443 (SSL) | PgAdmin 4 |
|
||||
| `prometheus.ouranos.helu.ca` | prospero.incus:443 (SSL) | Prometheus |
|
||||
| `freecad-mcp.ouranos.helu.ca` | caliban.incus:22032 | FreeCAD Robust MCP Server |
|
||||
| `rommie.ouranos.helu.ca` | caliban.incus:22031 | Rommie MCP Server (Agent S GUI automation) |
|
||||
| `searxng.ouranos.helu.ca` | oberon.incus:22073 | SearXNG (OAuth2-Proxy) |
|
||||
| `smtp4dev.ouranos.helu.ca` | oberon.incus:22085 | smtp4dev |
|
||||
| `spelunker.ouranos.helu.ca` | puck.incus:22881 | Spelunker (Django) |
|
||||
|
||||
@@ -100,6 +100,7 @@ class LLMModelAdmin(admin.ModelAdmin):
|
||||
"system_embedding_badge",
|
||||
"system_chat_badge",
|
||||
"system_reranker_badge",
|
||||
"system_vision_badge",
|
||||
"is_active",
|
||||
"created_at",
|
||||
)
|
||||
@@ -113,6 +114,7 @@ class LLMModelAdmin(admin.ModelAdmin):
|
||||
"is_system_embedding_model",
|
||||
"is_system_chat_model",
|
||||
"is_system_reranker_model",
|
||||
"is_system_vision_model",
|
||||
)
|
||||
search_fields = ("name", "display_name", "api__name")
|
||||
readonly_fields = (
|
||||
@@ -121,11 +123,13 @@ class LLMModelAdmin(admin.ModelAdmin):
|
||||
"is_system_embedding_model",
|
||||
"is_system_chat_model",
|
||||
"is_system_reranker_model",
|
||||
"is_system_vision_model",
|
||||
)
|
||||
actions = [
|
||||
"set_as_system_embedding_model",
|
||||
"set_as_system_chat_model",
|
||||
"set_as_system_reranker_model",
|
||||
"set_as_system_vision_model",
|
||||
]
|
||||
fieldsets = (
|
||||
("Model Info", {"fields": ("api", "name", "display_name", "model_type", "is_active")}),
|
||||
@@ -136,6 +140,7 @@ class LLMModelAdmin(admin.ModelAdmin):
|
||||
"is_system_embedding_model",
|
||||
"is_system_chat_model",
|
||||
"is_system_reranker_model",
|
||||
"is_system_vision_model",
|
||||
),
|
||||
"classes": ("collapse",),
|
||||
"description": (
|
||||
@@ -208,6 +213,16 @@ class LLMModelAdmin(admin.ModelAdmin):
|
||||
|
||||
system_reranker_badge.short_description = "Reranker Default"
|
||||
|
||||
def system_vision_badge(self, obj):
|
||||
if obj.is_system_vision_model and obj.model_type in ("vision", "chat"):
|
||||
return format_html(
|
||||
'<span style="background:#6f42c1;color:white;padding:3px 8px;'
|
||||
'border-radius:3px;font-weight:bold;">SYSTEM DEFAULT</span>'
|
||||
)
|
||||
return ""
|
||||
|
||||
system_vision_badge.short_description = "Vision Default"
|
||||
|
||||
# --- System model actions -----------------------------------------------
|
||||
|
||||
def _set_system_model(self, request, queryset, model_type, field_name, label):
|
||||
@@ -225,6 +240,8 @@ class LLMModelAdmin(admin.ModelAdmin):
|
||||
valid_types = [model_type]
|
||||
if model_type == "embedding":
|
||||
valid_types = ["embedding", "multimodal_embed"]
|
||||
elif model_type == "vision":
|
||||
valid_types = ["vision", "chat"]
|
||||
|
||||
if new_model.model_type not in valid_types:
|
||||
self.message_user(
|
||||
@@ -269,6 +286,11 @@ class LLMModelAdmin(admin.ModelAdmin):
|
||||
|
||||
set_as_system_reranker_model.short_description = "Set as System Reranker Model"
|
||||
|
||||
def set_as_system_vision_model(self, request, queryset):
|
||||
self._set_system_model(request, queryset, "vision", "is_system_vision_model", "vision model")
|
||||
|
||||
set_as_system_vision_model.short_description = "Set as System Vision Model"
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
"""Ensure only ONE model per type is marked as system default."""
|
||||
type_field_map = {
|
||||
@@ -276,6 +298,7 @@ class LLMModelAdmin(admin.ModelAdmin):
|
||||
"multimodal_embed": "is_system_embedding_model",
|
||||
"chat": "is_system_chat_model",
|
||||
"reranker": "is_system_reranker_model",
|
||||
"vision": "is_system_vision_model",
|
||||
}
|
||||
for mtype, field in type_field_map.items():
|
||||
if getattr(obj, field, False) and obj.model_type == mtype:
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.2.11 on 2026-03-22 15:15
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("llm_manager", "0003_add_vision_model_and_usage"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameIndex(
|
||||
model_name="llmmodel",
|
||||
new_name="llm_manager_is_syst_d190bb_idx",
|
||||
old_name="llm_manager__is_syst_b2f4e7_idx",
|
||||
),
|
||||
]
|
||||
Reference in New Issue
Block a user