개요

이 가이드에서는 Clova Studio Gov API를 사용하여 완전한 대화형 챗봇 애플리케이션을 만드는 방법을 다룹니다.

기본 Chat 구현

Python 예제

import requests
import json

class ClovaChat:
    def __init__(self, api_key):
        self.api_key = api_key
        self.base_url = "https://api.clovastudio.go.kr/v1"
        self.messages = []
    
    def chat(self, user_message):
        # 메시지 히스토리에 추가
        self.messages.append({
            "role": "user",
            "content": user_message
        })
        
        # API 호출
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        data = {
            "model": "clova-x",
            "messages": self.messages,
            "temperature": 0.7,
            "max_tokens": 1000
        }
        
        response = requests.post(
            f"{self.base_url}/chat/completions",
            headers=headers,
            json=data
        )
        
        if response.status_code == 200:
            result = response.json()
            assistant_message = result['choices'][0]['message']['content']
            
            # 어시스턴트 응답을 히스토리에 추가
            self.messages.append({
                "role": "assistant",
                "content": assistant_message
            })
            
            return assistant_message
        else:
            raise Exception(f"API Error: {response.status_code} - {response.text}")
    
    def reset(self):
        """대화 히스토리 초기화"""
        self.messages = []

# 사용 예제
if __name__ == "__main__":
    chat = ClovaChat("YOUR_API_KEY")
    
    # 첫 번째 메시지
    response = chat.chat("안녕하세요! Python에 대해 알려주세요.")
    print(f"AI: {response}")
    
    # 후속 질문 (컨텍스트 유지)
    response = chat.chat("Python의 주요 특징은 무엇인가요?")
    print(f"AI: {response}")

Node.js/TypeScript 예제

import fetch from 'node-fetch';

interface Message {
  role: 'system' | 'user' | 'assistant';
  content: string;
}

class ClovaChat {
  private apiKey: string;
  private baseUrl: string = 'https://api.clovastudio.go.kr/v1';
  private messages: Message[] = [];

  constructor(apiKey: string) {
    this.apiKey = apiKey;
  }

  async chat(userMessage: string): Promise<string> {
    // 메시지 히스토리에 추가
    this.messages.push({
      role: 'user',
      content: userMessage
    });

    const headers = {
      'Authorization': `Bearer ${this.apiKey}`,
      'Content-Type': 'application/json'
    };

    const data = {
      model: 'clova-x',
      messages: this.messages,
      temperature: 0.7,
      max_tokens: 1000
    };

    const response = await fetch(`${this.baseUrl}/chat/completions`, {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(data)
    });

    if (response.ok) {
      const result = await response.json();
      const assistantMessage = result.choices[0].message.content;

      // 어시스턴트 응답을 히스토리에 추가
      this.messages.push({
        role: 'assistant',
        content: assistantMessage
      });

      return assistantMessage;
    } else {
      throw new Error(`API Error: ${response.status} - ${await response.text()}`);
    }
  }

  reset(): void {
    this.messages = [];
  }
}

// 사용 예제
async function main() {
  const chat = new ClovaChat('YOUR_API_KEY');
  
  const response1 = await chat.chat('안녕하세요! TypeScript에 대해 알려주세요.');
  console.log(`AI: ${response1}`);
  
  const response2 = await chat.chat('TypeScript의 주요 특징은 무엇인가요?');
  console.log(`AI: ${response2}`);
}

main();

스트리밍 응답 구현

실시간으로 응답을 받아 사용자 경험을 개선할 수 있습니다.

Python 스트리밍 예제

import requests
import json

def chat_stream(api_key, messages):
    """스트리밍 방식으로 채팅 응답 받기"""
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    
    data = {
        "model": "clova-x",
        "messages": messages,
        "stream": True
    }
    
    response = requests.post(
        "https://api.clovastudio.go.kr/v1/chat/completions",
        headers=headers,
        json=data,
        stream=True
    )
    
    full_response = ""
    
    for line in response.iter_lines():
        if line:
            line = line.decode('utf-8')
            if line.startswith('data: '):
                data_str = line[6:]  # 'data: ' 제거
                if data_str == '[DONE]':
                    break
                try:
                    data = json.loads(data_str)
                    if 'choices' in data and len(data['choices']) > 0:
                        delta = data['choices'][0].get('delta', {})
                        content = delta.get('content', '')
                        if content:
                            print(content, end='', flush=True)
                            full_response += content
                except json.JSONDecodeError:
                    continue
    
    print()  # 새 줄
    return full_response

# 사용 예제
messages = [{"role": "user", "content": "Python의 역사에 대해 설명해주세요."}]
response = chat_stream("YOUR_API_KEY", messages)

시스템 프롬프트 활용

시스템 프롬프트를 사용하여 챗봇의 페르소나와 행동을 정의할 수 있습니다.
class CustomBot:
    def __init__(self, api_key, system_prompt):
        self.api_key = api_key
        self.base_url = "https://api.clovastudio.go.kr/v1"
        self.messages = [
            {"role": "system", "content": system_prompt}
        ]
    
    def chat(self, user_message):
        self.messages.append({"role": "user", "content": user_message})
        
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        response = requests.post(
            f"{self.base_url}/chat/completions",
            headers=headers,
            json={
                "model": "clova-x",
                "messages": self.messages,
                "temperature": 0.7
            }
        )
        
        assistant_message = response.json()['choices'][0]['message']['content']
        self.messages.append({"role": "assistant", "content": assistant_message})
        
        return assistant_message

# 전문가 봇 예제
expert_bot = CustomBot(
    "YOUR_API_KEY",
    "당신은 Python 프로그래밍 전문가입니다. 사용자의 질문에 명확하고 자세하게 답변하며, 코드 예제를 포함하여 설명합니다."
)

response = expert_bot.chat("함수 데코레이터에 대해 설명해주세요.")
print(response)

에러 처리 및 재시도 로직

import time
from typing import Optional

class RobustClovaChat:
    def __init__(self, api_key, max_retries=3):
        self.api_key = api_key
        self.base_url = "https://api.clovastudio.go.kr/v1"
        self.max_retries = max_retries
        self.messages = []
    
    def chat(self, user_message: str) -> Optional[str]:
        self.messages.append({"role": "user", "content": user_message})
        
        for attempt in range(self.max_retries):
            try:
                response = self._make_request()
                
                if response.status_code == 200:
                    assistant_message = response.json()['choices'][0]['message']['content']
                    self.messages.append({"role": "assistant", "content": assistant_message})
                    return assistant_message
                elif response.status_code == 429:  # Rate limit
                    wait_time = 2 ** attempt  # 지수 백오프
                    print(f"Rate limit reached. Waiting {wait_time} seconds...")
                    time.sleep(wait_time)
                else:
                    print(f"Error {response.status_code}: {response.text}")
                    if attempt == self.max_retries - 1:
                        raise Exception(f"Failed after {self.max_retries} attempts")
            except requests.exceptions.RequestException as e:
                print(f"Request failed: {e}")
                if attempt == self.max_retries - 1:
                    raise
                time.sleep(2 ** attempt)
        
        return None
    
    def _make_request(self):
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        return requests.post(
            f"{self.base_url}/chat/completions",
            headers=headers,
            json={
                "model": "clova-x",
                "messages": self.messages
            },
            timeout=30
        )

다음 단계

실제 프로덕션 환경에서는 API 키를 환경 변수로 관리하고, 적절한 로깅과 모니터링을 추가하는 것이 좋습니다.