Add model capabilities field

- Added capabilities TEXT column to models table
- Updated admin interface to show and edit model capabilities
- Default model has 'video to text, image to text' capabilities
- Added Capabilities column to models table
parent b14de81a
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>Type</th> <th>Type</th>
<th>Path</th> <th>Capabilities</th>
<th>VRAM (GB)</th> <th>VRAM (GB)</th>
<th>Status</th> <th>Status</th>
<th>Created</th> <th>Created</th>
...@@ -70,12 +70,12 @@ ...@@ -70,12 +70,12 @@
<tr> <tr>
<td>{{ model.get('name', 'N/A') }}</td> <td>{{ model.get('name', 'N/A') }}</td>
<td>{{ model.get('type', 'N/A').title() }}</td> <td>{{ model.get('type', 'N/A').title() }}</td>
<td>{{ model.get('path', 'N/A') }}</td> <td>{{ model.get('capabilities', 'N/A') or 'N/A' }}</td>
<td>{{ model.get('vram_estimate', 0) }}</td> <td>{{ model.get('vram_estimate', 0) }}</td>
<td><span class="status-{{ 'active' if model.get('available') else 'inactive' }}">{{ 'Available' if model.get('available') else 'Hidden' }}</span></td> <td><span class="status-{{ 'active' if model.get('available') else 'inactive' }}">{{ 'Available' if model.get('available') else 'Hidden' }}</span></td>
<td>{{ model.get('created_at', 'N/A')[:10] if model.get('created_at') else 'N/A' }}</td> <td>{{ model.get('created_at', 'N/A')[:10] if model.get('created_at') else 'N/A' }}</td>
<td class="actions-cell"> <td class="actions-cell">
<button onclick="editModel({{ model.get('id') }}, '{{ model.get('name') }}', '{{ model.get('type') }}', '{{ model.get('path') }}', {{ model.get('vram_estimate', 0) }}, {{ model.get('available')|lower }})" class="btn-icon" title="Edit"><i class="fas fa-edit"></i></button> <button onclick="editModel({{ model.get('id') }}, '{{ model.get('name') }}', '{{ model.get('type') }}', '{{ model.get('path') }}', {{ model.get('vram_estimate', 0) }}, {{ model.get('available')|lower }}, '{{ model.get('capabilities', '')|replace("'", "\\'") }}')" class="btn-icon" title="Edit"><i class="fas fa-edit"></i></button>
<button onclick="deleteModel({{ model.get('id') }}, '{{ model.get('name') }}')" class="btn-icon" title="Delete" style="color: #dc2626;"><i class="fas fa-trash"></i></button> <button onclick="deleteModel({{ model.get('id') }}, '{{ model.get('name') }}')" class="btn-icon" title="Delete" style="color: #dc2626;"><i class="fas fa-trash"></i></button>
</td> </td>
</tr> </tr>
...@@ -108,6 +108,11 @@ ...@@ -108,6 +108,11 @@
<input type="text" id="path" name="path" required placeholder="e.g., /path/to/model or Qwen/Qwen2.5-VL-7B-Instruct"> <input type="text" id="path" name="path" required placeholder="e.g., /path/to/model or Qwen/Qwen2.5-VL-7B-Instruct">
</div> </div>
<div class="form-group">
<label for="capabilities">Capabilities</label>
<input type="text" id="capabilities" name="capabilities" placeholder="e.g., video to text, image to text, audio to text">
</div>
<div class="form-group"> <div class="form-group">
<label for="vram_estimate">VRAM Estimate (GB)</label> <label for="vram_estimate">VRAM Estimate (GB)</label>
<input type="number" id="vram_estimate" name="vram_estimate" value="0" min="0" step="0.1"> <input type="number" id="vram_estimate" name="vram_estimate" value="0" min="0" step="0.1">
...@@ -151,6 +156,10 @@ ...@@ -151,6 +156,10 @@
<label for="editPath">Path/Model ID</label> <label for="editPath">Path/Model ID</label>
<input type="text" id="editPath" name="path" required> <input type="text" id="editPath" name="path" required>
</div> </div>
<div class="form-group">
<label for="editCapabilities">Capabilities</label>
<input type="text" id="editCapabilities" name="capabilities" placeholder="e.g., video to text, image to text, audio to text">
</div>
<div class="form-group"> <div class="form-group">
<label for="editVram">VRAM Estimate (GB)</label> <label for="editVram">VRAM Estimate (GB)</label>
<input type="number" id="editVram" name="vram_estimate" min="0" step="0.1" required> <input type="number" id="editVram" name="vram_estimate" min="0" step="0.1" required>
...@@ -171,13 +180,14 @@ ...@@ -171,13 +180,14 @@
</div> </div>
<script> <script>
function editModel(id, name, type, path, vram, available) { function editModel(id, name, type, path, vram, available, capabilities) {
document.getElementById('editModelId').value = id; document.getElementById('editModelId').value = id;
document.getElementById('editName').value = name; document.getElementById('editName').value = name;
document.getElementById('editType').value = type; document.getElementById('editType').value = type;
document.getElementById('editPath').value = path; document.getElementById('editPath').value = path;
document.getElementById('editVram').value = vram; document.getElementById('editVram').value = vram;
document.getElementById('editAvailable').checked = available; document.getElementById('editAvailable').checked = available;
document.getElementById('editCapabilities').value = capabilities;
document.getElementById('editModelForm').action = `/admin/models/${id}/update`; document.getElementById('editModelForm').action = `/admin/models/${id}/update`;
document.getElementById('editModelModal').classList.add('show'); document.getElementById('editModelModal').classList.add('show');
document.body.style.overflow = 'hidden'; document.body.style.overflow = 'hidden';
......
...@@ -500,6 +500,7 @@ def add_model(): ...@@ -500,6 +500,7 @@ def add_model():
path = request.form.get('path', '').strip() path = request.form.get('path', '').strip()
vram_estimate = int(request.form.get('vram_estimate', 0)) vram_estimate = int(request.form.get('vram_estimate', 0))
available = request.form.get('available') == 'on' available = request.form.get('available') == 'on'
capabilities = request.form.get('capabilities', '').strip()
if not name or not model_type or not path: if not name or not model_type or not path:
flash('All fields are required', 'error') flash('All fields are required', 'error')
...@@ -524,7 +525,7 @@ def add_model(): ...@@ -524,7 +525,7 @@ def add_model():
flash(f'Error downloading model: {str(e)}', 'error') flash(f'Error downloading model: {str(e)}', 'error')
return redirect(url_for('admin.models')) return redirect(url_for('admin.models'))
if create_model(name, model_type, path, vram_estimate, available): if create_model(name, model_type, path, vram_estimate, available, capabilities):
flash('Model added successfully!', 'success') flash('Model added successfully!', 'success')
else: else:
flash('Failed to add model', 'error') flash('Failed to add model', 'error')
...@@ -539,6 +540,7 @@ def update_model_route(model_id): ...@@ -539,6 +540,7 @@ def update_model_route(model_id):
path = request.form.get('path', '').strip() path = request.form.get('path', '').strip()
vram_estimate = int(request.form.get('vram_estimate', 0)) vram_estimate = int(request.form.get('vram_estimate', 0))
available = request.form.get('available') == 'on' available = request.form.get('available') == 'on'
capabilities = request.form.get('capabilities', '').strip()
if not name or not model_type or not path: if not name or not model_type or not path:
flash('All fields are required', 'error') flash('All fields are required', 'error')
...@@ -548,7 +550,7 @@ def update_model_route(model_id): ...@@ -548,7 +550,7 @@ def update_model_route(model_id):
flash('Invalid model type', 'error') flash('Invalid model type', 'error')
return redirect(url_for('admin.models')) return redirect(url_for('admin.models'))
if update_model(model_id, name=name, model_type=model_type, path=path, vram_estimate=vram_estimate, available=available): if update_model(model_id, name=name, model_type=model_type, path=path, vram_estimate=vram_estimate, available=available, capabilities=capabilities):
flash('Model updated successfully!', 'success') flash('Model updated successfully!', 'success')
else: else:
flash('Failed to update model', 'error') flash('Failed to update model', 'error')
......
...@@ -543,6 +543,7 @@ def init_db(conn) -> None: ...@@ -543,6 +543,7 @@ def init_db(conn) -> None:
path TEXT NOT NULL UNIQUE, path TEXT NOT NULL UNIQUE,
vram_estimate INT DEFAULT 0, vram_estimate INT DEFAULT 0,
available BOOLEAN DEFAULT 0, available BOOLEAN DEFAULT 0,
capabilities TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
...@@ -556,6 +557,7 @@ def init_db(conn) -> None: ...@@ -556,6 +557,7 @@ def init_db(conn) -> None:
path TEXT NOT NULL UNIQUE, path TEXT NOT NULL UNIQUE,
vram_estimate INTEGER DEFAULT 0, vram_estimate INTEGER DEFAULT 0,
available BOOLEAN DEFAULT 0, available BOOLEAN DEFAULT 0,
capabilities TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) )
...@@ -571,6 +573,16 @@ def init_db(conn) -> None: ...@@ -571,6 +573,16 @@ def init_db(conn) -> None:
# Column might already exist # Column might already exist
pass pass
# Add capabilities column if it doesn't exist
try:
if config['type'] == 'mysql':
cursor.execute('ALTER TABLE models ADD COLUMN capabilities TEXT')
else:
cursor.execute('ALTER TABLE models ADD COLUMN capabilities TEXT')
except:
# Column might already exist
pass
# Clean up duplicate models (keep only the first one for each path) # Clean up duplicate models (keep only the first one for each path)
if config['type'] == 'mysql': if config['type'] == 'mysql':
cursor.execute(''' cursor.execute('''
...@@ -592,8 +604,8 @@ def init_db(conn) -> None: ...@@ -592,8 +604,8 @@ def init_db(conn) -> None:
default_model_name = 'Qwen/Qwen2.5-VL-7B-Instruct' default_model_name = 'Qwen/Qwen2.5-VL-7B-Instruct'
cursor.execute('SELECT id FROM models WHERE path = ?', (default_model_name,)) cursor.execute('SELECT id FROM models WHERE path = ?', (default_model_name,))
if not cursor.fetchone(): if not cursor.fetchone():
cursor.execute('INSERT INTO models (name, type, path, vram_estimate, available) VALUES (?, ?, ?, ?, ?)', cursor.execute('INSERT INTO models (name, type, path, vram_estimate, available, capabilities) VALUES (?, ?, ?, ?, ?, ?)',
('Qwen 2.5 VL 7B Instruct', 'huggingface', default_model_name, 16, 1)) ('Qwen 2.5 VL 7B Instruct', 'huggingface', default_model_name, 16, 1, 'video to text, image to text'))
# Add data column to sessions table if it doesn't exist # Add data column to sessions table if it doesn't exist
try: try:
...@@ -1920,13 +1932,13 @@ def get_available_models() -> List[Dict[str, Any]]: ...@@ -1920,13 +1932,13 @@ def get_available_models() -> List[Dict[str, Any]]:
return [dict(row) for row in rows] return [dict(row) for row in rows]
def create_model(name: str, model_type: str, path: str, vram_estimate: int = 0, available: bool = False) -> bool: def create_model(name: str, model_type: str, path: str, vram_estimate: int = 0, available: bool = False, capabilities: str = '') -> bool:
"""Create a new model.""" """Create a new model."""
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
try: try:
cursor.execute('INSERT INTO models (name, type, path, vram_estimate, available) VALUES (?, ?, ?, ?, ?)', cursor.execute('INSERT INTO models (name, type, path, vram_estimate, available, capabilities) VALUES (?, ?, ?, ?, ?, ?)',
(name, model_type, path, vram_estimate, 1 if available else 0)) (name, model_type, path, vram_estimate, 1 if available else 0, capabilities))
conn.commit() conn.commit()
return True return True
except sqlite3.IntegrityError: except sqlite3.IntegrityError:
...@@ -1935,7 +1947,7 @@ def create_model(name: str, model_type: str, path: str, vram_estimate: int = 0, ...@@ -1935,7 +1947,7 @@ def create_model(name: str, model_type: str, path: str, vram_estimate: int = 0,
conn.close() conn.close()
def update_model(model_id: int, name: str = None, model_type: str = None, path: str = None, vram_estimate: int = None, available: bool = None) -> bool: def update_model(model_id: int, name: str = None, model_type: str = None, path: str = None, vram_estimate: int = None, available: bool = None, capabilities: str = None) -> bool:
"""Update a model.""" """Update a model."""
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
...@@ -1958,6 +1970,9 @@ def update_model(model_id: int, name: str = None, model_type: str = None, path: ...@@ -1958,6 +1970,9 @@ def update_model(model_id: int, name: str = None, model_type: str = None, path:
if available is not None: if available is not None:
update_fields.append('available = ?') update_fields.append('available = ?')
params.append(1 if available else 0) params.append(1 if available else 0)
if capabilities is not None:
update_fields.append('capabilities = ?')
params.append(capabilities)
if not update_fields: if not update_fields:
return False return False
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment