LLMLLM API 개발 · 1기초

OpenAI API 기초 — 코드로 LLM 호출하기

LLMOpenAIAPIPythonChatGPT개발

프롬프트 창을 벗어나 코드로

지금까지는 ChatGPT 웹 인터페이스에 직접 입력했습니다. 이제 코드로 LLM을 제어합니다.

API를 통해 LLM을 사용하면:

  • 자동화된 파이프라인 구축
  • 자체 서비스에 AI 기능 탑재
  • 대량 데이터 처리
  • 다른 시스템과 통합

이 모든 것이 가능해집니다.


API 호출 흐름

flowchart LR
    CODE["내 Python 코드"] -->|"HTTP 요청\n(메시지 + 설정)"| API["OpenAI API 서버"]
    API -->|"JSON 응답\n(생성된 텍스트)"| CODE
    
    subgraph REQUEST["요청 내용"]
        R1["모델 선택\ngpt-4o-mini"]
        R2["메시지 배열\n[system, user, assistant]"]
        R3["파라미터\ntemperature, max_tokens"]
    end

환경 설정

# 패키지 설치
pip install openai python-dotenv

# .env 파일 생성
OPENAI_API_KEY=sk-proj-...

API 키는 절대 코드에 직접 쓰지 마세요. .env 파일에 저장하고 .gitignore에 추가합니다.

# config.py
from dotenv import load_dotenv
import os

load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")

첫 번째 API 호출

from openai import OpenAI

client = OpenAI()  # 환경변수에서 API 키 자동 로드

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": "당신은 친절한 한국어 어시스턴트입니다."},
        {"role": "user", "content": "파이썬이란 무엇인가요? 한 문장으로 설명해줘."}
    ]
)

print(response.choices[0].message.content)
# 출력: 파이썬은 문법이 간결하고 읽기 쉬운 범용 프로그래밍 언어로,
#       데이터 분석, 웹 개발, AI 등 다양한 분야에서 활용됩니다.

메시지 구조 이해하기

flowchart TB
    subgraph MESSAGES["messages 배열"]
        direction TB
        SYS["system\n'어시스턴트의 역할과 규칙 정의'"]
        USR1["user\n'사용자의 첫 번째 질문'"]
        AST1["assistant\n'AI의 첫 번째 답변'"]
        USR2["user\n'사용자의 두 번째 질문'"]
        AST2["assistant\n'AI의 두 번째 답변 (현재 생성 중)'"]
    end

    SYS --> USR1 --> AST1 --> USR2 --> AST2

대화 기록을 배열로 유지하면 멀티턴 대화가 가능합니다.

# 멀티턴 대화 예시
messages = [
    {"role": "system", "content": "당신은 파이썬 튜터입니다."}
]

while True:
    user_input = input("질문: ")
    if user_input == "exit":
        break
    
    messages.append({"role": "user", "content": user_input})
    
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=messages
    )
    
    assistant_message = response.choices[0].message.content
    messages.append({"role": "assistant", "content": assistant_message})
    
    print(f"답변: {assistant_message}\n")

핵심 파라미터

flowchart LR
    subgraph PARAMS["주요 파라미터"]
        direction TB
        P1["model\n사용할 모델 선택"]
        P2["temperature\n0~2, 창의성 조절\n0=일관, 1=균형, 2=창의"]
        P3["max_tokens\n최대 출력 토큰 수"]
        P4["top_p\n확률 누적 샘플링"]
    end
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=messages,
    temperature=0.7,     # 창의성 (0: 결정적, 1: 균형, 2: 매우 창의적)
    max_tokens=500,      # 응답 최대 길이
    top_p=0.9,           # 확률 상위 90% 토큰만 사용
)

temperature 선택 가이드

작업 유형권장 temperature
코드 생성, SQL 쿼리0~0.2
데이터 추출, 분류0~0.3
일반 질의응답0.5~0.7
창의적 글쓰기0.8~1.2
브레인스토밍1.0~1.5

응답 구조 파싱

response = client.chat.completions.create(...)

# 응답 텍스트
text = response.choices[0].message.content

# 사용된 토큰 (비용 추적)
input_tokens = response.usage.prompt_tokens
output_tokens = response.usage.completion_tokens
total_tokens = response.usage.total_tokens

# 모델 정보
model_used = response.model

print(f"응답: {text}")
print(f"토큰: 입력 {input_tokens} + 출력 {output_tokens} = {total_tokens}")

비용 계산

# gpt-4o-mini 기준 (2024년, USD)
INPUT_PRICE = 0.15 / 1_000_000   # $0.15 per 1M tokens
OUTPUT_PRICE = 0.60 / 1_000_000  # $0.60 per 1M tokens

def calculate_cost(usage):
    cost = (
        usage.prompt_tokens * INPUT_PRICE +
        usage.completion_tokens * OUTPUT_PRICE
    )
    return cost

cost = calculate_cost(response.usage)
print(f"이번 호출 비용: ${cost:.6f}")

에러 처리

from openai import OpenAI, RateLimitError, APIError
import time

client = OpenAI()

def call_with_retry(messages, max_retries=3):
    for attempt in range(max_retries):
        try:
            response = client.chat.completions.create(
                model="gpt-4o-mini",
                messages=messages
            )
            return response.choices[0].message.content
            
        except RateLimitError:
            wait_time = 2 ** attempt  # 지수 백오프
            print(f"요청 한도 초과. {wait_time}초 후 재시도...")
            time.sleep(wait_time)
            
        except APIError as e:
            print(f"API 오류: {e}")
            raise
    
    raise Exception("최대 재시도 횟수 초과")

실전 예시: 텍스트 분류기

def classify_sentiment(text: str) -> dict:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        temperature=0,  # 분류는 일관성이 중요
        messages=[
            {
                "role": "system",
                "content": """텍스트의 감정을 분석하고 JSON으로만 응답하세요.
형식: {"sentiment": "positive|negative|neutral", "confidence": 0.0~1.0}"""
            },
            {"role": "user", "content": f"텍스트: {text}"}
        ]
    )
    
    import json
    return json.loads(response.choices[0].message.content)

# 테스트
result = classify_sentiment("이 제품 정말 마음에 들어요! 다음에 또 살게요.")
print(result)  # {'sentiment': 'positive', 'confidence': 0.97}

주요 모델 비교

모델특징추천 용도
gpt-4o최고 성능복잡한 추론, 코딩
gpt-4o-mini빠르고 저렴대부분의 작업
o1-mini수학·논리복잡한 수학, 알고리즘

정리

개념내용
OpenAI 클라이언트OpenAI() 인스턴스로 API 호출
messages 배열system/user/assistant 역할로 대화 구성
temperature응답 무작위성 조절 (0~2)
usage입력/출력 토큰 수 및 비용 추적
에러 처리RateLimitError 지수 백오프 재시도

다음 편에서는 스트리밍과 비동기 — 실시간으로 응답을 받아 UX를 개선하는 방법을 배웁니다.

궁금한 점이 있으신가요?

협업·의뢰는 아래로, 가벼운 소통은 인스타그램 @bluefox._.hi도 환영이에요.