Commit 42215947 authored by Timothy J. Baek's avatar Timothy J. Baek
Browse files

feat: chat export

parent a2b1e375
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( ...@@ -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: ...@@ -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 ...@@ -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 = '') => { ...@@ -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;
......
<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 @@ ...@@ -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) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment