From 80bfb09972e6f865453f604c37d8c3ffb99f6327 Mon Sep 17 00:00:00 2001 From: josc146 Date: Sat, 13 May 2023 23:36:30 +0800 Subject: [PATCH] update --- .gitignore | 3 +- backend-golang/file.go | 62 +++++++++++++++++++-- backend-golang/rwkv.go | 1 - frontend/src/pages/Models.tsx | 35 ++++++++---- frontend/src/startup.ts | 48 ++++++++++++++-- frontend/src/stores/commonStore.ts | 8 +-- frontend/wailsjs/go/backend_golang/App.d.ts | 7 ++- frontend/wailsjs/go/backend_golang/App.js | 12 +++- frontend/wailsjs/go/models.ts | 23 ++++++++ manifest.json | 3 +- 10 files changed, 170 insertions(+), 32 deletions(-) create mode 100644 frontend/wailsjs/go/models.ts diff --git a/.gitignore b/.gitignore index 7e6c48b..ca4aef3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ __pycache__ package.json.md5 cache.json stats.html -models \ No newline at end of file +*.pth +*.bin \ No newline at end of file diff --git a/backend-golang/file.go b/backend-golang/file.go index 73c62a6..01f996e 100644 --- a/backend-golang/file.go +++ b/backend-golang/file.go @@ -2,7 +2,11 @@ package backend_golang import ( "encoding/json" + "fmt" "os" + "os/exec" + "runtime" + "time" "github.com/cavaliergopher/grab/v3" ) @@ -42,16 +46,46 @@ func (a *App) FileExists(fileName string) (bool, error) { return false, err } -func (a *App) FileInfo(fileName string) (any, error) { +type FileInfo struct { + Name string `json:"name"` + Size int64 `json:"size"` + IsDir bool `json:"isDir"` + ModTime string `json:"modTime"` +} + +func (a *App) ReadFileInfo(fileName string) (FileInfo, error) { info, err := os.Stat(fileName) + if err != nil { + return FileInfo{}, err + } + return FileInfo{ + Name: info.Name(), + Size: info.Size(), + IsDir: info.IsDir(), + ModTime: info.ModTime().Format(time.RFC3339), + }, nil +} + +func (a *App) ListDirFiles(dirPath string) ([]FileInfo, error) { + files, err := os.ReadDir(dirPath) if err != nil { return nil, err } - return map[string]any{ - "name": info.Name(), - "size": info.Size(), - "isDir": info.IsDir(), - }, nil + + var filesInfo []FileInfo + for _, file := range files { + info, err := file.Info() + if err != nil { + return nil, err + } + filesInfo = append(filesInfo, FileInfo{ + Name: info.Name(), + Size: info.Size(), + IsDir: info.IsDir(), + ModTime: info.ModTime().Format(time.RFC3339), + }) + } + return filesInfo, nil } func (a *App) DownloadFile(path string, url string) error { @@ -61,3 +95,19 @@ func (a *App) DownloadFile(path string, url string) error { } return nil } + +func (a *App) OpenFileFolder(path string) error { + switch os := runtime.GOOS; os { + case "windows": + cmd := exec.Command("explorer", "/select,", path) + err := cmd.Run() + if err != nil { + return err + } + case "darwin": + fmt.Println("Running on macOS") + case "linux": + fmt.Println("Running on Linux") + } + return nil +} diff --git a/backend-golang/rwkv.go b/backend-golang/rwkv.go index 8f6a01b..df51334 100644 --- a/backend-golang/rwkv.go +++ b/backend-golang/rwkv.go @@ -5,7 +5,6 @@ import ( ) func (a *App) StartServer(strategy string, modelPath string) (string, error) { - //cmd := exec.Command(`explorer`, `/select,`, `e:\RWKV-4-Raven-7B-v10-Eng49%25-Chn50%25-Other1%25-20230420-ctx4096.pth`) cmd := exec.Command("cmd-helper", "python", "./backend-python/main.py", strategy, modelPath) out, err := cmd.CombinedOutput() if err != nil { diff --git a/frontend/src/pages/Models.tsx b/frontend/src/pages/Models.tsx index bb5f0ed..9c93917 100644 --- a/frontend/src/pages/Models.tsx +++ b/frontend/src/pages/Models.tsx @@ -13,11 +13,12 @@ import { Textarea } from '@fluentui/react-components'; import {ToolTipButton} from '../components/ToolTipButton'; -import {ArrowClockwise20Regular, ArrowDownload20Regular, Open20Regular} from '@fluentui/react-icons'; +import {ArrowClockwise20Regular, ArrowDownload20Regular, Folder20Regular, Open20Regular} from '@fluentui/react-icons'; import {observer} from 'mobx-react-lite'; import commonStore, {ModelSourceItem} from '../stores/commonStore'; import {BrowserOpenURL} from '../../wailsjs/runtime'; -import {DownloadFile} from '../../wailsjs/go/backend_golang/App'; +import {DownloadFile, OpenFileFolder} from '../../wailsjs/go/backend_golang/App'; +import manifest from '../../../manifest.json'; const columns: TableColumnDefinition[] = [ createTableColumn({ @@ -39,7 +40,10 @@ const columns: TableColumnDefinition[] = [ createTableColumn({ columnId: 'desc', compare: (a, b) => { - return a.desc['en'].localeCompare(b.desc['en']); + if (a.desc && b.desc) + return a.desc['en'].localeCompare(b.desc['en']); + else + return 0; }, renderHeaderCell: () => { return 'Desc'; @@ -47,7 +51,7 @@ const columns: TableColumnDefinition[] = [ renderCell: (item) => { return ( - {item.desc['en']} + {item.desc && item.desc['en']} ); } @@ -75,7 +79,7 @@ const columns: TableColumnDefinition[] = [ a.lastUpdatedMs = Date.parse(a.lastUpdated); if (!b.lastUpdatedMs) b.lastUpdatedMs = Date.parse(b.lastUpdated); - return a.lastUpdatedMs - b.lastUpdatedMs; + return b.lastUpdatedMs - a.lastUpdatedMs; }, renderHeaderCell: () => { return 'Last updated'; @@ -88,7 +92,7 @@ const columns: TableColumnDefinition[] = [ createTableColumn({ columnId: 'actions', compare: (a, b) => { - return a.isDownloading ? 0 : a.isLocal ? 1 : 2; + return a.isDownloading ? 0 : a.isLocal ? -1 : 1; }, renderHeaderCell: () => { return 'Actions'; @@ -97,12 +101,19 @@ const columns: TableColumnDefinition[] = [ return (
- } onClick={() => { - DownloadFile(`./models/${item.name}`, item.downloadUrl); - }}/> - } onClick={() => { - BrowserOpenURL(item.url); - }}/> + { + item.isLocal && + } onClick={() => { + OpenFileFolder(`.\\${manifest.localModelPath}\\${item.name}`); + }}/> + } + {item.downloadUrl && !item.isLocal && + } onClick={() => { + DownloadFile(`./${manifest.localModelPath}/${item.name}`, item.downloadUrl!); + }}/>} + {item.url && } onClick={() => { + BrowserOpenURL(item.url!); + }}/>}
); diff --git a/frontend/src/startup.ts b/frontend/src/startup.ts index 753eec3..2f68856 100644 --- a/frontend/src/startup.ts +++ b/frontend/src/startup.ts @@ -1,5 +1,5 @@ import commonStore, {ModelSourceItem} from './stores/commonStore'; -import {ReadJson, SaveJson} from '../wailsjs/go/backend_golang/App'; +import {ListDirFiles, ReadJson, SaveJson} from '../wailsjs/go/backend_golang/App'; import manifest from '../../manifest.json'; export async function startup() { @@ -15,14 +15,53 @@ async function initConfig() { await ReadJson('cache.json').then((cacheData: Cache) => { cache = cacheData; }).catch( - () => { + async () => { cache = {models: manifest.models}; - SaveJson('cache.json', cache).catch(() => { + await SaveJson('cache.json', cache).catch(() => { }); } ); + // built-in commonStore.setModelSourceList(cache.models); + await ListDirFiles(manifest.localModelPath).then((data) => { + cache.models.push(...data.flatMap(d => { + if (!d.isDir && d.name.endsWith('.pth')) + return [{ + name: d.name, + size: d.size, + lastUpdated: d.modTime, + isLocal: true + }]; + return []; + })); + }).catch(() => { + }); + + for (let i = 0; i < cache.models.length; i++) { + if (!cache.models[i].lastUpdatedMs) + cache.models[i].lastUpdatedMs = Date.parse(cache.models[i].lastUpdated); + + for (let j = i + 1; j < cache.models.length; j++) { + if (!cache.models[j].lastUpdatedMs) + cache.models[j].lastUpdatedMs = Date.parse(cache.models[j].lastUpdated); + + if (cache.models[i].name === cache.models[j].name && cache.models[i].size === cache.models[j].size) { + if (cache.models[i].lastUpdatedMs! < cache.models[j].lastUpdatedMs!) { + cache.models[i] = Object.assign({}, cache.models[i], cache.models[j]); + } else { + cache.models[i] = Object.assign({}, cache.models[j], cache.models[i]); + } + cache.models.splice(j, 1); + j--; + } + } + } + // local files + commonStore.setModelSourceList(cache.models); + await SaveJson('cache.json', cache).catch(() => { + }); + const manifestUrls = commonStore.modelSourceManifestList.split(/[,,;;\n]/); const requests = manifestUrls.filter(url => url.endsWith('.json')).map( url => fetch(url, {cache: 'no-cache'}).then(r => r.json())); @@ -40,7 +79,8 @@ async function initConfig() { cache.models = cache.models.filter((model, index, self) => { return model.name.endsWith('.pth') && index === self.findIndex(m => m.SHA256 === model.SHA256 && m.size === model.size); }); + // remote files commonStore.setModelSourceList(cache.models); - SaveJson('cache.json', cache).catch(() => { + await SaveJson('cache.json', cache).catch(() => { }); } \ No newline at end of file diff --git a/frontend/src/stores/commonStore.ts b/frontend/src/stores/commonStore.ts index f365c31..d1596d2 100644 --- a/frontend/src/stores/commonStore.ts +++ b/frontend/src/stores/commonStore.ts @@ -9,12 +9,12 @@ export enum ModelStatus { export type ModelSourceItem = { name: string; - desc: { [lang: string]: string; }; size: number; lastUpdated: string; - SHA256: string; - url: string; - downloadUrl: string; + desc?: { [lang: string]: string; }; + SHA256?: string; + url?: string; + downloadUrl?: string; isLocal?: boolean; isDownloading?: boolean; lastUpdatedMs?: number; diff --git a/frontend/wailsjs/go/backend_golang/App.d.ts b/frontend/wailsjs/go/backend_golang/App.d.ts index 1cad9a3..8253285 100644 --- a/frontend/wailsjs/go/backend_golang/App.d.ts +++ b/frontend/wailsjs/go/backend_golang/App.d.ts @@ -1,11 +1,16 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +import {backend_golang} from '../models'; export function DownloadFile(arg1:string,arg2:string):Promise; export function FileExists(arg1:string):Promise; -export function FileInfo(arg1:string):Promise; +export function ListDirFiles(arg1:string):Promise>; + +export function OpenFileFolder(arg1:string):Promise; + +export function ReadFileInfo(arg1:string):Promise; export function ReadJson(arg1:string):Promise; diff --git a/frontend/wailsjs/go/backend_golang/App.js b/frontend/wailsjs/go/backend_golang/App.js index 690f0cb..4162580 100644 --- a/frontend/wailsjs/go/backend_golang/App.js +++ b/frontend/wailsjs/go/backend_golang/App.js @@ -10,8 +10,16 @@ export function FileExists(arg1) { return window['go']['backend_golang']['App']['FileExists'](arg1); } -export function FileInfo(arg1) { - return window['go']['backend_golang']['App']['FileInfo'](arg1); +export function ListDirFiles(arg1) { + return window['go']['backend_golang']['App']['ListDirFiles'](arg1); +} + +export function OpenFileFolder(arg1) { + return window['go']['backend_golang']['App']['OpenFileFolder'](arg1); +} + +export function ReadFileInfo(arg1) { + return window['go']['backend_golang']['App']['ReadFileInfo'](arg1); } export function ReadJson(arg1) { diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts new file mode 100644 index 0000000..30edb01 --- /dev/null +++ b/frontend/wailsjs/go/models.ts @@ -0,0 +1,23 @@ +export namespace backend_golang { + + export class FileInfo { + name: string; + size: number; + isDir: boolean; + modTime: string; + + static createFrom(source: any = {}) { + return new FileInfo(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.size = source["size"]; + this.isDir = source["isDir"]; + this.modTime = source["modTime"]; + } + } + +} + diff --git a/manifest.json b/manifest.json index 400ebf3..05476d5 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,7 @@ { "version": "1.0.0", - "program-files": [ + "localModelPath": "models", + "programFiles": [ { "url": "https://cdn.jsdelivr.net/gh/josstorer/RWKV-Runner/backend-python/main.py", "path": "backend-python/main.py"