원 레포랑 완전 분리
This commit is contained in:
84
docs/ADR-0.md
Normal file
84
docs/ADR-0.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# LLM 게이트웨이 아키텍처
|
||||
|
||||
## 상태
|
||||
|
||||
제안됨
|
||||
|
||||
## 콘텍스트
|
||||
|
||||
본 프로젝트(`llm_gateway`)는 FastAPI를 기반으로 한 문서 추출 및 LLM 추론 API 시스템으로, PDF 및 이미지 기반의 문서 처리, LLM 기반 응답 생성, 다양한 다운로드 및 가이드 제공 기능을 제공한다.
|
||||
이를 효율적으로 구현하기 위해 비동기 처리를 활용하고, 기능별 모듈화 및 서비스 계층을 분리하여 유지보수성과 확장성을 고려한 구조를 설계했다.
|
||||
|
||||
## 아키텍처 구성 요소
|
||||
|
||||
### (1) API 계층
|
||||
|
||||
**FastAPI**
|
||||
|
||||
- 클라이언트와 직접 상호작용하는 API 레이어.
|
||||
- 비동기 요청을 처리하고 파일 업로드, LLM 추론, OCR, 다운로드 등의 엔드포인트를 제공.
|
||||
- 주요 엔드포인트:
|
||||
- `/extract`: 문서 텍스트 추출 및 LLM 응답
|
||||
- `/general/inner/outer`: 내부/외부 LLM 추론
|
||||
- `/ocr`: PDF/이미지 파일의 OCR 기반 텍스트 추출
|
||||
- `/download/*`: 프롬프트 및 스키마 다운로드
|
||||
- `/info`: 사용 가능한 모델 정보 제공
|
||||
- `/health`: 시스템 상태 확인
|
||||
|
||||
### (2) 서비스 계층
|
||||
|
||||
**서비스 모듈**
|
||||
|
||||
- 라우터에서 호출되는 비즈니스 로직 처리 레이어.
|
||||
- 주요 서비스:
|
||||
- `InferenceService`: 텍스트 추출 및 LLM 호출 처리
|
||||
- `DownloadService`: 프롬프트 및 스키마 다운로드 처리
|
||||
- `ModelInfoService`: 모델 정보 반환
|
||||
- `PipelineRunner`: 추론 파이프라인 실행 로직
|
||||
- `DummyService`: 테스트용 API 처리
|
||||
|
||||
### (3) 유틸리티 및 처리 계층
|
||||
|
||||
**utils 모듈**
|
||||
|
||||
- 공통 텍스트 추출(`extract_text_from_file`), LLM 응답 처리, 로깅 및 프롬프트 관리 기능 제공.
|
||||
- OCR 처리의 경우 업로드된 파일을 `aiofiles`를 통해 임시 디스크에 저장한 후 `extract_text_from_file`을 호출하여 텍스트를 추출한다.
|
||||
- 주요 모듈:
|
||||
- `text_extractor`: 파일 기반 텍스트 추출
|
||||
- `text_processor`: OCR 및 후처리
|
||||
- `text_generator`: LLM 추론 (Ollama, Gemini, Claude, GPT 등)
|
||||
- `logging_utils`, `prompt_cache`: 로깅 및 캐시 관리
|
||||
|
||||
### (4) 데이터 계층
|
||||
|
||||
**파일 저장소 및 정적 자원**
|
||||
|
||||
- 업로드된 파일은 서버 내 `UPLOAD_DIR`에 저장.
|
||||
- 정적 리소스(`/static/`)를 통해 HTML 가이드, 이미지, JSON 스키마 제공.
|
||||
- 추론 및 다운로드 요청에 필요한 리소스를 관리하고, 서버 안정성을 위해 디스크 기반 임시 저장소 활용.
|
||||
|
||||
## 결정
|
||||
|
||||
- FastAPI를 중심으로 기능별 라우터를 독립적으로 구성하고, 서비스 계층과 유틸리티 계층을 분리하여 유지보수성과 확장성을 확보한다.
|
||||
- `/ocr` 요청 시 파일 업로드는 임시 디스크 저장(aiofiles) 후 `text_extractor` 호출로 처리하며, 이를 Mermaid 흐름도에 반영한다.
|
||||
- 공통 텍스트 추출 모듈(`text_extractor`)은 `/extract`, `/general`, `/ocr`에서 재사용하도록 `utils` 계층에 위치시킨다.
|
||||
|
||||
## 근거
|
||||
|
||||
- 비동기 요청 처리 및 모듈화된 구조는 대규모 문서 추출 및 LLM 처리 환경에서 성능과 유지보수성을 동시에 확보한다.
|
||||
- `aiofiles` 기반 파일 저장은 메모리 상 `UploadFile` 객체를 안정적으로 처리하기 위해 필요하다.
|
||||
- `utils` 계층 통합으로 공통 로직 재사용성을 높여 코드 중복을 방지하고 유지보수를 용이하게 한다.
|
||||
|
||||
## 결과
|
||||
|
||||
- 클라이언트는 비동기 요청을 통해 빠르고 안정적인 문서 추출 및 LLM 응답을 받을 수 있다.
|
||||
- 서비스 계층과 유틸리티 계층 분리를 통해 확장 가능하고 유지보수성이 높은 구조를 확보했다.
|
||||
- Mermaid 다이어그램을 통해 아키텍처와 흐름을 명확하게 시각화하여 향후 리팩토링 및 개선 작업에 참고할 수 있도록 했다.
|
||||
|
||||
## 결정자
|
||||
|
||||
AI cell / 김용연 연구원
|
||||
|
||||
## 결정 날짜
|
||||
|
||||
2025-05-29
|
||||
6
docs/ADR-1.md
Normal file
6
docs/ADR-1.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# ADR-001: LLM Gateway 초기 아키텍처 개요
|
||||
|
||||
**상태:** 대체됨 (Superseded)
|
||||
**대체 문서:** [ADR-002](./ADR-2.md)
|
||||
|
||||
> 본 ADR-1의 내용은 ADR-2에 작성되었으며, 해당 문서를 참조 바랍니다.
|
||||
67
docs/ADR-2.md
Normal file
67
docs/ADR-2.md
Normal file
@@ -0,0 +1,67 @@
|
||||
## LLM Gateway 아키텍처
|
||||
|
||||
**문서 번호:** **ADR-002**
|
||||
|
||||
- 제목: **LLM Gateway 비동기 아키텍처 채택**
|
||||
- 날짜: **2025-06-02**
|
||||
- 상태: **제안됨 (Proposed)**
|
||||
- 작성자: **\[김용연 연구원]**
|
||||
|
||||
---
|
||||
|
||||
### 1. 컨텍스트 (Context)
|
||||
|
||||
**본 문서는 현재 운영 중인 OCR, LLM Service, STT 3개 AI 서비스의 통합 운영을 위해 선택한 멀티레포(Multi-Repository) 아키텍처를 정의함. 주요 요구사항은 다음과 같음**
|
||||
|
||||
- **서비스별 독립 개발 및 배포**: OCR, LLM, STT 각각의 서비스는 별도 개발자에 의해 독립적으로 개발/운영되며, 서비스별 라이프사이클 관리가 필요함
|
||||
- **모놀리식 구조 지양**: 모든 서비스를 하나의 코드베이스로 통합하는 모노레포 방식은 코드 충돌, 배포 및 관리 복잡성 등의 단점을 내포함
|
||||
- **비동기 처리 및 작업 분산 지원**: Redis 및 Celery를 활용하여 STT, OCR 등 장시간 소요되는 비동기 작업을 효율적으로 처리하고, 사용자 요청에 대한 응답성을 유지함
|
||||
- **서비스간 라우팅 및 통합 API 게이트웨이**: 각 서비스는 독립적인 엔드포인트를 가지되, 공통적으로 요청을 분산 처리하는 라우터 계층 및 통합 API를 통해 외부 서비스와의 연동을 단순화함
|
||||
|
||||
---
|
||||
|
||||
### 2. 결정 (Decision)
|
||||
|
||||
**OCR, LLM Service, STT 서비스를 멀티레포(Multi-Repository) 구조로 분리 관리함**
|
||||
공통 기능 및 설정은 common-utils에 모듈화하여 서비스 간 연계 및 확장을 지원함
|
||||
|
||||
```bash
|
||||
llm_gateway/
|
||||
├── ocr-service/ # OCR 서비스 (독립 레포)
|
||||
├── stt-service/ # STT 서비스 (독립 레포)
|
||||
└── common-utils/ # 공통 유틸 및 설정 (독립 레포)
|
||||
├── logging/ # 공통 로깅 설정
|
||||
└── config/ # 환경설정 및 공통 설정 모듈
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. 고려된 대안 (Alternatives Considered)
|
||||
|
||||
| 아키텍처 | 장점 | 단점 |
|
||||
| --------------------------------- | ------------------------------------------------- | ----------------------------------------------------------- |
|
||||
| **모노레포**(Monorepo) | 코드 관리와 통합 배포가 쉬움, 개발 환경 통일 가능 | 빌드 및 테스트 속도 저하, 서비스별 권한 및 배포 분리 어려움 |
|
||||
| **멀티레포**(Multirepo) ✅ 선택됨 | 서비스별 독립 개발/배포 용이, 작업 충돌 최소화 | 공통 코드 관리 복잡, 서비스 간 연동 이슈 처리 필요 |
|
||||
|
||||
---
|
||||
|
||||
### 4. 결과 (Consequences)
|
||||
|
||||
- **장점:**
|
||||
|
||||
- 서비스별로 독립적인 관리 체계를 유지하여 각 서비스의 개발, 배포 주기를 유연하게 설정 가능
|
||||
- Redis, Celery를 통한 비동기 처리 및 요청 분산으로 응답성과 효율성 확보
|
||||
- 공통 Router 계층을 통해 서비스 간 통합 요청 처리 가능, 아키텍처 확장 용이
|
||||
|
||||
- **단점:**
|
||||
|
||||
- 공통 코드(`common-utils`)의 관리와 배포 자동화 필요, 버전 충돌 가능성 존재
|
||||
- 서비스 간 연계 로직 및 의존성 관리 복잡, 유지보수 시 추가 개발 필요
|
||||
- 레포 수 증가에 따른 중앙 관리 및 모니터링 시스템 필요, 통합 이슈 관리와 배포 체계 도입 필요
|
||||
|
||||
---
|
||||
|
||||
### 5. 추가 노트 (Optional)
|
||||
|
||||
- **공통 코드 배포 방식:** `common-utils`는 git 서브모듈 또는 사설 PyPI 패키지로 배포 관리 예정. 버전 관리 체계 마련 필요
|
||||
- **서비스 확장 고려:** 새로운 AI 서비스 추가 시 현재 아키텍처의 확장성이 유리함
|
||||
82
docs/ADR-3.md
Normal file
82
docs/ADR-3.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# **ADR-003**
|
||||
|
||||
* 제목: **서비스 간 공통 모듈 연동 방식 결정**
|
||||
* 날짜: **2025-06-12**
|
||||
* 상태: 제안됨 (Proposed)
|
||||
* 작성자: **\[김용연 연구원]**
|
||||
|
||||
---
|
||||
|
||||
## 1. 컨텍스트 (Context)
|
||||
|
||||
ADR-002를 통해 **멀티레포 아키텍처**로 결정되었으며, 이에 따라 각 서비스 간 **공통 모듈을 어떤 방식으로 연동할 것인지**에 대한 결정을 내려야 한다. 이번 논의는 다음 피드백을 기반으로 진행된다.
|
||||
|
||||
> 1. 공통모듈이 많고 복잡한가?
|
||||
> 2. 관리포인트가 늘어날 여지가 많은가?
|
||||
|
||||
또한, Git 연동 방식 외에도 **Gitea Action 기반 자동 동기화 방식**을 함께 검토한다. 고려 요소는 다음과 같다.
|
||||
|
||||
* 공통 모듈의 복잡도 및 변경 빈도
|
||||
* 유지보수 및 형상관리 난이도
|
||||
* 개발자 사용성
|
||||
* 자동화 가능성과 CI/CD 연계
|
||||
* 로컬/원격 환경 간의 충돌 여부
|
||||
|
||||
---
|
||||
|
||||
## 2. 결정 (Decision)
|
||||
|
||||
현재 고려 중인 연동 방식은 다음과 같다.
|
||||
|
||||
| 방법 | 장점 | 단점 |
|
||||
| --------------------------- | ---------------------------- | ---------------------------- |
|
||||
| **git-submodule** | 참조만으로 관리되어 가볍고 명확한 버전 고정 가능 | 초기 사용 복잡, 동기화 어려움, 실수 발생 가능성 |
|
||||
| **git-subtree** ✅ | 병합, 업데이트 용이, 독립적인 서비스 유지 가능 | 충돌 시 수동 병합 필요, 코드 중복 위험 |
|
||||
| **Gitea Action(강제 동기화)** | CI로 일관된 코드 유지 가능, 자동화 쉬움 | 설정 복잡, 브랜치 충돌 발생 가능성 있음 |
|
||||
---
|
||||
|
||||
## ✅ 공통모듈
|
||||
|
||||
현재 공통적으로 사용되거나 예정된 모듈은 다음과 같다:
|
||||
|
||||
| 영역 | 모듈 예시 | 설명 |
|
||||
| ------------- | ---------------------------------- | ------------------------------------------ |
|
||||
| 로깅 | `logger.py` | 공통 포맷의 로그 기록, Loki 기반 모니터링 대응 |
|
||||
| 요청 로깅 추적 | `request_logger.py` | 클라이언트 IP, 요청 시간, API 경로 등을 기록, Loki/Grafana 연동 |
|
||||
| 설정 관리 | `config_loader.py` | 환경 변수 및 설정 파일 통합 로딩 |
|
||||
| 응답 구조 | `response.py` | API 응답 형식 표준화 |
|
||||
| 예외 처리 | `exceptions.py` | 공통 예외 클래스로 서비스간 처리 로직 통일 |
|
||||
| Celery 태스크 래퍼 | `celery_base.py` | 공통 Task 기반 클래스, 재시도/타임아웃/로깅 통일 |
|
||||
| 작업 상태 추적 | `redis_job_tracker.py` | Redis 기반 작업 상태 추적 기능 |
|
||||
| 모델 어댑터 | `llm_adapter.py`, `ocr_adapter.py` | 다양한 추론 서비스에 대한 공통 인터페이스 |
|
||||
| 라우터 템플릿 | `base_router.py` | FastAPI 기반 라우터 템플릿 및 공통 설정 |
|
||||
| 파일 유틸리티 | `file_utils.py` | 확장자 검사, 디렉토리 생성 등 파일 처리 로직 |
|
||||
---
|
||||
|
||||
## 3. 고려된 대안
|
||||
|
||||
### 1. **git-submodule**
|
||||
|
||||
* 경량화 및 버전 고정 측면에서 유리
|
||||
* 그러나 초기 진입장벽이 높고, 실수(예: 서브모듈 커밋 누락 등) 발생 가능
|
||||
|
||||
### 2. **git-subtree**
|
||||
|
||||
* 현재 가장 유력한 방식
|
||||
* 외부 저장소의 디렉터리를 내부로 복사하여 통합된 이력 관리 가능
|
||||
* CI/CD 파이프라인 내에서도 동기화 명령 (`pull`, `push`, `split`)이 명확
|
||||
|
||||
### 3. **Gitea Action 통한 자동 동기화**
|
||||
|
||||
* push 이벤트 발생 시 `main` 브랜치의 `common/` 디렉토리를 각 서비스의 `utils/`로 복사
|
||||
* 자동화는 강력하나, 충돌이나 병합 충돌 발생 시 수동 대응 필요
|
||||
|
||||
---
|
||||
|
||||
## 4. 향후 계획
|
||||
|
||||
* 실제 운영 중인 공통 모듈을 기준으로 **변경 빈도, 영향 범위 분석**
|
||||
* `subtree` 및 `Gitea Action` 기반 연동 테스트 진행
|
||||
* 두 방식을 병행 테스트하여 장단점 비교
|
||||
|
||||
---
|
||||
121
docs/ADR-4.md
Normal file
121
docs/ADR-4.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# **ADR-004**
|
||||
|
||||
- 제목: **LLM Gateway의 비동기 추론 구조 개선: OCR 및 추론 파이프라인 요청 처리 방식 전환**
|
||||
- 날짜: **2025-06-23**
|
||||
- 상태: 채택됨 (Proposed)
|
||||
- 작성자: **\[김용연 연구원]**
|
||||
|
||||
---
|
||||
|
||||
## 1. 컨텍스트 (Context)
|
||||
|
||||
기존 LLM Gateway에서는 `/ocr`, `/extract/*`, `/general/*` 요청 처리 시 다음과 같은 문제가 발생하였다:
|
||||
|
||||
- Gateway가 OCR 결과를 **최대 85초간 polling**하여 기다린 뒤, 후속 작업(LLM 추론 또는 최종 결과 응답)을 수행
|
||||
- 이 구조는 Gateway가 **해당 요청을 점유**한 상태로 유지되므로, 동시에 여러 사용자의 요청을 처리하기 어려워짐
|
||||
- 클라이언트는 장시간 대기해야 하며, 요청 실패 시 다시 처음부터 재시도해야 하는 구조였음
|
||||
|
||||
---
|
||||
|
||||
## 2. 결정 (Decision)
|
||||
|
||||
LLM Gateway는 **모든 OCR 및 LLM 요청을 비동기 백그라운드 처리 방식**으로 전환하여, Gateway가 요청을 즉시 반환하고 작업은 `asyncio.create_task()`를 통해 처리되도록 구조를 개선하였다.
|
||||
|
||||
### 📌 asyncio.create_task()를 사용한 이유:
|
||||
|
||||
- `asyncio.create_task()`는 FastAPI와 잘 통합되는 **간단한 백그라운드 실행 방식**으로,
|
||||
|
||||
- Gateway의 요청 핸들러를 차단하지 않으면서
|
||||
- 요청 수신 즉시 응답을 반환하고
|
||||
- 이후 파이프라인 작업을 **비동기 이벤트 루프에서 독립적으로 처리**할 수 있게 한다.
|
||||
|
||||
- FastAPI의 `BackgroundTasks`는 요청 스코프에 종속되어 **작업 진행 중 연결이 끊기면 실행되지 않을 수 있는 단점**이 있음.
|
||||
- `create_task()`를 사용하면 상태 추적, 결과 저장 등 복합 처리가 필요한 **OCR + LLM 파이프라인**에도 유연하게 대응 가능.
|
||||
|
||||
### 📌 주요 변경 사항:
|
||||
|
||||
- 클라이언트 요청 시 `request_id`와 `progress_url`만 응답
|
||||
- 전체 파이프라인(OCR → LLM → 후처리)은 백그라운드에서 실행
|
||||
- 최종 결과는 Redis에 저장되며, 클라이언트는 /progress/{request_id}를 통해 상태 및 결과를 직접 조회
|
||||
|
||||
---
|
||||
|
||||
## ✅ `/ocr`에서 요청
|
||||
|
||||
### 변경 전
|
||||
|
||||
- Gateway가 OCR API에 요청한 후, **최대 85초간 polling**
|
||||
- 완료 여부에 따라 최종 응답을 직접 반환
|
||||
|
||||
### 변경 후
|
||||
|
||||
- Gateway는 OCR API에 요청만 전송하고 다른 작업 요청 수행
|
||||
- 클라이언트에는 다음 정보만 반환:
|
||||
|
||||
- `request_id`: OCR 작업 식별자
|
||||
- `status`: 작업 접수
|
||||
- `message`: 사용자 안내 문구
|
||||
- `status_check_url`: `/ocr/progress/{request_id}`
|
||||
|
||||
- 클라이언트는 해당 URL로 결과 조회
|
||||
|
||||
---
|
||||
|
||||
## ✅ `/extract/*`, `/general/*`에서 요청
|
||||
|
||||
### 변경 전
|
||||
|
||||
- Gateway가 내부에서:
|
||||
|
||||
1. OCR API 요청 → 결과 polling
|
||||
2. 결과 수신 후 LLM API 요청
|
||||
3. 최종 결과 응답
|
||||
|
||||
### 변경 후
|
||||
|
||||
- 전체 파이프라인(OCR → LLM → 후처리)을 `asyncio.create_task()`로 **백그라운드 비동기 실행**
|
||||
- Gateway는 즉시 아래 정보 응답:
|
||||
|
||||
- `message`: 작업이 백그라운드에서 실행 중
|
||||
- `request_id`: 상태 추적용
|
||||
- `status_check_url`: `/extract/progress/{request_id}`
|
||||
|
||||
- 최종 결과는 Redis에 저장되고, `/extract/progress/{result_id}`로 확인 가능
|
||||
|
||||
```
|
||||
Client
|
||||
│
|
||||
├── POST /extract/outer (input + prompt)
|
||||
│ ↓
|
||||
│ Gateway → OCR → LLM → Result
|
||||
│ ↓
|
||||
└── return: request_id + progress URL
|
||||
|
||||
백그라운드 작업
|
||||
├── OCR API 호출
|
||||
├── 추출 텍스트 Redis 저장
|
||||
├── LLM API 호출
|
||||
└── 최종 결과 Redis 저장
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 고려된 대안
|
||||
|
||||
- **FastAPI BackgroundTasks** 사용:
|
||||
→ 요청 스코프와 연결되어 있어 상태 추적 및 작업 흐름 관리에 제한적
|
||||
- **Celery를 통한 전체 파이프라인 비동기화**
|
||||
→ 복잡성 증가, 구현 부담이 커서 1차 개선으로는 적절하지 않음
|
||||
- **기존 polling 방식 유지 + 타임아웃 설정 개선**
|
||||
→ 구조적 병목 문제 해결 불가
|
||||
|
||||
---
|
||||
|
||||
## 4. 결과
|
||||
|
||||
- Gateway가 작업을 점유하지 않고 **완전한 비동기 구조** 확보
|
||||
- 클라이언트 응답 속도 향상 및 사용자 경험 개선
|
||||
- Redis 기반 상태 추적 및 결과 조회 API 완비
|
||||
- 확장성 및 고부하 처리 능력 증가
|
||||
|
||||
---
|
||||
64
docs/ADR-5.md
Normal file
64
docs/ADR-5.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# **ADR-005**
|
||||
|
||||
- 제목: **LLM Gateway의 로깅 로직 개선: 클라이언트 IP 및 포트 추출 방식 보강**
|
||||
- 날짜: **2025-07-29**
|
||||
- 상태: 채택됨 (Proposed)
|
||||
- 작성자: **\[김용연 연구원]**
|
||||
|
||||
---
|
||||
|
||||
## 1. 컨텍스트 (Context)
|
||||
|
||||
LLM Gateway에서 API 요청을 처리할 때, 로그에 기록되는 `ip`와 `swagger_port` 값이 프록시 환경에서 정확하지 않은 문제가 발생했다.
|
||||
|
||||
- 외부망 요청 시 `request.client.host` 값이 **회사 공인 IP(프록시/NAT IP)** 로만 기록됨.
|
||||
- `Host` 헤더 기반 포트 추출이 실패해 `"unknown"`으로 로그에 기록되는 사례 발생.
|
||||
|
||||
---
|
||||
|
||||
## 2. 배경 (Background)
|
||||
|
||||
- 로드밸런서나 리버스 프록시(Nginx, ALB 등)를 거치는 구조에서, 원래 클라이언트 정보를 담은 헤더(`X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Port`)가 전달되지 않거나 무시되는 문제가 있었다.
|
||||
- 그 결과, 모니터링과 디버깅 과정에서 **실제 사용자의 접속 정보(IP/포트)** 를 추적하기 어려웠다.
|
||||
|
||||
---
|
||||
|
||||
## 3. 결정 (Decision)
|
||||
|
||||
- **클라이언트 IP**: `X-Forwarded-For` → `X-Real-IP` → `request.client.host` 순으로 확인해 기록.
|
||||
- **포트 정보**: `X-Forwarded-Port` → `request.url.port` → `Host` 헤더 → 기본 포트(443/80) 순으로 확인해 기록.
|
||||
|
||||
---
|
||||
|
||||
## 4. 대안 (Alternatives)
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
|
||||
|
||||
| 대안 | 장점 | 단점 |
|
||||
| -------------------------------------------------------------------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------- |
|
||||
| **기존 방식 유지**<br>`request.client.host`와 `Host`만 사용 | 코드 단순, 별도 설정 불필요 | 프록시 환경에서 실제 사용자 IP·포트 추적 불가,`"unknown"` 로그 발생 가능 |
|
||||
| **프록시 헤더 활용 (채택)**<br>`X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Port` 사용 | 외부망·내부망 모두에서 정확한 IP/포트 기록 가능 | 프록시 설정 누락 시 fallback 값(`request.client.host`, `443/80`)으로만 기록됨 |
|
||||
|
||||
=======
|
||||
|
||||
|
||||
| 대안 | 장점 | 단점 |
|
||||
| -------------------------------------------------------------------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------- |
|
||||
| **기존 방식 유지**<br>`request.client.host`와 `Host`만 사용 | 코드 단순, 별도 설정 불필요 | 프록시 환경에서 실제 사용자 IP·포트 추적 불가,`"unknown"` 로그 발생 가능 |
|
||||
| **프록시 헤더 활용 (채택)**<br>`X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Port` 사용 | 외부망·내부망 모두에서 정확한 IP/포트 기록 가능 | 프록시 설정 누락 시 fallback 값(`request.client.host`, `443/80`)으로만 기록됨 |
|
||||
|
||||
>>>>>>> Stashed changes
|
||||
>>>>>>>
|
||||
>>>>>>
|
||||
>>>>>
|
||||
>>>>
|
||||
>>>
|
||||
>>
|
||||
|
||||
---
|
||||
|
||||
## 5. 결과 (Consequences)
|
||||
|
||||
- LLM Gateway의 로그에 실제 사용자 접속 정보(IP, 포트)가 일관되게 기록되어 **모니터링과 디버깅 품질 개선**.
|
||||
- 프록시 설정(`X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Port`)이 누락되면 여전히 기본값(`request.client.host`, `443/80`)으로만 기록될 수 있으므로, 인프라 설정 가이드와 함께 배포 필요
|
||||
104
docs/API_KEY_USAGE.md
Normal file
104
docs/API_KEY_USAGE.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# API 키 사용 가이드
|
||||
|
||||
이 문서는 LLM Gateway의 API를 사용하기 위한 인증 방식, 특히 API 키의 발급, 관리 및 사용 방법에 대해 설명합니다.
|
||||
|
||||
## 개요
|
||||
|
||||
LLM Gateway는 두 종류의 API 키를 사용하여 접근을 제어합니다.
|
||||
|
||||
1. **관리자 키 (Admin Key):**
|
||||
- **헤더 이름:** `X-Admin-KEY`
|
||||
- **용도:** API 클라이언트 키를 생성, 조회, 폐기하는 관리용 API를 호출할 때 사용됩니다.
|
||||
- **특징:** 시스템 관리자만 알고 있어야 하는 마스터 키입니다. 서버의 `.env` 파일에 `ADMIN_API_KEY`로 저장되어 있습니다.
|
||||
|
||||
2. **클라이언트 키 (Client Key):**
|
||||
- **헤더 이름:** `X-API-KEY`
|
||||
- **용도:** 모델 추론, 파일 다운로드 등 일반적인 모든 API 서비스를 호출할 때 사용됩니다.
|
||||
- **특징:** 관리자가 각 사용자 또는 서비스별로 발급해주는 고유한 키입니다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 관리자 가이드
|
||||
|
||||
### 1.1. 새로운 클라이언트 키 발급하기
|
||||
|
||||
새로운 사용자나 서비스를 위해 신규 `X-API-KEY`를 발급합니다.
|
||||
|
||||
- **Endpoint:** `POST /manage/keys`
|
||||
- **요청 예시 (`curl`):**
|
||||
|
||||
```bash
|
||||
# 'my-first-client' 라는 이름으로 키를 발급하는 예시
|
||||
# X-Admin-KEY 헤더에 자신의 관리자 키를 입력하세요.
|
||||
|
||||
curl -X POST http://localhost:8000/manage/keys \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Admin-KEY: <여기에_관리자_키를_입력하세요>" \
|
||||
-d '{"client_name": "my-first-client"}'
|
||||
```
|
||||
|
||||
- **성공 응답:**
|
||||
```json
|
||||
{
|
||||
"message": "API Key created successfully",
|
||||
"key_info": {
|
||||
"api_key": "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||
"client_name": "my-first-client",
|
||||
"created_at": 1678886400,
|
||||
"is_active": "true"
|
||||
}
|
||||
}
|
||||
```
|
||||
> **중요:** 여기서 생성된 `api_key` 값을 사용자에게 전달해 주세요.
|
||||
|
||||
### 1.2. 발급된 모든 키 목록 조회하기
|
||||
|
||||
현재 시스템에 등록된 모든 클라이언트 키의 정보를 확인합니다.
|
||||
|
||||
- **Endpoint:** `GET /manage/keys`
|
||||
- **요청 예시 (`curl`):**
|
||||
|
||||
```bash
|
||||
curl -X GET http://localhost:8000/manage/keys \
|
||||
-H "X-Admin-KEY: <여기에_관리자_키를_입력하세요>"
|
||||
```
|
||||
|
||||
### 1.3. 클라이언트 키 폐기(삭제)하기
|
||||
|
||||
특정 클라이언트 키를 시스템에서 영구적으로 삭제하여 더 이상 사용할 수 없게 만듭니다.
|
||||
|
||||
- **Endpoint:** `DELETE /manage/keys/{api_key}`
|
||||
- **요청 예시 (`curl`):**
|
||||
|
||||
```bash
|
||||
# 폐기하려는 클라이언트 키를 URL 경로에 포함합니다.
|
||||
|
||||
curl -X DELETE http://localhost:8000/manage/keys/sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
|
||||
-H "X-Admin-KEY: <여기에_관리자_키를_입력하세요>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 일반 사용자/클라이언트 가이드
|
||||
|
||||
관리자로부터 발급받은 `X-API-KEY`를 사용하여 LLM Gateway의 일반 API를 호출할 수 있습니다.
|
||||
|
||||
### 2.1. API 호출 방법
|
||||
|
||||
- **요구사항:** 모든 요청의 HTTP 헤더에 `X-API-KEY`를 포함해야 합니다.
|
||||
- **예시: 모델 목록 조회 API 호출**
|
||||
|
||||
```bash
|
||||
# 발급받은 자신의 클라이언트 키를 X-API-KEY 헤더에 입력하세요.
|
||||
|
||||
curl -X GET http://localhost:8000/api/v1/model/list \
|
||||
-H "X-API-KEY: <여기에_발급받은_클라이언트_키를_입력하세요>"
|
||||
```
|
||||
|
||||
- **인증 실패 시:**
|
||||
만약 키가 없거나 유효하지 않은 키를 사용하면, `401 Unauthorized` 또는 `403 Forbidden` 오류가 발생합니다.
|
||||
```json
|
||||
{
|
||||
"detail": "Invalid or missing API Key"
|
||||
}
|
||||
```
|
||||
143
docs/PRD.md
Normal file
143
docs/PRD.md
Normal file
@@ -0,0 +1,143 @@
|
||||
## **LLM Gateway 프로젝트 제품 요구사항 문서 (PRD)**
|
||||
|
||||
### 1\. 문서 개요
|
||||
|
||||
본 문서는 사내 다양한 서비스에서 발생하는 LLM(거대 언어 모델) 및 관련 AI 모델(OCR, STT 등) 수요를 중앙에서 효율적으로 처리하고 관리하기 위한 **LLM Gateway** 프로젝트의 요구사항을 정의합니다.
|
||||
|
||||
* **프로젝트명:** LLM Gateway
|
||||
* **작성일:** 2025년 8월 8일
|
||||
* **담당자/팀:** 한치영 - AI 팀장
|
||||
|
||||
|
||||
### 2\. 프로젝트 배경 및 목표
|
||||
|
||||
#### 2.1. 배경 및 문제 정의
|
||||
|
||||
* **리소스 중복:** 유사한 기능이 팀별로 중복 운영
|
||||
* **일관성 부재:** 모델 API 규격, 인증 방식, 성능 기준이 다르고, 코드 재활용이 어려움
|
||||
* **확장성 한계:** 트래픽 증가 시 유연한 수평 확장에 대한 통일된 전략이 부재
|
||||
* **외부 LLM 사용량 측정:** 외부 LLM API를 사용하는 경우 사용량 측정을 위한 목(통일된 진입점)이 필요
|
||||
|
||||
#### 2.2. 프로젝트 목표
|
||||
|
||||
LLM Gateway는 이러한 문제들을 해결하고자 아래와 같은 목표를 가짐
|
||||
|
||||
* **API 통합 및 표준화:** 사내 모든 LLM 및 AI 모델 접근을 위한 단일 End-point를 제공하여 API 규격을 표준화
|
||||
* **전처리 파이프라인 제공:** OCR, STT 등 자주 사용되는 전처리 기능을 파이프라인으로 제공하여 개발 생산성을 향상
|
||||
* **효율적인 자원 관리:** Docker 기반의 통합 인프라와 Ollama 런타임을 통해 모델 서버를 효율적으로 운영하고, 수평 확장이 용이한 구조를 마련
|
||||
* **중앙 집중 관리 및 모니터링:** API 사용량, 응답 시간, 오류 등을 중앙에서 모니터링하여 안정적인 운영을 지원
|
||||
|
||||
|
||||
### 3\. 기능 요구사항
|
||||
|
||||
| 기능 ID | 기능명 | 상세 설명 | 우선순위 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **F-001** | **Gateway API 서버** | FastAPI 기반으로 모든 요청을 수신하고 적절한 서비스로 라우팅. 인증, 로깅, 요청/응답 형식 변환을 처리 | **높음** |
|
||||
| **F-002** | **LLM 추론 요청 처리** | Ollama로 구동되는 LLM에 대한 추론(Chat/Completion) 요청을 처리합니다. 향후 로드 밸런싱을 통해 여러 LLM 인스턴스로 요청을 분산 | **높음** |
|
||||
| **F-003** | **비동기 OCR 처리** | 이미지 파일을 입력받아 PaddleOCR 서버에 비동기 처리를 요청하고, 처리 결과를 Redis에 저장. 사용자에게는 Job ID를 즉시 반환 | **높음** |
|
||||
| **F-004** | **비동기 STT 처리** | 음성 파일을 입력받아 STT 모델(위스퍼) 서버에 비동기 처리를 요청 | **낮음** |
|
||||
| **F-005** | **비동기 작업 결과 조회** | Job ID를 통해 Redis에 저장된 OCR, STT 등의 작업 상태(대기, 처리 중, 완료, 실패) 및 최종 결과를 조회하는 API를 제공 | **높음** |
|
||||
| **F-006** | **모듈 추가 확장성** | 향후 새로운 AI 모델(번역, 문서 요약 등)이 추가될 때, 최소한의 설정으로 Gateway에 쉽게 통합할 수 있는 구조 | **중간** |
|
||||
| **F-007** | **공문 분석** | 국내외 수발신 공문에 대한 데이터 추출 | **높음** |
|
||||
| **F-008** | **문서 요약** | 문서에 대한 단문 요약 | **낮음** |
|
||||
|
||||
|
||||
### 4\. 비기능 요구사항
|
||||
|
||||
* **성능:** 기준 응답 시간이 채팅 인터페이스를 통한 입력보다 3초 이상 길지 않아야 함.
|
||||
* **확장성:** 모든 컴포넌트(Gateway, OCR, STT, LLM)는 Docker 컨테이너 기반으로 설계되어 트래픽 증가에 따라 `docker-compose up --scale <service_name>=N` 를 통해 수평 확장
|
||||
* **보안:** 내부망 사용을 전제로 하되, 서비스 구분을 위한 API Key 기반의 인증 체계를 도입
|
||||
* **모니터링:** API 요청/응답, 처리 시간, 에러율 등 주요 지표를 Prometheus, Grafana 등을 활용해 시각화하고 모니터링
|
||||
|
||||
-----
|
||||
|
||||
## **LLM Gateway 아키텍처**
|
||||
|
||||
하이레벨 아키텍처
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
User["👩💻 사내 서비스:PM 등"]
|
||||
|
||||
subgraph "Gateway Layer"
|
||||
Gateway["🚀 LLM Gateway (FastAPI)"]
|
||||
Result_Redis
|
||||
end
|
||||
|
||||
Ollama
|
||||
|
||||
subgraph "Worker Layer"
|
||||
Broker[(Celery Broker)]
|
||||
Worker_Redis["💾 Redis (Job Result Store)"]
|
||||
Worker_OCR["👷 OCR Celery Worker - PaddleOCR"]
|
||||
end
|
||||
%% --- Data Flow ---
|
||||
|
||||
%% Synchronous Flow (LLM Chat)
|
||||
User --"1.요청"--> Gateway
|
||||
Result_Redis -- "2.Job ID 즉시 반환" --> User
|
||||
Gateway -- "3.작업 등록" --> Broker
|
||||
Broker --> Worker_OCR --> Worker_Redis
|
||||
Gateway -- "3-background 작업 결과 반복 확인" --> Worker_Redis
|
||||
Gateway -- "4.LLM 추론 요청" --> Ollama
|
||||
Ollama -- "5.Json 기반 응답" --> Gateway
|
||||
Gateway -- "6.결과 확인 Cache 업데이트" --> Result_Redis
|
||||
User -- "7.결과 확인" --> Result_Redis
|
||||
|
||||
%% Style Definitions
|
||||
classDef default fill:#f9f9f9,stroke:#333,stroke-width:2px;
|
||||
classDef special fill:#E8E8FF,stroke:#663399,stroke-width:2px;
|
||||
class Gateway,LB_LLM,Broker,Redis special;
|
||||
```
|
||||
-----
|
||||
|
||||
시퀀스 기반 이해
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as 👩💻 Project Master
|
||||
participant Gateway as 🚀 LLM Gateway
|
||||
participant Broker as Celery Broker
|
||||
participant Worker as 👷 OCR Worker
|
||||
participant Worker_Redis as 💾 Redis (Job Store)
|
||||
participant Ollama
|
||||
|
||||
User->>+Gateway: 1. 이미지 처리 요청
|
||||
Gateway->>-User: 2. Job ID 즉시 반환
|
||||
|
||||
Gateway->>Broker: 3. OCR 작업 등록
|
||||
activate Gateway
|
||||
Broker->>Worker: OCR 작업 전달
|
||||
deactivate Gateway
|
||||
|
||||
activate Worker
|
||||
Worker->>Worker: PaddleOCR로 이미지 처리
|
||||
Worker->>Worker_Redis: 처리 결과 저장
|
||||
deactivate Worker
|
||||
|
||||
loop 3-background. 작업 결과 반복 확인
|
||||
Gateway->>Worker_Redis: Job ID로 결과 확인
|
||||
end
|
||||
|
||||
Note right of Gateway: OCR 작업 완료 확인 후
|
||||
|
||||
Gateway->>+Ollama: 4. OCR 결과 기반 LLM 추론 요청
|
||||
Ollama-->>-Gateway: 5. JSON 형식으로 응답
|
||||
|
||||
Note right of Gateway: 6. 최종 결과를<br/>내부 캐시에 저장 (Result_Redis)
|
||||
|
||||
User->>+Gateway: 7. Job ID로 최종 결과 확인 요청
|
||||
Gateway-->>-User: 최종 처리 결과 반환
|
||||
```
|
||||
|
||||
|
||||
### 아키텍처 설명
|
||||
|
||||
1. **User:** 사내의 다른 서비스나 개발자 등 Gateway의 API를 호출하는 주체
|
||||
2. **Gateway Layer:** 모든 요청의 진입점 FastAPI로 구현되어 동기/비동기 요청을 받아 적절한 백엔드 서비스로 분기
|
||||
3. **AI Model Layer:**
|
||||
* **LLM Serving:** Ollama 런타임을 사용
|
||||
4. **Worker Layer:** OCR, STT 등 각 기능을 독립적인 Docker Stack으로 묶습니다.
|
||||
* **Celery & Broker(Redis/RabbitMQ):** OCR, STT 같이 시간이 오래 걸리는 작업을 비동기로 처리하기 위한 메시지 큐
|
||||
* **Worker:** 실제 작업을 수행하는 프로세스. FastAPI로 랩핑해서 서비스
|
||||
* **Redis:** 비동기 작업의 최종 결과를 저장. 클라이언트는 Job ID를 통해 이곳에 저장된 결과를 조회
|
||||
115
docs/README_DEV.md
Normal file
115
docs/README_DEV.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# LLM Gateway API 가이드
|
||||
|
||||
## 1. 개요
|
||||
|
||||
LLM Gateway는 다양한 AI 모델(Ollama, OpenAI, Google, Anthropic 등)을 통합하여 일관된 인터페이스로 제공하는 API 서버입니다. 문서(PDF, 이미지) 처리, 텍스트 생성, 음성-텍스트 변환(STT), 객체 탐지(YOLO) 등 복잡한 AI 파이프라인을 비동기적으로 처리하고 관리하는 기능을 제공합니다.
|
||||
|
||||
주요 기술 스택은 다음과 같습니다:
|
||||
|
||||
- **프레임워크**: FastAPI
|
||||
- **비동기 작업 관리**: Redis
|
||||
- **파일 저장소**: MinIO
|
||||
- **내부 LLM 호스팅**: Ollama
|
||||
- **서비스 오케스트레이션**: Docker Compose
|
||||
|
||||
---
|
||||
|
||||
## 2. 핵심 아키텍처
|
||||
|
||||
### 비동기 처리 모델
|
||||
|
||||
대부분의 AI 작업은 시간이 오래 걸리므로, 본 시스템은 비동기 파이프라인을 채택했습니다.
|
||||
|
||||
1. **요청 접수**: 사용자가 파일을 포함하여 API를 호출하면, 시스템은 즉시 고유한 `request_id`를 발급하고 백그라운드 작업을 생성합니다.
|
||||
2. **상태 추적**: `request_id`를 사용하여 `/extract/progress/{request_id}`와 같은 `progress` 엔드포인트에서 작업 상태를 폴링(polling)할 수 있습니다.
|
||||
3. **결과 저장**: 작업이 완료되면, 최종 결과는 별도의 `result_id`와 매핑되어 Redis에 저장됩니다. `progress` 엔드포인트는 작업 완료 시 `final_result` 필드에 최종 결과를 포함하여 반환합니다.
|
||||
|
||||
### 서비스 의존성
|
||||
|
||||
- **Redis**: 작업 큐, 상태 로그, 최종 결과, API 키 등을 저장하는 핵심 데이터베이스입니다.
|
||||
- **MinIO**: 사용자가 업로드한 파일을 임시 저장하고, 각 서비스(OCR, STT 등)가 파일에 접근할 수 있도록 Presigned URL을 생성하는 역할을 합니다.
|
||||
- **OCR API**: PDF, 이미지 등에서 텍스트를 추출하는 별도의 서비스입니다. `/extract`, `/general` 엔드포인트에서 내부적으로 호출됩니다.
|
||||
- **STT API**: 음성 파일에서 텍스트를 추출하는 별도의 서비스입니다. `/stt` 엔드포인트가 프록시 역할을 합니다.
|
||||
- **YOLO API**: 이미지에서 객체를 탐지하는 별도의 서비스입니다. `/yolo` 엔드포인트가 프록시 역할을 합니다.
|
||||
|
||||
---
|
||||
|
||||
|
||||
## 3. API 엔드포인트 상세 설명
|
||||
|
||||
### Tag: `Extraction`
|
||||
|
||||
문서(PDF, 이미지 등)에서 사전 정의된 프롬프트를 기반으로 정보를 추출합니다.
|
||||
|
||||
* `POST /extract/inner`: **내부 LLM(Ollama)**을 사용합니다.
|
||||
* `POST /extract/outer`: **외부 LLM(GPT, Gemini 등)**을 사용합니다.
|
||||
* `POST /extract/structured`: **내외부 LLM을 사용해 JSON 형식 응답 생성**에 사용합니다.* **요청 (multipart/form-data)**:* `input_file`: 분석할 원본 문서 파일.
|
||||
* `prompt_file` (선택): 기본 프롬프트를 대체할 `.txt` 파일.
|
||||
* `model` (선택): 사용할 LLM 모델 이름.
|
||||
* `schema_file` (structured용/필수): 형식을 지정할 `.json` 파일.
|
||||
* **응답 (초기)**: `request_id`를 포함한 JSON 객체.
|
||||
* `GET /extract/progress/{request_id}`: 정보 추출 작업의 진행 상태와 최종 결과를 조회합니다.
|
||||
|
||||
### Tag: `General`
|
||||
|
||||
문서 기반의 범용 질의응답을 수행합니다. 사용자가 직접 프롬프트를 제공해야 합니다.
|
||||
|
||||
* `POST /general/inner`: **내부 LLM(Ollama)**을 사용합니다.
|
||||
* `POST /general/outer`: **외부 LLM(GPT, Gemini 등)**을 사용합니다.* **요청 (multipart/form-data)**:* `input_file`: 분석할 원본 문서 파일.
|
||||
* `prompt_file`: LLM에 전달할 명령어가 담긴 `.txt` 파일.
|
||||
* `schema_file` (선택): 결과 포맷을 강제할 `.json` 스키마 파일.
|
||||
* `model` (선택): 사용할 LLM 모델 이름.
|
||||
* **응답 (초기)**: `request_id`를 포함한 JSON 객체.
|
||||
* `GET /general/progress/{request_id}`: 범용 추론 작업의 진행 상태와 최종 결과를 조회합니다.
|
||||
|
||||
### Tag: `OCR Gateway`
|
||||
|
||||
문서에서 텍스트를 추출하는 OCR API를 프록시합니다.
|
||||
|
||||
* `POST /ocr`: 문서를 OCR 서버에 전달하고 `request_id`를 받습니다.
|
||||
* `GET /ocr/progress/{request_id}`: OCR 작업 상태를 조회합니다.
|
||||
|
||||
### Tag: `STT Gateway`
|
||||
|
||||
음성 파일을 텍스트로 변환하는 STT API를 프록시합니다.
|
||||
|
||||
* `POST /audio`: 단일 음성 파일을 STT 서버로 전달합니다.
|
||||
* `POST /dialog_processing`: 화자 분리가 포함된 음성 파일을 처리합니다.
|
||||
* `GET /progress/{request_id}`: STT 작업 상태를 조회합니다.
|
||||
|
||||
### Tag: `YOLO Gateway`
|
||||
|
||||
이미지 내 객체를 탐지하는 YOLO API를 프록시합니다.
|
||||
|
||||
* `POST /detect_view`: 이미지를 YOLO 서버로 전달하고 탐지 결과를 받습니다.
|
||||
* `GET /detect_view/images/{request_id}`: 탐지 결과가 시각화된 이미지를 조회합니다.
|
||||
* `GET /detect_view/results/{request_id}`: 탐지 결과 JSON을 조회합니다.
|
||||
|
||||
### Tag: `summary`
|
||||
|
||||
STT로 전사된 텍스트를 회의록으로 작성합니다.
|
||||
|
||||
* `POST /summary`: 등록된 모든 모델을 사용하여 요약을 수행하고 결과를 종합합니다.
|
||||
* `POST /ollama_summary`: 로컬 모델을 사용하여 요약을 수행하고 결과를 종합합니다.
|
||||
* `POST /gemini_summary`: gemini flash 모델을 사용하여 요약을 수행하고 결과를 종합합니다.
|
||||
* `POST /task_summary`: 비동기적으로 모든 모델의 요약을 수행하고 `task_id`를 반환합니다.
|
||||
* `GET /task_summary/{task_id}`: 비동기 요약 작업의 결과를 조회합니다.
|
||||
|
||||
### Tag: `API Key Management`
|
||||
|
||||
API 키를 관리합니다.
|
||||
|
||||
* `POST /manage/keys`: 새로운 API 키를 생성합니다.
|
||||
* `GET /manage/keys`: 모든 API 키 목록을 조회합니다.
|
||||
* `DELETE /manage/keys/{api_key}`: 지정된 API 키를 폐기합니다.
|
||||
|
||||
### Tag: `Model Management`
|
||||
|
||||
* `GET /info`: `/extract`, `/general` 엔드포인트에서 사용 가능한 내부/외부 모델 목록을 조회합니다.
|
||||
* `GET /default_prompt`: 기본 프롬프트 파일을 다운로드합니다.
|
||||
* `GET /structured_prompt`: 구조화 추출용 프롬프트 예시 파일을 다운로드합니다.
|
||||
* `GET /structured_schema`: 구조화 추출용 스키마 예시 파일을 다운로드합니다.
|
||||
|
||||
### Tag: `Guide Book`
|
||||
|
||||
* `/schema_file_guide`, `/general_guide`, `/extract_guide`: 각 기능에 대한 HTML 가이드 문서를 제공합니다.
|
||||
198
docs/summary_api.md
Normal file
198
docs/summary_api.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# Summary API 기능 명세서
|
||||
|
||||
제공된 코드를 기반으로 `summary` 태그로 그룹화된 API에 대한 기능 명세서입니다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 통합 요약 생성 (STT 요약)
|
||||
|
||||
여러 LLM 모델을 동시에 호출하여 입력된 텍스트에 대한 요약 결과를 통합하여 반환합니다.
|
||||
|
||||
* **Endpoint:** `/summary`
|
||||
* **Method:** `POST`
|
||||
* **Tag:** `summary`
|
||||
* **Description:**
|
||||
* 하나의 텍스트 입력을 받아 내부적으로 구성된 여러 모델(gpt-4.1-mini, qwen3:custom, gemini-2.5-flash, claude-3-7-sonnet-latest 등)을 통해 요약을 실행하고, 그 결과를 종합하여 반환합니다.
|
||||
* 동기적으로 처리되며, 모든 모델의 요약이 완료될 때까지 응답을 대기합니다.
|
||||
|
||||
### Request Body
|
||||
|
||||
| 필드명 | 타입 | 필수 여부 | 설명 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `text` | `string` | Y | 요약할 원본 텍스트 |
|
||||
|
||||
### Response Body
|
||||
|
||||
| 필드명 | 타입 | 설명 |
|
||||
| :--- | :--- | :--- |
|
||||
| `summary_results` | `object` | 각 모델별 요약 결과가 포함된 객체 |
|
||||
|
||||
### cURL Example
|
||||
|
||||
```bash
|
||||
curl -X 'POST' \
|
||||
'http://localhost:8888/summary' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"text": "오늘 회의에서는 3분기 신제품 출시 계획에 대해 논의했습니다. 주요 안건은..."
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Ollama 모델 요약 생성
|
||||
|
||||
Ollama를 통해 호스팅되는 `qwen` 모델을 사용하여 텍스트를 요약합니다.
|
||||
|
||||
* **Endpoint:** `/ollama_summary`
|
||||
* **Method:** `POST`
|
||||
* **Tag:** `summary`
|
||||
* **Description:**
|
||||
* 지정된 `qwen` 모델만을 사용하여 텍스트 요약을 수행합니다.
|
||||
|
||||
### Request Body
|
||||
|
||||
| 필드명 | 타입 | 필수 여부 | 설명 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `text` | `string` | Y | 요약할 원본 텍스트 |
|
||||
|
||||
### Response Body
|
||||
|
||||
| 필드명 | 타입 | 설명 |
|
||||
| :--- | :--- | :--- |
|
||||
| `summary_results` | `string` | `qwen` 모델의 요약 결과 |
|
||||
|
||||
### cURL Example
|
||||
|
||||
```bash
|
||||
curl -X 'POST' \
|
||||
'http://localhost:8888/ollama_summary' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"text": "Ollama QWEN 모델을 테스트하기 위한 샘플 텍스트입니다."
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Gemini 모델 요약 생성
|
||||
|
||||
Gemini 모델을 사용하여 텍스트를 요약합니다.
|
||||
|
||||
* **Endpoint:** `/gemini_summary`
|
||||
* **Method:** `POST`
|
||||
* **Tag:** `summary`
|
||||
* **Description:**
|
||||
* Gemini 모델만을 사용하여 텍스트 요약을 수행합니다.
|
||||
|
||||
### Request Body
|
||||
|
||||
| 필드명 | 타입 | 필수 여부 | 설명 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `text` | `string` | Y | 요약할 원본 텍스트 |
|
||||
|
||||
### Response Body
|
||||
|
||||
| 필드명 | 타입 | 설명 |
|
||||
| :--- | :--- | :--- |
|
||||
| `summary_results` | `string` | Gemini 모델의 요약 결과 |
|
||||
|
||||
### cURL Example
|
||||
|
||||
```bash
|
||||
curl -X 'POST' \
|
||||
'http://localhost:8888/gemini_summary' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"text": "Gemini 모델을 테스트하기 위한 샘플 텍스트입니다."
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 비동기 요약 작업 생성
|
||||
|
||||
모든 모델을 사용하여 텍스트 요약을 수행하는 백그라운드 작업을 시작합니다.
|
||||
|
||||
* **Endpoint:** `/task_summary`
|
||||
* **Method:** `POST`
|
||||
* **Tag:** `summary`
|
||||
* **Description:**
|
||||
* 요약 작업을 백그라운드에서 실행하도록 요청하고, 즉시 작업 ID(`task_id`)를 반환합니다.
|
||||
* 실제 요약 결과는 반환된 `task_id`를 사용하여 `/task_summary/{task_id}` 엔드포인트에서 조회해야 합니다.
|
||||
|
||||
### Request Body
|
||||
|
||||
| 필드명 | 타입 | 필수 여부 | 설명 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `text` | `string` | Y | 요약할 원본 텍스트 |
|
||||
|
||||
### Response Body
|
||||
|
||||
| 필드명 | 타입 | 설명 |
|
||||
| :--- | :--- | :--- |
|
||||
| `task_id` | `string` | 생성된 백그라운드 작업의 고유 ID |
|
||||
|
||||
### cURL Example
|
||||
|
||||
```bash
|
||||
curl -X 'POST' \
|
||||
'http://localhost:8888/task_summary' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"text": "이것은 비동기 요약 작업을 테스트하기 위한 긴 텍스트입니다..."
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 비동기 요약 작업 결과 조회
|
||||
|
||||
`task_summary`를 통해 생성된 백그라운드 작업의 상태와 결과를 조회합니다.
|
||||
|
||||
* **Endpoint:** `/task_summary/{task_id}`
|
||||
* **Method:** `GET`
|
||||
* **Tag:** `summary`
|
||||
* **Description:**
|
||||
* `task_id`를 사용하여 특정 요약 작업의 진행 상태(예: 처리 중, 완료) 및 완료 시 요약 결과를 확인합니다.
|
||||
|
||||
### Path Parameters
|
||||
|
||||
| 파라미터명 | 타입 | 필수 여부 | 설명 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `task_id` | `string` | Y | 조회할 작업의 고유 ID |
|
||||
|
||||
### Response Body
|
||||
|
||||
* **작업이 진행 중일 경우:**
|
||||
```json
|
||||
{
|
||||
"status": "processing",
|
||||
"results": {}
|
||||
}
|
||||
```
|
||||
* **작업이 완료되었을 경우:**
|
||||
```json
|
||||
{
|
||||
"status": "completed",
|
||||
"results": {
|
||||
"gpt_summary": "GPT 요약 결과...",
|
||||
"qwen_summary": "QWEN 요약 결과...",
|
||||
"gemini_summary": "Gemini 요약 결과...",
|
||||
"claude_summary": "Claude 요약 결과..."
|
||||
}
|
||||
}
|
||||
```
|
||||
* **잘못된 `task_id`일 경우:**
|
||||
```json
|
||||
{
|
||||
"error": "Invalid task_id"
|
||||
}
|
||||
```
|
||||
|
||||
### cURL Example
|
||||
|
||||
```bash
|
||||
curl -X 'GET' \
|
||||
'http://localhost:8888/task_summary/your_generated_task_id'
|
||||
```
|
||||
Reference in New Issue
Block a user