Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2735626
chore: env 파일 import
kjyyjk May 8, 2026
f75ad57
feat: 유저 챗 엔드포인트 및 ai 호출 구현
kjyyjk May 8, 2026
f6fa3c4
feat: llm에게 필요한 데이터 제공
kjyyjk May 9, 2026
d250287
refactor: builder에서 프롬프트 설정
kjyyjk May 9, 2026
4ecdb13
chore: advisors-vector-store 의존성 추가
kjyyjk May 9, 2026
4ac5a9a
refactor: 벡터 db 및 어드바이저 활용
kjyyjk May 9, 2026
46b20a7
chore: markdown-document-reader 의존성 추가
kjyyjk May 9, 2026
62b7aad
docs: resources/data에 layer_n 복사
kjyyjk May 9, 2026
28b3413
feat: md 파일 벡터 저장소에 저장
kjyyjk May 9, 2026
8759009
feat: 응답 content type json으로 변경
kjyyjk May 10, 2026
8ec9bac
refactor: RequestBody dto로 매핑
kjyyjk May 10, 2026
d2901a6
refactor: 테스트 incorrect 이유 글자수 2배 증가
kjyyjk May 10, 2026
64ee947
refactor: topk 2배 증가
kjyyjk May 10, 2026
aea6e10
feat: 디버깅용 엔드포인트 추가
kjyyjk May 11, 2026
e3fe990
docs: deprecated 문서 vector db에서 제거
kjyyjk May 11, 2026
071ec9b
refactor: advisor 커스텀 템플릿 설정
kjyyjk May 13, 2026
6eb21ee
refactor: 프롬프트 내 할루시네이션 방지 내용 추가
kjyyjk May 13, 2026
838f408
feat: 챗봇 응답에 token 정보 포함
kjyyjk May 15, 2026
162cb3c
feat: 디버깅 엔드포인트 응답에 token 정보 포함
kjyyjk May 15, 2026
ebaab45
refactor: controller 패키지 분리
kjyyjk May 15, 2026
ef3815c
refactor: service 분리
kjyyjk May 15, 2026
f8f89e7
feat: 대화 맥락 유지를 위한 chatmemory 추가
kjyyjk May 16, 2026
deb627d
feat: 챗봇 세션 시작/종료 엔드포인트 추가
kjyyjk May 16, 2026
2c6e041
feat: 챗봇 세션 시작/종료 엔드포인트 변경
kjyyjk May 16, 2026
9383c9a
refactor: config 설정 분리
kjyyjk May 16, 2026
3700df4
feat: 챗봇 ui 구현
kjyyjk May 16, 2026
53caf47
feat: 챗봇 ui 개선
kjyyjk May 16, 2026
71121c4
refactor: vip 연락수단 제거
kjyyjk May 16, 2026
5106f1d
refactor: 챗로그 청크 제거
kjyyjk May 17, 2026
ea159ca
chore: ai rag 의존성 추가
kjyyjk May 17, 2026
918edd4
refactor: qa 어드바이저 미사용 및 쿼리 확장 추가
kjyyjk May 18, 2026
d35b780
refactor: 미사용 코드 제거(디버깅 엔드포인트)
kjyyjk May 18, 2026
0d96e85
feat: 리랭크 구현
kjyyjk May 18, 2026
9f1ec40
refactor: 리랭크 수정 및 디버깅
kjyyjk May 18, 2026
f287a6d
refactor: 검색되 청크에 해당하는 문서 전체를 컨텍스트에 포함
kjyyjk May 19, 2026
24f09c9
refactor: 메모리 어드바이저 임시 제거
kjyyjk May 19, 2026
5f0b94c
refactor: 미사용 코드 제거
kjyyjk May 20, 2026
c5bb941
refactor: 주석 추가
kjyyjk May 20, 2026
165f724
docs: 벽 리포트 작성
kjyyjk May 20, 2026
d7f6d68
refactor: vector store 임베딩 runner 분리
kjyyjk May 28, 2026
83f9f41
docs: 미션 readme와 챗봇 readme 분리
kjyyjk May 28, 2026
0f3cc39
style: 초록 회사명 있어보이게 변경
kjyyjk May 28, 2026
d20992d
docs: readme 실행 섹션 수정
kjyyjk May 28, 2026
da03e45
refactor: 임베딩 벡터 영속화 및 임베딩 로직 runner로 분리
kjyyjk May 29, 2026
e01ede4
feat: vector 파일 gitignore
kjyyjk May 29, 2026
42b267f
docs: KPI 문서화
kjyyjk May 30, 2026
9a93fe1
docs: 직접 검수 데이터셋 생성
kjyyjk May 30, 2026
2d6ffbb
docs: 평가 수행 및 직접 검수
kjyyjk May 30, 2026
a52b816
refactor: 답변할 수 없는 질문에 대한 추가 문의 안내
kjyyjk May 30, 2026
37c1647
fix: 프롬프트 에러 수정
kjyyjk May 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ __pycache__/

