docs: companyx RAG phase4/5a plans, research, worklog 갱신
Made-with: Cursor
This commit is contained in:
parent
7eea592636
commit
930f87b70f
@ -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. 테스트 고정 및 검증
|
||||
|
||||
@ -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 직접 임베딩 전환으로 결정됨. 이 계획에서 닫음.
|
||||
|
||||
## 결론
|
||||
|
||||
@ -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` |
|
||||
Loading…
x
Reference in New Issue
Block a user