diff --git a/.eslintrc.json b/.eslintrc.json
index 38bcae860..32283e620 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -108,8 +108,8 @@
"getExif": "readonly",
"jobStatusEl": "readonly",
"removeSplash": "readonly",
- "initNVML": "readonly",
- "startNVML": "readonly",
+ "initGPU": "readonly",
+ "startGPU": "readonly",
"disableNVML": "readonly",
"idbGet": "readonly",
"idbPut": "readonly",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40ae34f9e..5c535695b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,7 @@
### Highlights for 2025-08-07
Several new models: [Qwen-Image](https://qwenlm.github.io/blog/qwen-image/), [FLUX.1-Krea-Dev](https://www.krea.ai/blog/flux-krea-open-source-release), [Chroma](https://huggingface.co/lodestones/Chroma), [SkyReels-V2](https://huggingface.co/Skywork/SkyReels-V2-DF-14B-720P-Diffusers)
-Plus continuing with major **UI** work, there is new embedded **Docs/Wiki** search, redesigned real-time **hints**, **CivitAI** integration and more!
+Plus continuing with major **UI** work, there is new embedded **Docs/Wiki** search, redesigned real-time **hints**, built-in **GPU monitor**, **CivitAI** integration and more!
On the compute side, new profiles for high-vram GPUs and offloading improvements
And (*as always*) many bugfixes and improvements to existing features!
@@ -43,16 +43,22 @@ And (*as always*) many bugfixes and improvements to existing features!
**Docs** search: fully-local and works in real-time on all document pages
**Wiki** search: uses github api to search online wiki pages
- updated real-time hints, thanks @CalamitousFelicitousness
- - rewritten **CivitAI downloader**
- in *models -> civitai*
+ - every heading element is collapsible!
- quicksettings reset button to restore all quicksettings to default values
because things do sometimes get wrong...
- configurable image fit in all image views
- - updated *models -> current* tab
- - updated *models -> list models* tab
- - updated *models -> metadata* tab
+ - rewritten **CivitAI downloader**
+ in *models -> civitai*
+ - redesigned **GPU monitor**
+ - standard-ui: *system -> gpu monitor*
+ - modern-ui: *aside -> console -> gpu monitor*
+ - configurable interval in *settings -> user interface*
+ - updated *models* tab
+ - updated *models -> current* tab
+ - updated *models -> list models* tab
+ - updated *models -> metadata* tab
- updated *extensions* tab
- - redesign *settings -> user interface*
+ - redesigned *settings -> user interface*
- gallery bypass browser cache for thumbnails
- gallery safer delete operation
- networks display indicator for currently active items
@@ -78,7 +84,8 @@ And (*as always*) many bugfixes and improvements to existing features!
- **Nunchaku** support for *FLUX.1-Fill* and *FLUX.1-Depth* models
- update requirements/packages
- **Other**
- - remove LDSR
+ - **prompt enhance** add `allura-org/Gemma-3-Glitter-4B` model support
+ - remove **LDSR**
- remove `api-only` cli option
- **Fixes**
- refactor legacy processing loop
diff --git a/extensions-builtin/sdnext-modernui b/extensions-builtin/sdnext-modernui
index 874ff0e88..d26fde293 160000
--- a/extensions-builtin/sdnext-modernui
+++ b/extensions-builtin/sdnext-modernui
@@ -1 +1 @@
-Subproject commit 874ff0e88099703cde91ab3c5347a78d002aa3c6
+Subproject commit d26fde293e8a2632e2c08add6ea1f44e0e98fc1f
diff --git a/javascript/base.css b/javascript/base.css
index 75ca46f55..f6a7f7d09 100644
--- a/javascript/base.css
+++ b/javascript/base.css
@@ -114,7 +114,7 @@ table.settings-value-table td { padding: 0.4em; border: 1px solid #ccc; max-widt
/* custom component */
.folder-selector textarea { height: 2em !important; padding: 6px !important; }
-.nvml { position: fixed; bottom: 10px; right: 10px; background: var(--background-fill-primary); border: 1px solid var(--button-primary-border-color); padding: 6px; color: var(--button-primary-text-color);
+.gpu { position: fixed; bottom: 10px; right: 10px; background: var(--background-fill-primary); border: 1px solid var(--button-primary-border-color); padding: 6px; color: var(--button-primary-text-color);
font-size: 0.7em; z-index: 50; font-family: monospace; display: none; }
/* image browser */
diff --git a/javascript/contextMenus.js b/javascript/contextMenus.js
index 3dfa16b7e..96c57a231 100644
--- a/javascript/contextMenus.js
+++ b/javascript/contextMenus.js
@@ -149,7 +149,6 @@ async function initContextMenu() {
appendContextMenuOption(id, 'Generate forever', () => generateForever(`#${tab}_generate`));
appendContextMenuOption(id, 'Apply selected style', quickApplyStyle);
appendContextMenuOption(id, 'Quick save style', quickSaveStyle);
- appendContextMenuOption(id, 'nVidia overlay', startNVML);
id = `#${tab}_reprocess`;
appendContextMenuOption(id, 'Decode full quality', () => reprocessClick(`${tab}`, 'reprocess_decode'), true);
appendContextMenuOption(id, 'Refine & HiRes pass', () => reprocessClick(`${tab}`, 'reprocess_refine'), true);
diff --git a/javascript/gpu.js b/javascript/gpu.js
new file mode 100644
index 000000000..d95542f3d
--- /dev/null
+++ b/javascript/gpu.js
@@ -0,0 +1,75 @@
+let gpuInterval = null; // eslint-disable-line prefer-const
+const chartData = { mem: [], load: [] };
+
+async function updateGPUChart(mem, load) {
+ const maxLen = 120;
+ const colorRangeMap = $.range_map({ // eslint-disable-line no-undef
+ '0:5': '#fffafa',
+ '6:10': '#fff7ed',
+ '11:20': '#fed7aa',
+ '21:30': '#fdba74',
+ '31:40': '#fb923c',
+ '41:50': '#f97316',
+ '51:60': '#ea580c',
+ '61:70': '#c2410c',
+ '71:80': '#9a3412',
+ '81:90': '#7c2d12',
+ '91:100': '#6c2e12',
+ });
+ const sparklineConfigLOAD = { type: 'bar', height: '128px', barWidth: '3px', barSpacing: '1px', chartRangeMin: 0, chartRangeMax: 100, barColor: '#89007D' };
+ const sparklineConfigMEM = { type: 'bar', height: '128px', barWidth: '3px', barSpacing: '1px', chartRangeMin: 0, chartRangeMax: 100, colorMap: colorRangeMap, composite: true };
+ if (chartData.load.length > maxLen) chartData.load.shift();
+ chartData.load.push(load);
+ if (chartData.mem.length > maxLen) chartData.mem.shift();
+ chartData.mem.push(mem);
+ $('#gpuChart').sparkline(chartData.load, sparklineConfigLOAD); // eslint-disable-line no-undef
+ $('#gpuChart').sparkline(chartData.mem, sparklineConfigMEM); // eslint-disable-line no-undef
+}
+
+async function updateGPU() {
+ const gpuEl = document.getElementById('gpu');
+ const gpuTable = document.getElementById('gpu-table');
+ try {
+ const res = await fetch(`${window.api}/gpu`);
+ if (!res.ok) {
+ clearInterval(gpuInterval);
+ gpuEl.style.display = 'none';
+ return;
+ }
+ const data = await res.json();
+ if (!data) {
+ clearInterval(gpuInterval);
+ gpuEl.style.display = 'none';
+ return;
+ }
+ const gpuTbody = gpuTable.querySelector('tbody');
+ for (const gpu of data) {
+ console.log(gpu);
+ let rows = `
| GPU | ${gpu.name} |
`;
+ for (const item of Object.entries(gpu.data)) rows += `| ${item[0]} | ${item[1]} |
`;
+ gpuTbody.innerHTML = rows;
+ if (gpu.chart && gpu.chart.length === 2) updateGPUChart(gpu.chart);
+ }
+ gpuEl.style.display = 'block';
+ } catch (e) {
+ error('updateGPU', e);
+ clearInterval(gpuInterval);
+ gpuEl.style.display = 'none';
+ }
+}
+
+async function startGPU() {
+ const gpuEl = document.getElementById('gpu');
+ gpuEl.style.display = 'block';
+ if (gpuInterval) clearInterval(gpuInterval);
+ const interval = window.opts?.gpu_monitor || 3000;
+ log('startGPU', interval);
+ gpuInterval = setInterval(updateGPU, interval);
+ updateGPU();
+}
+
+async function disableGPU() {
+ clearInterval(gpuInterval);
+ const gpuEl = document.getElementById('gpu');
+ gpuEl.style.display = 'none';
+}
diff --git a/javascript/nvml.js b/javascript/nvml.js
deleted file mode 100644
index 155dc3f89..000000000
--- a/javascript/nvml.js
+++ /dev/null
@@ -1,109 +0,0 @@
-let nvmlInterval = null; // eslint-disable-line prefer-const
-let nvmlEl = null;
-let nvmlTable = null;
-const chartData = { mem: [], load: [] };
-
-async function updateNVMLChart(mem, load) {
- const maxLen = 120;
- const colorRangeMap = $.range_map({ // eslint-disable-line no-undef
- '0:5': '#fffafa',
- '6:10': '#fff7ed',
- '11:20': '#fed7aa',
- '21:30': '#fdba74',
- '31:40': '#fb923c',
- '41:50': '#f97316',
- '51:60': '#ea580c',
- '61:70': '#c2410c',
- '71:80': '#9a3412',
- '81:90': '#7c2d12',
- '91:100': '#6c2e12',
- });
- const sparklineConfigLOAD = { type: 'bar', height: '100px', barWidth: '2px', barSpacing: '1px', chartRangeMin: 0, chartRangeMax: 100, barColor: '#89007D' };
- const sparklineConfigMEM = { type: 'bar', height: '100px', barWidth: '2px', barSpacing: '1px', chartRangeMin: 0, chartRangeMax: 100, colorMap: colorRangeMap, composite: true };
- if (chartData.load.length > maxLen) chartData.load.shift();
- chartData.load.push(load);
- if (chartData.mem.length > maxLen) chartData.mem.shift();
- chartData.mem.push(mem);
- $('#nvmlChart').sparkline(chartData.load, sparklineConfigLOAD); // eslint-disable-line no-undef
- $('#nvmlChart').sparkline(chartData.mem, sparklineConfigMEM); // eslint-disable-line no-undef
-}
-
-async function updateNVML() {
- try {
- const res = await fetch(`${window.api}/nvml`);
- if (!res.ok) {
- clearInterval(nvmlInterval);
- nvmlEl.style.display = 'none';
- return;
- }
- const data = await res.json();
- if (!data) {
- clearInterval(nvmlInterval);
- nvmlEl.style.display = 'none';
- return;
- }
- const nvmlTbody = nvmlTable.querySelector('tbody');
- for (const gpu of data) {
- const rows = `
- | GPU | ${gpu.name} |
- | Driver | ${gpu.version.driver} |
- | VBIOS | ${gpu.version.vbios} |
- | ROM | ${gpu.version.rom} |
- | Driver | ${gpu.version.driver} |
- | PCI | Gen.${gpu.pci.link} x${gpu.pci.width} |
- | Memory | ${gpu.memory.used}Mb / ${gpu.memory.total}Mb |
- | Clock | ${gpu.clock.gpu[0]}Mhz / ${gpu.clock.gpu[1]}Mhz |
- | Power | ${gpu.power[0]}W / ${gpu.power[1]}W |
- | Load GPU | ${gpu.load.gpu}% |
- | Load Memory | ${gpu.load.memory}% |
- | Temperature | ${gpu.load.temp}°C |
- | Fans | ${gpu.load.fan}% |
- | State | ${gpu.state} |
- `;
- nvmlTbody.innerHTML = rows;
- updateNVMLChart(gpu.load.memory, gpu.load.gpu);
- }
- nvmlEl.style.display = 'block';
- } catch (e) {
- clearInterval(nvmlInterval);
- nvmlEl.style.display = 'none';
- }
-}
-
-async function initNVML() {
- nvmlEl = document.getElementById('nvml');
- if (!nvmlEl) {
- nvmlEl = document.createElement('div');
- nvmlEl.className = 'nvml';
- nvmlEl.id = 'nvml';
- nvmlTable = document.createElement('table');
- nvmlTable.className = 'nvml-table';
- nvmlTable.id = 'nvml-table';
- nvmlTable.innerHTML = `
- | |
-
- `;
- const nvmlChart = document.createElement('div');
- nvmlChart.id = 'nvmlChart';
- nvmlEl.appendChild(nvmlTable);
- nvmlEl.appendChild(nvmlChart);
- gradioApp().appendChild(nvmlEl);
- log('initNVML');
- }
-}
-
-async function startNVML() {
- nvmlEl = document.getElementById('nvml');
- if (nvmlInterval) {
- clearInterval(nvmlInterval);
- nvmlInterval = null;
- nvmlEl.style.display = 'none';
- } else {
- nvmlInterval = setInterval(updateNVML, 1000);
- }
-}
-
-async function disableNVML() {
- clearInterval(nvmlInterval);
- nvmlEl.style.display = 'none';
-}
diff --git a/javascript/sdnext.css b/javascript/sdnext.css
index 636aeaec8..6e855e3c5 100644
--- a/javascript/sdnext.css
+++ b/javascript/sdnext.css
@@ -1616,14 +1616,13 @@ background: var(--background-color)
padding: 6px !important;
}
-.nvml {
+.gpu {
background: var(--background-fill-primary);
border: 1px solid var(--button-primary-border-color);
bottom: 10px;
color: var(--button-primary-text-color);
display: none;
font-family: monospace;
- font-size: var(--text-xxs);
padding: 6px;
position: fixed;
right: 10px;
diff --git a/javascript/startup.js b/javascript/startup.js
index 3629511ca..842f925ba 100644
--- a/javascript/startup.js
+++ b/javascript/startup.js
@@ -39,7 +39,6 @@ async function initStartup() {
executeCallbacks(uiReadyCallbacks);
initLogMonitor();
setupExtraNetworks();
- initNVML();
// optinally wait for modern ui
if (window.waitForUiReady) await waitForUiReady();
diff --git a/modules/api/api.py b/modules/api/api.py
index 539001ea4..0c151300d 100644
--- a/modules/api/api.py
+++ b/modules/api/api.py
@@ -5,7 +5,7 @@ from fastapi import FastAPI, APIRouter, Depends, Request
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.exceptions import HTTPException
from modules import errors, shared, postprocessing
-from modules.api import models, endpoints, script, helpers, server, nvml, generate, process, control, docs
+from modules.api import models, endpoints, script, helpers, server, generate, process, control, docs, gpu
errors.install()
@@ -54,7 +54,7 @@ class Api:
self.add_api_route("/sdapi/v1/options", server.get_config, methods=["GET"], response_model=models.OptionsModel)
self.add_api_route("/sdapi/v1/options", server.set_config, methods=["POST"])
self.add_api_route("/sdapi/v1/cmd-flags", server.get_cmd_flags, methods=["GET"], response_model=models.FlagsModel)
- self.add_api_route("/sdapi/v1/nvml", nvml.get_nvml, methods=["GET"], response_model=List[models.ResNVML])
+ self.add_api_route("/sdapi/v1/gpu", gpu.get_gpu_status, methods=["GET"], response_model=List[models.ResGPU])
# core api using locking
self.add_api_route("/sdapi/v1/txt2img", self.generate.post_text2img, methods=["POST"], response_model=models.ResTxt2Img)
diff --git a/modules/api/gpu.py b/modules/api/gpu.py
new file mode 100644
index 000000000..6586fbbc3
--- /dev/null
+++ b/modules/api/gpu.py
@@ -0,0 +1,28 @@
+import torch
+from installer import log
+
+
+device = None
+
+
+def get_gpu_status():
+ global device # pylint: disable=global-statement
+ if device is None:
+ try:
+ device = torch.cuda.get_device_name(torch.cuda.current_device())
+ log.info(f'GPU monitoring: device={device}')
+ except Exception:
+ device = ''
+ # per vendor modules
+ if 'nvidia' in device.lower():
+ from modules.api import nvml
+ return nvml.get_nvml()
+
+
+"""
+Resut mustb be list[ResGPU]
+class ResGPU(BaseModel):
+ name: str = Field(title="GPU Name")
+ data: dict = Field(title="Name/Value data")
+ chart: list[float, float] = Field(title="Exactly two items to place on chart")
+"""
diff --git a/modules/api/middleware.py b/modules/api/middleware.py
index 0d258c878..be136b516 100644
--- a/modules/api/middleware.py
+++ b/modules/api/middleware.py
@@ -43,7 +43,7 @@ def setup_middleware(app: FastAPI, cmd_opts):
endpoint = req.scope.get('path', 'err')
token = req.cookies.get("access-token") or req.cookies.get("access-token-unsecure")
if (cmd_opts.api_log) and endpoint.startswith('/sdapi'):
- if '/sdapi/v1/log' in endpoint or '/sdapi/v1/browser' in endpoint:
+ if ('/sdapi/v1/log' in endpoint) or ('/sdapi/v1/browser' in endpoint) or ('/sdapi/v1/gpu' in endpoint):
return res
log.info('API user={user} code={code} {prot}/{ver} {method} {endpoint} {cli} {duration}'.format( # pylint: disable=consider-using-f-string, logging-format-interpolation
user = app.tokens.get(token) if hasattr(app, 'tokens') else None,
diff --git a/modules/api/models.py b/modules/api/models.py
index 010467f66..a97ddff0c 100644
--- a/modules/api/models.py
+++ b/modules/api/models.py
@@ -424,16 +424,10 @@ class ResScripts(BaseModel):
img2img: list = Field(default=None, title="Img2img", description="Titles of scripts (img2img)")
control: list = Field(default=None, title="Control", description="Titles of scripts (control)")
-class ResNVML(BaseModel): # definition of http response
- name: str = Field(title="Name")
- version: dict = Field(title="Version")
- pci: dict = Field(title="Version")
- memory: dict = Field(title="Version")
- clock: dict = Field(title="Version")
- load: dict = Field(title="Version")
- power: list = []
- state: str = Field(title="State")
-
+class ResGPU(BaseModel): # definition of http response
+ name: str = Field(title="GPU Name")
+ data: dict = Field(title="Name/Value data")
+ chart: list[float, float] = Field(title="Exactly two items to place on chart")
# helper function
diff --git a/modules/api/nvml.py b/modules/api/nvml.py
index ba9d9b12f..4ecc73b0e 100644
--- a/modules/api/nvml.py
+++ b/modules/api/nvml.py
@@ -43,41 +43,34 @@ def get_nvml():
name = pynvml.nvmlDeviceGetName(dev)
except Exception:
name = ''
- device = {
- 'name': name,
- 'version': {
- 'cuda': pynvml.nvmlSystemGetCudaDriverVersion(),
- 'driver': pynvml.nvmlSystemGetDriverVersion(),
- 'vbios': pynvml.nvmlDeviceGetVbiosVersion(dev),
- 'rom': pynvml.nvmlDeviceGetInforomImageVersion(dev),
- 'capabilities': pynvml.nvmlDeviceGetCudaComputeCapability(dev),
- },
- 'pci': {
- 'link': pynvml.nvmlDeviceGetCurrPcieLinkGeneration(dev),
- 'width': pynvml.nvmlDeviceGetCurrPcieLinkWidth(dev),
- 'busid': pynvml.nvmlDeviceGetPciInfo(dev).busId,
- 'deviceid': pynvml.nvmlDeviceGetPciInfo(dev).pciDeviceId,
- },
- 'memory': {
- 'total': round(pynvml.nvmlDeviceGetMemoryInfo(dev).total/1024/1024, 2),
- 'free': round(pynvml.nvmlDeviceGetMemoryInfo(dev).free/1024/1024,2),
- 'used': round(pynvml.nvmlDeviceGetMemoryInfo(dev).used/1024/1024,2),
- },
- 'clock': { # gpu, sm, memory
- 'gpu': [pynvml.nvmlDeviceGetClockInfo(dev, 0), pynvml.nvmlDeviceGetMaxClockInfo(dev, 0)],
- 'sm': [pynvml.nvmlDeviceGetClockInfo(dev, 1), pynvml.nvmlDeviceGetMaxClockInfo(dev, 1)],
- 'memory': [pynvml.nvmlDeviceGetClockInfo(dev, 2), pynvml.nvmlDeviceGetMaxClockInfo(dev, 2)],
- },
+ load = pynvml.nvmlDeviceGetUtilizationRates(dev)
+ """
'load': {
- 'gpu': round(pynvml.nvmlDeviceGetUtilizationRates(dev).gpu),
- 'memory': round(pynvml.nvmlDeviceGetUtilizationRates(dev).memory),
+ 'gpu': round(load.gpu),
+ 'memory': round(load.memory),
'temp': pynvml.nvmlDeviceGetTemperature(dev, 0),
'fan': pynvml.nvmlDeviceGetFanSpeed(dev),
},
- 'power': [round(pynvml.nvmlDeviceGetPowerUsage(dev)/1000, 2), round(pynvml.nvmlDeviceGetEnforcedPowerLimit(dev)/1000, 2)],
- 'state': get_reason(pynvml.nvmlDeviceGetCurrentClocksThrottleReasons(dev)),
+ 'chart_val1': load.memory,
+ 'chart_val2': load.gpu,
}
- devices.append(device)
+ """
+ mem = pynvml.nvmlDeviceGetMemoryInfo(dev)
+ data = {
+ "CUDA": f'version {pynvml.nvmlSystemGetCudaDriverVersion()} compute {pynvml.nvmlDeviceGetCudaComputeCapability(dev)}',
+ "Driver": pynvml.nvmlSystemGetDriverVersion(),
+ "Hardware": f'VBIOS {pynvml.nvmlDeviceGetVbiosVersion(dev)} ROM {pynvml.nvmlDeviceGetInforomImageVersion(dev)}',
+ "PCI link": f'gen.{pynvml.nvmlDeviceGetCurrPcieLinkGeneration(dev)} x{pynvml.nvmlDeviceGetCurrPcieLinkWidth(dev)}',
+ "Power": f'{round(pynvml.nvmlDeviceGetPowerUsage(dev)/1000, 2)} W / {round(pynvml.nvmlDeviceGetEnforcedPowerLimit(dev)/1000, 2)} W',
+ "GPU clock": f'{pynvml.nvmlDeviceGetClockInfo(dev, 0)} Mhz / {pynvml.nvmlDeviceGetMaxClockInfo(dev, 0)} Mhz',
+ "SM clock": f'{pynvml.nvmlDeviceGetClockInfo(dev, 1)} Mhz / {pynvml.nvmlDeviceGetMaxClockInfo(dev, 1)} Mhz',
+ "Memory clock": f'{pynvml.nvmlDeviceGetClockInfo(dev, 2)} Mhz / {pynvml.nvmlDeviceGetMaxClockInfo(dev, 2)} Mhz',
+ "Memory usage": f'used {round(mem.used / 1024 / 1024)} MB | free {round(mem.free / 1024 / 1024)} MB | total {round(mem.total / 1024 / 1024)} MB',
+ "System load": f'GPU {load.gpu}% | Memory {load.memory}% | temp {pynvml.nvmlDeviceGetTemperature(dev, 0)}C | fan {pynvml.nvmlDeviceGetFanSpeed(dev)}%',
+ 'State': get_reason(pynvml.nvmlDeviceGetCurrentClocksThrottleReasons(dev)),
+ }
+ chart = [load.memory, load.gpu]
+ devices.append({ 'name': name, 'data': data, 'chart': chart })
# log.debug(f'nmvl: {devices}')
return devices
except Exception as e:
diff --git a/modules/shared.py b/modules/shared.py
index 31d878601..628b83911 100644
--- a/modules/shared.py
+++ b/modules/shared.py
@@ -535,6 +535,7 @@ options_templates.update(options_section(('ui', "User Interface"), {
"other_sep_ui": OptionInfo("Other...
", "", gr.HTML),
"ui_locale": OptionInfo("Auto", "UI locale", gr.Dropdown, lambda: {"choices": theme.list_locales()}),
"font_size": OptionInfo(14, "Font size", gr.Slider, {"minimum": 8, "maximum": 32, "step": 1}),
+ "gpu_monitor": OptionInfo(3000, "GPU monitor interval", gr.Slider, {"minimum": 100, "maximum": 60000, "step": 100}),
"aspect_ratios": OptionInfo("1:1, 4:3, 3:2, 16:9, 16:10, 21:9, 2:3, 3:4, 9:16, 10:16, 9:21", "Allowed aspect ratios"),
"compact_view": OptionInfo(False, "Compact view"),
"ui_columns": OptionInfo(4, "Gallery view columns", gr.Slider, {"minimum": 1, "maximum": 8, "step": 1}),
diff --git a/modules/ui_settings.py b/modules/ui_settings.py
index 9a5a47a13..f15fd8985 100644
--- a/modules/ui_settings.py
+++ b/modules/ui_settings.py
@@ -251,6 +251,22 @@ def create_ui():
with gr.TabItem("History", id="system_history", elem_id="tab_history"):
ui_history.create_ui()
+ with gr.TabItem("GPU Monitor", id="system_gpu", elem_id="tab_gpu"):
+ with gr.Row(elem_id='gpu-controls'):
+ gpu_start = gr.Button(value="Start", elem_id="gpu_start", variant="primary")
+ gpu_stop = gr.Button(value="Stop", elem_id="gpu_stop", variant="primary")
+ gpu_start.click(fn=lambda: None, _js='startGPU', inputs=[], outputs=[])
+ gpu_stop.click(fn=lambda: None, _js='disableGPU', inputs=[], outputs=[])
+ gr.HTML('''
+
+ ''', elem_id='gpu-container', visible=True)
+
with gr.TabItem("ONNX", id="onnx_config", elem_id="tab_onnx"):
from modules.onnx_impl import ui as ui_onnx
ui_onnx.create_ui()
diff --git a/scripts/prompt_enhance.py b/scripts/prompt_enhance.py
index 697f5691f..622a12374 100644
--- a/scripts/prompt_enhance.py
+++ b/scripts/prompt_enhance.py
@@ -57,6 +57,7 @@ class Options:
'cognitivecomputations/Dolphin3.0-Llama3.2-1B': {},
'cognitivecomputations/Dolphin3.0-Llama3.2-3B': {},
'nidum/Nidum-Gemma-3-4B-it-Uncensored': {},
+ 'allura-org/Gemma-3-Glitter-4B': {},
# 'llava/Llama-3-8B-v1.1-Extracted': {
# 'repo': 'hunyuanvideo-community/HunyuanVideo',
# 'subfolder': 'text_encoder',