forked from open-webui/open-webui
		
	feat: chat export
This commit is contained in:
		
							parent
							
								
									a2b1e3756b
								
							
						
					
					
						commit
						4221594778
					
				
					 5 changed files with 81 additions and 11 deletions
				
			
		|  | @ -1,7 +1,7 @@ | ||||||
| from fastapi import FastAPI, Request, Depends, HTTPException | from fastapi import FastAPI, Request, Depends, HTTPException | ||||||
| from fastapi.middleware.cors import CORSMiddleware | from fastapi.middleware.cors import CORSMiddleware | ||||||
| 
 | 
 | ||||||
| from apps.web.routers import auths, users, chats, utils | from apps.web.routers import auths, users, chats, modelfiles, utils | ||||||
| from config import WEBUI_VERSION, WEBUI_AUTH | from config import WEBUI_VERSION, WEBUI_AUTH | ||||||
| 
 | 
 | ||||||
| app = FastAPI() | app = FastAPI() | ||||||
|  | @ -19,8 +19,11 @@ app.add_middleware( | ||||||
| 
 | 
 | ||||||
| app.include_router(auths.router, prefix="/auths", tags=["auths"]) | app.include_router(auths.router, prefix="/auths", tags=["auths"]) | ||||||
| app.include_router(users.router, prefix="/users", tags=["users"]) | app.include_router(users.router, prefix="/users", tags=["users"]) | ||||||
| app.include_router(utils.router, prefix="/utils", tags=["utils"]) |  | ||||||
| app.include_router(chats.router, prefix="/chats", tags=["chats"]) | app.include_router(chats.router, prefix="/chats", tags=["chats"]) | ||||||
|  | app.include_router(modelfiles.router, prefix="/modelfiles", tags=["modelfiles"]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | app.include_router(utils.router, prefix="/utils", tags=["utils"]) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @app.get("/") | @app.get("/") | ||||||
|  |  | ||||||
|  | @ -123,6 +123,14 @@ class ChatTable: | ||||||
|             # .offset(skip) |             # .offset(skip) | ||||||
|         ] |         ] | ||||||
| 
 | 
 | ||||||
