docs: 트러블슈팅 문서 업데이트 및 추가
This commit is contained in:
parent
087bd1a650
commit
941eb34b91
@ -7,103 +7,68 @@
|
||||
- `rb8001/app/services/coldmail_processor.py`
|
||||
- `rb8001/tests/test_coldmail_extraction.py`
|
||||
|
||||
**관련 문서**: `251014_coldmail_ir_analysis_scenario.md`
|
||||
**관련 문서**:
|
||||
- `251014_coldmail_ir_analysis_scenario.md`
|
||||
- `251122_happybell80_chromadb_dimension_mismatch.md`
|
||||
- `251122_rag_search_chunk_text_key_fix.md`
|
||||
|
||||
---
|
||||
|
||||
## 문제 상황
|
||||
|
||||
### 현재 추출 로직의 한계
|
||||
**실제 파일 테스트 결과**: IR 분석 모든 필드 N/A
|
||||
|
||||
1. **회사명 추출**: IR 분석에서 추출하지 않음, 휴리스틱(`_derive_company_name()`)에만 의존
|
||||
- 제목/발신자 기반 추출로 정확도 낮음
|
||||
- IR 본문에 정확한 회사명("주식회사 ABC", "(주)ABC")이 있어도 활용하지 않음
|
||||
### 초기 가설 (오류)
|
||||
1. IR 분석에서 회사명 추출하지 않음 → **실제로는 이미 구현됨** (ir_analyzer.py:148,169,283)
|
||||
2. 우선순위 미정의 → **코드에 우선순위 로직 존재** (coldmail_processor.py:139-144)
|
||||
|
||||
2. **연락처 추출**: From 헤더 파싱에만 의존
|
||||
- 헤더 형식이 다르면 실패 가능
|
||||
- IR 본문의 연락처 정보 미활용
|
||||
|
||||
3. **우선순위 미정의**: IR → 휴리스틱 → 헤더 순서가 명확하지 않음
|
||||
### 실제 원인
|
||||
1. **RAG 검색 실패** → `raw_results = {}` → LLM에 빈 입력 → N/A
|
||||
2. **연쇄 문제**: 차원 불일치(384→768) → 재인덱싱 → 키 불일치(chunk_text vs content)
|
||||
|
||||
---
|
||||
|
||||
## 해결 방안
|
||||
## 분석 결과
|
||||
|
||||
### 1. IR 분석에 회사명 추출 추가
|
||||
- `extract_ir_metrics()` 프롬프트에 회사명 추출 쿼리 추가
|
||||
- JSON 키 `company_name`으로 반환
|
||||
- IR 본문 기반 추출로 정확도 향상
|
||||
### 코드 확인
|
||||
- **ir_analyzer.py:148,169,244,283**: `company_name` 추출 이미 구현됨
|
||||
- **coldmail_processor.py:139-144**: 우선순위 로직 존재 (IR → 휴리스틱)
|
||||
- **문제**: RAG 검색 0건 → `raw_results = {}` → N/A
|
||||
|
||||
### 2. 우선순위 분리
|
||||
- **회사명**: IR → 휴리스틱 → 헤더 (IR 본문이 가장 정확)
|
||||
- **연락처**: 헤더 → IR → 휴리스틱 (From 헤더가 가장 신뢰도 높음)
|
||||
|
||||
### 3. 방어 로직
|
||||
- IR 추출 실패/공백 시에만 후속 경로로 폴백
|
||||
- 불필요한 LLM 호출 최소화
|
||||
### Mock 테스트의 한계
|
||||
- `tests/test_coldmail_extraction.py`: Mock 기반으로 실제 RAG 문제 감지 못함
|
||||
- 테스트 통과했으나 실제 파일에서는 N/A
|
||||
- 교훈: 실제 document_id로 통합 테스트 필수
|
||||
|
||||
---
|
||||
|
||||
## TDD 계획
|
||||
## 해결 과정
|
||||
|
||||
### 테스트 작성 (Red Phase)
|
||||
1. `test_extract_ir_metrics_with_company_name`: IR 분석에서 회사명 추출 테스트
|
||||
2. `test_company_name_priority`: 우선순위 테스트 (IR → 휴리스틱 → 헤더)
|
||||
3. `test_contact_priority`: 연락처 우선순위 테스트 (헤더 → IR → 휴리스틱)
|
||||
### 1단계: 차원 불일치 발견 및 해결
|
||||
- ChromaDB 384차원 → 768차원 재인덱싱 완료
|
||||
- 참고: `251122_happybell80_chromadb_dimension_mismatch.md`
|
||||
|
||||
### 구현 (Green Phase)
|
||||
1. `extract_ir_metrics()`: 회사명 추출 쿼리 및 JSON 파싱 추가
|
||||
2. `coldmail_processor.py`: 우선순위 분리 로직 수정
|
||||
|
||||
### 리팩터링 (Refactor Phase)
|
||||
- 중복 코드 제거
|
||||
- 에러 처리 개선
|
||||
|
||||
---
|
||||
|
||||
## 구현 완료 (2025-11-22)
|
||||
|
||||
### 수정된 파일
|
||||
- `rb8001/app/services/ir_analyzer.py`:
|
||||
- 회사명 추출 쿼리 추가 (`company_name`)
|
||||
- Gemini/RAG 경로 모두 프롬프트에 `company_name` 키 추가
|
||||
- config 제거, `os.getenv()` 직접 사용
|
||||
- `rb8001/app/services/coldmail_processor.py`:
|
||||
- 회사명 우선순위: IR → 휴리스틱 → 헤더
|
||||
- 연락처 우선순위: 헤더 → IR → 휴리스틱 (향후 확장 가능)
|
||||
- IR 추출 실패/공백 시에만 후속 경로로 폴백
|
||||
- `rb8001/tests/test_coldmail_extraction.py`: TDD 테스트 작성
|
||||
|
||||
### 검증 방법
|
||||
```bash
|
||||
# 단위 테스트 (Mock)
|
||||
cd /home/admin/ivada_project/rb8001
|
||||
docker exec -it rb8001 python3 tests/test_coldmail_extraction.py
|
||||
|
||||
# 실제 파일 테스트
|
||||
docker exec -it rb8001 python3 /code/scripts/test_ir_extraction_real_file.py [document_id] [team_id]
|
||||
# 예시: docker exec -it rb8001 python3 /code/scripts/test_ir_extraction_real_file.py dc1da3f6-f0b6-4688-a399-9faf54aefe1d 79441171-3951-4870-beb8-916d07fe8be5
|
||||
```
|
||||
|
||||
**참고**: 실제 파일 테스트 시 RAG 인덱싱이 완료된 document_id를 사용해야 함. 파일 저장 위치: `/mnt/51123data/documents/{team_id}/YYYY-MM/{document_id}.pdf`
|
||||
### 2단계: 키 불일치 발견 및 수정
|
||||
- skill-rag-file: `chunk_text` 키로 반환
|
||||
- ir_analyzer.py:47: `content` 키 읽기 시도 → 빈 문자열
|
||||
- 커밋 `8feea8b`: `content` → `chunk_text` 수정
|
||||
- 참고: `251122_rag_search_chunk_text_key_fix.md`
|
||||
|
||||
---
|
||||
|
||||
## 교훈
|
||||
|
||||
### IR 본문 활용의 중요성
|
||||
- 휴리스틱보다 IR 본문에서 추출한 정보가 정확도 높음
|
||||
- 회사명은 본문에 정확한 법인명("주식회사 ABC", "(주)ABC")이 포함되어 있음
|
||||
- LLM이 본문에서 직접 추출하면 휴리스틱보다 신뢰도 높음
|
||||
### 코드 확인 먼저, 가정은 나중에
|
||||
- "IR에서 회사명 추출 안 함"이라고 가정 → 실제로는 이미 구현됨
|
||||
- 교훈: 문제 분석 시 코드 직접 읽고 확인 (가정으로 시작하지 말 것)
|
||||
|
||||
### 우선순위 분리의 필요성
|
||||
- 회사명과 연락처는 신뢰도가 다른 소스에서 나옴
|
||||
- 회사명: IR 본문이 가장 정확 (법인명 명시)
|
||||
- 연락처: From 헤더가 가장 신뢰도 높음 (발신자 정보)
|
||||
- 각각 최적의 우선순위를 설정하여 정확도 향상
|
||||
### Mock 테스트의 한계
|
||||
- Mock 테스트 통과 ≠ 실제 환경 정상 동작
|
||||
- RAG/ChromaDB 같은 외부 의존성은 실제 데이터로 검증 필수
|
||||
- 교훈: 통합 테스트용 실제 document_id 항상 준비
|
||||
|
||||
### config 사용 금지 원칙 적용
|
||||
- `ir_analyzer.py`에서 `settings.DEFAULT_LLM_MODEL` 제거
|
||||
- `os.getenv("DEFAULT_LLM_MODEL", "gemini-2.5-flash-lite")` 직접 사용
|
||||
- AGENTS.md 규칙 준수
|
||||
### 연쇄 문제 해결 시 각 단계 검증
|
||||
- 차원 불일치 해결 → 재인덱싱 → 여전히 N/A
|
||||
- 각 단계마다 실제 API 응답 출력/로그 확인으로 숨은 문제 조기 발견
|
||||
- 교훈: 문제 해결 후 반드시 end-to-end 검증
|
||||
|
||||
|
||||
@ -3,7 +3,10 @@
|
||||
- **날짜**: 2025-11-22
|
||||
- **작성자**: happybell80
|
||||
- **관련 서비스**: skill-rag-file (8508), skill-embedding (8515), rb8001
|
||||
- **관련 문서**: 370_임베딩_서비스_분리_아키텍처.md, 2025_ko_sroberta_runtime_eval.md
|
||||
- **관련 문서**:
|
||||
- 370_임베딩_서비스_분리_아키텍처.md
|
||||
- 2025_ko_sroberta_runtime_eval.md
|
||||
- 251122_rag_search_chunk_text_key_fix.md (후속 문제)
|
||||
|
||||
## 상황
|
||||
- skill-embedding이 ko-sroberta(multitask) 768차원으로 교체된 상태에서 기존 ChromaDB 컬렉션이 384차원 설정으로 남아 있음.
|
||||
@ -14,10 +17,10 @@
|
||||
1. 이전 MiniLM(384d)로 생성된 컬렉션에 새 임베딩(768d)을 조회/삽입하면서 차원 불일치 발생.
|
||||
2. 업로드 직후 호출 타이밍 이슈가 보조적으로 있을 수 있으나, 차원 불일치 때문에 검색 결과가 0건으로 고정.
|
||||
|
||||
## 조치/계획
|
||||
- **재인덱싱 필요**: `skill_rag_file_79441171-3951-4870-beb8-916d07fe8be5_documents` 등 기존 컬렉션을 768차원으로 재생성 후 해당 document_id를 재인덱싱.
|
||||
- 재인덱싱 전 임시 우회 없음. 기존 384d 컬렉션 유지 시 검색 0건 → IR `N/A`.
|
||||
- 재인덱싱 후 `scripts/test_ir_extraction_real_file.py <document_id> <team_id>`로 검증 예정.
|
||||
## 조치 완료
|
||||
- **재인덱싱 완료**: `skill_rag_file_79441171-3951-4870-beb8-916d07fe8be5_documents` 768차원으로 재생성, 731개 청크 재인덱싱 완료.
|
||||
- **후속 문제 발견**: 재인덱싱 후에도 IR 결과 N/A → API 응답 키 불일치 발견 (`chunk_text` vs `content`)
|
||||
- **참고**: 251122_rag_search_chunk_text_key_fix.md
|
||||
|
||||
## 교훈
|
||||
- 임베딩 모델 교체 시 기존 벡터 DB 차원과 일관성 확인 필수(배포 전 마이그레이션/dual-write 계획).
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
# RAG 검색 응답 키 불일치 수정 (chunk_text vs content)
|
||||
|
||||
**날짜**: 2025-11-22
|
||||
**작성자**: Claude
|
||||
**관련 파일**:
|
||||
- `rb8001/app/services/ir_analyzer.py`
|
||||
- `skill-rag-file/app/models/requests.py`
|
||||
- `skill-rag-file/app/api/search.py`
|
||||
|
||||
**관련 문서**:
|
||||
- `251122_happybell80_chromadb_dimension_mismatch.md`
|
||||
- `251122_coldmail_extraction_improvement_tdd.md`
|
||||
|
||||
---
|
||||
|
||||
## 문제 상황
|
||||
|
||||
차원 불일치(384→768) 해결 및 재인덱싱 완료 후에도 IR 분석 결과 모든 필드 N/A.
|
||||
|
||||
**실제 파일 테스트**: `650c305b-e45a-4ff4-8bcb-87096f804605` (team `79441171-3951-4870-beb8-916d07fe8be5`)
|
||||
- ChromaDB 컬렉션: 731개 청크 존재
|
||||
- RAG 검색 시 결과 0건
|
||||
- LLM에 빈 입력 전달 → N/A
|
||||
|
||||
---
|
||||
|
||||
## 원인 분석
|
||||
|
||||
### 1. skill-rag-file API 응답 형식
|
||||
- **requests.py:25**: `SearchResult.chunk_text` 필드 정의
|
||||
- **search.py:55**: `chunk_text=doc` 로 텍스트 반환
|
||||
- 응답: `{"results": [{"chunk_text": "내용", ...}], ...}`
|
||||
|
||||
### 2. ir_analyzer 파싱 로직
|
||||
- **ir_analyzer.py:47**: `r.get("content", "")` 로 읽기 시도
|
||||
- `chunk_text` ≠ `content` → 빈 문자열 반환
|
||||
- `raw_results = {}` → LLM에 `{}` 전달 → N/A
|
||||
|
||||
---
|
||||
|
||||
## 해결 방안
|
||||
|
||||
**ir_analyzer.py:47**: `content` → `chunk_text` 키 수정
|
||||
|
||||
```python
|
||||
# 변경 전
|
||||
return "\n".join([r.get("content", "") for r in results])
|
||||
|
||||
# 변경 후
|
||||
return "\n".join([r.get("chunk_text", "") for r in results])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 구현 완료
|
||||
|
||||
**커밋**: `8feea8b` - fix: read chunk_text from rag search results
|
||||
**수정 파일**: `rb8001/app/services/ir_analyzer.py:47`
|
||||
|
||||
**검증 필요**: 재인덱싱 완료 후 실제 파일 테스트
|
||||
```bash
|
||||
docker exec -i rb8001 python3 /code/scripts/test_ir_extraction_real_file.py \
|
||||
650c305b-e45a-4ff4-8bcb-87096f804605 79441171-3951-4870-beb8-916d07fe8be5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 교훈
|
||||
|
||||
### API 스펙 확인 부족
|
||||
- skill-rag-file 통합 시 응답 형식 추측으로 구현 (`content` 키 사용)
|
||||
- 실제 스펙: `SearchResult` 모델의 `chunk_text` 필드
|
||||
- 교훈: 스킬 통합 전 Pydantic 모델 또는 API 문서 직접 확인 필수
|
||||
|
||||
### 연쇄 문제 해결 시 중간 검증
|
||||
- 차원 불일치 해결 → 재인덱싱 → 여전히 N/A
|
||||
- 각 단계마다 실제 API 응답 확인 필요 (ChromaDB 로그, API 응답 출력)
|
||||
- 교훈: 문제 해결 후 실제 데이터 흐름 검증으로 숨은 문제 조기 발견
|
||||
Loading…
x
Reference in New Issue
Block a user