2024-02-02 22:00:01 +08:00
// Considering some whitespace and multilingual support, the functions in rwkv.go should always be executed with cwd as RWKV-Runner, and never use a.GetAbsPath() here.
2023-05-06 23:39:23 +08:00
package backend_golang
import (
2023-07-09 11:31:07 +08:00
"encoding/json"
2023-05-20 23:34:33 +08:00
"errors"
2023-06-14 22:21:17 +08:00
"os"
2023-05-06 23:39:23 +08:00
"os/exec"
2023-05-27 14:40:59 +08:00
"runtime"
2023-05-17 11:39:00 +08:00
"strconv"
2023-06-14 22:21:17 +08:00
"strings"
2023-05-06 23:39:23 +08:00
)
2023-12-14 18:37:07 +08:00
func ( a * App ) StartServer ( python string , port int , host string , webui bool , rwkvBeta bool , rwkvcpp bool , webgpu bool ) ( string , error ) {
2024-02-02 22:00:01 +08:00
execFile := "./backend-python/main.py"
_ , err := os . Stat ( execFile )
if err != nil {
return "" , err
}
2023-05-31 15:45:26 +08:00
if python == "" {
python , err = GetPython ( )
}
2023-05-17 11:39:00 +08:00
if err != nil {
return "" , err
}
2024-02-02 22:00:01 +08:00
args := [ ] string { python , execFile }
2023-11-07 22:24:06 +08:00
if webui {
args = append ( args , "--webui" )
}
2023-08-14 22:07:15 +08:00
if rwkvBeta {
args = append ( args , "--rwkv-beta" )
}
2023-12-12 20:29:55 +08:00
if rwkvcpp {
args = append ( args , "--rwkv.cpp" )
}
2023-12-14 18:37:07 +08:00
if webgpu {
args = append ( args , "--webgpu" )
}
2023-08-14 22:07:15 +08:00
args = append ( args , "--port" , strconv . Itoa ( port ) , "--host" , host )
return Cmd ( args ... )
2023-05-20 23:34:33 +08:00
}
2023-08-16 23:07:58 +08:00
func ( a * App ) StartWebGPUServer ( port int , host string ) ( string , error ) {
2024-02-02 22:00:01 +08:00
var execFile string
execFiles := [ ] string { "./backend-rust/webgpu_server" , "./backend-rust/webgpu_server.exe" }
for _ , file := range execFiles {
_ , err := os . Stat ( file )
if err == nil {
execFile = file
break
}
}
if execFile == "" {
return "" , errors . New ( execFiles [ 0 ] + " not found" )
}
args := [ ] string { execFile }
2023-10-25 21:02:44 +08:00
args = append ( args , "--port" , strconv . Itoa ( port ) , "--ip" , host )
2023-08-16 23:07:58 +08:00
return Cmd ( args ... )
}
2023-05-31 15:45:26 +08:00
func ( a * App ) ConvertModel ( python string , modelPath string , strategy string , outPath string ) ( string , error ) {
2024-02-02 22:00:01 +08:00
execFile := "./backend-python/convert_model.py"
_ , err := os . Stat ( execFile )
if err != nil {
return "" , err
}
2023-05-31 15:45:26 +08:00
if python == "" {
python , err = GetPython ( )
}
2023-05-06 23:39:23 +08:00
if err != nil {
2023-05-13 20:15:18 +08:00
return "" , err
2023-05-06 23:39:23 +08:00
}
2024-02-02 22:00:01 +08:00
return Cmd ( python , execFile , "--in" , modelPath , "--out" , outPath , "--strategy" , strategy )
2023-05-06 23:39:23 +08:00
}
2023-05-17 21:20:41 +08:00
2023-12-07 23:26:39 +08:00
func ( a * App ) ConvertSafetensors ( modelPath string , outPath string ) ( string , error ) {
2024-02-02 22:00:01 +08:00
var execFile string
execFiles := [ ] string { "./backend-rust/web-rwkv-converter" , "./backend-rust/web-rwkv-converter.exe" }
for _ , file := range execFiles {
_ , err := os . Stat ( file )
if err == nil {
execFile = file
break
}
}
if execFile == "" {
return "" , errors . New ( execFiles [ 0 ] + " not found" )
}
args := [ ] string { execFile }
2023-12-07 23:26:39 +08:00
args = append ( args , "--input" , modelPath , "--output" , outPath )
return Cmd ( args ... )
2023-08-16 23:07:58 +08:00
}
2023-12-14 18:37:07 +08:00
func ( a * App ) ConvertSafetensorsWithPython ( python string , modelPath string , outPath string ) ( string , error ) {
2024-02-02 22:00:01 +08:00
execFile := "./backend-python/convert_safetensors.py"
_ , err := os . Stat ( execFile )
if err != nil {
return "" , err
}
2023-12-14 18:37:07 +08:00
if python == "" {
python , err = GetPython ( )
}
if err != nil {
return "" , err
}
2024-02-02 22:00:01 +08:00
return Cmd ( python , execFile , "--input" , modelPath , "--output" , outPath )
2023-12-14 18:37:07 +08:00
}
2023-12-12 20:29:55 +08:00
func ( a * App ) ConvertGGML ( python string , modelPath string , outPath string , Q51 bool ) ( string , error ) {
2024-02-02 22:00:01 +08:00
execFile := "./backend-python/convert_pytorch_to_ggml.py"
_ , err := os . Stat ( execFile )
if err != nil {
return "" , err
}
2023-12-12 20:29:55 +08:00
if python == "" {
python , err = GetPython ( )
}
if err != nil {
return "" , err
}
dataType := "FP16"
if Q51 {
dataType = "Q5_1"
}
2024-02-02 22:00:01 +08:00
return Cmd ( python , execFile , modelPath , outPath , dataType )
2023-12-12 20:29:55 +08:00
}
2023-07-03 17:41:47 +08:00
func ( a * App ) ConvertData ( python string , input string , outputPrefix string , vocab string ) ( string , error ) {
2024-02-02 22:00:01 +08:00
execFile := "./finetune/json2binidx_tool/tools/preprocess_data.py"
_ , err := os . Stat ( execFile )
if err != nil {
return "" , err
}
2023-07-03 17:41:47 +08:00
if python == "" {
python , err = GetPython ( )
}
if err != nil {
return "" , err
}
tokenizerType := "HFTokenizer"
if strings . Contains ( vocab , "rwkv_vocab_v20230424" ) {
tokenizerType = "RWKVTokenizer"
}
2023-07-07 21:57:01 +08:00
input = strings . TrimSuffix ( input , "/" )
if fi , err := os . Stat ( input ) ; err == nil && fi . IsDir ( ) {
files , err := os . ReadDir ( input )
if err != nil {
return "" , err
}
jsonlFile , err := os . Create ( outputPrefix + ".jsonl" )
if err != nil {
return "" , err
}
defer jsonlFile . Close ( )
for _ , file := range files {
if file . IsDir ( ) || ! strings . HasSuffix ( file . Name ( ) , ".txt" ) {
continue
}
2023-07-09 11:31:07 +08:00
textContent , err := os . ReadFile ( input + "/" + file . Name ( ) )
2023-07-07 21:57:01 +08:00
if err != nil {
return "" , err
}
2023-07-11 12:19:39 +08:00
textJson , err := json . Marshal ( map [ string ] string { "text" : strings . ReplaceAll ( strings . ReplaceAll ( string ( textContent ) , "\r\n" , "\n" ) , "\r" , "\n" ) } )
2023-07-09 11:31:07 +08:00
if err != nil {
return "" , err
}
if _ , err := jsonlFile . WriteString ( string ( textJson ) + "\n" ) ; err != nil {
return "" , err
2023-07-07 21:57:01 +08:00
}
}
input = outputPrefix + ".jsonl"
} else if err != nil {
return "" , err
}
2024-02-02 22:00:01 +08:00
return Cmd ( python , execFile , "--input" , input , "--output-prefix" , outputPrefix , "--vocab" , vocab ,
2023-07-03 17:41:47 +08:00
"--tokenizer-type" , tokenizerType , "--dataset-impl" , "mmap" , "--append-eod" )
}
func ( a * App ) MergeLora ( python string , useGpu bool , loraAlpha int , baseModel string , loraPath string , outputPath string ) ( string , error ) {
2024-02-02 22:00:01 +08:00
execFile := "./finetune/lora/merge_lora.py"
_ , err := os . Stat ( execFile )
if err != nil {
return "" , err
}
2023-07-03 17:41:47 +08:00
if python == "" {
python , err = GetPython ( )
}
if err != nil {
return "" , err
}
2024-02-02 22:00:01 +08:00
args := [ ] string { python , execFile }
2023-07-03 17:41:47 +08:00
if useGpu {
args = append ( args , "--use-gpu" )
}
args = append ( args , strconv . Itoa ( loraAlpha ) , baseModel , loraPath , outputPath )
return Cmd ( args ... )
}
2023-05-31 15:45:26 +08:00
func ( a * App ) DepCheck ( python string ) error {
var err error
if python == "" {
python , err = GetPython ( )
}
2023-05-20 23:34:33 +08:00
if err != nil {
return err
}
2024-02-02 22:00:01 +08:00
out , err := exec . Command ( python , a . exDir + "backend-python/dep_check.py" ) . CombinedOutput ( )
2023-05-20 23:34:33 +08:00
if err != nil {
2024-02-02 22:00:01 +08:00
return errors . New ( "DepCheck Error: " + string ( out ) + " GError: " + err . Error ( ) )
2023-05-20 23:34:33 +08:00
}
return nil
2023-05-17 23:27:52 +08:00
}
2023-05-31 15:45:26 +08:00
func ( a * App ) InstallPyDep ( python string , cnMirror bool ) ( string , error ) {
var err error
if python == "" {
python , err = GetPython ( )
2023-06-14 22:21:17 +08:00
if runtime . GOOS == "windows" {
2023-06-21 12:08:04 +08:00
python = ` "%CD%/ ` + python + ` " `
2023-06-14 22:21:17 +08:00
}
2023-05-31 15:45:26 +08:00
}
2023-05-20 23:34:33 +08:00
if err != nil {
return "" , err
}
2023-06-07 20:38:19 +08:00
2023-05-27 14:40:59 +08:00
if runtime . GOOS == "windows" {
ChangeFileLine ( "./py310/python310._pth" , 3 , "Lib\\site-packages" )
2024-03-13 21:37:35 +08:00
installScript := python + " ./backend-python/get-pip.py -i https://mirrors.aliyun.com/pypi/simple --no-warn-script-location\n" +
2023-10-25 17:08:50 +08:00
python + " -m pip install torch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 --index-url https://download.pytorch.org/whl/cu117 --no-warn-script-location\n" +
2024-03-13 21:37:35 +08:00
python + " -m pip install -r ./backend-python/requirements.txt -i https://mirrors.aliyun.com/pypi/simple --no-warn-script-location\n" +
2023-06-14 22:21:17 +08:00
"exit"
if ! cnMirror {
2024-03-13 21:37:35 +08:00
installScript = strings . Replace ( installScript , " -i https://mirrors.aliyun.com/pypi/simple" , "" , - 1 )
2023-06-07 20:38:19 +08:00
}
2024-02-02 22:00:01 +08:00
err = os . WriteFile ( a . exDir + "install-py-dep.bat" , [ ] byte ( installScript ) , 0644 )
2023-06-07 20:38:19 +08:00
if err != nil {
return "" , err
}
2023-06-14 22:21:17 +08:00
return Cmd ( "install-py-dep.bat" )
2023-05-20 23:34:33 +08:00
}
2023-06-07 20:38:19 +08:00
2023-06-14 22:21:17 +08:00
if cnMirror {
2024-03-13 21:37:35 +08:00
return Cmd ( python , "-m" , "pip" , "install" , "-r" , "./backend-python/requirements_without_cyac.txt" , "-i" , "https://mirrors.aliyun.com/pypi/simple" )
2023-05-21 10:49:45 +08:00
} else {
2023-06-14 22:21:17 +08:00
return Cmd ( python , "-m" , "pip" , "install" , "-r" , "./backend-python/requirements_without_cyac.txt" )
2023-05-21 10:49:45 +08:00
}
2023-05-17 21:20:41 +08:00
}
2023-07-07 20:16:35 +08:00
func ( a * App ) GetPyError ( ) string {
content , err := os . ReadFile ( "./error.txt" )
if err != nil {
return ""
}
return string ( content )
}