diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..c2152102 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.1.102] - 2024-02-22 + +### Added + +- **๐Ÿ–ผ๏ธ Image Generation**: Generate Images using the stable-difusion-webui API. You can set this up in settings -> images. +- **๐Ÿ“ Change title generation prompt**: Change the promt used to generate titles for your chats. You can set this up in the settings -> interface. +- **๐Ÿค– Change embedding model**: Change the embedding model used to generate embeddings for your chats in the Dockerfile. Use any sentence transformer model from huggingface.co. +- **๐Ÿ“ข CHANGELOG.md/Popup**: This popup will show you the latest changes. You can edit it in the constants.ts file. + +## [0.1.101] - 2024-02-22 + +### Fixed + +- LaTex output formatting issue (#828) + +### Changed + +- Instead of having the previous 1.0.0-alpha.101, we switched to semantic versioning as a way to respect global conventions. diff --git a/Dockerfile b/Dockerfile index 03dccefe..7eb34dab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -73,6 +73,8 @@ COPY --from=build /app/onnx /root/.cache/chroma/onnx_models/all-MiniLM-L6-v2/onn # copy built frontend files COPY --from=build /app/build /app/build +COPY --from=build /app/CHANGELOG.md /app/CHANGELOG.md +COPY --from=build /app/package.json /app/package.json # copy backend files COPY ./backend . diff --git a/backend/config.py b/backend/config.py index caf2cc45..784c95d1 100644 --- a/backend/config.py +++ b/backend/config.py @@ -6,6 +6,8 @@ from base64 import b64encode from constants import ERROR_MESSAGES from pathlib import Path import json +import markdown +from bs4 import BeautifulSoup try: @@ -23,6 +25,75 @@ except ImportError: ENV = os.environ.get("ENV", "dev") +try: + with open(f"../package.json", "r") as f: + PACKAGE_DATA = json.load(f) +except: + PACKAGE_DATA = {"version": "0.0.0"} + +VERSION = PACKAGE_DATA["version"] + + +# Function to parse each section +def parse_section(section): + items = [] + for li in section.find_all("li"): + # Extract raw HTML string + raw_html = str(li) + + # Extract text without HTML tags + text = li.get_text(separator=" ", strip=True) + + # Split into title and content + parts = text.split(": ", 1) + title = parts[0].strip() if len(parts) > 1 else "" + content = parts[1].strip() if len(parts) > 1 else text + + items.append({"title": title, "content": content, "raw": raw_html}) + return items + + +try: + with open("../CHANGELOG.md", "r") as file: + changelog_content = file.read() +except: + changelog_content = "" + +# Convert markdown content to HTML +html_content = markdown.markdown(changelog_content) + +# Parse the HTML content +soup = BeautifulSoup(html_content, "html.parser") + +# Initialize JSON structure +changelog_json = {} + +# Iterate over each version +for version in soup.find_all("h2"): + version_number = version.get_text().strip().split(" - ")[0][1:-1] # Remove brackets + date = version.get_text().strip().split(" - ")[1] + + version_data = {"date": date} + + # Find the next sibling that is a h3 tag (section title) + current = version.find_next_sibling() + + print(current) + + while current and current.name != "h2": + if current.name == "h3": + section_title = current.get_text().lower() # e.g., "added", "fixed" + section_items = parse_section(current.find_next_sibling("ul")) + version_data[section_title] = section_items + + # Move to the next element + current = current.find_next_sibling() + + changelog_json[version_number] = version_data + + +CHANGELOG = changelog_json + #################################### # DATA/FRONTEND BUILD DIR #################################### diff --git a/backend/main.py b/backend/main.py index d1fb0c20..8a9b9dce 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,5 +1,9 @@ +from bs4 import BeautifulSoup +import json +import markdown import time + from fastapi import FastAPI, Request from fastapi.staticfiles import StaticFiles from fastapi import HTTPException @@ -16,7 +20,7 @@ from apps.rag.main import app as rag_app from apps.web.main import app as webui_app -from config import ENV, FRONTEND_BUILD_DIR +from config import ENV, VERSION, CHANGELOG, FRONTEND_BUILD_DIR class SPAStaticFiles(StaticFiles): @@ -65,14 +69,21 @@ app.mount("/rag/api/v1", rag_app) @app.get("/api/config") async def get_app_config(): + return { "status": True, + "version": VERSION, "images": images_app.state.ENABLED, "default_models": webui_app.state.DEFAULT_MODELS, "default_prompt_suggestions": webui_app.state.DEFAULT_PROMPT_SUGGESTIONS, } +@app.get("/api/changelog") +async def get_app_changelog(): + return CHANGELOG + + app.mount( "/", SPAStaticFiles(directory=FRONTEND_BUILD_DIR, html=True), diff --git a/bun.lockb b/bun.lockb index 7768741d..e0a038da 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package-lock.json b/package-lock.json index ded65c9a..9fdfdb8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "open-webui", - "version": "0.0.1", + "version": "v1.0.0-alpha.101", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "open-webui", - "version": "0.0.1", + "version": "v1.0.0-alpha.101", "dependencies": { "@sveltejs/adapter-node": "^1.3.1", "async": "^3.2.5", @@ -38,6 +38,7 @@ "prettier-plugin-svelte": "^2.10.1", "svelte": "^4.0.5", "svelte-check": "^3.4.3", + "svelte-confetti": "^1.3.2", "tailwindcss": "^3.3.3", "tslib": "^2.4.1", "typescript": "^5.0.0", @@ -3174,6 +3175,15 @@ "svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0" } }, + "node_modules/svelte-confetti": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svelte-confetti/-/svelte-confetti-1.3.2.tgz", + "integrity": "sha512-R+JwFTC7hIgWVA/OuXrkj384B7CMoceb0t9VacyW6dORTQg0pWojVBB8Bo3tM30cLEQE48Fekzqgx+XSzHESMA==", + "dev": true, + "peerDependencies": { + "svelte": "^4.0.0" + } + }, "node_modules/svelte-eslint-parser": { "version": "0.33.1", "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.33.1.tgz", @@ -5852,6 +5862,13 @@ "typescript": "^5.0.3" } }, + "svelte-confetti": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svelte-confetti/-/svelte-confetti-1.3.2.tgz", + "integrity": "sha512-R+JwFTC7hIgWVA/OuXrkj384B7CMoceb0t9VacyW6dORTQg0pWojVBB8Bo3tM30cLEQE48Fekzqgx+XSzHESMA==", + "dev": true, + "requires": {} + }, "svelte-eslint-parser": { "version": "0.33.1", "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.33.1.tgz", diff --git a/package.json b/package.json index 33236274..30549fdd 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "prettier-plugin-svelte": "^2.10.1", "svelte": "^4.0.5", "svelte-check": "^3.4.3", + "svelte-confetti": "^1.3.2", "tailwindcss": "^3.3.3", "tslib": "^2.4.1", "typescript": "^5.0.0", diff --git a/src/lib/apis/index.ts b/src/lib/apis/index.ts index c20107ce..db29e548 100644 --- a/src/lib/apis/index.ts +++ b/src/lib/apis/index.ts @@ -21,3 +21,25 @@ export const getBackendConfig = async () => { return res; }; + +export const getChangelog = async () => { + let error = null; + + const res = await fetch(`${WEBUI_BASE_URL}/api/changelog`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.log(err); + error = err; + return null; + }); + + return res; +}; diff --git a/src/lib/components/ChangelogModal.svelte b/src/lib/components/ChangelogModal.svelte new file mode 100644 index 00000000..00c12a39 --- /dev/null +++ b/src/lib/components/ChangelogModal.svelte @@ -0,0 +1,115 @@ + + + +
+
+
+ Whatโ€™s New in {WEBUI_NAME} + +
+ +
+
+
Release Notes
+
+
+ v{WEB_UI_VERSION} +
+
+
+ +
+ +
+
+
+ {#if changelog} + {#each Object.keys(changelog) as version} +
+
+ v{version} - {changelog[version].date} +
+ +
+ + {#each Object.keys(changelog[version]).filter((section) => section !== 'date') as section} +
+
+ {section} +
+ +
+ {#each Object.keys(changelog[version][section]) as item} +
+
+ {changelog[version][section][item].title} +
+
{changelog[version][section][item].content}
+
+ {/each} +
+
+ {/each} +
+ {/each} + {/if} +
+
+
+ +
+
+ diff --git a/src/lib/components/chat/Settings/About.svelte b/src/lib/components/chat/Settings/About.svelte index e9f7e8d6..16830226 100644 --- a/src/lib/components/chat/Settings/About.svelte +++ b/src/lib/components/chat/Settings/About.svelte @@ -1,7 +1,7 @@