diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 000000000..fa3fa296d --- /dev/null +++ b/.github/workflows/build-release.yml @@ -0,0 +1,49 @@ +name: Release + +on: + push: + branches: + - main # or whatever branch you want to use + +jobs: + release: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Check for changes in package.json + run: | + git diff --cached --diff-filter=d package.json || { + echo "No changes to package.json" + exit 1 + } + + - name: Get version number from package.json + id: get_version + run: | + VERSION=$(jq -r '.version' package.json) + echo "::set-output name=version::$VERSION" + + - name: Create GitHub release + uses: actions/github-script@v5 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const release = await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: `v${{ steps.get_version.outputs.version }}`, + name: `v${{ steps.get_version.outputs.version }}`, + body: 'Automatically created new release', + }) + console.log(`Created release ${release.data.html_url}`) + + - name: Upload package to GitHub release + uses: actions/upload-artifact@v3 + with: + name: package + path: . + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 421a9bd2f..c5cc439b5 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [](https://discord.gg/5rJgQTnV4s) [](https://github.com/sponsors/tjbck) -ChatGPT-Style Web Interface for Ollama 🦙 +User-friendly WebUI for LLMs, Inspired by ChatGPT  diff --git a/backend/apps/images/main.py b/backend/apps/images/main.py index 998af3ddb..39d3f96aa 100644 --- a/backend/apps/images/main.py +++ b/backend/apps/images/main.py @@ -1,4 +1,4 @@ -import os +import re import requests from fastapi import ( FastAPI, @@ -34,6 +34,7 @@ app.add_middleware( app.state.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL app.state.ENABLED = app.state.AUTOMATIC1111_BASE_URL != "" +app.state.IMAGE_SIZE = "512x512" @app.get("/enabled", response_model=bool) @@ -74,6 +75,33 @@ async def update_openai_url(form_data: UrlUpdateForm, user=Depends(get_admin_use } +class ImageSizeUpdateForm(BaseModel): + size: str + + +@app.get("/size") +async def get_image_size(user=Depends(get_admin_user)): + return {"IMAGE_SIZE": app.state.IMAGE_SIZE} + + +@app.post("/size/update") +async def update_image_size( + form_data: ImageSizeUpdateForm, user=Depends(get_admin_user) +): + pattern = r"^\d+x\d+$" # Regular expression pattern + if re.match(pattern, form_data.size): + app.state.IMAGE_SIZE = form_data.size + return { + "IMAGE_SIZE": app.state.IMAGE_SIZE, + "status": True, + } + else: + raise HTTPException( + status_code=400, + detail=ERROR_MESSAGES.INCORRECT_FORMAT(" (e.g., 512x512)."), + ) + + @app.get("/models") def get_models(user=Depends(get_current_user)): try: @@ -140,7 +168,7 @@ def generate_image( if form_data.model: set_model_handler(form_data.model) - width, height = tuple(map(int, form_data.size.split("x"))) + width, height = tuple(map(int, app.state.IMAGE_SIZE.split("x"))) data = { "prompt": form_data.prompt, diff --git a/backend/constants.py b/backend/constants.py index 580db9c5f..cb802c7f4 100644 --- a/backend/constants.py +++ b/backend/constants.py @@ -44,3 +44,6 @@ class ERROR_MESSAGES(str, Enum): MALICIOUS = "Unusual activities detected, please try again in a few minutes." PANDOC_NOT_INSTALLED = "Pandoc is not installed on the server. Please contact your administrator for assistance." + INCORRECT_FORMAT = ( + lambda err="": f"Invalid format. Please use the correct format{err if err else ''}" + ) diff --git a/src/lib/apis/images/index.ts b/src/lib/apis/images/index.ts index b25499d64..205ee90ac 100644 --- a/src/lib/apis/images/index.ts +++ b/src/lib/apis/images/index.ts @@ -131,6 +131,73 @@ export const updateAUTOMATIC1111Url = async (token: string = '', url: string) => return res.AUTOMATIC1111_BASE_URL; }; +export const getImageSize = async (token: string = '') => { + let error = null; + + const res = await fetch(`${IMAGES_API_BASE_URL}/size`, { + 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_SIZE; +}; + +export const updateImageSize = async (token: string = '', size: string) => { + let error = null; + + const res = await fetch(`${IMAGES_API_BASE_URL}/size/update`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + ...(token && { authorization: `Bearer ${token}` }) + }, + body: JSON.stringify({ + size: size + }) + }) + .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_SIZE; +}; + export const getDiffusionModels = async (token: string = '') => { let error = null; diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index 64574530f..c9e516abb 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -222,6 +222,34 @@ scrollToBottom(); }, 100); }; + + // TODO: change delete behaviour + // const deleteMessageAndDescendants = async (messageId: string) => { + // if (history.messages[messageId]) { + // history.messages[messageId].deleted = true; + + // for (const childId of history.messages[messageId].childrenIds) { + // await deleteMessageAndDescendants(childId); + // } + // } + // }; + + // const triggerDeleteMessageRecursive = async (messageId: string) => { + // await deleteMessageAndDescendants(messageId); + // await updateChatById(localStorage.token, chatId, { history }); + // await chats.set(await getChatList(localStorage.token)); + // }; + + const messageDeleteHandler = async (messageId) => { + if (history.messages[messageId]) { + history.messages[messageId].deleted = true; + + for (const childId of history.messages[messageId].childrenIds) { + history.messages[childId].deleted = true; + } + } + await updateChatById(localStorage.token, chatId, { history }); + }; {#if messages.length == 0} @@ -230,99 +258,103 @@
{message.content}-