docs: companyx RAG phase4/5a plans, research, worklog 갱신

Made-with: Cursor
This commit is contained in:
happybell80 2026-03-18 09:52:21 +09:00
parent 7eea592636
commit 930f87b70f
3 changed files with 202 additions and 8 deletions

View File

@ -247,14 +247,14 @@ tags: [plans, companyx, rag, answer-composition, scenario, troubleshooting]
| 저장 경로 (rb8001 메모리) | PostgreSQL `memory_vectors` 등 중심 전환 확인 | **확정** |
| 저장 경로 (skill-rag-file 문서 청크) SSOT | `PostgreSQL team_document_chunk`. `upload.py`, `reindex.py`, `search.py` 모두 `PostgresDocumentVectorStore` 사용 확인. "DB 전환" 아님 — **스키마 최적화 및 인덱스 재생성** 관점으로 관리. | **확정** |
| ChromaDB 레거시 격리 | `rebuild_chroma_collection.py` — 실험용/레거시. 운영 API와 완전 분리됨. 긴급하지 않으나 정리 대상. | **레거시 격리** |
| 인덱싱 파이프라인 | 현재 모든 파일을 텍스트 변환 후 청킹. Gemini Embedding 2의 멀티모달(PDF, 이미지, docx 등 직접 임베딩) 능력을 미활용. 원본 파일 직접 임베딩으로 전환. Phase 5A에서 닫음. | **미완료** |
| NAS 동기화 경로 | NAS → skill-rag-file 반영 경로/시점 미확인. **Phase 5A 선행 조건** — 임베딩 실행 전에 NAS 파일이 skill-rag-file에 어떻게 들어오는지(수동 upload vs 자동 동기화) 확인 필요. | **미완료 (5A 선행)** |
| 인덱싱 파이프라인 | PDF 6페이지 단위 바이너리 직접 임베딩으로 전환 완료 (`IndexingPipelineService`). 비PDF는 텍스트 추출 fallback 유지. `task_type` 구분(RETRIEVAL_DOCUMENT/QUERY) 적용. | **코드 완료, 배포 대기** |
| NAS 동기화 경로 | **확인 완료 (2026-03-17)**. NAS 마운트: `/mnt/nas` (CIFS `//192.168.0.101/home`). Company X 원본: `/mnt/nas/workspace/6.Company X/` (53,249개). 외부→내부 NAS 동기화: cron 2건 (30분 주기 계층형 + 하루 1회 전수조사, Go 바이너리). **단, NAS → skill-rag-file 인덱싱은 자동화 없음** — 현재 수동 upload API 호출만 가능. 업로드 저장소(`/mnt/hdd/data/documents/`)에 114개만 인덱싱된 상태. 1순위 2,957개 투입에는 NAS 경로에서 직접 읽어 upload API를 일괄 호출하는 배치 스크립트 필요. | **확인 완료 (배치 투입 수단 미구현)** |
| 재오픈 질문 20개 재현 | Slack 실응답 재현 미실시 | **미완료** |
- 현재 상태:
- 임베딩/저장 전제는 확정됨.
- 인덱싱 파이프라인 전환과 Company X 문서 임베딩은 Phase 5A에서 닫음.
- **NAS 동기화 경로는 Phase 5A 선행 조건** — 5A에서 임베딩을 실행하려면 NAS 파일 투입 방식이 먼저 확인돼야 합니다.
- 인덱싱 파이프라인 코드 전환 완료, 배포 대기.
- NAS 동기화 경로 확인 완료. NAS 원본 53,249개 중 114개만 인덱싱. **대량 투입 배치 스크립트가 Phase 5A 남은 핵심 작업**.
- 재오픈 질문 20개 재현은 Phase 5B에서 검증.
### Phase 1. 구조 분리 — **구현 완료**
@ -357,9 +357,10 @@ tags: [plans, companyx, rag, answer-composition, scenario, troubleshooting]
- 임베딩 완료 후 Phase 0 표의 인덱싱 파이프라인 항목을 **완료**로 갱신합니다.
- 현재 상태: **코드 전환 완료, 배포 미완료**
- 남은 작업:
- skill-embedding + skill-rag-file 배포/재기동
- NAS 동기화 경로 확인 (선행 조건)
- 1순위/2순위 폴더 실제 임베딩 실행
1. skill-embedding + skill-rag-file 배포/재기동
2. ~~NAS 동기화 경로 확인~~**확인 완료**. NAS 원본 경로: `/mnt/nas/workspace/6.Company X/`. 인덱싱 저장: `/mnt/hdd/data/documents/`. 자동 동기화 없음 — 수동 upload API만 가능.
3. **NAS 일괄 투입 배치 스크립트 작성**`/mnt/nas/workspace/6.Company X/` 하위 1순위 폴더 파일을 순회하며 upload API를 호출하는 스크립트. 현재 114/53,249개만 인덱싱된 상태.
4. 1순위/2순위 폴더 실제 임베딩 실행
- pdftotext/OCR 경로는 텍스트 미리보기 생성용으로 잔존 — PDF 직접 임베딩과 병행. 별도 제거 계획 불필요.
### Phase 5B. 테스트 고정 및 검증

