- lookup_docs 도구로 React, OpenAI 등 공식 문서 실시간 조회 - README에 Context7 연동 기능 문서화 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
339 lines
8.9 KiB
Markdown
339 lines
8.9 KiB
Markdown
# Cloudflare Workers 텔레그램 봇
|
|
|
|
> Cloudflare Workers + D1 + OpenAI를 활용한 사용자 프로필 기반 텔레그램 봇
|
|
|
|
## 목차
|
|
|
|
1. [개요](#개요)
|
|
2. [아키텍처](#아키텍처)
|
|
3. [Function Calling](#function-calling)
|
|
4. [프로젝트 구조](#프로젝트-구조)
|
|
5. [배포 가이드](#배포-가이드)
|
|
6. [보안 설정](#보안-설정)
|
|
7. [봇 명령어](#봇-명령어)
|
|
|
|
---
|
|
|
|
## 개요
|
|
|
|
### 주요 기능
|
|
|
|
- **OpenAI GPT-4o-mini**: 고품질 AI 응답 및 Function Calling 지원
|
|
- **사용자 프로필**: 대화에서 사용자의 관심사, 목표, 맥락을 추출하여 프로필 구축
|
|
- **Function Calling**: 날씨, 검색, 시간, 계산, **문서 조회** 등 AI가 자동으로 도구 호출
|
|
- **Context7 연동**: 프로그래밍 라이브러리 공식 문서 실시간 조회
|
|
- **무한 컨텍스트**: 슬라이딩 윈도우(3개)로 프로필 유지, 무제한 대화 기억
|
|
- **개인화 응답**: 프로필 기반으로 맞춤형 AI 응답 제공
|
|
- **폴백 지원**: OpenAI 미설정 시 Workers AI(Llama)로 자동 전환
|
|
|
|
### 기술 스택
|
|
|
|
| 서비스 | 용도 |
|
|
|--------|------|
|
|
| **Workers** | 서버리스 런타임 |
|
|
| **D1** | SQLite 데이터베이스 |
|
|
| **OpenAI** | GPT-4o-mini + Function Calling |
|
|
| **Context7** | 라이브러리 문서 조회 API |
|
|
| **Workers AI** | 폴백용 (Llama 3.1 8B) |
|
|
|
|
---
|
|
|
|
## 아키텍처
|
|
|
|
### 메시지 처리 흐름
|
|
|
|
```
|
|
[사용자 메시지]
|
|
│
|
|
▼
|
|
┌──────────────────┐
|
|
│ Cloudflare │
|
|
│ Worker │
|
|
└──────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────┐
|
|
│ OpenAI API │ ← GPT-4o-mini
|
|
│ (Function Call) │ 도구 호출 자동 판단
|
|
└──────────────────┘
|
|
│
|
|
┌───┴───┬───────┬───────┬───────┐
|
|
▼ ▼ ▼ ▼ ▼
|
|
[날씨] [검색] [시간] [계산] [문서] → 외부 API
|
|
│ │ │ │ │
|
|
│ │ │ │ └── Context7 API
|
|
└───┬───┴───────┴───────┴───────┘
|
|
▼
|
|
┌──────────────────┐
|
|
│ 최종 응답 생성 │
|
|
└──────────────────┘
|
|
│
|
|
▼
|
|
[D1 저장] → [Telegram 응답]
|
|
```
|
|
|
|
### 사용자 프로필 시스템
|
|
|
|
```
|
|
[사용자 메시지]
|
|
│
|
|
▼
|
|
┌──────────────────┐
|
|
│ message_buffer │ ← 최대 19개 (20개 되면 프로필 업데이트)
|
|
└──────────────────┘
|
|
│ 20개 도달
|
|
▼
|
|
┌──────────────────┐
|
|
│ 프로필 분석 │ ← 사용자 발언만 추출하여 분석
|
|
│ (OpenAI) │ 봇 응답은 무시
|
|
└──────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────┐
|
|
│ summaries │ ← 최근 3개만 유지 (슬라이딩 윈도우)
|
|
│ [v1] [v2] [v3] │
|
|
└──────────────────┘
|
|
```
|
|
|
|
### 프로필 분석 내용
|
|
|
|
| 추출 정보 | 설명 |
|
|
|-----------|------|
|
|
| **관심사** | 사용자가 자주 언급하는 주제 |
|
|
| **목표** | 해결하려는 문제, 달성하려는 것 |
|
|
| **맥락** | 직업, 상황, 배경 정보 |
|
|
| **선호도** | 좋아하는 것, 싫어하는 것 |
|
|
| **질문 패턴** | 무엇에 대해 알고 싶어하는지 |
|
|
|
|
---
|
|
|
|
## Function Calling
|
|
|
|
OpenAI Function Calling을 통해 AI가 자동으로 필요한 도구를 호출합니다.
|
|
|
|
### 지원 기능
|
|
|
|
| 기능 | 예시 질문 | API |
|
|
|------|-----------|-----|
|
|
| **날씨** | "서울 날씨", "도쿄 날씨 알려줘" | wttr.in |
|
|
| **검색** | "파이썬이 뭐야", "클라우드플레어란" | DuckDuckGo |
|
|
| **시간** | "지금 몇 시야", "뉴욕 시간" | 내장 |
|
|
| **계산** | "123 * 456", "100의 20%" | 내장 |
|
|
| **문서** | "React hooks 사용법", "OpenAI API 예제" | Context7 |
|
|
|
|
### 동작 방식
|
|
|
|
```
|
|
사용자: "서울 날씨 어때?"
|
|
│
|
|
▼
|
|
OpenAI: "get_weather 함수를 호출해야겠다"
|
|
│
|
|
▼
|
|
Worker: wttr.in API 호출 → 날씨 데이터 수신
|
|
│
|
|
▼
|
|
OpenAI: 날씨 데이터를 자연어로 응답 생성
|
|
│
|
|
▼
|
|
응답: "🌤 서울 날씨\n온도: 5°C\n습도: 45%..."
|
|
```
|
|
|
|
---
|
|
|
|
## 프로젝트 구조
|
|
|
|
```
|
|
telegram-bot-workers/
|
|
├── src/
|
|
│ ├── index.ts # 메인 Worker
|
|
│ ├── types.ts # 타입 정의
|
|
│ ├── security.ts # Webhook 보안 검증
|
|
│ ├── telegram.ts # Telegram API 유틸
|
|
│ ├── summary-service.ts # 프로필 분석 서비스
|
|
│ ├── openai-service.ts # OpenAI + Function Calling
|
|
│ ├── n8n-service.ts # n8n 연동 (선택)
|
|
│ └── commands.ts # 봇 명령어 핸들러
|
|
├── schema.sql # D1 스키마
|
|
├── wrangler.toml # Wrangler 설정
|
|
├── n8n-workflow-example.json # n8n 워크플로우 예시
|
|
├── package.json
|
|
├── tsconfig.json
|
|
└── README.md
|
|
```
|
|
|
|
---
|
|
|
|
## 배포 가이드
|
|
|
|
### 1. 프로젝트 설정
|
|
|
|
```bash
|
|
cd telegram-bot-workers
|
|
npm install
|
|
```
|
|
|
|
### 2. D1 데이터베이스
|
|
|
|
현재 설정:
|
|
|
|
```toml
|
|
[[d1_databases]]
|
|
binding = "DB"
|
|
database_name = "telegram-conversations"
|
|
database_id = "c285bb5b-888b-405d-b36f-475ae5aed20e"
|
|
```
|
|
|
|
스키마:
|
|
- `users` - 사용자 정보
|
|
- `message_buffer` - 메시지 임시 저장
|
|
- `summaries` - 프로필 저장
|
|
|
|
### 3. Secrets 설정
|
|
|
|
```bash
|
|
# Bot Token (BotFather에서 발급)
|
|
wrangler secret put BOT_TOKEN
|
|
|
|
# Webhook Secret
|
|
wrangler secret put WEBHOOK_SECRET
|
|
|
|
# OpenAI API Key (필수)
|
|
wrangler secret put OPENAI_API_KEY
|
|
```
|
|
|
|
### Vault 연동 (선택)
|
|
|
|
API 키는 HashiCorp Vault에서 중앙 관리됩니다.
|
|
|
|
```bash
|
|
# Vault에서 OpenAI API 키 조회
|
|
vault kv get secret/openai
|
|
|
|
# 저장된 정보
|
|
# - api_key: OpenAI API 키
|
|
# - email: kappa.inouter@gmail.com (계정 관리용)
|
|
|
|
# Vault에서 키 가져와서 Worker에 설정
|
|
OPENAI_KEY=$(vault kv get -field=api_key secret/openai)
|
|
echo $OPENAI_KEY | wrangler secret put OPENAI_API_KEY
|
|
```
|
|
|
|
> **참고**: Vault 서버: `https://vault.anvil.it.com`
|
|
|
|
### 4. 배포
|
|
|
|
```bash
|
|
wrangler deploy
|
|
```
|
|
|
|
### 5. Webhook 설정
|
|
|
|
```bash
|
|
curl https://telegram-summary-bot.kappa-d8e.workers.dev/setup-webhook
|
|
curl https://telegram-summary-bot.kappa-d8e.workers.dev/webhook-info
|
|
```
|
|
|
|
---
|
|
|
|
## 보안 설정
|
|
|
|
### Webhook 보안 검증
|
|
|
|
| 검증 항목 | 설명 |
|
|
|-----------|------|
|
|
| **Secret Token** | `X-Telegram-Bot-Api-Secret-Token` 헤더 검증 |
|
|
| **Timing-safe 비교** | 타이밍 공격 방지 |
|
|
| **Timestamp** | 60초 이내 메시지만 처리 |
|
|
| **Rate Limiting** | 30req/분/사용자 |
|
|
|
|
### API 키 관리
|
|
|
|
| 키 | 저장 위치 | 비고 |
|
|
|----|-----------|------|
|
|
| `BOT_TOKEN` | Wrangler Secret | BotFather 발급 |
|
|
| `WEBHOOK_SECRET` | Wrangler Secret | 자동 생성 |
|
|
| `OPENAI_API_KEY` | Wrangler Secret + Vault | kappa.inouter@gmail.com |
|
|
|
|
**Vault 경로**: `secret/openai` @ `vault.anvil.it.com`
|
|
|
|
---
|
|
|
|
## 봇 명령어
|
|
|
|
| 명령어 | 설명 |
|
|
|--------|------|
|
|
| `/start` | 봇 시작, 기능 소개 |
|
|
| `/help` | 도움말 |
|
|
| `/context` | 현재 컨텍스트 상태 (버퍼 수, 프로필 버전) |
|
|
| `/profile` | 내 프로필 보기 |
|
|
| `/stats` | 대화 통계 |
|
|
| `/reset` | 모든 대화 기록 삭제 |
|
|
|
|
---
|
|
|
|
## 설정값
|
|
|
|
`wrangler.toml`:
|
|
|
|
```toml
|
|
name = "telegram-summary-bot"
|
|
main = "src/index.ts"
|
|
compatibility_date = "2024-01-01"
|
|
|
|
[ai]
|
|
binding = "AI"
|
|
|
|
[vars]
|
|
SUMMARY_THRESHOLD = "20"
|
|
MAX_SUMMARIES_PER_USER = "3"
|
|
N8N_WEBHOOK_URL = "https://n8n.anvil.it.com"
|
|
|
|
[[d1_databases]]
|
|
binding = "DB"
|
|
database_name = "telegram-conversations"
|
|
database_id = "c285bb5b-888b-405d-b36f-475ae5aed20e"
|
|
```
|
|
|
|
---
|
|
|
|
## 비용 예측
|
|
|
|
### 월간 예상 비용
|
|
|
|
| 사용량 | D1 | OpenAI | Workers | 총 |
|
|
|--------|-----|--------|---------|-----|
|
|
| 1만 메시지 | $0 | ~$0.20 | $0 | **~$0.20** |
|
|
| 10만 메시지 | $0 | ~$2.00 | $0 | **~$2.00** |
|
|
| 100만 메시지 | $0 | ~$20.00 | ~$0.30 | **~$20.30** |
|
|
|
|
> GPT-4o-mini: 입력 $0.15/1M, 출력 $0.60/1M 토큰
|
|
|
|
---
|
|
|
|
## API 엔드포인트
|
|
|
|
| 경로 | 메서드 | 설명 |
|
|
|------|--------|------|
|
|
| `/` | GET | 서비스 정보 |
|
|
| `/health` | GET | 헬스 체크 |
|
|
| `/webhook-info` | GET | Webhook 상태 |
|
|
| `/setup-webhook` | GET | Webhook 설정 |
|
|
| `/webhook` | POST | Telegram Webhook |
|
|
|
|
---
|
|
|
|
## 참고
|
|
|
|
- [OpenAI API](https://platform.openai.com/docs)
|
|
- [Cloudflare D1](https://developers.cloudflare.com/d1/)
|
|
- [Cloudflare Workers](https://developers.cloudflare.com/workers/)
|
|
- [Telegram Bot API](https://core.telegram.org/bots/api)
|
|
- [Context7 API](https://context7.com/docs/api-guide)
|
|
|
|
---
|
|
|
|
## 소스 코드
|
|
|
|
**Gitea**: https://gitea.anvil.it.com/kaffa/telegram-bot-workers
|