diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index c53d7e8..c89bee7 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -11,6 +11,8 @@ | 날짜 | 버전 | 변경 | | --- | --- | --- | +| 2026-10-30 | v3.79 | **0.5.3 릴리스 준비(브랜치 `feat/univa-8bit`).** 버전 0.5.3을 다섯 매니페스트와 잠금 파일에 맞췄다(소유자는 0.5.2.1을 말했지만 Tauri 업데이트·Cargo·npm이 세 자리 semver만 받고 `0.5.2-1`은 0.5.2보다 낮고 `0.5.2+1`은 같은 버전이라 업데이트가 가지 않아 0.5.3으로 냈다). 0.5.2 이후: 한국어 파인튜닝 엔진 8bit 변환본 교체(v3.78). 릴리스 노트 `docs/releases/v0.5.3.md`, 로드맵 항목. | +| 2026-10-30 | v3.78 | **한국어 파인튜닝 엔진을 8bit 변환본으로 교체(브랜치 `feat/univa-8bit`).** 0.5.2에 올린 `asr-ko-univa`가 원본 bf16(4.7GB)이었다(변환·업로드 위치를 정하지 않고 허브 원본을 그대로 등록했다). `mlx_audio.convert -q --q-bits 8 --q-group-size 64 --q-mode affine`로 변환해(표준 엔진과 같은 설정, `model.safetensors` 2,463,307,541바이트로 공식 Qwen3-ASR 1.7B 8bit와 같다) 소유자 계정에 `voyagar/Qwen3-ASR-1.7B-ko-mlx-8bit`(공개, Apache-2.0, 커밋 `8fcc32c4`, 모델 카드에 원 제작자·원본 revision·변환 명령)로 올리고 등록 목록을 바꿨다. ID `asr-ko-univa`·`level_note`는 그대로라 사용자가 고른 엔진 설정은 유지되고, 새 폴더(`qwen3-asr-1.7b-ko-8bit`)를 받을 때까지는 받아 둔 다른 엔진으로 변환한다. 0.5.2로 bf16을 받은 폴더(`qwen3-asr-1.7b-ko-bf16`)는 등록 밖이 되어 `models prune`으로 지운다. 간이 점검: 원본과 출력 차이 CER 2.5, 처리 시간 약 30% 단축(docs/design/asr-engines.md). | | 2026-10-30 | v3.77 | **0.5.2 릴리스 준비(브랜치 `fix/mic-config-change-crash`).** 버전 0.5.2를 다섯 매니페스트와 잠금 파일에 맞췄다. 0.5.1 이후: 한국어 파인튜닝 엔진 `asr-ko-univa` 등록과 모델 화면 변환 엔진 라디오 목록(v3.75), 장치 전환 중 녹음 프로그램 크래시 수정(v3.76, 이슈 #57). 릴리스 노트 `docs/releases/v0.5.2.md`, 로드맵 항목. | | 2026-10-30 | v3.76 | **녹음 중 입력 장치가 바뀌면 `tractus-rec`가 죽던 것(이슈 #57, 브랜치 `fix/mic-config-change-crash`).** `AVAudioEngineConfigurationChange` → `Recorder.restart` → `MicSource.open`의 `installTap`이 Objective-C 예외(NSException)를 던져 Swift `do/catch`를 지나 프로세스가 abort됐다(66분 녹음 중 크래시, `recording.json`의 `duration`이 null로 남음). ① `RecorderKit.micFormatProblem`: tap 전에 채널·표본 속도 0과 하드웨어 포맷 불일치를 오류로 던진다(`restart`의 경고와 watchdog 2초 재시도로 넘어감). 음성 처리(에코 제거) 중에는 두 포맷이 다를 수 있어 표본 속도 일치는 보지 않는다. ② `MicSource.stop()`마다 새 `AVAudioEngine`으로 바꾸고 관찰자를 다시 단다(장치가 바뀐 뒤 같은 엔진의 입력 노드가 낡은 포맷을 쥐는 것을 피함). ③ 새 SwiftPM 타깃 `ObjCCatch`(Objective-C, `TractusObjC.catching { }`)로 `installTap`을 감싸 NSException을 Swift 오류로 바꾼다(`recorder/`의 tools-version 5.10·플랫폼은 그대로). 이 Mac의 실제 마이크로 일반·에코 제거 녹음이 정상임은 확인했고, **실제 장치 전환(블루투스 연결·해제)은 재현하지 못했다.** 비정상 종료로 `duration`이 null인 녹음은 앱의 `변환 대기 중인 녹음`에 보이고 코어가 그대로 변환 전 노트로 저장한다는 것을 테스트로 고정했다. | | 2026-10-30 | v3.75 | **변환 엔진 목록(브랜치 `feat/engine-list-univa`).** 소유자 불만: 0.5.1의 드롭다운에는 받아 둔 엔진만 있었고, 설치한 앱의 모델 폴더(`~/Library/Application Support/dev.tractus.app/models`)에는 개발 Mac의 `models/custom-models.json`에 넣은 TeamUNIVA 모델이 없었다. ① `asr-ko-univa`(`TeamUNIVA/qwen3_asr_1.7b_ko` 3e66f586, Apache-2.0, bf16 4.7GB, 계열 `qwen3`)를 등록 목록에 올렸다(`level_note: one_of`, 벤치마크 면제: CLAUDE.md 기록). `--preset all`은 약 12GB. ② 모델 화면 디자인: 변환 엔진 선택(드롭다운)·받기/삭제(평평한 모델 목록 속)·직접 추가(맨 아래)가 세 곳에 흩어져 있었고, 모델 10개가 같은 무게로 줄줄이 늘어서 한 줄이 5줄·오른쪽 열이 두 줄이었다. 이제 `변환 엔진` 구역 하나에 라디오 목록(자동 + 엔진 넷, 받지 않은 엔진도 고르면 설정에 저장하고 받기 시작, 받기 전에는 받아 둔 다른 엔진으로 변환)과 직접 추가를 모았다. 줄 제목은 모델 이름(`model_name`), 크기·상태·삭제·받기는 한 줄에 같은 자리. 엔진이 아닌 모델은 `다른 기능의 모델` 구역(컴포넌트 `EngineChoice`, `renderActions`). | diff --git a/CLAUDE.md b/CLAUDE.md index c7087a9..7aaa416 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,7 +27,7 @@ Local-first 노트·녹음 도구(메모·노트가 본체이고, 녹음은 텍 - 런타임은 `mlx-audio`(`mlx_audio.stt.utils.load`)를 **프로세스 안에서** 호출한다. `mlx_audio.server` HTTP 엔드포인트는 `hotwords`를 전달하지 않으므로 쓰지 않는다. 두 트랙은 모델 경로만 다르고 코드는 같다. - VAD는 `mlx-community/silero-vad-v6`(`models/silero-vad-v6`). torch를 의존성에 넣지 않는다. - Whisper·Nemotron은 Phase 0에서 탈락했다(`ARCHITECTURE.md` §8 "Phase 0 결과"). 새 벤치마크(`bench/`) 없이 ASR 모델을 바꾸거나 **등록 목록에** 추가하지 않는다. 사용자가 앱에서 직접 추가하는 엔진(`tractus models add`)은 사용자의 선택이라 측정을 요구하지 않는다. -- **등록 목록 면제 기록 (2026-10-30, 소유자 결정).** `asr-ko-univa`(`TeamUNIVA/qwen3_asr_1.7b_ko` bf16, 4.7GB)를 **벤치마크(`bench/`) 없이** 등록 목록에 올렸다. 확인한 것은 스프린트 회의 5분 구간의 간이 비교(반복 루프 없음, 자동 감지에서 빈 청크가 나와 `asr.py`가 한국어로 다시 변환)뿐이다. 즉 FLEURS·HiKE·AI Hub 품질은 검증되지 않았다. 다음에 이 엔진을 기본으로 권하거나 설명을 바꿀 때 `bench/run.py`로 셋 다 잰다. +- **등록 목록 면제 기록 (2026-10-30, 소유자 결정).** `asr-ko-univa`(`TeamUNIVA/qwen3_asr_1.7b_ko`를 mlx-audio로 8bit 변환해 소유자 계정에 올린 `voyagar/Qwen3-ASR-1.7B-ko-mlx-8bit`, 2.5GB)를 **벤치마크(`bench/`) 없이** 등록 목록에 올렸다. 확인한 것은 스프린트 회의 5분 구간의 간이 비교(반복 루프 없음, 자동 감지에서 빈 청크가 나와 `asr.py`가 한국어로 다시 변환)뿐이다. 즉 FLEURS·HiKE·AI Hub 품질은 검증되지 않았다. 다음에 이 엔진을 기본으로 권하거나 설명을 바꿀 때 `bench/run.py`로 셋 다 잰다. - **변환 엔진은 계열 어댑터로 돈다(v3.59, docs/design/asr-engines.md)**: `asr.ENGINES`(qwen3·whisper·sensevoice), 계열은 모델 폴더 `config.json`의 `model_type`. 새 계열을 더하면 `ENGINES`·`models_install.NEEDED_FILES`·`bench/asr.py`를 함께 고친다. 자주 쓰는 단어는 Qwen만 넣는다(Whisper는 Phase 0에서 프롬프트가 CER을 크게 나쁘게 했다: 다시 넣으려면 측정한다). 고르기는 `transcribe --engine `(앱 설정 `asr_engine`)이고 실시간 텍스트 변환은 0.6B 그대로다. ## 화자 분리 모델 (2026-10-04 확정) diff --git a/app/package.json b/app/package.json index 071c57c..ab859d1 100644 --- a/app/package.json +++ b/app/package.json @@ -1,7 +1,7 @@ { "name": "tractus-app", "private": true, - "version": "0.5.2", + "version": "0.5.3", "license": "Apache-2.0", "type": "module", "scripts": { diff --git a/app/src-tauri/Cargo.lock b/app/src-tauri/Cargo.lock index e9afab7..cf79e60 100644 --- a/app/src-tauri/Cargo.lock +++ b/app/src-tauri/Cargo.lock @@ -4426,7 +4426,7 @@ dependencies = [ [[package]] name = "tractus-app" -version = "0.5.2" +version = "0.5.3" dependencies = [ "base64 0.22.1", "minisign-verify", diff --git a/app/src-tauri/Cargo.toml b/app/src-tauri/Cargo.toml index 14b766b..7a27704 100644 --- a/app/src-tauri/Cargo.toml +++ b/app/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tractus-app" -version = "0.5.2" +version = "0.5.3" description = "Tractus 데스크톱 앱" license = "Apache-2.0" edition = "2021" diff --git a/app/src-tauri/tauri.conf.json b/app/src-tauri/tauri.conf.json index 37398c7..0d9e2d1 100644 --- a/app/src-tauri/tauri.conf.json +++ b/app/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Tractus", - "version": "0.5.2", + "version": "0.5.3", "identifier": "dev.tractus.app", "build": { "beforeDevCommand": "pnpm dev", diff --git a/app/src/preview/data/models-en.json b/app/src/preview/data/models-en.json index be9e351..3b9ccdd 100644 --- a/app/src/preview/data/models-en.json +++ b/app/src/preview/data/models-en.json @@ -111,10 +111,10 @@ { "id": "asr-ko-univa", "name": "Transcription engine (Korean fine-tune)", - "purpose": "Qwen3-ASR 1.7B trained further on Korean. Not quantized, so it is large (4.7GB), and it has only had a quick check. Custom vocabulary works.", + "purpose": "Qwen3-ASR 1.7B trained further on Korean. It has only had a quick check. Custom vocabulary works.", "level": "required", "level_note": "one_of", - "size_bytes": 4714422446, + "size_bytes": 2479288769, "installed": false, "installed_bytes": 0, "state": "missing", @@ -122,12 +122,12 @@ "convert" ], "group": "convert", - "path": "models/qwen3-asr-1.7b-ko-bf16", - "model_name": "Qwen3-ASR 1.7B Korean (bf16)", + "path": "models/qwen3-asr-1.7b-ko-8bit", + "model_name": "Qwen3-ASR 1.7B Korean (8-bit quantized)", "publisher": "TeamUNIVA", - "converted_by": null, - "source": "TeamUNIVA/qwen3_asr_1.7b_ko", - "revision": "3e66f586033753589c3effeb2c8cbce46a1ddabb", + "converted_by": "Tractus (MLX conversion)", + "source": "voyagar/Qwen3-ASR-1.7B-ko-mlx-8bit", + "revision": "8fcc32c42a93394b8c822487e2d595670edae23f", "license": "Apache-2.0", "languages": "Korean", "params": "1.7B", diff --git a/app/src/preview/data/models.json b/app/src/preview/data/models.json index 65bebf1..bd9caf2 100644 --- a/app/src/preview/data/models.json +++ b/app/src/preview/data/models.json @@ -111,10 +111,10 @@ { "id": "asr-ko-univa", "name": "변환 엔진 (한국어 파인튜닝)", - "purpose": "Qwen3-ASR 1.7B를 한국어로 더 학습한 엔진입니다. 양자화하지 않아 용량이 크고(4.7GB) 간이 점검만 했습니다. 자주 쓰는 단어를 쓸 수 있습니다.", + "purpose": "Qwen3-ASR 1.7B를 한국어로 더 학습한 엔진입니다. 간이 점검만 했습니다. 자주 쓰는 단어를 쓸 수 있습니다.", "level": "required", "level_note": "one_of", - "size_bytes": 4714422446, + "size_bytes": 2479288769, "installed": false, "installed_bytes": 0, "state": "missing", @@ -122,12 +122,12 @@ "convert" ], "group": "convert", - "path": "models/qwen3-asr-1.7b-ko-bf16", - "model_name": "Qwen3-ASR 1.7B 한국어 (bf16)", + "path": "models/qwen3-asr-1.7b-ko-8bit", + "model_name": "Qwen3-ASR 1.7B 한국어 (8bit 양자화)", "publisher": "TeamUNIVA", - "converted_by": null, - "source": "TeamUNIVA/qwen3_asr_1.7b_ko", - "revision": "3e66f586033753589c3effeb2c8cbce46a1ddabb", + "converted_by": "Tractus (MLX 변환본)", + "source": "voyagar/Qwen3-ASR-1.7B-ko-mlx-8bit", + "revision": "8fcc32c42a93394b8c822487e2d595670edae23f", "license": "Apache-2.0", "languages": "한국어", "params": "1.7B", diff --git a/docs/design/asr-engines.md b/docs/design/asr-engines.md index 460b99b..8337559 100644 --- a/docs/design/asr-engines.md +++ b/docs/design/asr-engines.md @@ -66,7 +66,7 @@ - **Sorimac은 탈락.** 회의와 한·영 혼용에서 반복 루프에 빠져 무너진다. - **BuzzASR은 쓸 만한 대안.** 회의 CER은 기본보다 0.8%p 나쁘지만, 영어 용어를 자주 쓰는 단어 없이도 86% 맞히고(기본은 단어를 넣어야 84%) 한·영 혼용은 가장 좋다. 메모리는 1.3GB 덜 쓰고 속도는 25% 느리다. 낭독(FLEURS)은 나쁘다. -- **TeamUNIVA/qwen3_asr_1.7b_ko**(Qwen3-ASR 1.7B 한국어 파인튜닝, Apache-2.0, bf16)는 간이 점검만 했다(2026-10-30, 스프린트 회의 5분, 같은 청크 11개): 반복 루프는 없고, 언어를 한국어로 고정하면 기본과 비슷하게 나온다(CER 25.4 대 24.1, 기준은 스마트 교정본이라 기본에 유리). **자동 감지에서는 청크의 27%가 영어로 오감지되며 토큰 0개로 비었다.** 그래서 `asr.py`는 자동 감지가 빈 글을 내면 그 청크만 한국어로 다시 변환한다. 숫자·고유명사(`본부장님`, `CMP`)는 나았고 영어 브랜드는 한글로 적는 경향이 있다(`ALMS` → `알류엠에스`). 소유자가 직접 추가해 쓴다(`models add`). FLEURS·HiKE·AI Hub는 재지 않았다. +- **TeamUNIVA/qwen3_asr_1.7b_ko**(Qwen3-ASR 1.7B 한국어 파인튜닝, Apache-2.0)는 원본 bf16으로 간이 점검만 했다(2026-10-30, 스프린트 회의 5분, 같은 청크 11개): 반복 루프는 없고, 언어를 한국어로 고정하면 기본과 비슷하게 나온다(CER 25.4 대 24.1, 기준은 스마트 교정본이라 기본에 유리). **자동 감지에서는 청크의 27%가 영어로 오감지되며 토큰 0개로 비었다.** 그래서 `asr.py`는 자동 감지가 빈 글을 내면 그 청크만 한국어로 다시 변환한다. 숫자·고유명사(`본부장님`, `CMP`)는 나았고 영어 브랜드는 한글로 적는 경향이 있다(`ALMS` → `알류엠에스`). 소유자가 직접 추가해 쓴다(`models add`). FLEURS·HiKE·AI Hub는 재지 않았다. - ghost613·seastar·SenseVoice는 소유자 요청으로 측정을 멈췄다(14:00). 짧은 합성 음성에서 ghost613은 글자가 깨지고, seastar는 문장 뒤를 지어내고, SenseVoice는 띄어쓰기가 깨졌다. 측정: FLEURS(낭독, CER), HiKE(한·영 혼용, MER), AI Hub 회의(CER, 용어 재현율). 한국어 전용 파인튜닝은 영어 용어를 한글로 적는 경향이 있고, AI Hub 정답도 한글 표기라 AI Hub CER이 좋게 나온다. **HiKE를 같이 본다.** 기준: Qwen3-ASR 1.7B 8bit — AI Hub 9.49(자주 쓰는 단어 넣으면 9.36), FLEURS 2.62. @@ -75,7 +75,8 @@ - **왜:** HF에 BuzzASR의 MLX 판이 없어 직접 추가로는 쓸 수 없었다(`BuzzASR/korean`은 transformers 형식). 측정(위 표)에서 한·영 혼용과 영어 용어가 가장 좋았다. - **어떻게:** `BuzzASR/korean` @ `411b6854`를 mlx-audio 0.5.7 `mlx_audio.convert --quantize --q-bits 8`로 바꿔 소유자 계정 [`voyagar/BuzzASR-korean-mlx-8bit`](https://huggingface.co/voyagar/BuzzASR-korean-mlx-8bit)에 공개로 올렸다(커밋 `b73fdad4`, `model.safetensors` sha256 `51e3f340…5d78`, MIT 원작자 표기와 측정표를 모델 카드에 적음). 다시 바꾼 것이 지난 측정본과 같은지는 FLEURS 50문장으로 봤다: 47개가 글자까지 같고, 나머지 3개는 같은 모델로도 돌릴 때마다 달랐다(Whisper 온도 재시도). -- **목록(v0.5.2):** `asr-ko-univa` = `변환 엔진 (한국어 파인튜닝)`, TeamUNIVA/qwen3_asr_1.7b_ko bf16 4.7GB, 계열 `qwen3`(자주 쓰는 단어 사용), 소유자가 측정 없이 올렸다(CLAUDE.md 면제 기록). 위 간이 점검만 했다. +- **목록(v0.5.2):** `asr-ko-univa` = `변환 엔진 (한국어 파인튜닝)`, `voyagar/Qwen3-ASR-1.7B-ko-mlx-8bit`(원본 `TeamUNIVA/qwen3_asr_1.7b_ko` 3e66f586을 `mlx_audio.convert -q --q-bits 8 --q-group-size 64`로 변환, 2.5GB; 표준 엔진과 같은 설정, 가중치 파일 크기도 같다), 계열 `qwen3`(자주 쓰는 단어 사용), 소유자가 측정 없이 올렸다(CLAUDE.md 면제 기록). 위 간이 점검만 했다. + - 8bit 변환(2026-10-30, 같은 5분 구간·청크): 원본 bf16과 출력 차이 CER 2.5(한국어 고정)·4.5(자동 감지+재시도), 스마트 교정본 대비 25.4 → 26.9(참조본이 AI 교정본이라 신뢰도 낮음), 처리 시간 60초 → 41~44초, 가중치 4.7GB → 2.5GB. 반복 루프·빈 청크 없음. 그래서 목록에는 8bit 변환본을 올렸다. - **목록:** `asr-ko-mix` = `변환 엔진 (영어 섞인 한국어)`, `required` + `one_of`(직접 추가한 엔진과 같다), 계열 `whisper`(자주 쓰는 단어 없음). 기본 엔진 순서(`pick_asr`)는 그대로라 사용자가 모델 화면의 `변환 엔진` 목록에서 고를 때만 쓴다. 구성: 앱의 표준·저사양·필수에는 넣지 않고, 명령줄 `--preset all`(약 7.3GB)에만 들어간다. - **확인:** 빈 모델 폴더에서 `tractus models download asr-ko-mix` → `transcribe --engine asr-ko-mix`(가상 `say` 음성): `asr.model`이 이 저장소, 영어 용어·숫자(`30만원`)를 그대로 적었다. - 바꾸지 않은 것: 실시간 텍스트 변환(0.6B), 자주 쓰는 단어(Whisper 계열은 넣지 않는다, 다시 넣으려면 재서 정한다). diff --git a/docs/en/setup.md b/docs/en/setup.md index 0d1a8bf..2d2df8a 100644 --- a/docs/en/setup.md +++ b/docs/en/setup.md @@ -89,7 +89,7 @@ If a download is interrupted, run the same command again to resume. | `asr-std` | Standard transcription engine (Qwen3-ASR 1.7B) | 2.5GB | Required (any one engine) | Transcription | | `asr-lite` | Lite transcription engine (Qwen3-ASR 0.6B) | 1.0GB | Required (any one engine) | Transcription, **live transcription (needs this engine even if the standard engine is installed)** | | `asr-ko-mix` | Korean-with-English transcription engine (BuzzASR Korean, Whisper large-v3 fine-tuned for Korean) | 1.7GB | Required (any one engine) | Transcription | -| `asr-ko-univa` | Korean fine-tuned transcription engine (TeamUNIVA Qwen3-ASR 1.7B Korean, bf16) | 4.7GB | Required (any one engine) | Transcription (custom vocabulary works) | +| `asr-ko-univa` | Korean fine-tuned transcription engine (TeamUNIVA Qwen3-ASR 1.7B Korean, 8-bit conversion) | 2.5GB | Required (any one engine) | Transcription (custom vocabulary works) | | `diarizer` | Speaker detection (Nemotron 3 Diarization) | 199MB | Recommended | Speaker detection (without it, transcripts have no speakers) | | `aligner` | Word sync (Qwen3 ForcedAligner 0.6B) | 1.3GB | Optional | Word sync, word highlighting during playback | | `embedding` | Smart search (Qwen3 Embedding 0.6B, 8bit) | 0.6GB | Optional | Smart search (word match search still works) | diff --git a/docs/models.md b/docs/models.md index ae55649..67e4aeb 100644 --- a/docs/models.md +++ b/docs/models.md @@ -10,7 +10,7 @@ uv run tractus models download --preset standard # required | standard | lite uv run tractus models remove aligner # 하나 지우기 ``` -구성은 `standard`(약 4.6GB, 메모리 16GB 이상), `lite`(약 1.2GB, 메모리 8GB), `required`(1.0~2.5GB, 변환에 꼭 필요한 것만), `all`(약 12GB, 변환 엔진 넷 모두)입니다. 기본 흐름(녹음·가져오기 → 변환 → 요약)은 `required`로 됩니다. 실시간 텍스트 변환(미리보기)은 메모리 16GB 이상에서만 켜지고 가벼운 엔진(`asr-lite`)이 따로 필요하므로, 8GB Mac(`lite` 구성)에서는 쓸 수 없습니다. 변환 엔진(`asr-std`·`asr-lite`·`asr-ko-mix`·`asr-ko-univa`)은 **필수 (엔진 중 하나)** 입니다: 하나만 받아도 텍스트 변환이 되고, 모델 화면에는 `변환 엔진: 설치됨`으로 보입니다. +구성은 `standard`(약 4.6GB, 메모리 16GB 이상), `lite`(약 1.2GB, 메모리 8GB), `required`(1.0~2.5GB, 변환에 꼭 필요한 것만), `all`(약 10GB, 변환 엔진 넷 모두)입니다. 기본 흐름(녹음·가져오기 → 변환 → 요약)은 `required`로 됩니다. 실시간 텍스트 변환(미리보기)은 메모리 16GB 이상에서만 켜지고 가벼운 엔진(`asr-lite`)이 따로 필요하므로, 8GB Mac(`lite` 구성)에서는 쓸 수 없습니다. 변환 엔진(`asr-std`·`asr-lite`·`asr-ko-mix`·`asr-ko-univa`)은 **필수 (엔진 중 하나)** 입니다: 하나만 받아도 텍스트 변환이 되고, 모델 화면에는 `변환 엔진: 설치됨`으로 보입니다. 모델이 없는 기능은 단추를 눌러 보면 이유와 설치 방법을 알려 줍니다. 녹음은 모델 없이 되고, 변환 엔진이 없으면 `변환 대기 중인 녹음`으로 남습니다. diff --git a/docs/releases/v0.5.3.md b/docs/releases/v0.5.3.md new file mode 100644 index 0000000..0644c8c --- /dev/null +++ b/docs/releases/v0.5.3.md @@ -0,0 +1,49 @@ +--- +version: 0.5.3 +date: 2026-10-30 +summary: 한국어 파인튜닝 변환 엔진을 8bit 변환본으로 바꿔 받는 용량을 4.7GB에서 2.5GB로 줄이고 변환을 약 30% 빠르게 했습니다. +summary_en: The Korean fine-tuned transcription engine is now an 8-bit conversion: a 2.5GB download instead of 4.7GB, and about 30% faster. +--- +# Tractus v0.5.3 + +녹음과 메모를 내 Mac 안에서 텍스트로 바꾸고, 요약·검색·AI 질문까지 가능한 앱입니다. 이번 버전은 0.5.2에 더한 한국어 파인튜닝 변환 엔진을 가볍게 했습니다. (English below) + +## 이번 버전에서 바뀐 것 + +- **`Qwen3-ASR 1.7B 한국어` 엔진이 8bit 변환본이 됐습니다.** 0.5.2에서는 원본(bf16) 4.7GB를 받아야 했는데, 이제 2.5GB입니다. 같은 회의 5분 구간에서 원본보다 약 30% 빨랐습니다. + - 정확도는 원본과 거의 같게 나왔습니다(같은 구간 출력 차이 CER 2.5, 반복 루프 없음). 다만 5분 구간 하나로 본 간이 점검이고, 한·영 혼용과 공개 벤치마크는 재지 않았습니다. + - 변환본은 제작자 TeamUNIVA의 모델을 8bit로 바꿔 올린 것입니다(`voyagar/Qwen3-ASR-1.7B-ko-mlx-8bit`, Apache-2.0). +- **0.5.2에서 이 엔진(4.7GB)을 이미 받으셨다면:** 설정 › 모델의 `변환 엔진`에서 이 엔진을 한 번 더 받아 주세요(2.5GB). 고른 엔진 설정은 그대로이고, 새로 받는 동안에는 받아 둔 다른 엔진으로 변환합니다. 옛 4.7GB 폴더는 설정 › 모델의 `사용하지 않는 폴더 … 정리` 단추로 지울 수 있습니다. + +## 업데이트·설치 + +- **v0.1.1 이상을 쓰고 있다면:** 설정 › 업데이트에서 `업데이트 확인` → `업데이트 설치` → `다시 열기`. +- **새로 설치한다면:** DMG를 열고 `Tractus.app`을 `Applications`로 끌어다 놓습니다. + - 처음 열 때 "확인되지 않은 개발자" 경고가 나오면: 시스템 설정 → 개인정보 보호 및 보안 → "그래도 열기" (또는 `xattr -dr com.apple.quarantine /Applications/Tractus.app`) + - **ffmpeg가 필요합니다:** `brew install ffmpeg` +- 노트·모델·설정 파일은 그대로입니다. + +## 받을 파일 + +| 파일 | 설명 | +| --- | --- | +| `Tractus-0.5.3-arm64.dmg` | 설치 파일 (Apple Silicon 전용) | +| `Tractus-0.5.3-arm64.dmg.sha256` | 체크섬. `shasum -a 256 -c Tractus-0.5.3-arm64.dmg.sha256` | +| `Tractus.app.tar.gz`, `.sig`, `latest.json` | 앱 안 업데이트가 쓰는 파일입니다. 직접 받을 필요는 없습니다. | + +## 요구 사항 + +- Apple Silicon(M1 이상), 메모리 16GB 이상 권장(8GB는 저사양 구성) +- macOS 14.4 이상(설계상 최소) + +--- + +## English + +Tractus turns recordings and memos into text on your Mac, then summarizes, searches and answers questions about them. **New in 0.5.3: the Korean fine-tuned engine added in 0.5.2 is now lighter.** + +- **`Qwen3-ASR 1.7B Korean` is now an 8-bit conversion.** 0.5.2 needed the 4.7GB original (bf16); it is now 2.5GB and about 30% faster on the same 5-minute stretch of a meeting. Accuracy came out close to the original (2.5 CER difference on that stretch, no repetition loops) — but this is only a quick check on one 5-minute stretch; mixed Korean–English speech and public benchmarks were not measured. The converted model is TeamUNIVA's model quantized to 8-bit (`voyagar/Qwen3-ASR-1.7B-ko-mlx-8bit`, Apache-2.0). +- **If you already downloaded the 4.7GB engine in 0.5.2:** open Settings › Models › `Transcription engine` and download this engine once more (2.5GB). Your engine choice stays, and until the new download finishes the engines you already have are used. The old 4.7GB folder can be removed with the `Clean up … unused folder` button in Settings › Models. +- Install: open the DMG and drag `Tractus.app` to `Applications`; you need `brew install ffmpeg`. The build isn't notarized yet — use System Settings › Privacy & Security › Open Anyway on first launch. Apple Silicon, macOS 14.4+. + +Guides: [Setup](https://github.com/sjoon21/Tractus/blob/main/docs/en/setup.md) · [Usage](https://github.com/sjoon21/Tractus/blob/main/docs/en/usage.md) · [Agents (MCP)](https://github.com/sjoon21/Tractus/blob/main/docs/en/mcp.md) diff --git a/docs/roadmap.md b/docs/roadmap.md index ab792da..4899cbf 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -33,6 +33,7 @@ - [x] 0.5.0: 변환 중에도 녹음, 내보내기에서 넣을 요약·내용 고르기, 시작 때 새 버전 안내 창, 글만 있는 노트의 떠 있는 녹음 추가 단추, 새 아이콘 (v3.71~v3.73) - [x] 0.5.1: 사이드바 노트 목록이 길어져도 쓰기 쉽게(달 묶음 접기·위에 붙는 검색창과 달 머리글·제목 바로가기), 모델 화면의 변환 엔진 드롭다운, 자동 감지가 빈 글을 낼 때 한국어로 다시 변환 (v3.74) - [x] 0.5.2: 모델 화면 변환 엔진을 라디오 목록 하나로(받지 않은 엔진도 고르면 받기 시작), 한국어 파인튜닝 엔진(TeamUNIVA) 목록에 추가, 녹음 중 입력 장치가 바뀌면 녹음이 죽던 것 수정 (v3.75~v3.77, 이슈 #57) +- [x] 0.5.3: 한국어 파인튜닝 엔진을 8bit 변환본으로 교체(4.7GB → 2.5GB, 약 30% 빠름) (v3.78~v3.79) - [ ] Windows 지원 (MLX를 대신할 런타임, Windows 녹음 프로그램, 설치·서명). 2026-10-22 소유자 결정: macOS에서 충분히 다듬은 뒤로 최대한 미룬다(1.0일 수 있다) - [ ] 영어 화면에서 실제 AI 요약·노트 완성 품질 확인 - [ ] 깨끗한 Mac(새 계정)과 macOS 14.4~15에서 미리 만든 앱 실행, 내려받은 `.dmg`의 Gatekeeper 동작과 권한 이름 확인 diff --git a/docs/setup.md b/docs/setup.md index c332839..bcadacf 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -87,7 +87,7 @@ uv run tractus models remove aligner # 하나 지우기 | `asr-std` | 표준 변환 엔진 (Qwen3-ASR 1.7B) | 2.5GB | 필수 (엔진 중 하나) | 텍스트 변환 | | `asr-lite` | 저사양 변환 엔진 (Qwen3-ASR 0.6B) | 1.0GB | 필수 (엔진 중 하나) | 텍스트 변환, **실시간 텍스트 변환 (표준 엔진이 있어도 이 엔진이 따로 필요)** | | `asr-ko-mix` | 영어 섞인 한국어 변환 엔진 (BuzzASR Korean, Whisper large-v3 한국어 파인튜닝) | 1.7GB | 필수 (엔진 중 하나) | 텍스트 변환 | -| `asr-ko-univa` | 한국어 파인튜닝 변환 엔진 (TeamUNIVA Qwen3-ASR 1.7B 한국어, bf16) | 4.7GB | 필수 (엔진 중 하나) | 텍스트 변환 (자주 쓰는 단어 사용) | +| `asr-ko-univa` | 한국어 파인튜닝 변환 엔진 (TeamUNIVA Qwen3-ASR 1.7B 한국어, 8bit 변환) | 2.5GB | 필수 (엔진 중 하나) | 텍스트 변환 (자주 쓰는 단어 사용) | | `diarizer` | 참석자 구분 (Nemotron 3 Diarization) | 199MB | 권장 | 참석자 구분 (없으면 참석자 없이 변환) | | `aligner` | 단어 싱크 (Qwen3 ForcedAligner 0.6B) | 1.3GB | 선택 | 단어 싱크 맞추기, 재생 중 단어 강조 | | `embedding` | 스마트 검색 (Qwen3 Embedding 0.6B, 8bit) | 0.6GB | 선택 | 스마트 검색 (키워드 검색은 그대로 됨) | @@ -96,7 +96,7 @@ uv run tractus models remove aligner # 하나 지우기 - **`필수 (엔진 중 하나)`**: 변환 엔진(`asr-std`·`asr-lite`·`asr-ko-mix`·`asr-ko-univa`)은 하나만 있으면 텍스트 변환이 됩니다. 다 받을 필요는 없습니다. 모델 화면에는 하나라도 설치돼 있으면 `변환 엔진: 설치됨`으로 보입니다. 표준 엔진은 가장 정확하고 메모리 16GB 이상을 권합니다. 가벼운 엔진은 메모리를 덜 쓰고, **실시간 텍스트 변환에는 이 엔진이 따로 필요합니다.** 표준 엔진(1.7B)도 실시간에 써 봤지만 글자가 확정되기까지 p95로 약 1.6~2초(부하가 있는 Mac에서 잰 값, 중간값도 약 1초 이상)라 기준 1초를 넘어 쓰지 않습니다 (2026-10-14 실측, docs/desktop.md §2.8). - **`asr-ko-mix`(BuzzASR)**: 영어 용어가 많이 섞인 한국어 대화에서 표준 엔진보다 정확합니다(한·영 혼용 HiKE MER 22.8 vs 28.3, 영어 용어 재현율 86% vs 72%). 한국어만 쓰는 회의는 표준 엔진이 조금 더 정확합니다(AI Hub CER 9.5 vs 10.3). Whisper 계열이라 자주 쓰는 단어를 쓰지 않습니다. 모델 화면의 `변환 엔진` 목록에서 고르면 이 엔진으로 변환합니다(받지 않았으면 받기부터 시작합니다). -- **`asr-ko-univa`(TeamUNIVA)**: Qwen3-ASR 1.7B를 한국어로 더 학습한 엔진입니다. 양자화하지 않은 bf16이라 4.7GB입니다. 간이 점검(노트 5분 구간)만 했고 FLEURS·HiKE·AI Hub는 재지 않았습니다. 언어 자동 감지가 빈 글을 내면 한국어로 다시 변환합니다. +- **`asr-ko-univa`(TeamUNIVA)**: Qwen3-ASR 1.7B를 한국어로 더 학습한 엔진입니다. 원본(bf16, 4.7GB)을 8bit로 변환한 2.5GB 판이고, 원본보다 약 30% 빠릅니다. 간이 점검(노트 5분 구간)만 했고 FLEURS·HiKE·AI Hub는 재지 않았습니다. 언어 자동 감지가 빈 글을 내면 한국어로 다시 변환합니다. - 기능이 아닌 항목도 있습니다. **녹음**은 모델 없이 됩니다. 변환 엔진이 없으면 녹음만 저장하고 `변환 대기 중인 녹음`으로 남깁니다. 나중에 모델을 받으면 변환합니다. - **요약과 AI 질문**은 모델이 아니라 API 키가 필요합니다 ([API 키](#api-키-넣기)). - `fluid`는 모델 외에 헬퍼 `tractus-diar`가 필요합니다. `scripts/install.sh --with-fluid`로 빌드한 뒤 받습니다(Swift 6.2 이상 필요). diff --git a/plugins/tractus/.claude-plugin/plugin.json b/plugins/tractus/.claude-plugin/plugin.json index 4af8e42..602405a 100644 --- a/plugins/tractus/.claude-plugin/plugin.json +++ b/plugins/tractus/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "tractus", "displayName": "Tractus", - "version": "0.5.2", + "version": "0.5.3", "description": "Your meetings as local memory for Claude Code: search notes, transcripts, decisions and action items recorded on this Mac with Tractus. Nothing leaves your Mac except what Claude reads.", "author": { "name": "sjoon21", "url": "https://github.com/sjoon21" }, "homepage": "https://github.com/sjoon21/Tractus", diff --git a/pyproject.toml b/pyproject.toml index 4a01a77..553bd6f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "tractus" -version = "0.5.2" +version = "0.5.3" description = "Local-first 노트·녹음 도구" readme = "README.md" license = "Apache-2.0" diff --git a/src/tractus/i18n_en.json b/src/tractus/i18n_en.json index 143975f..f99f929 100644 --- a/src/tractus/i18n_en.json +++ b/src/tractus/i18n_en.json @@ -416,6 +416,6 @@ "회의록": "Minutes", "회의록을 저장하지 못했습니다: 형식이 맞지 않습니다": "Couldn't save the minutes: the format is invalid", "변환 엔진 (한국어 파인튜닝)": "Transcription engine (Korean fine-tune)", - "Qwen3-ASR 1.7B를 한국어로 더 학습한 엔진입니다. 양자화하지 않아 용량이 크고(4.7GB) 간이 점검만 했습니다. 자주 쓰는 단어를 쓸 수 있습니다.": "Qwen3-ASR 1.7B trained further on Korean. Not quantized, so it is large (4.7GB), and it has only had a quick check. Custom vocabulary works.", - "Qwen3-ASR 1.7B 한국어 (bf16)": "Qwen3-ASR 1.7B Korean (bf16)" + "Qwen3-ASR 1.7B를 한국어로 더 학습한 엔진입니다. 간이 점검만 했습니다. 자주 쓰는 단어를 쓸 수 있습니다.": "Qwen3-ASR 1.7B trained further on Korean. It has only had a quick check. Custom vocabulary works.", + "Qwen3-ASR 1.7B 한국어 (8bit 양자화)": "Qwen3-ASR 1.7B Korean (8-bit quantized)" } diff --git a/src/tractus/models_registry.py b/src/tractus/models_registry.py index f8e5579..b887ebf 100644 --- a/src/tractus/models_registry.py +++ b/src/tractus/models_registry.py @@ -120,15 +120,24 @@ def _qwen_asr(size_cfg: int, weights: int, index: int, extra_cfg: int = 12487, g # BuzzASR/korean(411b6854, MIT, Whisper large-v3 한국어 파인튜닝, arXiv 2609.09554)을 mlx-audio 0.5.7로 8bit 변환해 소유자 계정에 올린 것(2026-10-22). # 측정(docs/design/asr-engines.md): AI Hub CER 10.29(표준 9.49), HiKE MER 22.79(표준 28.3), 영어 용어 재현율 86.3%(단어 없이). Whisper 계열이라 자주 쓰는 단어를 넣지 않는다(asr.ENGINES) model_name=t("BuzzASR Korean (8bit 양자화)"), publisher="BuzzASR", converted_by=t("Tractus (MLX 변환본)"), license="MIT", languages=t("한국어"), params="1.5B"), - _hf("asr-ko-univa", t("변환 엔진 (한국어 파인튜닝)"), t("Qwen3-ASR 1.7B를 한국어로 더 학습한 엔진입니다. 양자화하지 않아 용량이 크고(4.7GB) 간이 점검만 했습니다. 자주 쓰는 단어를 쓸 수 있습니다."), "required", "convert", - "TeamUNIVA/qwen3_asr_1.7b_ko", "3e66f586033753589c3effeb2c8cbce46a1ddabb", "qwen3-asr-1.7b-ko-bf16", - {"added_tokens.json": 1566, "chat_template.jinja": 1099, "config.json": 5971, "generation_config.json": 143, "merges.txt": 1671853, - "model.safetensors": 4698521600, "preprocessor_config.json": 357, "special_tokens_map.json": 1008, "tokenizer.json": 11429499, - "tokenizer_config.json": 12517, "vocab.json": 2776833}, + _hf("asr-ko-univa", t("변환 엔진 (한국어 파인튜닝)"), t("Qwen3-ASR 1.7B를 한국어로 더 학습한 엔진입니다. 간이 점검만 했습니다. 자주 쓰는 단어를 쓸 수 있습니다."), "required", "convert", + "voyagar/Qwen3-ASR-1.7B-ko-mlx-8bit", "8fcc32c42a93394b8c822487e2d595670edae23f", "qwen3-asr-1.7b-ko-8bit", + {"added_tokens.json": 1566, + "chat_template.jinja": 1099, + "config.json": 7425, + "generation_config.json": 143, + "merges.txt": 1671853, + "model.safetensors": 2463307541, + "model.safetensors.index.json": 78928, + "preprocessor_config.json": 357, + "special_tokens_map.json": 1008, + "tokenizer.json": 11429499, + "tokenizer_config.json": 12517, + "vocab.json": 2776833}, level_note=ONE_OF, engine="qwen3", - # TeamUNIVA/qwen3_asr_1.7b_ko(3e66f586, Apache-2.0, Qwen/Qwen3-ASR-1.7B 한국어 SFT 두 번 + GSPO 강화학습, bf16 원본). 소유자가 2026-10-30 목록에 올림(벤치마크 없이: CLAUDE.md 면제 기록). - # 간이 점검(docs/design/asr-engines.md): 노트 5분 구간에서 반복 루프 없음, 자동 감지가 영어로 오감지해 빈 글을 내면 asr.py가 한국어로 다시 변환한다. FLEURS·HiKE·AI Hub는 재지 않았다 - model_name=t("Qwen3-ASR 1.7B 한국어 (bf16)"), publisher="TeamUNIVA", license="Apache-2.0", languages=t("한국어"), params="1.7B"), + # TeamUNIVA/qwen3_asr_1.7b_ko(3e66f586, Apache-2.0, Qwen/Qwen3-ASR-1.7B 한국어 SFT 두 번 + GSPO 강화학습)를 mlx_audio.convert로 8bit(affine, 그룹 64: 표준 엔진과 같은 설정) 변환해 소유자 계정에 올린 것(2026-10-30). + # 원본 bf16(4.7GB) 대비 같은 5분 구간 출력 차이 CER 2.5, 스마트 교정본 대비 25.4 → 26.9, 처리 시간 약 30% 단축(docs/design/asr-engines.md). 벤치마크 없이 올렸다(CLAUDE.md 면제 기록). 자동 감지가 영어로 오감지해 빈 글을 내면 asr.py가 한국어로 다시 변환한다 + model_name=t("Qwen3-ASR 1.7B 한국어 (8bit 양자화)"), publisher="TeamUNIVA", converted_by=t("Tractus (MLX 변환본)"), license="Apache-2.0", languages=t("한국어"), params="1.7B"), _hf("diarizer", t("참석자 구분"), t("누가 말했는지 나눕니다. 8명까지 구분합니다."), "recommended", "speakers", diarize.MODEL_REPO, diarize.MODEL_REVISION, diarize.MODEL_DIR, {"config.json": 1521, "model.safetensors": 198632220}, diff --git a/tests/test_models.py b/tests/test_models.py index 152fd9b..df9f4ad 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -72,7 +72,7 @@ def test_every_model_says_what_it_is_and_agrees_with_download_constants(): consts = {"vad": (cli.VAD_MODEL, reg.get("vad").revision), "asr-std": (cli.MODELS[cli.Track.standard], reg.get("asr-std").revision), "asr-lite": (cli.MODELS[cli.Track.lite], reg.get("asr-lite").revision), "asr-ko-mix": ("voyagar/BuzzASR-korean-mlx-8bit", "b73fdad446cfa19ad50dd919d06d7f96af1726ff"), - "asr-ko-univa": ("TeamUNIVA/qwen3_asr_1.7b_ko", "3e66f586033753589c3effeb2c8cbce46a1ddabb"), + "asr-ko-univa": ("voyagar/Qwen3-ASR-1.7B-ko-mlx-8bit", "8fcc32c42a93394b8c822487e2d595670edae23f"), "diarizer": (diarize.MODEL_REPO, diarize.MODEL_REVISION), "aligner": (align.MODEL_REPO, align.MODEL_REVISION), "embedding": (embed.MODEL_REPO, embed.MODEL_REVISION), "voices": (voices.MODEL_URL, None), "fluid": (diarize.FLUID_REPO, None)} assert set(consts) == {m.id for m in reg.MODELS} diff --git a/uv.lock b/uv.lock index c27583e..12e9129 100644 --- a/uv.lock +++ b/uv.lock @@ -1767,7 +1767,7 @@ wheels = [ [[package]] name = "tractus" -version = "0.5.2" +version = "0.5.3" source = { editable = "." } dependencies = [ { name = "kaldi-native-fbank" },