Split STT-only and STT+LLM test modes
This commit is contained in:
23
README.md
23
README.md
@@ -1,6 +1,6 @@
|
|||||||
# realtime_voice_bot
|
# realtime_voice_bot
|
||||||
|
|
||||||
출력장치로 재생되는 소리를 파일 저장 없이 바로 받아서 `faster-whisper`로 STT 테스트를 하고, 별도로 `Ollama` LLM 에이전트 CLI 테스트를 할 수 있는 최소 프로토타입입니다.
|
출력장치로 재생되는 소리를 파일 저장 없이 바로 받아서 `faster-whisper`로 STT 테스트를 하고, 필요하면 `Ollama` LLM과 연결된 통합 테스트와 LLM CLI 테스트를 할 수 있는 최소 프로토타입입니다.
|
||||||
|
|
||||||
현재 문서는 **Windows PC에서 실행하는 기준**으로 적었습니다.
|
현재 문서는 **Windows PC에서 실행하는 기준**으로 적었습니다.
|
||||||
|
|
||||||
@@ -11,7 +11,8 @@
|
|||||||
- 메모리 버퍼 기반 간단한 저지연 발화 분리
|
- 메모리 버퍼 기반 간단한 저지연 발화 분리
|
||||||
- 미리 로드한 `faster-whisper` 워커에 PCM 직접 전달
|
- 미리 로드한 `faster-whisper` 워커에 PCM 직접 전달
|
||||||
- 디스크에 WAV 저장 없이 바로 전사
|
- 디스크에 WAV 저장 없이 바로 전사
|
||||||
- STT 결과에 대해 답변 가치 판단 후 필요할 때만 LLM 답변
|
- STT 전용 테스트
|
||||||
|
- STT 결과에 대해 답변 가치 판단 후 필요할 때만 LLM 답변하는 통합 테스트
|
||||||
- 로컬 `Ollama` LLM 에이전트 CLI 테스트
|
- 로컬 `Ollama` LLM 에이전트 CLI 테스트
|
||||||
|
|
||||||
## 빠른 시작
|
## 빠른 시작
|
||||||
@@ -34,6 +35,12 @@ bun run devices
|
|||||||
bun run test:stt
|
bun run test:stt
|
||||||
```
|
```
|
||||||
|
|
||||||
|
STT + LLM 통합 테스트:
|
||||||
|
|
||||||
|
```bat
|
||||||
|
bun run test:sttllm
|
||||||
|
```
|
||||||
|
|
||||||
LLM 단독 테스트:
|
LLM 단독 테스트:
|
||||||
|
|
||||||
```bat
|
```bat
|
||||||
@@ -76,7 +83,7 @@ bun run test:llm
|
|||||||
|
|
||||||
## 메모
|
## 메모
|
||||||
|
|
||||||
- 이 버전은 `STT` 테스트와 `LLM` 테스트를 따로 합니다.
|
- 이 버전은 `STT`, `STT+LLM`, `LLM` 테스트를 따로 제공합니다.
|
||||||
- 최소 지연을 위해 파일 저장은 하지 않습니다.
|
- 최소 지연을 위해 파일 저장은 하지 않습니다.
|
||||||
- VAD는 현재 모델 기반이 아니라 진폭 기반 단순 분리입니다.
|
- VAD는 현재 모델 기반이 아니라 진폭 기반 단순 분리입니다.
|
||||||
- Windows에서는 보통 출력 루프백이 가능한 장치나 `Stereo Mix`, 오디오 인터페이스 loopback 채널을 `AUDIO_SOURCE`로 잡아야 합니다.
|
- Windows에서는 보통 출력 루프백이 가능한 장치나 `Stereo Mix`, 오디오 인터페이스 loopback 채널을 `AUDIO_SOURCE`로 잡아야 합니다.
|
||||||
@@ -92,7 +99,13 @@ bun run test:llm
|
|||||||
4. `bun run devices`
|
4. `bun run devices`
|
||||||
5. `.env`에서 `AUDIO_SOURCE=`에 루프백 장치 이름 입력
|
5. `.env`에서 `AUDIO_SOURCE=`에 루프백 장치 이름 입력
|
||||||
6. `bun run test:stt`
|
6. `bun run test:stt`
|
||||||
7. 유튜브, 디스코드 통화, 동영상 같은 소리를 재생해서 전사와 LLM 답변 확인
|
7. 유튜브, 디스코드 통화, 동영상 같은 소리를 재생해서 전사만 확인
|
||||||
|
|
||||||
|
## Windows STT+LLM 통합 테스트 순서
|
||||||
|
|
||||||
|
1. `bun run setup:llm`
|
||||||
|
2. `bun run test:sttllm`
|
||||||
|
3. 유튜브, 디스코드 통화, 동영상 같은 소리를 재생해서 전사와 답변 확인
|
||||||
|
|
||||||
## Windows LLM 테스트 순서
|
## Windows LLM 테스트 순서
|
||||||
|
|
||||||
@@ -112,7 +125,7 @@ bun run test:llm
|
|||||||
동작 원칙:
|
동작 원칙:
|
||||||
- 일반 대화는 로컬 LLM만 답변
|
- 일반 대화는 로컬 LLM만 답변
|
||||||
- 최신 정보, 뉴스, 사실 확인, 검색 요청일 때만 웹 도구 사용
|
- 최신 정보, 뉴스, 사실 확인, 검색 요청일 때만 웹 도구 사용
|
||||||
- STT 경로에서는 먼저 "대답할 가치가 있는 텍스트인지" 판정한 뒤 필요할 때만 답변
|
- `test:sttllm` 에서는 먼저 "대답할 가치가 있는 텍스트인지" 판정한 뒤 필요할 때만 답변
|
||||||
- 웹 검색이 실제로 시작되면 결과 전에 `검색해볼게요.` 같은 진행 메시지를 먼저 출력
|
- 웹 검색이 실제로 시작되면 결과 전에 `검색해볼게요.` 같은 진행 메시지를 먼저 출력
|
||||||
|
|
||||||
## Windows용 .env 예시
|
## Windows용 .env 예시
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"setup:llm": "bun src/setup-llm.ts",
|
"setup:llm": "bun src/setup-llm.ts",
|
||||||
"setup:python": "bun run setup:stt",
|
"setup:python": "bun run setup:stt",
|
||||||
"test:stt": "bun src/index.ts test-stt",
|
"test:stt": "bun src/index.ts test-stt",
|
||||||
|
"test:sttllm": "bun src/index.ts test-sttllm",
|
||||||
"test:llm": "bun src/index.ts test-llm",
|
"test:llm": "bun src/index.ts test-llm",
|
||||||
"devices": "bun src/index.ts devices",
|
"devices": "bun src/index.ts devices",
|
||||||
"check": "tsc --noEmit",
|
"check": "tsc --noEmit",
|
||||||
|
|||||||
24
src/index.ts
24
src/index.ts
@@ -10,11 +10,11 @@ import { OllamaLlmService } from "./services/ollama-llm.js";
|
|||||||
|
|
||||||
const mode = process.argv[2] ?? "test-stt";
|
const mode = process.argv[2] ?? "test-stt";
|
||||||
|
|
||||||
async function runSttTest(): Promise<void> {
|
async function runSttTest(enableLlm: boolean): Promise<void> {
|
||||||
const config = loadConfig();
|
const config = loadConfig();
|
||||||
const logger = new Logger(config.DEBUG ? config.LOG_LEVEL : "error");
|
const logger = new Logger(config.DEBUG ? config.LOG_LEVEL : "error");
|
||||||
const stt = new FasterWhisperSttService(config, logger);
|
const stt = new FasterWhisperSttService(config, logger);
|
||||||
const llm = new OllamaLlmService(config, logger);
|
const llm = enableLlm ? new OllamaLlmService(config, logger) : null;
|
||||||
let capture = null as ReturnType<typeof spawnLoopbackCapture> | null;
|
let capture = null as ReturnType<typeof spawnLoopbackCapture> | null;
|
||||||
let shuttingDown: Promise<void> | null = null;
|
let shuttingDown: Promise<void> | null = null;
|
||||||
let receivedChunks = 0;
|
let receivedChunks = 0;
|
||||||
@@ -69,10 +69,16 @@ async function runSttTest(): Promise<void> {
|
|||||||
void stt.destroy();
|
void stt.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("STT 준비중...");
|
||||||
await stt.warmup();
|
await stt.warmup();
|
||||||
logger.info("STT warmup finished");
|
logger.info("STT warmup finished");
|
||||||
|
console.log("STT 준비 완료");
|
||||||
|
if (llm) {
|
||||||
|
console.log("LLM 준비중...");
|
||||||
await llm.warmup();
|
await llm.warmup();
|
||||||
logger.info("LLM warmup finished");
|
logger.info("LLM warmup finished");
|
||||||
|
console.log("LLM 준비 완료");
|
||||||
|
}
|
||||||
|
|
||||||
const transcriptionQueue: Array<{ pcm16: Buffer; queuedAt: number; index: number }> = [];
|
const transcriptionQueue: Array<{ pcm16: Buffer; queuedAt: number; index: number }> = [];
|
||||||
let transcribing = false;
|
let transcribing = false;
|
||||||
@@ -108,6 +114,7 @@ async function runSttTest(): Promise<void> {
|
|||||||
console.log(`사용자> ${text}`);
|
console.log(`사용자> ${text}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (llm) {
|
||||||
const assessmentStartedAt = Date.now();
|
const assessmentStartedAt = Date.now();
|
||||||
const assessment = await llm.assessReplyNeed(text);
|
const assessment = await llm.assessReplyNeed(text);
|
||||||
logger.info("Reply assessment", {
|
logger.info("Reply assessment", {
|
||||||
@@ -149,6 +156,7 @@ async function runSttTest(): Promise<void> {
|
|||||||
console.log(`답변> ${reply}`);
|
console.log(`답변> ${reply}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("STT/LLM failed", error);
|
logger.error("STT/LLM failed", error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -238,11 +246,14 @@ async function runSttTest(): Promise<void> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (config.DEBUG) {
|
if (config.DEBUG) {
|
||||||
console.log("실시간 출력장치 STT 테스트를 시작합니다. Ctrl+C 로 종료합니다.");
|
console.log(enableLlm ? "실시간 출력장치 STT+LLM 테스트를 시작합니다. Ctrl+C 로 종료합니다." : "실시간 출력장치 STT 테스트를 시작합니다. Ctrl+C 로 종료합니다.");
|
||||||
console.log(`source: ${config.AUDIO_SOURCE ?? "unset"}`);
|
console.log(`source: ${config.AUDIO_SOURCE ?? "unset"}`);
|
||||||
console.log(`model: ${config.WHISPER_MODEL}`);
|
console.log(`model: ${config.WHISPER_MODEL}`);
|
||||||
console.log(`language: ${config.WHISPER_LANGUAGE}`);
|
console.log(`language: ${config.WHISPER_LANGUAGE}`);
|
||||||
console.log(`beam: ${config.WHISPER_BEAM_SIZE}`);
|
console.log(`beam: ${config.WHISPER_BEAM_SIZE}`);
|
||||||
|
if (enableLlm) {
|
||||||
|
console.log(`llm: ${config.OLLAMA_MODEL}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
@@ -325,13 +336,16 @@ async function main(): Promise<void> {
|
|||||||
await printAudioDevices();
|
await printAudioDevices();
|
||||||
return;
|
return;
|
||||||
case "test-stt":
|
case "test-stt":
|
||||||
await runSttTest();
|
await runSttTest(false);
|
||||||
|
return;
|
||||||
|
case "test-sttllm":
|
||||||
|
await runSttTest(true);
|
||||||
return;
|
return;
|
||||||
case "test-llm":
|
case "test-llm":
|
||||||
await runLlmCli();
|
await runLlmCli();
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
throw new Error(`알 수 없는 실행 모드입니다: ${mode}. 사용 가능: test-stt, test-llm, devices`);
|
throw new Error(`알 수 없는 실행 모드입니다: ${mode}. 사용 가능: test-stt, test-sttllm, test-llm, devices`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -376,6 +376,7 @@ export class OllamaLlmService {
|
|||||||
"bun run setup:llm",
|
"bun run setup:llm",
|
||||||
"bun run devices",
|
"bun run devices",
|
||||||
"bun run test:stt",
|
"bun run test:stt",
|
||||||
|
"bun run test:sttllm",
|
||||||
"bun run test:llm",
|
"bun run test:llm",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user