From d0fd480bd694e9da3b7bc21bf0b5dfbf09863127 Mon Sep 17 00:00:00 2001 From: josc146 Date: Wed, 26 Jul 2023 22:24:26 +0800 Subject: [PATCH] chore --- .gitattributes | 1 + .gitignore | 1 + backend-python/main.py | 4 +-- backend-python/routes/completion.py | 16 +++++----- backend-python/routes/config.py | 6 ++-- backend-python/routes/midi.py | 47 +++++++++++++++++++++++++--- backend-python/routes/state_cache.py | 12 +++---- backend-python/utils/midi.py | 12 +++++++ vendor.yml | 3 ++ 9 files changed, 78 insertions(+), 24 deletions(-) diff --git a/.gitattributes b/.gitattributes index d2728ba..522b33b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,6 +2,7 @@ backend-python/rwkv_pip/** linguist-vendored backend-python/wkv_cuda_utils/** linguist-vendored backend-python/get-pip.py linguist-vendored backend-python/convert_model.py linguist-vendored +backend-python/utils/midi.py linguist-vendored build/** linguist-vendored finetune/lora/** linguist-vendored finetune/json2binidx_tool/** linguist-vendored diff --git a/.gitignore b/.gitignore index fa7a04b..688c5f3 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ __pycache__ *.log train_log.txt finetune/json2binidx_tool/data +/wsl.state diff --git a/backend-python/main.py b/backend-python/main.py index a3bc7d5..8f65d25 100644 --- a/backend-python/main.py +++ b/backend-python/main.py @@ -42,12 +42,12 @@ def init(): ngrok_connect() -@app.get("/") +@app.get("/", tags=["Root"]) def read_root(): return {"Hello": "World!"} -@app.post("/exit") +@app.post("/exit", tags=["Root"]) def exit(): parent_pid = os.getpid() parent = psutil.Process(parent_pid) diff --git a/backend-python/routes/completion.py b/backend-python/routes/completion.py index 0fd1b39..99a7bc7 100644 --- a/backend-python/routes/completion.py +++ b/backend-python/routes/completion.py @@ -206,8 +206,8 @@ async def eval_rwkv( } -@router.post("/v1/chat/completions") -@router.post("/chat/completions") +@router.post("/v1/chat/completions", tags=["Completions"]) +@router.post("/chat/completions", tags=["Completions"]) async def chat_completions(body: ChatCompletionBody, request: Request): model: TextRWKV = global_var.get(global_var.Model) if model is None: @@ -299,8 +299,8 @@ The following is a coherent verbose detailed conversation between a girl named { return None -@router.post("/v1/completions") -@router.post("/completions") +@router.post("/v1/completions", tags=["Completions"]) +@router.post("/completions", tags=["Completions"]) async def completions(body: CompletionBody, request: Request): model: AbstractRWKV = global_var.get(global_var.Model) if model is None: @@ -346,10 +346,10 @@ def embedding_base64(embedding: List[float]) -> str: return base64.b64encode(np.array(embedding).astype(np.float32)).decode("utf-8") -@router.post("/v1/embeddings") -@router.post("/embeddings") -@router.post("/v1/engines/text-embedding-ada-002/embeddings") -@router.post("/engines/text-embedding-ada-002/embeddings") +@router.post("/v1/embeddings", tags=["Embeddings"]) +@router.post("/embeddings", tags=["Embeddings"]) +@router.post("/v1/engines/text-embedding-ada-002/embeddings", tags=["Embeddings"]) +@router.post("/engines/text-embedding-ada-002/embeddings", tags=["Embeddings"]) async def embeddings(body: EmbeddingsBody, request: Request): model: AbstractRWKV = global_var.get(global_var.Model) if model is None: diff --git a/backend-python/routes/config.py b/backend-python/routes/config.py index 108f0d2..8cb58e8 100644 --- a/backend-python/routes/config.py +++ b/backend-python/routes/config.py @@ -42,7 +42,7 @@ class SwitchModelBody(BaseModel): } -@router.post("/switch-model") +@router.post("/switch-model", tags=["Configs"]) def switch_model(body: SwitchModelBody, response: Response, request: Request): if global_var.get(global_var.Model_Status) is global_var.ModelStatus.Loading: response.status_code = Status.HTTP_304_NOT_MODIFIED @@ -98,7 +98,7 @@ def switch_model(body: SwitchModelBody, response: Response, request: Request): return "success" -@router.post("/update-config") +@router.post("/update-config", tags=["Configs"]) def update_config(body: ModelConfigBody): """ Will not update the model config immediately, but set it when completion called to avoid modifications during generation @@ -110,7 +110,7 @@ def update_config(body: ModelConfigBody): return "success" -@router.get("/status") +@router.get("/status", tags=["Configs"]) def status(): gpus = GPUtil.getGPUs() if len(gpus) == 0: diff --git a/backend-python/routes/midi.py b/backend-python/routes/midi.py index 28cba22..4fdfb94 100644 --- a/backend-python/routes/midi.py +++ b/backend-python/routes/midi.py @@ -1,4 +1,6 @@ +import io from fastapi import APIRouter, HTTPException, status +from starlette.responses import StreamingResponse from pydantic import BaseModel from utils.midi import * from midi2audio import FluidSynth @@ -6,6 +8,29 @@ from midi2audio import FluidSynth router = APIRouter() +class TextToMidiBody(BaseModel): + text: str + + class Config: + schema_extra = { + "example": { + "text": "p:24:a p:2a:a p:31:a p:39:a p:3b:a p:45:a b:26:a g:3e:a g:3e:a g:42:a g:42:a g:45:a g:45:a pi:3e:a pi:42:a pi:45:a t14 p:24:0 p:2a:0 p:31:0 p:39:0 p:3b:0 p:45:0 t2 p:2a:a p:3b:a p:45:a t14 p:2a:0 p:3b:0 p:45:0 b:26:0 g:3e:0 g:3e:0 g:42:0 g:42:0 g:45:0 g:45:0 pi:3e:0 pi:42:0 pi:45:0 t2 p:2e:a p:3b:a p:45:a b:26:a g:3e:a g:3e:a g:42:a g:42:a g:45:a g:45:a pi:3e:a pi:42:a pi:45:a t14 p:2e:0 p:3b:0 p:45:0 g:3e:0 g:3e:0 g:42:0 g:42:0 g:45:0 g:45:0 pi:3e:0 pi:42:0 pi:45:0 t2 p:2e:a p:3b:a p:45:a g:3e:a g:3e:a g:42:a g:42:a g:45:a g:45:a pi:3e:a pi:42:a pi:45:a t14 p:2e:0 p:3b:0 p:45:0 b:26:0 g:3e:0 g:3e:0 g:42:0 g:42:0 g:45:0 g:45:0 pi:3e:0 pi:42:0 pi:45:0 t2 p:26:a p:2a:a p:3b:a p:45:a t14 p:26:0 p:2a:0 p:3b:0 p:45:0 t2 p:2a:a p:3b:a p:45:a b:26:a g:3e:a g:3e:a g:42:a g:42:a g:45:a g:45:a pi:3e:a pi:42:a pi:45:a t14 p:2a:0 p:3b:0 p:45:0 b:26:0 t2 p:24:a p:2a:a p:3b:a p:45:a b:2d:a t14 p:24:0 p:2a:0 p:3b:0 p:45:0 b:2d:0 g:3e:0 g:3e:0 g:42:0 g:42:0 g:45:0 g:45:0 pi:3e:0 pi:42:0 pi:45:0 t2 p:24:a p:2a:a p:3b:a p:45:a b:21:a g:39:a g:39:a g:3d:a g:3d:a g:40:a g:40:a pi:39:a pi:3d:a pi:40:a t14 p:24:0 p:2a:0 p:3b:0 p:45:0 t2 p:2a:a p:3b:a p:45:a t14 p:2a:0 p:3b:0 p:45:0 b:21:0 g:39:0 g:39:0 g:3d:0 g:3d:0 g:40:0 g:40:0 pi:39:0 pi:3d:0 pi:40:0 t2 p:24:a p:2e:a p:3b:a p:45:a b:21:a g:39:a g:39:a g:3d:a g:3d:a g:40:a g:40:a pi:39:a pi:3d:a pi:40:a t14 p:24:0 p:2e:0 p:3b:0 p:45:0 b:21:0 g:39:0 g:39:0 g:3d:0 g:3d:0 g:40:0 g:40:0 pi:39:0 pi:3d:0 pi:40:0 t2 p:24:a p:2a:a p:3b:a p:45:a b:21:a g:39:a g:39:a g:3d:a g:3d:a g:40:a g:40:a pi:39:a pi:3d:a pi:40:a t14 p:24:0 p:2a:0 p:3b:0 p:45:0 t2 p:2a:a p:3b:a p:45:a t14 p:2a:0 p:3b:0 p:45:0 b:21:0 g:39:0 g:39:0 g:3d:0 g:3d:0 g:40:0 g:40:0 pi:39:0 pi:3d:0 pi:40:0 t2 p:26:a p:2a:a p:3b:a p:45:a b:21:a g:39:a g:39:a g:3d:a g:3d:a g:40:a g:40:a pi:39:a pi:3d:a pi:40:a t14 p:26:0 p:2a:0 p:3b:0 p:45:0 t2 p:2a:a p:3b:a p:45:a t14 p:2a:0 p:3b:0 p:45:0 b:21:0 g:39:0 g:39:0 g:3d:0 g:3d:0 g:40:0 g:40:0 pi:39:0 pi:3d:0 pi:40:0 t2 p:26:a p:2e:a p:31:a p:39:a p:3b:a p:45:a b:21:a g:39:a g:39:a g:3d:a g:3d:a g:40:a g:40:a pi:39:a pi:3d:a pi:40:a t14 p:26:0 p:2e:0 p:31:0 p:39:0 p:3b:0 p:45:0 b:21:0 t2 p:26:a p:2e:a p:31:a p:39:a p:3b:a p:45:a b:21:a t14 p:26:0 p:2e:0 p:31:0 p:39:0 p:3b:0 p:45:0 b:21:0 g:39:0 g:39:0 g:3d:0 g:3d:0 g:40:0 g:40:0 pi:39:0 pi:3d:0 pi:40:0 t2 p:24:a p:2a:a p:31:a p:39:a p:3b:a p:45:a b:1f:a g:3b:a g:3b:a g:3e:a g:3e:a g:43:a g:43:a pi:3b:a pi:3e:a pi:43:a t14 p:24:0 p:2a:0 p:31:0 p:39:0 p:3b:0 p:45:0 t2 p:2a:a p:3b:a p:45:a t14 p:2a:0 p:3b:0 p:45:0 b:1f:0 g:3b:0 g:3b:0 g:3e:0 g:3e:0 g:43:0 g:43:0 pi:3b:0 pi:3e:0 pi:43:0 t2 p:2e:a p:3b:a p:45:a b:1f:a g:3b:a g:3b:a g:3e:a g:3e:a g:43:a g:43:a pi:3b:a pi:3e:a pi:43:a t14 p:2e:0 p:3b:0 p:45:0 g:3b:0 g:3b:0 g:3e:0 g:3e:0 g:43:0 g:43:0 pi:3b:0 pi:3e:0 pi:43:0 t2 p:2e:a p:3b:a p:45:a g:3b:a g:3b:a g:3e:a g:3e:a g:43:a g:43:a pi:3b:a pi:3e:a pi:43:a t14 p:2e:0 p:3b:0 p:45:0 b:1f:0 g:3b:0 g:3b:0 g:3e:0 g:3e:0 g:43:0 g:43:0 pi:3b:0 pi:3e:0 pi:43:0 t2 p:26:a p:2a:a p:3b:a p:45:a t14 p:26:0 p:2a:0 p:3b:0 p:45:0 t2 p:2a:a p:3b:a p:45:a b:1f:a g:3b:a g:3b:a g:3e:a g:3e:a g:43:a g:43:a pi:3b:a pi:3e:a pi:43:a t14 p:2a:0 p:3b:0 p:45:0 b:1f:0 t2 p:24:a p:2a:a p:3b:a p:45:a b:1f:a t14 p:24:0 p:2a:0 p:3b:0 p:45:0 b:1f:0 g:3b:0 g:3b:0 g:3e:0 g:3e:0 g:43:0 g:43:0 pi:3b:0 pi:3e:0 pi:43:0 t2 p:24:a p:2e:a p:3b:a p:45:a b:26:a g:39:a g:39:a g:3e:a g:3e:a g:42:a g:42:a pi:39:a pi:3e:a pi:42:a t14 p:24:0 p:2e:0 p:3b:0 p:45:0 t2 p:2a:a p:3b:a p:45:a t14 p:2a:0 p:3b:0", + } + } + + +@router.post("/text-to-midi", tags=["MIDI"]) +def text_to_midi(body: TextToMidiBody): + vocab_config = "backend-python/utils/midi_vocab_config.json" + cfg = VocabConfig.from_json(vocab_config) + mid = convert_str_to_midi(cfg, body.text.strip()) + mid_data = io.BytesIO() + mid.save(None, mid_data) + mid_data.seek(0) + + return StreamingResponse(mid_data, media_type="audio/midi") + + class TxtToMidiBody(BaseModel): txt_path: str midi_path: str @@ -19,7 +44,7 @@ class TxtToMidiBody(BaseModel): } -@router.post("/txt-to-midi") +@router.post("/txt-to-midi", tags=["MIDI"]) def txt_to_midi(body: TxtToMidiBody): if not body.midi_path.startswith("midi/"): raise HTTPException(status.HTTP_400_BAD_REQUEST, "bad output path") @@ -32,6 +57,8 @@ def txt_to_midi(body: TxtToMidiBody): mid = convert_str_to_midi(cfg, text) mid.save(body.midi_path) + return "success" + class MidiToWavBody(BaseModel): midi_path: str @@ -48,15 +75,20 @@ class MidiToWavBody(BaseModel): } -# install fluidsynth first, see more: https://github.com/FluidSynth/fluidsynth/wiki/Download#distributions -@router.post("/midi-to-wav") +@router.post("/midi-to-wav", tags=["MIDI"]) def midi_to_wav(body: MidiToWavBody): + """ + Install fluidsynth first, see more: https://github.com/FluidSynth/fluidsynth/wiki/Download#distributions + """ + if not body.wav_path.startswith("midi/"): raise HTTPException(status.HTTP_400_BAD_REQUEST, "bad output path") fs = FluidSynth(body.sound_font_path) fs.midi_to_audio(body.midi_path, body.wav_path) + return "success" + class TextToWavBody(BaseModel): text: str @@ -73,9 +105,12 @@ class TextToWavBody(BaseModel): } -# install fluidsynth first, see more: https://github.com/FluidSynth/fluidsynth/wiki/Download#distributions -@router.post("/text-to-wav") +@router.post("/text-to-wav", tags=["MIDI"]) def text_to_wav(body: TextToWavBody): + """ + Install fluidsynth first, see more: https://github.com/FluidSynth/fluidsynth/wiki/Download#distributions + """ + text = body.text.strip() if not text.startswith(""): text = " " + text @@ -92,3 +127,5 @@ def text_to_wav(body: TextToWavBody): midi_path=midi_path, wav_path=wav_path, sound_font_path=body.sound_font_path ) ) + + return "success" diff --git a/backend-python/routes/state_cache.py b/backend-python/routes/state_cache.py index 8c646b1..74d6f65 100644 --- a/backend-python/routes/state_cache.py +++ b/backend-python/routes/state_cache.py @@ -32,7 +32,7 @@ def init(): print("cyac not found") -@router.post("/disable-state-cache") +@router.post("/disable-state-cache", tags=["State Cache"]) def disable_state_cache(): global trie, dtrie @@ -43,7 +43,7 @@ def disable_state_cache(): return "success" -@router.post("/enable-state-cache") +@router.post("/enable-state-cache", tags=["State Cache"]) def enable_state_cache(): global trie, dtrie try: @@ -65,7 +65,7 @@ class AddStateBody(BaseModel): logits: Any -@router.post("/add-state") +@router.post("/add-state", tags=["State Cache"]) def add_state(body: AddStateBody): global trie, dtrie, loop_del_trie_id if trie is None: @@ -105,7 +105,7 @@ def add_state(body: AddStateBody): ) -@router.post("/reset-state") +@router.post("/reset-state", tags=["State Cache"]) def reset_state(): global trie, dtrie if trie is None: @@ -141,7 +141,7 @@ def _get_a_dtrie_buff_size(dtrie_v): return 54 * len(dtrie_v["tokens"]) + 491520 + 262144 + 28 # TODO -@router.post("/longest-prefix-state") +@router.post("/longest-prefix-state", tags=["State Cache"]) def longest_prefix_state(body: LongestPrefixStateBody, request: Request): global trie if trie is None: @@ -180,7 +180,7 @@ def longest_prefix_state(body: LongestPrefixStateBody, request: Request): } -@router.post("/save-state") +@router.post("/save-state", tags=["State Cache"]) def save_state(): global trie if trie is None: diff --git a/backend-python/utils/midi.py b/backend-python/utils/midi.py index f54a3c6..6993de6 100644 --- a/backend-python/utils/midi.py +++ b/backend-python/utils/midi.py @@ -1,3 +1,15 @@ +# https://github.com/briansemrau/MIDI-LLM-tokenizer + +# MIT License + +# Copyright (c) 2023 Brian Semrau + +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + import json import random from dataclasses import dataclass diff --git a/vendor.yml b/vendor.yml index d48a9f7..593f515 100644 --- a/vendor.yml +++ b/vendor.yml @@ -2,5 +2,8 @@ - ^backend-python/wkv_cuda_utils/ - ^backend-python/get-pip\.py - ^backend-python/convert_model\.py +- ^backend-python/utils/midi\.py - ^build/ +- ^finetune/lora/ +- ^finetune/json2binidx_tool/ - ^frontend/wailsjs/ \ No newline at end of file