Merge pull request #888 from jmfirth/feature/img-gen-steps-setting

Add steps setting for image generation
This commit is contained in:
Timothy Jaeryang Baek 2024-02-24 21:11:16 -05:00 committed by GitHub
commit 92ec0d90e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 119 additions and 2 deletions

View File

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Built-in LiteLLM Proxy**: Open WebUI now ships with LiteLLM Proxy. - **Built-in LiteLLM Proxy**: Open WebUI now ships with LiteLLM Proxy.
- **Image Generation Enhancements**: Advanced Settings + Image Preview Feature. - **Image Generation Enhancements**: Advanced Settings + Image Preview Feature.
- Allows setting number of steps for image generation; defaults to a1111 default value.
### Fixed ### Fixed

View File

@ -35,6 +35,7 @@ app.add_middleware(
app.state.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL app.state.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL
app.state.ENABLED = app.state.AUTOMATIC1111_BASE_URL != "" app.state.ENABLED = app.state.AUTOMATIC1111_BASE_URL != ""
app.state.IMAGE_SIZE = "512x512" app.state.IMAGE_SIZE = "512x512"
app.state.IMAGE_STEPS = 50
@app.get("/enabled", response_model=bool) @app.get("/enabled", response_model=bool)
@ -102,6 +103,32 @@ async def update_image_size(
) )
class ImageStepsUpdateForm(BaseModel):
steps: int
@app.get("/steps")
async def get_image_size(user=Depends(get_admin_user)):
return {"IMAGE_STEPS": app.state.IMAGE_STEPS}
@app.post("/steps/update")
async def update_image_size(
form_data: ImageStepsUpdateForm, user=Depends(get_admin_user)
):
if form_data.steps >= 0:
app.state.IMAGE_STEPS = form_data.steps
return {
"IMAGE_STEPS": app.state.IMAGE_STEPS,
"status": True,
}
else:
raise HTTPException(
status_code=400,
detail=ERROR_MESSAGES.INCORRECT_FORMAT(" (e.g., 50)."),
)
@app.get("/models") @app.get("/models")
def get_models(user=Depends(get_current_user)): def get_models(user=Depends(get_current_user)):
try: try:
@ -179,6 +206,9 @@ def generate_image(
"height": height, "height": height,
} }
if app.state.IMAGE_STEPS != None:
data["steps"] = app.state.IMAGE_STEPS
if form_data.negative_prompt != None: if form_data.negative_prompt != None:
data["negative_prompt"] = form_data.negative_prompt data["negative_prompt"] = form_data.negative_prompt

View File

@ -198,6 +198,71 @@ export const updateImageSize = async (token: string = '', size: string) => {
return res.IMAGE_SIZE; return res.IMAGE_SIZE;
}; };
export const getImageSteps = async (token: string = '') => {
let error = null;
const res = await fetch(`${IMAGES_API_BASE_URL}/steps`, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token && { authorization: `Bearer ${token}` })
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
if ('detail' in err) {
error = err.detail;
} else {
error = 'Server connection failed';
}
return null;
});
if (error) {
throw error;
}
return res.IMAGE_STEPS;
};
export const updateImageSteps = async (token: string = '', steps: number) => {
let error = null;
const res = await fetch(`${IMAGES_API_BASE_URL}/steps/update`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token && { authorization: `Bearer ${token}` })
},
body: JSON.stringify({ steps })
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.catch((err) => {
console.log(err);
if ('detail' in err) {
error = err.detail;
} else {
error = 'Server connection failed';
}
return null;
});
if (error) {
throw error;
}
return res.IMAGE_STEPS;
};
export const getDiffusionModels = async (token: string = '') => { export const getDiffusionModels = async (token: string = '') => {
let error = null; let error = null;

View File

@ -12,7 +12,9 @@
toggleImageGenerationEnabledStatus, toggleImageGenerationEnabledStatus,
updateAUTOMATIC1111Url, updateAUTOMATIC1111Url,
updateDefaultDiffusionModel, updateDefaultDiffusionModel,
updateImageSize updateImageSize,
getImageSteps,
updateImageSteps
} from '$lib/apis/images'; } from '$lib/apis/images';
import { getBackendConfig } from '$lib/apis'; import { getBackendConfig } from '$lib/apis';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@ -21,13 +23,14 @@
let loading = false; let loading = false;
let enableImageGeneration = true; let enableImageGeneration = false;
let AUTOMATIC1111_BASE_URL = ''; let AUTOMATIC1111_BASE_URL = '';
let selectedModel = ''; let selectedModel = '';
let models = []; let models = [];
let imageSize = ''; let imageSize = '';
let steps = 50;
const getModels = async () => { const getModels = async () => {
models = await getDiffusionModels(localStorage.token).catch((error) => { models = await getDiffusionModels(localStorage.token).catch((error) => {
@ -85,6 +88,7 @@
if (enableImageGeneration && AUTOMATIC1111_BASE_URL) { if (enableImageGeneration && AUTOMATIC1111_BASE_URL) {
imageSize = await getImageSize(localStorage.token); imageSize = await getImageSize(localStorage.token);
steps = await getImageSteps(localStorage.token);
getModels(); getModels();
} }
} }
@ -100,6 +104,10 @@
toast.error(error); toast.error(error);
return null; return null;
}); });
await updateImageSteps(localStorage.token, steps).catch((error) => {
toast.error(error);
return null;
});
dispatch('save'); dispatch('save');
loading = false; loading = false;
@ -212,6 +220,19 @@
</div> </div>
</div> </div>
</div> </div>
<div>
<div class=" mb-2.5 text-sm font-medium">Set Steps</div>
<div class="flex w-full">
<div class="flex-1 mr-2">
<input
class="w-full rounded py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-800 outline-none"
placeholder="Enter Number of Steps (e.g. 50)"
bind:value={steps}
/>
</div>
</div>
</div>
{/if} {/if}
</div> </div>