Nokia123543 commited on
Commit
14c30a9
·
verified ·
1 Parent(s): 724b62d

PLUS: мультипроход со слиянием и проверкой нот по аудио

Browse files
Files changed (1) hide show
  1. plus/serve_muscriptor.py +49 -8
plus/serve_muscriptor.py CHANGED
@@ -90,7 +90,31 @@ def healthy(port: int, timeout: float = 3.0) -> bool:
90
  return False
91
 
92
 
93
- def start_server(port: int, model: str, device: str, dtype: str | None) -> subprocess.Popen:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  command = [sys.executable, "-m", "muscriptor", "serve",
95
  "--model", model, "--device", device, "--host", "0.0.0.0", "--port", str(port)]
96
  if dtype:
@@ -98,7 +122,8 @@ def start_server(port: int, model: str, device: str, dtype: str | None) -> subpr
98
  log = open("muscriptor_server.log", "a")
99
  say("запускаю: " + " ".join(command[1:]))
100
  process = subprocess.Popen(command, stdout=log, stderr=subprocess.STDOUT,
101
- stdin=open(os.devnull, "rb"))
 
102
  deadline = time.time() + 600
103
  started = time.time()
104
  while time.time() < deadline:
@@ -342,7 +367,8 @@ def ensure_audio_tools() -> bool:
342
 
343
 
344
  def start_proxy(server_port: int, listen_port: int,
345
- instruments: str = BAND_INSTRUMENTS) -> subprocess.Popen:
 
346
  """SSE-прокси: держит поток /transcribe живым через медленный туннель."""
347
  script = pathlib.Path(__file__).with_name("sse_proxy.py")
348
  if not script.exists():
