Add support for ACE-Step 1.5 and ACE-Step 1.5 XL. Also added dataset captioning through the UI. (#785)

* Base ace step 1.5 xl added. Generating, still wip on training and ui

* Base training code done

* Fix some issues with caching text embeddings. Update sample cards to show audio

* Fix issue with quantizing ace step

* Add album artwork to samples with waveform.

* Cleanup logs

* Add album art endpoint to speed up album art loading

* Made an make video with artwork script

* Make ui handle basic audio models. Make multi line adjustments to the editor and better syntax hilighting.

* Add prompt tagging system for special tagged models.

* prompt tagging processing for ui working.

* Moved default samples to a special file so we can add more when needed and they can be adjusted for a specific model

* Add a captioner job with music captioner that is prepped for use with the ui

* Add basit ui setup for captioning modal and handeling captioning jobs

* Starting captioning job from ui working. Still better management for it.

* Better filtering of job options in the job view for captioning jobs

* Added qwen3 vl as a captioner for images

* Have an indicator when a dataset is being captioned.

* Adjust the way caption jobs look in the queue

* Fix a few issues. Adjust defaults.

* Version bump

* Added ace step to the readme.
This commit is contained in:
Jaret Burkett
2026-04-09 15:02:03 -06:00
committed by GitHub
parent 9ca58e9aa2
commit 78cf049c29
54 changed files with 5589 additions and 536 deletions

View File

@@ -9,6 +9,7 @@ import { isVideo, isAudio } from '@/utils/basic';
interface DatasetImageCardProps {
imageUrl: string;
alt: string;
isAutoCaptioning: boolean;
children?: ReactNode;
className?: string;
onDelete?: () => void;
@@ -17,6 +18,7 @@ interface DatasetImageCardProps {
const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
imageUrl,
alt,
isAutoCaptioning,
children,
className = '',
onDelete = () => {},
@@ -80,6 +82,16 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
}
}, [inViewport, isVisible]);
// Poll for caption updates every 5 seconds while auto-captioning
useEffect(() => {
if (!isAutoCaptioning || !inViewport || !isVisible) return;
const interval = setInterval(() => {
// Reset so fetchCaption will re-fetch
setIsCaptionLoaded(false);
}, 5000);
return () => clearInterval(interval);
}, [isAutoCaptioning, inViewport, isVisible]);
useEffect(() => {
// Create intersection observer to check viewport visibility
const observer = new IntersectionObserver(
@@ -129,6 +141,8 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
const isCaptionCurrent = caption.trim() === savedCaption;
const [showAudioPlayer, setShowAudioPlayer] = useState(true);
const isItAVideo = isVideo(imageUrl);
const isItAudio = isAudio(imageUrl);
const isItImage = !isItAVideo && !isItAudio;
@@ -154,7 +168,22 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
controls
/>
)}
{isItAudio && (
{isItAudio && !showAudioPlayer && (
<div
className="w-full h-full cursor-pointer flex items-center justify-center bg-gray-900"
onClick={() => setShowAudioPlayer(true)}
>
<img
src={`/api/audio/art/${encodeURIComponent(imageUrl)}`}
alt={alt}
className="w-full h-full object-contain"
onError={e => {
(e.target as HTMLImageElement).style.display = 'none';
}}
/>
</div>
)}
{isItAudio && showAudioPlayer && (
<AudioPlayer
src={`/api/img/${encodeURIComponent(imageUrl)}`}
title={imageUrl.replace(/^.*[\\/]/, '')}
@@ -221,9 +250,12 @@ const DatasetImageCard: React.FC<DatasetImageCardProps> = ({
onBlur={saveCaption}
>
<textarea
className="w-full bg-transparent resize-none outline-none focus:ring-0 focus:outline-none"
className={classNames("w-full bg-transparent resize-none outline-none focus:ring-0 focus:outline-none", {
'opacity-50 cursor-not-allowed': isAutoCaptioning,
})}
value={caption}
rows={3}
readOnly={isAutoCaptioning}
onChange={e => setCaption(e.target.value)}
onKeyDown={handleKeyDown}
/>