351 lines
10 KiB
Markdown
351 lines
10 KiB
Markdown
|
|
# Sam AI 개발 문서
|
||
|
|
|
||
|
|
## 프로젝트 개요
|
||
|
|
|
||
|
|
Sam AI는 Google Gemini Live API를 활용한 실시간 음성 AI 어시스턴트입니다. React (CDN)와 PHP를 사용하여 구현되었으며, 사용자의 음성 명령으로 대시보드 네비게이션과 파일 검색 기능을 제공합니다.
|
||
|
|
|
||
|
|
## 기술 스택
|
||
|
|
|
||
|
|
- **Frontend**: React 18 (CDN), Tailwind CSS (CDN), Babel (브라우저 변환)
|
||
|
|
- **Backend**: PHP 7.3+
|
||
|
|
- **AI SDK**: Google GenAI SDK (`@google/genai@^1.31.0`)
|
||
|
|
- **API**: Gemini Live API (`gemini-2.5-flash-native-audio-preview-09-2025`)
|
||
|
|
- **오디오**: Web Audio API, ScriptProcessorNode
|
||
|
|
|
||
|
|
## 설치 과정
|
||
|
|
|
||
|
|
### 1. 파일 구조
|
||
|
|
|
||
|
|
```
|
||
|
|
ai_sam/
|
||
|
|
├── index.php # 메인 애플리케이션 파일
|
||
|
|
├── api/
|
||
|
|
│ └── get_api_key.php # API 키 조회 엔드포인트
|
||
|
|
├── API_KEY_GUIDE.md # API 키 발급 가이드
|
||
|
|
└── dev.md # 개발 문서 (본 파일)
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. API 키 설정
|
||
|
|
|
||
|
|
#### 필요한 API 키
|
||
|
|
|
||
|
|
**Gemini Live API**를 사용하기 위해서는 **Google AI Studio**에서 발급받은 **Gemini API 키**가 필요합니다.
|
||
|
|
|
||
|
|
⚠️ **중요**:
|
||
|
|
- Vertex AI API 키가 아닙니다
|
||
|
|
- 서비스 계정 OAuth 토큰이 아닙니다
|
||
|
|
- Google AI Studio의 일반 Gemini API 키입니다
|
||
|
|
|
||
|
|
#### API 키 발급 방법
|
||
|
|
|
||
|
|
**방법 1: Google AI Studio (권장)**
|
||
|
|
|
||
|
|
1. https://makersuite.google.com/app/apikey 접속
|
||
|
|
2. Google 계정으로 로그인 (Codebridge-Chatbot 프로젝트 계정)
|
||
|
|
3. "Create API Key" 버튼 클릭
|
||
|
|
4. 프로젝트 선택: **Codebridge-Chatbot**
|
||
|
|
5. 생성된 API 키 복사
|
||
|
|
|
||
|
|
**방법 2: Google Cloud Console**
|
||
|
|
|
||
|
|
1. https://console.cloud.google.com/ 접속
|
||
|
|
2. 프로젝트 선택: **Codebridge-Chatbot**
|
||
|
|
3. "API 및 서비스" > "라이브러리"
|
||
|
|
4. "Generative Language API" 검색 후 "사용 설정"
|
||
|
|
5. "API 및 서비스" > "자격 증명"
|
||
|
|
6. "자격 증명 만들기" > "API 키"
|
||
|
|
7. 생성된 API 키 복사
|
||
|
|
|
||
|
|
#### API 키 저장
|
||
|
|
|
||
|
|
생성된 API 키를 `apikey/gemini_api_key.txt` 파일에 저장합니다.
|
||
|
|
|
||
|
|
```
|
||
|
|
# 파일 위치: apikey/gemini_api_key.txt
|
||
|
|
# 파일 내용: API 키만 저장 (설명 텍스트 제외)
|
||
|
|
AIzaSyAbCdEfGhIjKlMnOpQrStUvWxYz1234567
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 프로젝트 확인
|
||
|
|
|
||
|
|
`ai_sam/api/get_api_key.php`는 Codebridge-Chatbot 프로젝트의 서비스 계정(`apikey/google_service_account.json`)을 확인하여 프로젝트 일치 여부를 검증합니다.
|
||
|
|
|
||
|
|
```php
|
||
|
|
// 프로젝트 ID 확인
|
||
|
|
if ($serviceAccount['project_id'] !== 'codebridge-chatbot') {
|
||
|
|
// 오류 반환
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. 의존성
|
||
|
|
|
||
|
|
모든 의존성은 CDN을 통해 로드됩니다:
|
||
|
|
|
||
|
|
- **React & ReactDOM**: `https://unpkg.com/react@18/umd/react.development.js`
|
||
|
|
- **Babel**: `https://unpkg.com/@babel/standalone/babel.min.js`
|
||
|
|
- **Tailwind CSS**: `https://cdn.tailwindcss.com`
|
||
|
|
- **Google GenAI SDK**: `https://aistudiocdn.com/@google/genai@^1.31.0` (ES Module)
|
||
|
|
|
||
|
|
### 4. 서버 요구사항
|
||
|
|
|
||
|
|
- PHP 7.3 이상
|
||
|
|
- `openssl` 확장 (서비스 계정 인증용, 선택사항)
|
||
|
|
- HTTPS 또는 localhost (마이크 접근 권한 필요)
|
||
|
|
|
||
|
|
## 개발 과정에서 발생한 이슈 및 해결
|
||
|
|
|
||
|
|
### 이슈 1: WebSocket이 즉시 종료되는 문제
|
||
|
|
|
||
|
|
**증상**: "Call Sam" 버튼을 클릭하면 연결이 시작되자마자 즉시 종료됨
|
||
|
|
|
||
|
|
**원인 분석**:
|
||
|
|
- WebSocket 연결 상태 추적 부족
|
||
|
|
- 세션 객체 관리 미흡
|
||
|
|
- 오디오 스트림 정리 로직 부재
|
||
|
|
|
||
|
|
**해결 방법**:
|
||
|
|
|
||
|
|
1. **연결 상태 추적 추가**
|
||
|
|
```javascript
|
||
|
|
this.isConnected = false;
|
||
|
|
this.session = null;
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **안전한 데이터 전송**
|
||
|
|
```javascript
|
||
|
|
if (this.session && this.isConnected) {
|
||
|
|
try {
|
||
|
|
this.session.sendRealtimeInput({ media: pcmBlob });
|
||
|
|
} catch (sendError) {
|
||
|
|
// WebSocket이 닫힌 경우 처리
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **리소스 정리 개선**
|
||
|
|
- `cleanup()` 메서드 추가
|
||
|
|
- 미디어 스트림 트랙 중지
|
||
|
|
- ScriptProcessor 연결 해제
|
||
|
|
- AudioContext 종료
|
||
|
|
- 세션 종료
|
||
|
|
|
||
|
|
### 이슈 2: 디버그 로깅 시스템 구축
|
||
|
|
|
||
|
|
**목적**: 연결 과정의 각 단계를 추적하여 문제점 파악
|
||
|
|
|
||
|
|
**구현 내용**:
|
||
|
|
|
||
|
|
1. **LiveManager 클래스에 디버그 로깅 추가**
|
||
|
|
```javascript
|
||
|
|
this.debugLog = [];
|
||
|
|
this.log = (msg, data = null) => {
|
||
|
|
const timestamp = new Date().toISOString();
|
||
|
|
const logEntry = { timestamp, msg, data };
|
||
|
|
this.debugLog.push(logEntry);
|
||
|
|
console.log(`[Sam AI Debug ${timestamp}]`, msg, data || '');
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **주요 디버그 포인트**
|
||
|
|
- API 키 확인
|
||
|
|
- Google GenAI SDK 로드 상태
|
||
|
|
- AudioContext 생성
|
||
|
|
- WebSocket 연결 (시도, 성공, 실패, 종료)
|
||
|
|
- 미디어 스트림 (마이크 접근 권한)
|
||
|
|
- 세션 관리
|
||
|
|
|
||
|
|
3. **콘솔 출력**
|
||
|
|
- 연결 성공/실패/종료 시 전체 디버그 로그 출력
|
||
|
|
- 각 단계별 상세 정보 표시
|
||
|
|
|
||
|
|
### 이슈 3: API 키 종류 혼동
|
||
|
|
|
||
|
|
**문제**: Vertex AI API 키와 Gemini API 키의 차이점 불명확
|
||
|
|
|
||
|
|
**해결**:
|
||
|
|
- Google AI Studio에서 발급받은 일반 Gemini API 키 사용
|
||
|
|
- `API_KEY_GUIDE.md` 문서 작성
|
||
|
|
- `get_api_key.php`에서 프로젝트 검증 로직 추가
|
||
|
|
|
||
|
|
### 이슈 4: ScriptProcessorNode Deprecation 경고
|
||
|
|
|
||
|
|
**경고**: `ScriptProcessorNode`는 deprecated되었으며 `AudioWorkletNode` 사용 권장
|
||
|
|
|
||
|
|
**현재 상태**:
|
||
|
|
- 기능은 정상 동작
|
||
|
|
- 향후 `AudioWorkletNode`로 마이그레이션 필요
|
||
|
|
|
||
|
|
**참고**: https://bit.ly/audio-worklet
|
||
|
|
|
||
|
|
## 주요 컴포넌트
|
||
|
|
|
||
|
|
### LiveManager 클래스
|
||
|
|
|
||
|
|
Gemini Live API와의 연결을 관리하는 핵심 클래스입니다.
|
||
|
|
|
||
|
|
**주요 메서드**:
|
||
|
|
|
||
|
|
- `initAI()`: Google GenAI SDK 초기화
|
||
|
|
- `connect()`: WebSocket 연결 시작
|
||
|
|
- `handleOpen()`: 연결 성공 시 미디어 스트림 시작
|
||
|
|
- `handleMessage()`: 서버 메시지 처리 (오디오, 도구 호출)
|
||
|
|
- `cleanup()`: 리소스 정리
|
||
|
|
- `disconnect()`: 연결 종료
|
||
|
|
|
||
|
|
**상태 관리**:
|
||
|
|
- `isConnected`: 연결 상태 플래그
|
||
|
|
- `session`: WebSocket 세션 객체
|
||
|
|
- `inputAudioContext`: 입력 오디오 컨텍스트 (16kHz)
|
||
|
|
- `outputAudioContext`: 출력 오디오 컨텍스트 (24kHz)
|
||
|
|
- `mediaStream`: 마이크 스트림
|
||
|
|
- `scriptProcessor`: 오디오 처리 노드
|
||
|
|
|
||
|
|
### App 컴포넌트
|
||
|
|
|
||
|
|
메인 React 컴포넌트로 UI와 상태를 관리합니다.
|
||
|
|
|
||
|
|
**주요 기능**:
|
||
|
|
- 메뉴 네비게이션
|
||
|
|
- 파일 검색
|
||
|
|
- Sam AI 연결 관리
|
||
|
|
- 오디오 시각화
|
||
|
|
|
||
|
|
### 도구 (Tools)
|
||
|
|
|
||
|
|
AI가 사용할 수 있는 기능들:
|
||
|
|
|
||
|
|
1. **navigateToPage**: 대시보드 메뉴 네비게이션
|
||
|
|
2. **searchDocuments**: 파일 검색
|
||
|
|
|
||
|
|
## 사용 방법
|
||
|
|
|
||
|
|
### 1. 기본 사용
|
||
|
|
|
||
|
|
1. 브라우저에서 `ai_sam/index.php` 접속
|
||
|
|
2. "Call Sam" 버튼 클릭
|
||
|
|
3. 마이크 접근 권한 허용
|
||
|
|
4. 음성으로 명령 (예: "Settings 화면으로 이동해줘")
|
||
|
|
|
||
|
|
### 2. 디버그 모드
|
||
|
|
|
||
|
|
1. 브라우저 개발자 도구 열기 (F12)
|
||
|
|
2. Console 탭 선택
|
||
|
|
3. "Call Sam" 버튼 클릭
|
||
|
|
4. 콘솔에 출력되는 디버그 로그 확인
|
||
|
|
|
||
|
|
### 3. 예시 명령어
|
||
|
|
|
||
|
|
- "Show me the finance dashboard"
|
||
|
|
- "Find the Q3 report from October"
|
||
|
|
- "Settings 화면으로 이동해줘"
|
||
|
|
- "Find the financial report"
|
||
|
|
|
||
|
|
## 파일 구조 상세
|
||
|
|
|
||
|
|
### index.php
|
||
|
|
|
||
|
|
메인 애플리케이션 파일로 다음을 포함합니다:
|
||
|
|
|
||
|
|
- HTML 구조
|
||
|
|
- React 컴포넌트 (Sidebar, FileList, Visualizer, App)
|
||
|
|
- LiveManager 클래스
|
||
|
|
- 오디오 유틸리티 함수
|
||
|
|
- 상수 정의 (MOCK_FILES, MOCK_MENU, SYSTEM_INSTRUCTION)
|
||
|
|
|
||
|
|
### api/get_api_key.php
|
||
|
|
|
||
|
|
API 키를 안전하게 조회하는 PHP 엔드포인트:
|
||
|
|
|
||
|
|
- 서비스 계정 프로젝트 검증
|
||
|
|
- API 키 파일 읽기
|
||
|
|
- 플레이스홀더 텍스트 필터링
|
||
|
|
- JSON 응답 반환
|
||
|
|
|
||
|
|
## 보안 고려사항
|
||
|
|
|
||
|
|
1. **API 키 보호**
|
||
|
|
- API 키는 서버 측에서만 관리
|
||
|
|
- 클라이언트에 직접 노출되지 않음
|
||
|
|
- `get_api_key.php`를 통해서만 전달
|
||
|
|
|
||
|
|
2. **프로젝트 검증**
|
||
|
|
- Codebridge-Chatbot 프로젝트만 허용
|
||
|
|
- 서비스 계정 정보로 검증
|
||
|
|
|
||
|
|
3. **HTTPS 권장**
|
||
|
|
- 마이크 접근 권한은 HTTPS 또는 localhost에서만 가능
|
||
|
|
- 프로덕션 환경에서는 반드시 HTTPS 사용
|
||
|
|
|
||
|
|
## 성능 최적화
|
||
|
|
|
||
|
|
1. **오디오 처리**
|
||
|
|
- ScriptProcessorNode 사용 (향후 AudioWorkletNode로 마이그레이션 예정)
|
||
|
|
- 16kHz 샘플레이트로 입력 최적화
|
||
|
|
- 24kHz 샘플레이트로 출력 최적화
|
||
|
|
|
||
|
|
2. **리소스 관리**
|
||
|
|
- 연결 종료 시 모든 리소스 정리
|
||
|
|
- 메모리 누수 방지
|
||
|
|
|
||
|
|
3. **에러 처리**
|
||
|
|
- 모든 비동기 작업에 try-catch 적용
|
||
|
|
- 사용자 친화적 에러 메시지
|
||
|
|
|
||
|
|
## 향후 개선 사항
|
||
|
|
|
||
|
|
1. **AudioWorkletNode 마이그레이션**
|
||
|
|
- ScriptProcessorNode 대신 AudioWorkletNode 사용
|
||
|
|
- 더 나은 성능과 안정성
|
||
|
|
|
||
|
|
2. **에러 복구 메커니즘**
|
||
|
|
- 자동 재연결 기능
|
||
|
|
- 네트워크 오류 처리 개선
|
||
|
|
|
||
|
|
3. **사용자 경험 개선**
|
||
|
|
- 연결 상태 시각적 표시 개선
|
||
|
|
- 오디오 레벨 표시 개선
|
||
|
|
- 더 많은 도구 추가
|
||
|
|
|
||
|
|
## 참고 자료
|
||
|
|
|
||
|
|
- [Google AI Studio](https://makersuite.google.com/)
|
||
|
|
- [Google Cloud Console](https://console.cloud.google.com/)
|
||
|
|
- [Gemini API 문서](https://ai.google.dev/docs)
|
||
|
|
- [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)
|
||
|
|
- [AudioWorklet](https://developer.mozilla.org/en-US/docs/Web/API/AudioWorklet)
|
||
|
|
|
||
|
|
## 변경 이력
|
||
|
|
|
||
|
|
### 2025-01-XX (초기 개발)
|
||
|
|
|
||
|
|
- Sam AI 기본 구조 구현
|
||
|
|
- React (CDN) 기반 UI 구성
|
||
|
|
- Gemini Live API 통합
|
||
|
|
- 실시간 음성 대화 기능 구현
|
||
|
|
- 도구 시스템 (navigateToPage, searchDocuments) 구현
|
||
|
|
- 디버그 로깅 시스템 구축
|
||
|
|
- WebSocket 연결 안정화
|
||
|
|
- API 키 관리 시스템 구축
|
||
|
|
- Codebridge-Chatbot 프로젝트 연동
|
||
|
|
|
||
|
|
## 문제 해결 체크리스트
|
||
|
|
|
||
|
|
연결이 안 될 때 확인 사항:
|
||
|
|
|
||
|
|
- [ ] API 키가 올바르게 설정되었는가? (`apikey/gemini_api_key.txt`)
|
||
|
|
- [ ] API 키 형식이 올바른가? (약 39자, `AIzaSy`로 시작)
|
||
|
|
- [ ] Google Cloud Console에서 "Generative Language API"가 활성화되었는가?
|
||
|
|
- [ ] Codebridge-Chatbot 프로젝트에서 API 키가 생성되었는가?
|
||
|
|
- [ ] 브라우저 콘솔에 에러 메시지가 있는가?
|
||
|
|
- [ ] 마이크 접근 권한이 허용되었는가?
|
||
|
|
- [ ] HTTPS 또는 localhost에서 실행 중인가?
|
||
|
|
- [ ] Google GenAI SDK가 정상적으로 로드되었는가?
|
||
|
|
|
||
|
|
## 개발자 노트
|
||
|
|
|
||
|
|
- 모든 디버그 로그는 브라우저 콘솔에서 확인 가능
|
||
|
|
- 연결 과정의 각 단계는 타임스탬프와 함께 로깅됨
|
||
|
|
- 에러 발생 시 전체 디버그 로그가 자동으로 출력됨
|
||
|
|
- API 키는 절대 클라이언트 코드에 하드코딩하지 않음
|
||
|
|
|