@@ -350,7 +376,8 @@ def start_proxy(server_port: int, listen_port: int,
350
  proc = subprocess.Popen(
351
  [sys.executable, "-u", str(script),
352
  "--listen", str(listen_port), "--target", str(server_port),
353
- "--instruments", instruments],
 
354
  stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
355
  for _ in range(20):
356
  time.sleep(0.5)
@@ -391,8 +418,16 @@ def main(argv: list[str] | None = None) -> int:
391
  help="имя пользователя для локального туннеля (по умолчанию nokey)")
392
  parser.add_argument("--no-tunnel", action="store_true", help="без публичной ссылки")
393
  parser.add_argument("--keep", type=int, default=0, help="держать N секунд и выйти")
 
 
 
 
 
394
  parser.add_argument("--skip-audio", action="store_true",
395
  help="не ставить fluidsynth (рендер аудио будет недоступен)")
 
 
 
396
  parser.add_argument("--instruments", default=BAND_INSTRUMENTS,
397
  help="инструменты для модели через запятую; auto = пусть решает сама")
398
  args = parser.parse_args(argv)
@@ -407,10 +442,15 @@ def main(argv: list[str] | None = None) -> int:
407
  ensure_audio_tools()
408
  ensure_ssh()
409
  ensure_key()
410
- server = start_server(args.port, args.model, args.device, args.dtype)
 
 
 
 
 
411
  say("[1/2] сервер отвечает: http://127.0.0.1:%d" % args.port)
412
  proxy_port = args.port + 1
413
- proxy = start_proxy(args.port, proxy_port, args.instruments)
414
  if proxy.poll() is None:
415
  say(" поток защищён прокси: http://127.0.0.1:%d" % proxy_port)
416
  else:
@@ -445,10 +485,11 @@ def main(argv: list[str] | None = None) -> int:
445
  break
446
  if server.poll() is not None:
447
  say("сервер упал, поднимаю заново")
448
- server = start_server(args.port, args.model, args.device, args.dtype)
449
  if proxy.poll() is not None:
450
  say("прокси упал, поднимаю заново")
451
- proxy = start_proxy(args.port, proxy_port, args.instruments)
 
452
  if tunnel is not None and not tunnel.alive():
453
  say("туннель умер, открываю новый")
454
  tunnel.kill()
 
90
  return False
91
 
92
 
93
+ def low_memory_env(threads: int | None = None) -> dict:
94
+ """Убрать раздувание памяти аллокаторами, не трогая точность модели.
95
+
96
+ Веса остаются float32, никакого квантования: экономия идёт за счёт числа
97
+ потоков (у каждого своя арена malloc) и возврата освобождённых страниц ОС.
98
+ """
99
+ cores = os.cpu_count() or 4
100
+ count = threads or max(1, min(4, cores // 2))
101
+ env = dict(os.environ)
102
+ env.update({
103
+ "OMP_NUM_THREADS": str(count),
104
+ "MKL_NUM_THREADS": str(count),
105
+ "OPENBLAS_NUM_THREADS": str(count),
106
+ "NUMEXPR_NUM_THREADS": str(count),
107
+ "MALLOC_ARENA_MAX": "2",
108
+ "MALLOC_TRIM_THRESHOLD_": "1000000",
109
+ "MALLOC_MMAP_THRESHOLD_": "131072",
110
+ "TOKENIZERS_PARALLELISM": "false",
111
+ "PYTORCH_CPU_ALLOC_CONF": "garbage_collection_threshold:0.6",
112
+ })
113
+ return env
114
+
115
+
116
+ def start_server(port: int, model: str, device: str, dtype: str | None,
117
+ env: dict | None = None) -> subprocess.Popen:
118
  command = [sys.executable, "-m", "muscriptor", "serve",
119
  "--model", model, "--device", device, "--host", "0.0.0.0", "--port", str(port)]
120
  if dtype:
 
122
  log = open("muscriptor_server.log", "a")
123
  say("запускаю: " + " ".join(command[1:]))
124
  process = subprocess.Popen(command, stdout=log, stderr=subprocess.STDOUT,
125
+ stdin=open(os.devnull, "rb"),
126
+ env=env or dict(os.environ))
127
  deadline = time.time() + 600
128
  started = time.time()
129
  while time.time() < deadline:
 
367
 
368
 
369
  def start_proxy(server_port: int, listen_port: int,
370
+ instruments: str = BAND_INSTRUMENTS,
371
+ multi_pass: str = "") -> subprocess.Popen:
372
  """SSE-прокси: держит поток /transcribe живым через медленный туннель."""
373
  script = pathlib.Path(__file__).with_name("sse_proxy.py")
374
  if not script.exists():
 
376
  proc = subprocess.Popen(
377
  [sys.executable, "-u", str(script),
378
  "--listen", str(listen_port), "--target", str(server_port),
379
+ "--instruments", instruments]
380
+ + (["--multi-pass", multi_pass] if multi_pass else []),
381
  stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
382
  for _ in range(20):
383
  time.sleep(0.5)
 
418
  help="имя пользователя для локального туннеля (по умолчанию nokey)")
419
  parser.add_argument("--no-tunnel", action="store_true", help="без публичной ссылки")
420
  parser.add_argument("--keep", type=int, default=0, help="держать N секунд и выйти")
421
+ parser.add_argument("--low-memory", action="store_true",
422
+ help="экономный режим для слабого ПК: меньше потоков и арен,"
423
+ " веса всё так же float32")
424
+ parser.add_argument("--threads", type=int, default=None,
425
+ help="сколько потоков дать модели (по умолчанию половина ядер)")
426
  parser.add_argument("--skip-audio", action="store_true",
427
  help="не ставить fluidsynth (рендер аудио будет недоступен)")
428
+ parser.add_argument("--multi-pass", default="",
429
+ help="второй проход с другим набором инструментов и слияние,"
430
+ " например: chromatic_percussion,electric_bass,acoustic_bass")
431
  parser.add_argument("--instruments", default=BAND_INSTRUMENTS,
432
  help="инструменты для модели через запятую; auto = пусть решает сама")
433
  args = parser.parse_args(argv)
 
442
  ensure_audio_tools()
443
  ensure_ssh()
444
  ensure_key()
445
+ env = None
446
+ if args.low_memory or args.threads:
447
+ env = low_memory_env(args.threads)
448
+ say(" экономный режим: потоков %s, арен malloc 2, веса float32"
449
+ % env["OMP_NUM_THREADS"])
450
+ server = start_server(args.port, args.model, args.device, args.dtype, env)
451
  say("[1/2] сервер отвечает: http://127.0.0.1:%d" % args.port)
452
  proxy_port = args.port + 1
453
+ proxy = start_proxy(args.port, proxy_port, args.instruments, args.multi_pass)
454
  if proxy.poll() is None:
455
  say(" поток защищён прокси: http://127.0.0.1:%d" % proxy_port)
456
  else:
 
485
  break
486
  if server.poll() is not None:
487
  say("сервер упал, поднимаю заново")
488
+ server = start_server(args.port, args.model, args.device, args.dtype, env)
489
  if proxy.poll() is not None:
490
  say("прокси упал, поднимаю заново")
491
+ proxy = start_proxy(args.port, proxy_port, args.instruments,
492
+ args.multi_pass)
493
  if tunnel is not None and not tunnel.alive():
494
  say("туннель умер, открываю новый")
495
  tunnel.kill()