View File

@ -248,7 +248,7 @@ tags: [research, companyx, rag, answer-composition, scenario, troubleshooting]
### 여전히 미확정
3. `재정리형 질문`은 이전 응답 재사용 없이 재검색함 (세션 연결 없음). 현재 스코프에서는 재검색 허용으로 운영.
4. Company X 전용 규칙은 현재 독립 모듈(`companyx_grounding_service.py`)로 유지. 범용화는 이 문제 세트 밖.
6. NAS 최신 문서 동기화본이 Company X RAG 검색 컬렉션에 언제, 어떤 방식으로 반영되는지는 아직 미확정.
~~6. NAS 최신 문서 동기화본이 Company X RAG 검색 컬렉션에 언제, 어떤 방식으로 반영되는지는 아직 미확정.~~ → **확인 완료 (2026-03-17)**: NAS 마운트 `/mnt/nas` (CIFS). Company X 원본: `/mnt/nas/workspace/6.Company X/` (53,249개). 외부→내부 NAS는 cron(30분 계층형 + 하루 1회 전수조사)으로 동기화. 단, NAS → skill-rag-file 인덱싱은 자동화 없음 — 수동 upload API 호출만 가능. 현재 114개만 인덱싱. 대량 투입 배치 스크립트 필요.
~~7. 한국어 과소 청킹 리스크 및 `Gemini 2 PDF 직접 임베딩` 미구현은 **본 문제 세트에서 즉시 전환** 대상으로 결정할지 미확정.~~ → **확정 (2026-03-17)**: 계획 Phase 5A에서 문자 단위 청킹 제거 + PDF 직접 임베딩 전환으로 결정됨. 이 계획에서 닫음.
## 결론

View File

