Spaces:
Running
Running
Add bulk caption paste feature to training UI
Browse files
src/content_engine/api/ui.html
CHANGED
|
@@ -1309,8 +1309,17 @@ select { cursor: pointer; }
|
|
| 1309 |
<div class="caption-toolbar">
|
| 1310 |
<span style="font-size:12px;color:var(--text-secondary)">Captions per image (improves LoRA quality)</span>
|
| 1311 |
<button class="btn btn-secondary btn-small" onclick="autoCaptionAll()">Auto-fill from trigger word</button>
|
|
|
|
| 1312 |
<button class="btn btn-secondary btn-small" onclick="clearTrainImages()">Clear all</button>
|
| 1313 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1314 |
<div id="caption-editor" class="caption-editor"></div>
|
| 1315 |
</div>
|
| 1316 |
|
|
@@ -1944,6 +1953,40 @@ function autoCaptionAll() {
|
|
| 1944 |
toast(`Applied "${trigger}" to ${trainImageFiles.length} images`, 'success');
|
| 1945 |
}
|
| 1946 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1947 |
function clearTrainImages() {
|
| 1948 |
trainImageFiles = [];
|
| 1949 |
trainCaptions = {};
|
|
|
|
| 1309 |
<div class="caption-toolbar">
|
| 1310 |
<span style="font-size:12px;color:var(--text-secondary)">Captions per image (improves LoRA quality)</span>
|
| 1311 |
<button class="btn btn-secondary btn-small" onclick="autoCaptionAll()">Auto-fill from trigger word</button>
|
| 1312 |
+
<button class="btn btn-secondary btn-small" onclick="toggleBulkCaptions()">Bulk Paste</button>
|
| 1313 |
<button class="btn btn-secondary btn-small" onclick="clearTrainImages()">Clear all</button>
|
| 1314 |
</div>
|
| 1315 |
+
<div id="bulk-caption-area" style="display:none;margin:8px 0">
|
| 1316 |
+
<textarea id="bulk-caption-text" style="width:100%;height:200px;font-size:12px;padding:8px;border-radius:6px;border:1px solid var(--border);background:var(--bg-primary);color:var(--text-primary);resize:vertical;font-family:inherit" placeholder="Paste numbered captions, one per line. They map to images in order. 1. ohwx woman, portrait, natural lighting, smiling 2. ohwx woman, full body, outdoor, park 3. ohwx woman, close-up, studio lighting ..."></textarea>
|
| 1317 |
+
<div style="display:flex;gap:8px;margin-top:6px">
|
| 1318 |
+
<button class="btn btn-primary btn-small" onclick="applyBulkCaptions()">Apply to images</button>
|
| 1319 |
+
<button class="btn btn-secondary btn-small" onclick="toggleBulkCaptions()">Cancel</button>
|
| 1320 |
+
<span style="font-size:11px;color:var(--text-secondary);align-self:center">Accepts: "1. text", "1) text", or plain lines</span>
|
| 1321 |
+
</div>
|
| 1322 |
+
</div>
|
| 1323 |
<div id="caption-editor" class="caption-editor"></div>
|
| 1324 |
</div>
|
| 1325 |
|
|
|
|
| 1953 |
toast(`Applied "${trigger}" to ${trainImageFiles.length} images`, 'success');
|
| 1954 |
}
|
| 1955 |
|
| 1956 |
+
function toggleBulkCaptions() {
|
| 1957 |
+
const area = document.getElementById('bulk-caption-area');
|
| 1958 |
+
area.style.display = area.style.display === 'none' ? 'block' : 'none';
|
| 1959 |
+
}
|
| 1960 |
+
|
| 1961 |
+
function applyBulkCaptions() {
|
| 1962 |
+
const raw = document.getElementById('bulk-caption-text').value.trim();
|
| 1963 |
+
if (!raw) { toast('Paste captions first', 'error'); return; }
|
| 1964 |
+
if (trainImageFiles.length === 0) { toast('Upload images first', 'error'); return; }
|
| 1965 |
+
|
| 1966 |
+
// Parse lines: strip numbering like "1. ", "1) ", "1: ", or plain lines
|
| 1967 |
+
const lines = raw.split('\n')
|
| 1968 |
+
.map(l => l.trim())
|
| 1969 |
+
.filter(l => l.length > 0)
|
| 1970 |
+
.map(l => l.replace(/^\d+[\.\)\:\-]\s*/, ''));
|
| 1971 |
+
|
| 1972 |
+
const count = Math.min(lines.length, trainImageFiles.length);
|
| 1973 |
+
const textareas = document.querySelectorAll('#caption-editor textarea');
|
| 1974 |
+
|
| 1975 |
+
for (let i = 0; i < count; i++) {
|
| 1976 |
+
trainCaptions[trainImageFiles[i].name] = lines[i];
|
| 1977 |
+
if (textareas[i]) textareas[i].value = lines[i];
|
| 1978 |
+
}
|
| 1979 |
+
|
| 1980 |
+
document.getElementById('bulk-caption-area').style.display = 'none';
|
| 1981 |
+
document.getElementById('bulk-caption-text').value = '';
|
| 1982 |
+
toast(`Applied captions to ${count} of ${trainImageFiles.length} images`, 'success');
|
| 1983 |
+
if (lines.length > trainImageFiles.length) {
|
| 1984 |
+
toast(`${lines.length - trainImageFiles.length} extra captions ignored (more captions than images)`, 'warning');
|
| 1985 |
+
} else if (lines.length < trainImageFiles.length) {
|
| 1986 |
+
toast(`${trainImageFiles.length - lines.length} images have no caption yet`, 'warning');
|
| 1987 |
+
}
|
| 1988 |
+
}
|
| 1989 |
+
|
| 1990 |
function clearTrainImages() {
|
| 1991 |
trainImageFiles = [];
|
| 1992 |
trainCaptions = {};
|