diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..86e83fbd4 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,33 @@ +# 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. + +### Fixed + +- X, Y, and Z + +### Changed + +- X, Y, and Z + +### Removed + +- X, Y, and Z + +## [0.1.101] - 2024-02-21 + +### Added + +- X, Y, and Z diff --git a/backend/config.py b/backend/config.py index caf2cc457..51416b34b 100644 --- a/backend/config.py +++ b/backend/config.py @@ -23,6 +23,14 @@ 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"] + #################################### # DATA/FRONTEND BUILD DIR #################################### diff --git a/backend/main.py b/backend/main.py index d1fb0c205..9e4da7842 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, FRONTEND_BUILD_DIR class SPAStaticFiles(StaticFiles): @@ -65,14 +69,85 @@ 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, } +# 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 + + +@app.get("/api/changelog") +async def get_app_changelog(): + try: + with open("../CHANGELOG.md", "r") as file: + changelog_content = file.read() + # Convert markdown content to HTML + html_content = markdown.markdown(changelog_content) + + # Parse the HTML content + soup = BeautifulSoup(html_content, "html.parser") + + print(soup) + # 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 + + # print(changelog_json) + + # Return content as JSON string + return changelog_json + except FileNotFoundError: + return {"error": "readme.md not found"} + except Exception as e: + return {"error": f"An error occurred: {e}"} + + app.mount( "/", SPAStaticFiles(directory=FRONTEND_BUILD_DIR, html=True), diff --git a/package.json b/package.json index ba5d2089c..30549fdd5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-webui", - "version": "v1.0.0-alpha.101", + "version": "0.1.102", "private": true, "scripts": { "dev": "vite dev --host", @@ -53,4 +53,4 @@ "tippy.js": "^6.3.7", "uuid": "^9.0.1" } -} +} \ No newline at end of file diff --git a/src/lib/apis/index.ts b/src/lib/apis/index.ts index c20107ce2..db29e5485 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 000000000..a20f4e697 --- /dev/null +++ b/src/lib/components/ChangelogModal.svelte @@ -0,0 +1,90 @@ + + + +
+
+
+ {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/Interface.svelte b/src/lib/components/chat/Settings/Interface.svelte index 8ddb0133b..f2dfac5ca 100644 --- a/src/lib/components/chat/Settings/Interface.svelte +++ b/src/lib/components/chat/Settings/Interface.svelte @@ -1,7 +1,7 @@ - - -
-
-
- {WEBUI_NAME} - -
- -
-
-
Release Notes
-
-
- {$config && $config.version ? $config.version : WEB_UI_VERSION} -
-
-
-
- {#if !hasValidNotes} -
There are no notes given.
- -
- Check - - Open WebUI on GitHub for more information. -
- {:else} - {#each RELEASE_NOTES as { title, description }} -
-
{title}
-
{description}
-
- {/each} - {/if} -
-
- -
-
- diff --git a/src/lib/constants.ts b/src/lib/constants.ts index ac5faed6f..698f021f3 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -12,29 +12,6 @@ export const IMAGES_API_BASE_URL = `${WEBUI_BASE_URL}/images/api/v1`; export const RAG_API_BASE_URL = `${WEBUI_BASE_URL}/rag/api/v1`; export const WEB_UI_VERSION = APP_VERSION; -export const RELEASE_NOTES = [ - { - title: ' 🖼️ Image Generation', - description: - 'Generate Images using the stable-difusion-webui API. You can set this up in settings -> images.' - }, - { - title: ' 📝 Change title generation prompt', - description: - 'Change the promt used to generate titles for your chats. You can set this up in the settings -> interface.' - }, - { - title: ' 🤖 Change embedding model', - description: - 'Change the embedding model used to generate embeddings for your chats in the Dockerfile. Use any sentence transformer model from huggingface.co.' - }, - { - title: ' 📢 This Whats Changed Popup', - description: - 'This popup will show you the latest changes. You can edit it in the constants.ts file.' - } - //... -]; export const REQUIRED_OLLAMA_VERSION = '0.1.16'; export const SUPPORTED_FILE_TYPE = [ diff --git a/src/lib/stores/index.ts b/src/lib/stores/index.ts index d9814368d..7880235cf 100644 --- a/src/lib/stores/index.ts +++ b/src/lib/stores/index.ts @@ -32,16 +32,3 @@ export const documents = writable([ export const settings = writable({}); export const showSettings = writable(false); -function createLocalStorageStore(key, startValue) { - const storedValue = localStorage.getItem(key); - const initialValue = storedValue ? JSON.parse(storedValue) : startValue; - - const store = writable(initialValue); - - store.subscribe((value) => { - localStorage.setItem(key, JSON.stringify(value)); - }); - - return store; -} -export const showWhatsChanged = createLocalStorageStore('showWhatsChanged', true); diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index af3bb31c4..8ef8991d2 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -31,6 +31,7 @@ import ShortcutsModal from '$lib/components/chat/ShortcutsModal.svelte'; import { getDocs } from '$lib/apis/documents'; import { getAllChatTags } from '$lib/apis/chats'; + import ChangelogModal from '$lib/components/ChangelogModal.svelte'; let ollamaVersion = ''; let loaded = false; @@ -348,6 +349,8 @@
+ {:else} + {/if}
- {#if $showWhatsChanged && !['pending'].includes($user.role) && $settings.enableWhatsChanged} - - {/if} 0} {initNewChat} {tags} {addTag} {deleteTag} />