# Matrix metadata
**/.omc/

data/vector-store.json
92 changes: 92 additions & 0 deletions BASE-README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Stage 1: 고객지원 챗봇 만들기

Spring AI로 FAQ 챗봇을 직접 만드는 실습입니다.

커리큘럼 소개는 [SYLLABUS.md](SYLLABUS.md)를, 진행 방법은 [GUIDE.md](GUIDE.md)를 참고하세요.

---

## 필요한 것

| 항목 | 비고 |
|------|------|
| Java 17+ | `java -version`으로 확인 |
| OpenAI API 키 | [platform.openai.com](https://platform.openai.com)에서 발급 |
| IDE | IntelliJ IDEA 권장 (VS Code + Java Extension Pack도 가능) |

- Spring Boot로 REST API를 만들어 본 경험이 있으면 됩니다
- AI/ML 사전 지식은 없어도 됩니다
- 끝까지 해도 API 비용은 **$1-5** 안쪽입니다 (GPT-4.1-nano)

---

## 빠른 시작

```bash
# 프로젝트 루트에서
cp .env.example .env # OpenAI API 키 입력
./gradlew bootRun
```

서버가 `http://localhost:8080`에서 시작됩니다.

그 다음 [mission/MISSION.md](mission/MISSION.md)를 여세요. 거기서부터 시작입니다.

---

## 평가

`data/test_questions.json`에 100개의 테스트 질문이 있습니다 (easy 30 / medium 44 / hard 26).

서버를 띄운 상태에서 평가 스크립트를 실행할 수 있습니다:

```bash
cd data

# Python 환경 준비
python -m venv .venv
.venv/bin/pip install openai qdrant-client python-dotenv

# 평가 실행 (judge 모델 gpt-4o-mini 사용, 100문항 기준 약 $0.5~1 추가 비용)
.venv/bin/python evaluate_rag.py
```

---

## 프로젝트 구조

```
spring-ai-bootcamp-basic/
├── mission/
│ ├── MISSION.md # 미션 설명 (여기서 시작)
│ └── wall-report.md # 벽 리포트 (마지막에 작성)
├── hints/
│ ├── HINT_01.md ~ HINT_06.md # 막혔을 때 열어보세요
├── data/
│ ├── layer1_faq/ # 공식 FAQ 문서
│ ├── layer2_policies/ # 사내 정책 문서
│ ├── layer3_chatlogs/ # 고객 상담 로그
│ └── test_questions.json # 평가용 질문 100개
├── src/
│ └── main/java/com/cholog/bootcamp/
│ └── Application.java # 여기서부터 만드세요
├── SYLLABUS.md # 커리큘럼 소개 ← 과정 전체 그림
├── GUIDE.md # 진행 가이드 ← 미션 중 참고
└── build.gradle
```

---

## 자주 묻는 질문

**Q: API 키 없이 시작할 수 있나요?**

코드 작성과 컴파일은 가능하지만, 실제 실행에는 OpenAI API 키가 필요합니다.

**Q: FAQ 데이터가 영어인데 질문은 한국어로 해도 되나요?**

네. GPT-4.1-nano는 교차 언어 이해가 가능합니다.

**Q: 어떤 도구를 써도 되나요?**

네. 구현 방법에 제약은 없습니다.
43 changes: 43 additions & 0 deletions KPI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# 챗봇 KPI 평가 영역

### 전체
- 사용자 만족도
- 비용(토큰 사용량)
- 챗봇 사용률/상담사 상담 감소율
- 응답 속도
- 사실 정확성
- 답변 보안성
- 챗봇 보안성
- 답변 명확성
- 챗봇 로그 관리
- 모니터링 및 장애 대응

### 개발/품질
- 응답 속도
- 사실 정확성
- 맥락 적합성
- 보안성
- 비용(토큰 사용량)
- 답변 명확성


### 운영
- 사용자 만족도
- 챗봇 사용률/상담사 상담 감소율
- 챗봇 로그 관리
- 모니터링 및 장애 대응
- 챗봇 보안성


# 영역 별 평가 기준

비용 영역은 사용량 모니터링 이후에 세부 기준을 설정한다.

| 평가 영역 | 설명 | 우선순위 | 상(3) | 중(2) | 하(1) |
| ---------- | ------------------------------------- | ---- | ------------------------------------- | ------------------------------------------------------- | ------------------------------------------------ |
| 사실 정확성 | 문서에 근거한 사실을 정확하게 답변하는가? | 1 | 문서에 근거하여 사실을 정확하게 답변한다. | 문서에 근거가 있으나 내용이 왜곡되거나 부정확하다. | 문서에 근거하지 않은 사실을 답변하거나 잘못된 정보를 제공한다. |
| 보안성 | 권한이 없거나 노출되면 안 되는 민감/기밀 정보를 드러내지 않는가? | 2 | 민감/기밀 정보를 드러내지 않고 허용된 정보 범위 내에서 답변한다. | 민감도는 낮지만 내부 문서명, 내부 정책 표현, 상담 로그 일부 등 불필요한 내부 정보를 드러낸다. | 개인정보, 기밀 문서, 보안과 직결된 내부 정보 등 노출되면 안 되는 정보를 드러낸다. |
| 맥락 적합성 | 사용자 질문의 의도와 대화 맥락에 맞게 답변하는가? | 3 | 사용자의 질문 의도와 대화 맥락에 맞는 정보를 답변한다. | 질문과 일부 관련은 있으나 사용자의 의도나 맥락을 충분히 반영하지 못한다. | 사용자의 질문 해결에 필요한 정보가 아닌 다른 정보를 답변한다. |
| 비용(토큰 사용량) | 챗봇 호출에 필요한 토큰 사용량이 과도하지 않은가? | 4 | - | - | - |
| 응답 속도 | 사용자가 불편을 느끼지 않을 정도로 신속하게 응답하는가? | 5 | 5초 이내에 답변한다. | 5초 초과, 10초 이내에 답변한다. | 10초를 초과하여 답변한다. |
| 답변 명확성 | 답변이 명확하고 이해하기 쉬우며 혼란을 주지 않는가? | 6 | 표준 어투로 이해하기 쉽고 일관되며 명확한 답변을 제공한다. | 일부 표현이 모호하거나 일관되지 않아 이해에 약간의 어려움이 있다. | 과도한 전문 용어, 모호한 표현, 불명확한 구조로 인해 이해하거나 활용하기 어렵다. |
97 changes: 13 additions & 84 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,92 +1,21 @@
# Stage 1: 고객지원 챗봇 만들기
# 프로젝트 개요

Spring AI로 FAQ 챗봇을 직접 만드는 실습입니다.
초록코퍼레이션 고객 응대 챗봇입니다.

커리큘럼 소개는 [SYLLABUS.md](SYLLABUS.md)를, 진행 방법은 [GUIDE.md](GUIDE.md)를 참고하세요.
# 애플리케이션 실행

---
## 실행 옵션

## 필요한 것

| 항목 | 비고 |
|------|------|
| Java 17+ | `java -version`으로 확인 |
| OpenAI API 키 | [platform.openai.com](https://platform.openai.com)에서 발급 |
| IDE | IntelliJ IDEA 권장 (VS Code + Java Extension Pack도 가능) |

- Spring Boot로 REST API를 만들어 본 경험이 있으면 됩니다
- AI/ML 사전 지식은 없어도 됩니다
- 끝까지 해도 API 비용은 **$1-5** 안쪽입니다 (GPT-4.1-nano)

---

## 빠른 시작

```bash
# 프로젝트 루트에서
cp .env.example .env # OpenAI API 키 입력
./gradlew bootRun
```

서버가 `http://localhost:8080`에서 시작됩니다.

그 다음 [mission/MISSION.md](mission/MISSION.md)를 여세요. 거기서부터 시작입니다.

---

## 평가

`data/test_questions.json`에 100개의 테스트 질문이 있습니다 (easy 30 / medium 44 / hard 26).

서버를 띄운 상태에서 평가 스크립트를 실행할 수 있습니다:
애플리케이션 실행 시 VectorStore 임베딩을 수행하려면 인자로 --mode=embedding 옵션을 주어야합니다.
임베딩 수행하지 않을 경우 옵션을 제외합니다.

## 실행 명령어
```bash
cd data

# Python 환경 준비
python -m venv .venv
.venv/bin/pip install openai qdrant-client python-dotenv
# bootrun 실행 시
./gradlew bootrun
./gradlew bootrun --args='--mode=embedding'

# 평가 실행 (judge 모델 gpt-4o-mini 사용, 100문항 기준 약 $0.5~1 추가 비용)
.venv/bin/python evaluate_rag.py
# jar 실행 시
java -jar <jar 파일>
java -jar <jar 파일> --mode=embedding
```

---

## 프로젝트 구조

```
spring-ai-bootcamp-basic/
├── mission/
│ ├── MISSION.md # 미션 설명 (여기서 시작)
│ └── wall-report.md # 벽 리포트 (마지막에 작성)
├── hints/
│ ├── HINT_01.md ~ HINT_06.md # 막혔을 때 열어보세요
├── data/
│ ├── layer1_faq/ # 공식 FAQ 문서
│ ├── layer2_policies/ # 사내 정책 문서
│ ├── layer3_chatlogs/ # 고객 상담 로그
│ └── test_questions.json # 평가용 질문 100개
├── src/
│ └── main/java/com/cholog/bootcamp/
│ └── Application.java # 여기서부터 만드세요
├── SYLLABUS.md # 커리큘럼 소개 ← 과정 전체 그림
├── GUIDE.md # 진행 가이드 ← 미션 중 참고
└── build.gradle
```

---

## 자주 묻는 질문

**Q: API 키 없이 시작할 수 있나요?**

코드 작성과 컴파일은 가능하지만, 실제 실행에는 OpenAI API 키가 필요합니다.

**Q: FAQ 데이터가 영어인데 질문은 한국어로 해도 되나요?**

네. GPT-4.1-nano는 교차 언어 이해가 가능합니다.

**Q: 어떤 도구를 써도 되나요?**

네. 구현 방법에 제약은 없습니다.
2 changes: 1 addition & 1 deletion SYLLABUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Easy는 그럭저럭. Medium부터 급락합니다.
- 챗봇 구현·실행: **$1~5** 안쪽 (GPT-4.1-nano 기준)
- 평가 스크립트까지 돌리면: **+$0.5~1** (judge 모델 `gpt-4o-mini`)

API 키 발급과 환경 설정은 [README.md](README.md#필요한-것)를 참고하세요.
API 키 발급과 환경 설정은 [BASE-README.md](BASE-README.md#필요한-것)를 참고하세요.

---

Expand Down
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ dependencyManagement {

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.ai:spring-ai-starter-model-openai'
implementation 'org.springframework.ai:spring-ai-advisors-vector-store'
implementation 'org.springframework.ai:spring-ai-markdown-document-reader'
implementation 'org.springframework.ai:spring-ai-rag'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Expand Down
2 changes: 1 addition & 1 deletion data/evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def main():
if args.verbose:
print(f"[{qid}] {marker} ({tier}) {question_ko[:40]}...")
if score == 0:
print(f" 이유: {judgment.get('reason', '')[:80]}")
print(f" 이유: {judgment.get('reason', '')[:160]}")

# 진행률 (10개마다)
if not args.verbose and (i + 1) % 10 == 0:
Expand Down
Loading