Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c5eae1983 | ||
|
|
375af3bc1a | ||
|
|
85493da730 | ||
|
|
bbad153ecb | ||
|
|
035c6ab8de | ||
|
|
c98c32f2f6 | ||
|
|
b2960052d9 | ||
|
|
74ceffb32c | ||
|
|
c40e57aafd | ||
|
|
394a7aef42 | ||
|
|
927d1a78b5 | ||
|
|
39222f037d |
84
README.md
84
README.md
@@ -1,3 +1,83 @@
|
||||
# RWKV-Runner
|
||||
<p align="center">
|
||||
<img src="https://github.com/josStorer/RWKV-Runner/assets/13366013/d24834b0-265d-45f5-93c0-fac1e19562af">
|
||||
</p>
|
||||
|
||||
In development
|
||||
<h1 align="center">RWKV Runner</h1>
|
||||
|
||||
<div align="center">
|
||||
|
||||
This project aims to eliminate the barriers of using large language models by automating everything for you. All you
|
||||
need is a lightweight executable program of just a few megabytes. Additionally, this project provides an interface
|
||||
compatible with the OpenAI API, which means that every ChatGPT client is an RWKV client.
|
||||
|
||||
[![license][license-image]][license-url]
|
||||
[![release][release-image]][release-url]
|
||||
|
||||
English | [简体中文](README_ZH.md)
|
||||
|
||||
[Preview](#Preview) | [Download][download-url]
|
||||
|
||||
[license-image]: http://img.shields.io/badge/license-MIT-blue.svg
|
||||
|
||||
[license-url]: https://github.com/josStorer/RWKV-Runner/blob/master/LICENSE
|
||||
|
||||
[release-image]: https://img.shields.io/github/release/josStorer/RWKV-Runner.svg
|
||||
|
||||
[release-url]: https://github.com/josStorer/RWKV-Runner/releases/latest
|
||||
|
||||
[download-url]: https://github.com/josStorer/RWKV-Runner/releases/download/v1.0.0/RWKV-Runner_windows_x64.exe
|
||||
|
||||
</div>
|
||||
|
||||
## Features
|
||||
|
||||
- RWKV model management and one-click startup
|
||||
- Fully compatible with the OpenAI API, making every ChatGPT client an RWKV client. After starting the model,
|
||||
open http://127.0.0.1:8000/docs to view more details.
|
||||
- Automatic dependency installation, requiring only a lightweight executable program
|
||||
- User-friendly chat interaction interface included
|
||||
- Easy-to-understand and operate parameter configuration
|
||||
- Built-in model conversion tool
|
||||
- Built-in download management and remote model inspection
|
||||
- Multilingual localization
|
||||
- Theme switching
|
||||
- Automatic updates
|
||||
|
||||
## Todo
|
||||
|
||||
- Model training functionality
|
||||
- CUDA operator int8 acceleration
|
||||
- macOS support
|
||||
- Linux support
|
||||
|
||||
## Related Repositories:
|
||||
|
||||
- RWKV-4-Raven: https://huggingface.co/BlinkDL/rwkv-4-raven/tree/main
|
||||
- ChatRWKV: https://github.com/BlinkDL/ChatRWKV
|
||||
- RWKV-LM: https://github.com/BlinkDL/RWKV-LM
|
||||
|
||||
## Preview
|
||||
|
||||
### Homepage
|
||||
|
||||

|
||||
|
||||
### Chat
|
||||
|
||||

|
||||
|
||||
### Configuration
|
||||
|
||||

|
||||
|
||||
### Model Management
|
||||
|
||||

|
||||
|
||||
### Download Management
|
||||
|
||||

|
||||
|
||||
### Settings
|
||||
|
||||

|
||||
|
||||
81
README_ZH.md
Normal file
81
README_ZH.md
Normal file
@@ -0,0 +1,81 @@
|
||||
<p align="center">
|
||||
<img src="https://github.com/josStorer/RWKV-Runner/assets/13366013/d24834b0-265d-45f5-93c0-fac1e19562af">
|
||||
</p>
|
||||
|
||||
<h1 align="center">RWKV Runner</h1>
|
||||
|
||||
<div align="center">
|
||||
|
||||
本项目旨在消除大语言模型的使用门槛,全自动为你处理一切,你只需要一个仅仅几MB的可执行程序。此外本项目提供了与OpenAI
|
||||
API兼容的接口,这意味着一切ChatGPT客户端都是RWKV客户端。
|
||||
|
||||
[![license][license-image]][license-url]
|
||||
[![release][release-image]][release-url]
|
||||
|
||||
[English](README.md) | 简体中文
|
||||
|
||||
[预览](#Preview) | [下载][download-url]
|
||||
|
||||
[license-image]: http://img.shields.io/badge/license-MIT-blue.svg
|
||||
|
||||
[license-url]: https://github.com/josStorer/RWKV-Runner/blob/master/LICENSE
|
||||
|
||||
[release-image]: https://img.shields.io/github/release/josStorer/RWKV-Runner.svg
|
||||
|
||||
[release-url]: https://github.com/josStorer/RWKV-Runner/releases/latest
|
||||
|
||||
[download-url]: https://github.com/josStorer/RWKV-Runner/releases/download/v1.0.0/RWKV-Runner_windows_x64.exe
|
||||
|
||||
</div>
|
||||
|
||||
## 功能
|
||||
|
||||
- RWKV模型管理,一键启动
|
||||
- 与OpenAI API完全兼容,一切ChatGPT客户端,都是RWKV客户端。启动模型后,打开 http://127.0.0.1:8000/docs 查看详细内容
|
||||
- 全自动依赖安装,你只需要一个轻巧的可执行程序
|
||||
- 自带用户友好的聊天交互页面
|
||||
- 易于理解和操作的参数配置
|
||||
- 内置模型转换工具
|
||||
- 内置下载管理和远程模型检视
|
||||
- 多语言本地化
|
||||
- 主题切换
|
||||
- 自动更新
|
||||
|
||||
## Todo
|
||||
|
||||
- 模型训练功能
|
||||
- CUDA算子int8提速
|
||||
- macOS支持
|
||||
- linux支持
|
||||
|
||||
## 相关仓库:
|
||||
|
||||
- RWKV-4-Raven: https://huggingface.co/BlinkDL/rwkv-4-raven/tree/main
|
||||
- ChatRWKV: https://github.com/BlinkDL/ChatRWKV
|
||||
- RWKV-LM: https://github.com/BlinkDL/RWKV-LM
|
||||
|
||||
## Preview
|
||||
|
||||
### 主页
|
||||
|
||||

|
||||
|
||||
### 聊天
|
||||
|
||||

|
||||
|
||||
### 配置
|
||||
|
||||

|
||||
|
||||
### 模型管理
|
||||
|
||||

|
||||
|
||||
### 下载管理
|
||||
|
||||

|
||||
|
||||
### 设置
|
||||
|
||||

|
||||
@@ -53,5 +53,16 @@ def exit():
|
||||
parent.kill()
|
||||
|
||||
|
||||
def debug():
|
||||
model = RWKV(
|
||||
model="../models/RWKV-4-Raven-7B-v11-Eng49%-Chn49%-Jpn1%-Other1%-20230430-ctx8192.pth",
|
||||
strategy="cuda fp16",
|
||||
tokens_path="20B_tokenizer.json",
|
||||
)
|
||||
d = model.tokenizer.decode([])
|
||||
print(d)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run("main:app", port=8000 if len(sys.argv) == 1 else int(sys.argv[1]))
|
||||
# debug()
|
||||
|
||||
@@ -17,10 +17,11 @@ class Message(BaseModel):
|
||||
content: str
|
||||
|
||||
|
||||
class CompletionBody(ModelConfigBody):
|
||||
class ChatCompletionBody(ModelConfigBody):
|
||||
messages: List[Message]
|
||||
model: str = "rwkv"
|
||||
stream: bool = False
|
||||
stop: str = None
|
||||
|
||||
|
||||
completion_lock = Lock()
|
||||
@@ -28,7 +29,7 @@ completion_lock = Lock()
|
||||
|
||||
@router.post("/v1/chat/completions")
|
||||
@router.post("/chat/completions")
|
||||
async def completions(body: CompletionBody, request: Request):
|
||||
async def chat_completions(body: ChatCompletionBody, request: Request):
|
||||
model: RWKV = global_var.get(global_var.Model)
|
||||
if model is None:
|
||||
raise HTTPException(status.HTTP_400_BAD_REQUEST, "model not loaded")
|
||||
@@ -42,9 +43,23 @@ async def completions(body: CompletionBody, request: Request):
|
||||
completion_text = ""
|
||||
for message in body.messages:
|
||||
if message.role == "user":
|
||||
completion_text += "Bob: " + message.content + "\n\n"
|
||||
completion_text += (
|
||||
"Bob: "
|
||||
+ message.content.replace("\\n", "\n")
|
||||
.replace("\r\n", "\n")
|
||||
.replace("\n\n", "\n")
|
||||
.strip()
|
||||
+ "\n\n"
|
||||
)
|
||||
elif message.role == "assistant":
|
||||
completion_text += "Alice: " + message.content + "\n\n"
|
||||
completion_text += (
|
||||
"Alice: "
|
||||
+ message.content.replace("\\n", "\n")
|
||||
.replace("\r\n", "\n")
|
||||
.replace("\n\n", "\n")
|
||||
.strip()
|
||||
+ "\n\n"
|
||||
)
|
||||
completion_text += "Alice:"
|
||||
|
||||
async def eval_rwkv():
|
||||
@@ -56,7 +71,9 @@ async def completions(body: CompletionBody, request: Request):
|
||||
set_rwkv_config(model, body)
|
||||
if body.stream:
|
||||
for response, delta in rwkv_generate(
|
||||
model, completion_text, stop="\n\nBob"
|
||||
model,
|
||||
completion_text,
|
||||
stop="\n\nBob" if body.stop is None else body.stop,
|
||||
):
|
||||
if await request.is_disconnected():
|
||||
break
|
||||
@@ -93,7 +110,9 @@ async def completions(body: CompletionBody, request: Request):
|
||||
else:
|
||||
response = None
|
||||
for response, delta in rwkv_generate(
|
||||
model, completion_text, stop="\n\nBob"
|
||||
model,
|
||||
completion_text,
|
||||
stop="\n\nBob" if body.stop is None else body.stop,
|
||||
):
|
||||
if await request.is_disconnected():
|
||||
break
|
||||
@@ -121,3 +140,90 @@ async def completions(body: CompletionBody, request: Request):
|
||||
return EventSourceResponse(eval_rwkv())
|
||||
else:
|
||||
return await eval_rwkv().__anext__()
|
||||
|
||||
|
||||
class CompletionBody(ModelConfigBody):
|
||||
prompt: str
|
||||
model: str = "rwkv"
|
||||
stream: bool = False
|
||||
stop: str = None
|
||||
|
||||
|
||||
@router.post("/v1/completions")
|
||||
@router.post("/completions")
|
||||
async def completions(body: CompletionBody, request: Request):
|
||||
model: RWKV = global_var.get(global_var.Model)
|
||||
if model is None:
|
||||
raise HTTPException(status.HTTP_400_BAD_REQUEST, "model not loaded")
|
||||
|
||||
async def eval_rwkv():
|
||||
while completion_lock.locked():
|
||||
await asyncio.sleep(0.1)
|
||||
else:
|
||||
completion_lock.acquire()
|
||||
set_rwkv_config(model, global_var.get(global_var.Model_Config))
|
||||
set_rwkv_config(model, body)
|
||||
if body.stream:
|
||||
for response, delta in rwkv_generate(
|
||||
model, body.prompt, stop=body.stop
|
||||
):
|
||||
if await request.is_disconnected():
|
||||
break
|
||||
yield json.dumps(
|
||||
{
|
||||
"response": response,
|
||||
"model": "rwkv",
|
||||
"choices": [
|
||||
{
|
||||
"text": delta,
|
||||
"index": 0,
|
||||
"finish_reason": None,
|
||||
}
|
||||
],
|
||||
}
|
||||
)
|
||||
if await request.is_disconnected():
|
||||
completion_lock.release()
|
||||
return
|
||||
yield json.dumps(
|
||||
{
|
||||
"response": response,
|
||||
"model": "rwkv",
|
||||
"choices": [
|
||||
{
|
||||
"text": "",
|
||||
"index": 0,
|
||||
"finish_reason": "stop",
|
||||
}
|
||||
],
|
||||
}
|
||||
)
|
||||
yield "[DONE]"
|
||||
else:
|
||||
response = None
|
||||
for response, delta in rwkv_generate(
|
||||
model, body.prompt, stop=body.stop
|
||||
):
|
||||
if await request.is_disconnected():
|
||||
break
|
||||
if await request.is_disconnected():
|
||||
completion_lock.release()
|
||||
return
|
||||
yield {
|
||||
"response": response,
|
||||
"model": "rwkv",
|
||||
"choices": [
|
||||
{
|
||||
"text": response,
|
||||
"index": 0,
|
||||
"finish_reason": "stop",
|
||||
}
|
||||
],
|
||||
}
|
||||
# torch_gc()
|
||||
completion_lock.release()
|
||||
|
||||
if body.stream:
|
||||
return EventSourceResponse(eval_rwkv())
|
||||
else:
|
||||
return await eval_rwkv().__anext__()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import zhHans from './zh-hans/main.json'
|
||||
import zhHans from './zh-hans/main.json';
|
||||
|
||||
export const resources = {
|
||||
zh: {
|
||||
@@ -34,4 +34,4 @@ export const resources = {
|
||||
// zhHant: {
|
||||
// translation: zhHant,
|
||||
// },
|
||||
}
|
||||
};
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
"Copy": "复制",
|
||||
"Read Aloud": "朗读",
|
||||
"Hello! I'm RWKV, an open-source and commercially available large language model.": "你好! 我是RWKV, 一个开源可商用的大语言模型.",
|
||||
"This tool’s API is compatible with OpenAI API. It can be used with any ChatGPT tool you like. Go to the settings of some ChatGPT tool, replace the 'https://api.openai.com' part in the API address with '": "本工具的API与OpenAI API兼容. 因此可以配合任意你喜欢的ChatGPT工具使用. 打开某个ChatGPT工具的设置, 将API地址中的'https://api.openai.com'部分替换为'",
|
||||
"This tool's API is compatible with OpenAI API. It can be used with any ChatGPT tool you like. Go to the settings of some ChatGPT tool, replace the 'https://api.openai.com' part in the API address with '": "本工具的API与OpenAI API兼容. 因此可以配合任意你喜欢的ChatGPT工具使用. 打开某个ChatGPT工具的设置, 将API地址中的'https://api.openai.com'部分替换为'",
|
||||
"New Version Available": "新版本可用",
|
||||
"Update": "更新",
|
||||
"Please click the button in the top right corner to start the model": "请点击右上角的按钮启动模型",
|
||||
@@ -96,5 +96,6 @@
|
||||
"Install": "安装",
|
||||
"This is the latest version": "已是最新版",
|
||||
"Use Tsinghua Pip Mirrors": "使用清华大学Pip镜像源",
|
||||
"Model Config Exception": "模型配置异常"
|
||||
"Model Config Exception": "模型配置异常",
|
||||
"Use Gitee Updates Source": "使用Gitee更新源"
|
||||
}
|
||||
@@ -46,7 +46,8 @@ export const ReadButton: FC<{ content: string }> = observer(({content}) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<ToolTipButton desc={t('Read Aloud')} size="small" appearance="subtle" icon={speaking ? <MuteIcon/> : <UnmuteIcon/>}
|
||||
<ToolTipButton desc={t('Read Aloud')} size="small" appearance="subtle"
|
||||
icon={speaking ? <MuteIcon /> : <UnmuteIcon />}
|
||||
onClick={speaking ? stopSpeak : startSpeak} />
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import React, { FC, MouseEventHandler, ReactElement } from 'react';
|
||||
import commonStore, { ModelStatus } from '../stores/commonStore';
|
||||
import { AddToDownloadList, DepCheck, FileExists, InstallPyDep, StartServer } from '../../wailsjs/go/backend_golang/App';
|
||||
import {
|
||||
AddToDownloadList,
|
||||
DepCheck,
|
||||
FileExists,
|
||||
InstallPyDep,
|
||||
StartServer
|
||||
} from '../../wailsjs/go/backend_golang/App';
|
||||
import { Button } from '@fluentui/react-components';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { exit, readRoot, switchModel, updateConfig } from '../apis';
|
||||
@@ -40,8 +46,8 @@ export const RunButton: FC<{ onClickRun?: MouseEventHandler, iconMode?: boolean
|
||||
commonStore.setModelStatus(ModelStatus.Starting);
|
||||
|
||||
const modelConfig = commonStore.getCurrentModelConfig();
|
||||
let modelName = ''
|
||||
let modelPath = ''
|
||||
let modelName = '';
|
||||
let modelPath = '';
|
||||
if (modelConfig && modelConfig.modelParameters) {
|
||||
modelName = modelConfig.modelParameters.modelName;
|
||||
modelPath = `./${manifest.localModelDir}/${modelName}`;
|
||||
@@ -66,7 +72,7 @@ export const RunButton: FC<{ onClickRun?: MouseEventHandler, iconMode?: boolean
|
||||
} else if (depErrorMsg.includes('DepCheck Error')) {
|
||||
toastWithButton(t('Python dependencies are incomplete, would you like to install them?'), t('Install'), () => {
|
||||
InstallPyDep(commonStore.settings.cnMirror);
|
||||
setTimeout(WindowShow, 1000)
|
||||
setTimeout(WindowShow, 1000);
|
||||
});
|
||||
} else {
|
||||
toast(depErrorMsg, { type: 'error' });
|
||||
@@ -103,7 +109,7 @@ export const RunButton: FC<{ onClickRun?: MouseEventHandler, iconMode?: boolean
|
||||
await exit(1000).catch(() => {
|
||||
});
|
||||
StartServer(port);
|
||||
setTimeout(WindowShow, 1000)
|
||||
setTimeout(WindowShow, 1000);
|
||||
|
||||
let timeoutCount = 6;
|
||||
let loading = false;
|
||||
|
||||
@@ -170,6 +170,7 @@ const ChatPanel: FC = observer(() => {
|
||||
scrollToBottom();
|
||||
if (e.data === '[DONE]') {
|
||||
commonStore.conversations[answerId].done = true;
|
||||
commonStore.conversations[answerId].content = commonStore.conversations[answerId].content.trim();
|
||||
commonStore.setConversations(commonStore.conversations);
|
||||
commonStore.setConversationsOrder([...commonStore.conversationsOrder]);
|
||||
return;
|
||||
@@ -322,7 +323,7 @@ export const Chat: FC = observer(() => {
|
||||
</div>
|
||||
</div>
|
||||
<Text size={100}>
|
||||
{t('This tool’s API is compatible with OpenAI API. It can be used with any ChatGPT tool you like. Go to the settings of some ChatGPT tool, replace the \'https://api.openai.com\' part in the API address with \'') + `http://127.0.0.1:${port}` + '\'.'}
|
||||
{t('This tool\'s API is compatible with OpenAI API. It can be used with any ChatGPT tool you like. Go to the settings of some ChatGPT tool, replace the \'https://api.openai.com\' part in the API address with \'') + `http://127.0.0.1:${port}` + '\'.'}
|
||||
</Text>
|
||||
<Divider style={{ flexGrow: 0 }} />
|
||||
<ChatPanel />
|
||||
|
||||
@@ -633,7 +633,7 @@ export const Configs: FC = observer(() => {
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||
<Labeled label={t('API Port')}
|
||||
desc={t('Open the following URL with your browser to view the API documentation') + `: http://127.0.0.1:${port}/docs. ` +
|
||||
t('This tool’s API is compatible with OpenAI API. It can be used with any ChatGPT tool you like. Go to the settings of some ChatGPT tool, replace the \'https://api.openai.com\' part in the API address with \'') + `http://127.0.0.1:${port}` + '\'.'}
|
||||
t('This tool\'s API is compatible with OpenAI API. It can be used with any ChatGPT tool you like. Go to the settings of some ChatGPT tool, replace the \'https://api.openai.com\' part in the API address with \'') + `http://127.0.0.1:${port}` + '\'.'}
|
||||
content={
|
||||
<NumberInput value={port} min={1} max={65535} step={1}
|
||||
onChange={(e, data) => {
|
||||
@@ -734,7 +734,7 @@ export const Configs: FC = observer(() => {
|
||||
}).catch(e => {
|
||||
toast(`${t('Convert Failed')} - ${e.message || e}`, { type: 'error' });
|
||||
});
|
||||
setTimeout(WindowShow, 1000)
|
||||
setTimeout(WindowShow, 1000);
|
||||
} else {
|
||||
toast(`${t('Model Not Found')} - ${modelPath}`, { type: 'error' });
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ export type SettingsType = {
|
||||
language: Language,
|
||||
darkMode: boolean
|
||||
autoUpdatesCheck: boolean
|
||||
giteeUpdatesSource: boolean
|
||||
cnMirror: boolean
|
||||
}
|
||||
|
||||
@@ -64,6 +65,17 @@ export const Settings: FC = observer(() => {
|
||||
checkUpdate(true);
|
||||
}} />
|
||||
} />
|
||||
{
|
||||
commonStore.settings.language === 'zh' &&
|
||||
<Labeled label={t('Use Gitee Updates Source')} flex spaceBetween content={
|
||||
<Switch checked={commonStore.settings.giteeUpdatesSource}
|
||||
onChange={(e, data) => {
|
||||
commonStore.setSettings({
|
||||
giteeUpdatesSource: data.checked
|
||||
});
|
||||
}} />
|
||||
} />
|
||||
}
|
||||
{
|
||||
commonStore.settings.language === 'zh' &&
|
||||
<Labeled label={t('Use Tsinghua Pip Mirrors')} flex spaceBetween content={
|
||||
|
||||
@@ -9,6 +9,7 @@ import {DownloadStatus} from '../pages/Downloads';
|
||||
import { SettingsType } from '../pages/Settings';
|
||||
import { IntroductionContent } from '../pages/Home';
|
||||
import { AboutContent } from '../pages/About';
|
||||
import i18n from 'i18next';
|
||||
|
||||
export enum ModelStatus {
|
||||
Offline,
|
||||
@@ -18,43 +19,37 @@ export enum ModelStatus {
|
||||
}
|
||||
|
||||
class CommonStore {
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
// global
|
||||
modelStatus: ModelStatus = ModelStatus.Offline;
|
||||
depComplete: boolean = false;
|
||||
|
||||
// home
|
||||
introduction: IntroductionContent = manifest.introduction;
|
||||
|
||||
// chat
|
||||
conversations: Conversations = {};
|
||||
conversationsOrder: string[] = [];
|
||||
|
||||
// configs
|
||||
currentModelConfigIndex: number = 0;
|
||||
modelConfigs: ModelConfig[] = [];
|
||||
|
||||
// models
|
||||
modelSourceManifestList: string = 'https://cdn.jsdelivr.net/gh/josstorer/RWKV-Runner/manifest.json;';
|
||||
modelSourceList: ModelSourceItem[] = [];
|
||||
|
||||
// downloads
|
||||
downloadList: DownloadStatus[] = [];
|
||||
|
||||
// settings
|
||||
settings: SettingsType = {
|
||||
language: getUserLanguage(),
|
||||
darkMode: !isSystemLightMode(),
|
||||
autoUpdatesCheck: true,
|
||||
giteeUpdatesSource: getUserLanguage() === 'zh',
|
||||
cnMirror: getUserLanguage() === 'zh'
|
||||
};
|
||||
|
||||
// about
|
||||
about: AboutContent = manifest.about;
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
getCurrentModelConfig = () => {
|
||||
return this.modelConfigs[this.currentModelConfigIndex];
|
||||
};
|
||||
@@ -120,6 +115,9 @@ class CommonStore {
|
||||
else
|
||||
WindowSetLightTheme();
|
||||
|
||||
if (this.settings.language)
|
||||
i18n.changeLanguage(this.settings.language);
|
||||
|
||||
if (saveConfig)
|
||||
saveConfigs();
|
||||
};
|
||||
|
||||
@@ -210,13 +210,18 @@ export function bytesToKb(size: number) {
|
||||
|
||||
export async function checkUpdate(notifyEvenLatest: boolean = false) {
|
||||
let updateUrl = '';
|
||||
await fetch('https://api.github.com/repos/josstorer/RWKV-Runner/releases/latest').then((r) => {
|
||||
await fetch(!commonStore.settings.giteeUpdatesSource ?
|
||||
'https://api.github.com/repos/josstorer/RWKV-Runner/releases/latest' :
|
||||
'https://gitee.com/api/v5/repos/josc146/RWKV-Runner/releases/latest'
|
||||
).then((r) => {
|
||||
if (r.ok) {
|
||||
r.json().then((data) => {
|
||||
if (data.tag_name) {
|
||||
const versionTag = data.tag_name;
|
||||
if (versionTag.replace('v', '') > manifest.version) {
|
||||
updateUrl = `https://github.com/josStorer/RWKV-Runner/releases/download/${versionTag}/RWKV-Runner_windows_x64.exe`;
|
||||
updateUrl = !commonStore.settings.giteeUpdatesSource ?
|
||||
`https://github.com/josStorer/RWKV-Runner/releases/download/${versionTag}/RWKV-Runner_windows_x64.exe` :
|
||||
`https://gitee.com/josc146/RWKV-Runner/releases/download/${versionTag}/RWKV-Runner_windows_x64.exe`;
|
||||
toastWithButton(t('New Version Available') + ': ' + versionTag, t('Update'), () => {
|
||||
deletePythonProgramFiles();
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
"path": "backend-python/20B_tokenizer.json"
|
||||
},
|
||||
{
|
||||
"url": "https://bootstrap.pypa.io/get-pip.py",
|
||||
"url": "https://cdn.jsdelivr.net/gh/pypa/get-pip/public/get-pip.py",
|
||||
"path": "backend-python/get-pip.py"
|
||||
}
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user