Skip to content

Commit

Permalink
Merge pull request #9 from SkywardAI/first-time-setup
Browse files Browse the repository at this point in the history
add settings on user start application
  • Loading branch information
cbh778899 authored Sep 12, 2024
2 parents 09c6726 + ba11d6e commit 8c4bab0
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 26 deletions.
16 changes: 3 additions & 13 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useEffect, useState } from "react";
import { useState } from "react";
import { createBrowserRouter, Navigate, RouterProvider, } from "react-router-dom";
import Sidebar from "./sidebar";
import Chat from "./chat";
import Settings from "./Settings";
import useIDB from "../utils/idb";
import Entry from "./Entry";

export default function App() {
const router = useState(createBrowserRouter([
Expand All @@ -26,17 +26,7 @@ export default function App() {
]
},
]))[0];

const idb = useIDB();
const [warmup, setWarmUp] = useState(false);

useEffect(()=>{
(async function() {
await idb.initDB();
setWarmUp(true);
})()
// eslint-disable-next-line
}, [])

return warmup ? <RouterProvider router={router} /> : <></>
return warmup ? <RouterProvider router={router} /> : <Entry complete={()=>setWarmUp(true)} />
}
68 changes: 68 additions & 0 deletions src/components/Entry.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useEffect, useState } from 'react'
import useIDB from '../utils/idb'
import { downloadModel, isModelDownloaded, loadModel } from '../utils/worker'