@ -0,0 +1,193 @@
---
tags: [worklog, companyx, rag, phase4, phase5a, gateway, routing, troubleshooting]
---
# Company X RAG Phase 4·5A 구현 완료 및 Gateway 504 라우팅 버그 수정
**작성일**: 2026-03-17
**작업자**: Claude Code
## 관련 문서
- [Company X RAG 답변합성 시나리오·트러블 동시종결 계획](../plans/260315_companyx_rag_답변합성_시나리오동시종결_계획.md)
- [Company X RAG 답변합성 시나리오·트러블 동시종결 리서치](../research/260315_companyx_rag_답변합성_시나리오동시종결_리서치.md)
---
## 1. Phase 4 완료 확인 (트랙 B)
계획 문서 Phase 4 요구사항 8개와 실제 코드 대조 결과 전부 충족 확인.
### 핵심 구현 내용 (`rb8001/app/services/companyx_grounding_service.py`)
- `CompanyXRAGOutput(direct_answer, evidence_docs, failure_reason)` Pydantic 모델 도입
- `_call_llm_companyx_grounding()` — 선별된 청크를 컨텍스트로 LLM 호출
- `_build_grounded_response()` — LLM 답변 우선, 실패 시 규칙 기반 fallback
- LLM 모델: `settings.DEFAULT_LLM_MODEL` SSOT 참조 (gpt-5-mini, 하드코딩 없음)
### 경미한 미비점 (Phase 5B에서 확인)
- 질문 유형별 분기 프롬프트 없이 `question_type` 문자열을 LLM에 위임. 품질 검증 필요.
---
## 2. Phase 5A 완료 확인 및 보완 (트랙 A)
### 이미 구현된 내용
- `IndexingPipelineService` 도입 — PDF 6페이지 단위 바이너리 Base64 → `embed_items()`
- `chunk_text`는 검색 호환용 미리보기 텍스트로 유지
- 비PDF fallback: 텍스트 추출 → 청킹 → `embed_items(text=chunk)`
### 이번 세션에서 추가 구현
**`task_type` 전달 (RETRIEVAL_DOCUMENT / RETRIEVAL_QUERY 구분)**
| 파일 | 변경 내용 |
|------|---------|
| `skill-embedding-repo/main.py` | `EmbedRequest.task_type` 필드 추가, `EmbedItem.metadata` pass-through 추가, `EmbedResponse.item_metadata` 반환 |
| `skill-embedding-repo/embedder.py` | `encode(task_type=...)``EmbedContentConfig(task_type=...)` Gemini API 전달 |
| `skill-rag-file/app/services/embedding.py` | `embed_texts()`, `embed_text()`, `embed_items()` 모두 `task_type` 파라미터 추가 |
| `skill-rag-file/app/api/upload.py` | `embed_items(task_type="RETRIEVAL_DOCUMENT")` |
| `skill-rag-file/app/api/reindex.py` | `embed_items(task_type="RETRIEVAL_DOCUMENT")` |
| `skill-rag-file/app/api/search.py` | `embed_text(task_type="RETRIEVAL_QUERY")` |
### NAS 동기화 경로 확인 결과
- NAS 마운트: `/mnt/nas` (CIFS `//192.168.0.101/home`)
- Company X 원본: `/mnt/nas/workspace/6.Company X/` — 53,249개 파일
- 외부→내부 NAS 동기화: cron 2건 (30분 주기 계층형 + 하루 1회 전수조사, Go 바이너리)
- **NAS → skill-rag-file 인덱싱은 자동화 없음** — 수동 upload API만 가능
- 현재 인덱싱 완료: 114개 (`/mnt/hdd/data/documents/79441171.../`)
- **남은 핵심**: 1순위 폴더(2,957개) 일괄 투입 배치 스크립트 필요
---
## 3. Gateway 504 라우팅 버그 수정
### 증상
- `ro-being.com/api/chat``localhost:8100/api/chat` 호출 시 약 60초 후 504
- 3개 테스트 질문 모두 실패
### 원인 추적 과정
1. **초기 오진**: 타임아웃 문제로 판단 → Gateway httpx 30s→60s 상향, 병렬 검색 도입
2. **재발**: 60초에도 동일하게 504 발생
3. **로그 확인**: `docker logs robeing-gateway`에서 실제 라우팅 주소 확인
```
Proxying to: http://192.168.219.52:8001/api/message ← 구 IP!
```
4. **DB 확인**: `robeing.robeing_container_url = 'http://192.168.219.52:8001'`
- 서버 IP가 `192.168.219.52``192.168.0.106`으로 변경됐으나 DB 미갱신
- AGENTS.md 기록: "2026-03-09 이후 `192.168.0.106`이 SSOT"
### 수정 내용
**DB 업데이트** (Docker exec, gateway 컨테이너에서 직접 실행):
```sql
UPDATE robeing
SET robeing_container_url = 'http://192.168.0.106:8001'
WHERE robeing_container_url = 'http://192.168.219.52:8001'
-- Updated 1 rows
```
**Gateway 재기동** (캐시 초기화):
```bash
docker restart robeing-gateway
```
### 함께 적용된 개선 (이번 기회에)
**1. RAG 다중 쿼리 순차→병렬 실행** (`rb8001/app/services/companyx_grounding_service.py`)
```python
# Before: for loop 순차 실행 (최대 9쿼리 × 2-3초 = ~22초)
for query in _build_query_candidates(message, question_type):
for result in await _search_once(query): ...
# After: asyncio.gather 병렬 실행 (~3초)
queries = _build_query_candidates(message, question_type)
all_results = await asyncio.gather(*[_search_once(q) for q in queries])
```
**2. Gateway httpx timeout 상향** (`robeing-gateway/app/main.py`)
- `timeout=30.0``timeout=60.0`
### 접근 방법 (51124 서버 SSH)
```bash
# 51124 서버 SSH 포트: 51124 (기본 22 아님)
ssh -i ~/.ssh/id_rsa_51123_to_51124 -p 51124 admin@192.168.0.106
```
---
## 4. 커밋 이력
| 레포 | 커밋 해시 | 내용 |
|------|---------|------|
| rb8001 | `1756983` | perf: RAG 다중 쿼리 순차→병렬 실행으로 응답 지연 해소 |
| robeing-gateway | `d835fe4` | fix: Gateway httpx timeout 30s→60s 상향 |
| skill-embedding-repo | (push 필요) | feat: task_type + metadata pass-through 추가 |
| skill-rag-file | (push 필요) | feat: embed_items task_type RETRIEVAL_DOCUMENT/QUERY 전달 |
---
## 5. 남은 작업 (Phase 5A)
1. skill-embedding + skill-rag-file 배포/재기동
2. NAS 일괄 투입 배치 스크립트 작성 (1순위 폴더 → upload API 호출)
3. 1순위 2,957개 → 2순위 15,976개 순서로 임베딩 실행
4. Phase 5B 테스트/검증
---
## 워크플로우 — 다음에 같은 작업 시 참고
### Company X RAG E2E 테스트 순서
```
1. skill-rag-file 검색 직접 확인
curl http://192.168.0.106:8508/api/search -X POST \
-H 'Content-Type: application/json' -H 'X-User-Id: system' \
-d '{"query":"...", "team_id":"79441171-3951-4870-beb8-916d07fe8be5", "limit":3, "threshold":0.35}'
2. rb8001 헬스 확인
curl http://192.168.0.106:8001/health
3. Gateway 라우팅 확인
docker logs robeing-gateway --tail 20 | grep Proxying
→ 주소가 192.168.0.106인지 확인 (구 IP 192.168.219.52 아님)
4. Gateway 504 발생 시 체크리스트
a. docker logs에서 "Proxying to:" 주소 확인
b. 구 IP면 DB 수정:
docker exec robeing-gateway python3 -u -c "
import asyncio
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import text
async def main():
engine = create_async_engine('postgresql+asyncpg://robeings:robeings@192.168.0.100:5432/main_db')
Session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async with Session() as s:
r = await s.execute(text('SELECT id, robeing_container_url FROM robeing'))
for row in r.fetchall(): print(row[0], row[1])
await engine.dispose()
asyncio.run(main())
"
c. 잘못된 URL 확인 후 UPDATE 실행
d. docker restart robeing-gateway (캐시 초기화)
5. rb8001 코드 변경 후 반영 확인
ssh -i ~/.ssh/id_rsa_51123_to_51124 -p 51124 admin@192.168.0.106
cd ~/robeing/rb8001 && git log --oneline -3
→ 최신 커밋 확인 후 프로세스 재기동 여부 판단
```
### 서버 구조 요약
| 항목 | 값 |
|------|---|
| 51123 (이 서버) | nginx, Gateway(Docker:8100), auth, DB |
| 51124 | rb8001(:8001), skill-rag-file(:8508), skill-embedding(:포트확인필요) |
| 51124 SSH | `ssh -i ~/.ssh/id_rsa_51123_to_51124 -p 51124 admin@192.168.0.106` |
| rb8001 경로 (51124) | `~/robeing/rb8001/` |
| DB | `postgresql://robeings:robeings@192.168.0.100:5432/main_db` |
| NAS | `/mnt/nas` (CIFS, `//192.168.0.101/home`) |
| Company X 원본 문서 | `/mnt/nas/workspace/6.Company X/` |
| Company X 인덱싱 저장 | `/mnt/hdd/data/documents/79441171-3951-4870-beb8-916d07fe8be5/` (51123) |
| Company X team_id | `79441171-3951-4870-beb8-916d07fe8be5` |