|  |     def get_all_chats_by_user_id(self, user_id: str) -> List[ChatModel]: | ||||||
|  |         return [ | ||||||
|  |             ChatModel(**model_to_dict(chat)) | ||||||
|  |             for chat in Chat.select() | ||||||
|  |             .where(Chat.user_id == user_id) | ||||||
|  |             .order_by(Chat.timestamp.desc()) | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|     def get_chat_by_id_and_user_id(self, id: str, user_id: str) -> Optional[ChatModel]: |     def get_chat_by_id_and_user_id(self, id: str, user_id: str) -> Optional[ChatModel]: | ||||||
|         try: |         try: | ||||||
|             chat = Chat.get(Chat.id == id, Chat.user_id == user_id) |             chat = Chat.get(Chat.id == id, Chat.user_id == user_id) | ||||||
|  |  | ||||||
|  | @ -43,6 +43,28 @@ async def get_user_chats(skip: int = 0, limit: int = 50, cred=Depends(bearer_sch | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | ############################ | ||||||
|  | # GetAllChats | ||||||
|  | ############################ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @router.get("/all", response_model=List[ChatResponse]) | ||||||
|  | async def get_all_user_chats(cred=Depends(bearer_scheme)): | ||||||
|  |     token = cred.credentials | ||||||
|  |     user = Users.get_user_by_token(token) | ||||||
|  | 
 | ||||||
|  |     if user: | ||||||
|  |         return [ | ||||||
|  |             ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)}) | ||||||
|  |             for chat in Chats.get_all_chats_by_user_id(user.id) | ||||||
|  |         ] | ||||||
|  |     else: | ||||||
|  |         raise HTTPException( | ||||||
|  |             status_code=status.HTTP_401_UNAUTHORIZED, | ||||||
|  |             detail=ERROR_MESSAGES.INVALID_TOKEN, | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ############################ | ############################ | ||||||
| # CreateNewChat | # CreateNewChat | ||||||
| ############################ | ############################ | ||||||
|  |  | ||||||
|  | @ -62,6 +62,37 @@ export const getChatList = async (token: string = '') => { | ||||||
| 	return res; | 	return res; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | export const getAllChats = async (token: string) => { | ||||||
|  | 	let error = null; | ||||||
|  | 
 | ||||||
|  | 	const res = await fetch(`${WEBUI_API_BASE_URL}/chats/all`, { | ||||||
|  | 		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(); | ||||||
|  | 		}) | ||||||
|  | 		.then((json) => { | ||||||
|  | 			return json; | ||||||
|  | 		}) | ||||||
|  | 		.catch((err) => { | ||||||
|  | 			error = err; | ||||||
|  | 			console.log(err); | ||||||
|  | 			return null; | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 	if (error) { | ||||||
|  | 		throw error; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return res; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| export const getChatById = async (token: string, id: string) => { | export const getChatById = async (token: string, id: string) => { | ||||||
| 	let error = null; | 	let error = null; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,20 +1,23 @@ | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| 	import Modal from '../common/Modal.svelte'; | 	import toast from 'svelte-french-toast'; | ||||||
|  | 	import fileSaver from 'file-saver'; | ||||||
|  | 	const { saveAs } = fileSaver; | ||||||
| 
 | 
 | ||||||
|  | 	import { onMount } from 'svelte'; | ||||||
|  | 	import { config, models, settings, user, chats } from '$lib/stores'; | ||||||
|  | 	import { splitStream, getGravatarURL } from '$lib/utils'; | ||||||
|  | 
 | ||||||
|  | 	import { getOllamaVersion } from '$lib/apis/ollama'; | ||||||
|  | 	import { createNewChat, getAllChats, getChatList } from '$lib/apis/chats'; | ||||||
| 	import { | 	import { | ||||||
| 		WEB_UI_VERSION, | 		WEB_UI_VERSION, | ||||||
| 		OLLAMA_API_BASE_URL, | 		OLLAMA_API_BASE_URL, | ||||||
| 		WEBUI_API_BASE_URL, | 		WEBUI_API_BASE_URL, | ||||||
| 		WEBUI_BASE_URL | 		WEBUI_BASE_URL | ||||||
| 	} from '$lib/constants'; | 	} from '$lib/constants'; | ||||||
| 	import toast from 'svelte-french-toast'; | 
 | ||||||
| 	import { onMount } from 'svelte'; |  | ||||||
| 	import { config, models, settings, user, chats } from '$lib/stores'; |  | ||||||
| 	import { splitStream, getGravatarURL } from '$lib/utils'; |  | ||||||
| 	import Advanced from './Settings/Advanced.svelte'; | 	import Advanced from './Settings/Advanced.svelte'; | ||||||
| 	import { stringify } from 'postcss'; | 	import Modal from '../common/Modal.svelte'; | ||||||
| 	import { getOllamaVersion } from '$lib/apis/ollama'; |  | ||||||
| 	import { createNewChat, getChatList } from '$lib/apis/chats'; |  | ||||||
| 
 | 
 | ||||||
| 	export let show = false; | 	export let show = false; | ||||||
| 
 | 
 | ||||||
|  | @ -91,7 +94,10 @@ | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	const exportChats = async () => { | 	const exportChats = async () => { | ||||||
| 		console.log('TODO: export all chats'); | 		let blob = new Blob([JSON.stringify(await getAllChats(localStorage.token))], { | ||||||
|  | 			type: 'application/json' | ||||||
|  | 		}); | ||||||
|  | 		saveAs(blob, `chat-export-${Date.now()}.json`); | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	$: if (importFiles) { | 	$: if (importFiles) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy J. Baek
						Timothy J. Baek