export default function Entry({complete}) {

const [loadStep, setLoadStep] = useState(0);
const [download_progress, setProgress] = useState(-1);
const idb = useIDB();

async function firstTimeSetup() {
if(!(await isModelDownloaded())) {
await downloadModel('completion', (progress)=>{
setProgress(progress);
})
}
localStorage.setItem('not-first-time', '1');
setLoadStep(2);
}

async function startUp() {
await idb.initDB();
loadStep !== 3 && await loadModel();
complete();
}

useEffect(()=>{
loadStep >= 2 && startUp();
// eslint-disable-next-line
}, [loadStep])

useEffect(()=>{
setLoadStep(
1+!!localStorage.getItem('not-first-time')
)
}, [])

return (
<div className='load-page'>
{
loadStep === 0 ?
<div className='loading'>Loading, please wait...</div> :
loadStep === 1 ?
<div className="first-time">
<div className="title">Welcome to SkywardAI Chat!</div>
<div className="description">
Seems like this is the first time you using SkywardAI Chat.<br/>
To start chat, you need to download a basic model that is around 400MiB.<br/>
You don&apos;t need to download it again in the future<br/>
If you want to use your own model or you want to setup later, please skip.
</div>
{
download_progress < 0 ?
<>
<div className="download-model clickable" onClick={firstTimeSetup}>Set Me Up Now!</div>
<div className="skip clickable" onClick={()=>setLoadStep(2)}>Skip for now</div>
</> :
<div className='download-progress'>
<div className='progress-bar' style={{transform: `translateX(-${100-download_progress}%)`}}></div>
<div className='progress-num'>{Math.round(download_progress)}%</div>
</div>
}
</div>:
<div className='loading'>Loading necessary resources, please wait...</div>
}
</div>
)
}
3 changes: 3 additions & 0 deletions src/components/chat/Conversation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ export default function Conversation({ uid }) {
content: text,
createdAt: Date.now()
})
idb.updateOne(
'chat-history', {updatedAt: Date.now()}, [{uid}]
)
setHidePending(true);
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/components/chat/Tickets.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export default function Tickets({selectChat, current_chat}) {
const idb = useIDB();

async function syncHistory() {
setTickets(await idb.getAll('chat-history'))
const history = await idb.getAll('chat-history')
history.sort((a, b)=>b.updatedAt - a.updatedAt)
setTickets(history)
}

async function startNewConversation() {
Expand All @@ -22,7 +24,7 @@ export default function Tickets({selectChat, current_chat}) {
uid: genRandomID()
}
)
const new_conv_info = await idb.getById('chat-history', conv_id);
const new_conv_info = await idb.getByID('chat-history', conv_id);
new_conv_info &&
setTickets([
...tickets,
Expand Down
1 change: 1 addition & 0 deletions src/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import App from './components/App';
import './styles/index.css';
import './styles/sidebar.css';
import './styles/chat.css';
import './styles/entry.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
Expand Down
80 changes: 80 additions & 0 deletions src/styles/entry.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
.load-page > .loading {
width: 100%;
user-select: none;
text-align: center;
color: gray;
margin-top: 20px;
}

.load-page > .first-time {
width: 100%;
padding: 60px 40px;
text-align: center;
}

.load-page > .first-time > .title {
font-size: 30px;
color: gray;
}

.load-page > .first-time > .description {
font-size: 18px;
color: gray;
margin-top: 20px;
line-height: 25px;
}

.load-page > .first-time > .download-model {
width: 270px;
height: 40px;
border-radius: 10px;
align-content: center;
margin: auto;
background-color: rgb(150, 150, 150);
margin-top: 20px;
color: white;
user-select: none;
font-size: 20px;
transition-duration: .3s;
}
.load-page > .first-time > .download-model:hover {
background-color: gray;
}

.load-page > .first-time > .skip {
width: fit-content;
margin: auto;
margin-top: 10px;
text-decoration: underline;
color: gray;
}

.load-page > .first-time > .download-progress {
margin: auto;
margin-top: 20px;
width: 500px;
background-color: lightgray;
border-radius: 20px;
height: 20px;
align-content: center;
font-size: 12px;
color: white;
position: relative;
overflow: hidden;
}

.load-page > .first-time > .download-progress > .progress-bar {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: limegreen;
transform: translateX(-100%);
z-index: 1;
}

.load-page > .first-time > .download-progress > .progress-num {
z-index: 2;
position: relative;
}
4 changes: 2 additions & 2 deletions src/styles/sidebar.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
}
.app-sidebar > .section > .item > svg {
color: gray;
width: 50%;
height: 50%;
width: 45%;
height: 45%;
margin: auto;
}
12 changes: 7 additions & 5 deletions src/utils/idb/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class IDB {
resolved = true;
}; return;
case "update-one":
cursor.update(value).onsuccess = () => {
cursor.update({...cursor.value, ...value}).onsuccess = () => {
resolve(true);
resolved = true;
}; return;
Expand All @@ -107,7 +107,7 @@ class IDB {
};
cursor.continue(); return;
case 'update-all':
cursor.update(value).onerror = () => {
cursor.update({...cursor.value, ...value}).onerror = () => {
resolve(false);
resolved = true;
};
Expand Down Expand Up @@ -214,7 +214,7 @@ class IDB {
* @param {String[]|null} select list of keys to be selected
* @returns {Promise<Object>}
*/
getById(table, id, select = null) {
getByID(table, id, select = null) {
return new Promise(resolve=>{
const req = this._getTable(table, 'readonly').get(id);
req.onsuccess = () => resolve(formatSelect(select, req.result));
Expand Down Expand Up @@ -242,9 +242,11 @@ class IDB {
})
}

updateByID(table, id, column) {
async updateByID(table, id, column) {
const record = await this.getByID(table, id);
if(!record) return false;
return new Promise(resolve=>{
const req = this._getTable(table, 'readwrite').put(column, id);
const req = this._getTable(table, 'readwrite').put({...record, ...column}, id);
req.onsuccess = () => resolve(true);
req.onerror = () => resolve(false);
})
Expand Down
2 changes: 1 addition & 1 deletion src/utils/idb/settings.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const DEFAULT_TABLE_SETTINGS = { keyPath: 'id', autoIncrement: true }
export const DEFAULT_TABLE_SETTINGS = { autoIncrement: true }

export const DB_NAME = 'shibuya-idb'

Expand Down
5 changes: 2 additions & 3 deletions src/utils/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,9 @@ export async function chatCompletions(messages, cb = null) {
try {
const prompt = await formatPrompt(messages)
const result = await engines['completion'].instance.createCompletion(prompt, {
nPredict: 128,
nPredict: 256,
sampling: {
temp: 0.7,
top_p: 0.9
temp: 0.7
},
onNewToken: (token, piece, currentText, optionals) => {
cb && cb(currentText, false);
Expand Down

0 comments on commit 8c4bab0

Please sign in to comment.