C.W.K.
Stream
Lesson 04 of 05 · published

Chat 과 에러 핸들링

~14 min · chat, history, errors, retry

Level 0Spark
0 XP0/35 lessons0/10 achievements
0/140 XP to next level140 XP to go0% complete

Chat 은 generate_content 의 얇은 wrapper

client.chats.create() 가 history 유지하는 chat session 반환. 각 send_message 는 user turn append, full history 로 generate_content 호출, 모델 답변 append. 너가 직접 20 줄로 같은 거 짤 수 있어 — wrapper 는 그 20 줄과 "모델 turn append 까먹는" 버그 절약.

Streaming chat 도 있어

chat.send_message_stream(...) 가 streaming variant. generate_content_stream 과 같은 iterator 모양.

디버깅할 때 history 검사

chat.get_history() 가 full conversation 을 list[Content] 로 반환. print, persist, rewind 할 때 유용.

에러는 세 클래스 hierarchy

  • errors.APIError — base class. sub-class 신경 안 쓰면 catch.
  • errors.ClientError — 4xx (400, 401, 403, 404, 429). 너 잘못: bad request, bad auth, rate limit.
  • errors.ServerError — 5xx (500, 503). 그쪽 잘못: backoff 으로 retry.

HTTP status 는 e.code; 사람 읽을 메시지는 e.message.

Code

Multi-turn chat·python
chat = client.chats.create(
    model='gemini-2.5-flash',
    config=types.GenerateContentConfig(
        system_instruction='You are a precise but warm tutor.',
    ),
)

r1 = chat.send_message('Tell me a fact about octopuses.')
print('AI:', r1.text)

r2 = chat.send_message('Now relate that fact to neural networks.')
print('AI:', r2.text)

# History 검사
for msg in chat.get_history():
    role = msg.role
    text = msg.parts[0].text if msg.parts and hasattr(msg.parts[0], 'text') else '<non-text>'
    print(f'{role}: {text[:80]}...')
Streaming chat·python
chat = client.chats.create(model='gemini-2.5-flash')

for chunk in chat.send_message_stream('Write me a haiku about debugging.'):
    if chunk.text:
        print(chunk.text, end='', flush=True)
print()
내성 있는 에러 핸들링·python
import time
from google.genai import errors

def robust_generate(client, model, contents, max_retries=4):
    for attempt in range(max_retries):
        try:
            return client.models.generate_content(
                model=model, contents=contents)
        except errors.ClientError as e:
            if e.code == 429:
                # Rate limit — exponential backoff
                sleep = min(2 ** attempt, 30)
                print(f'429 — sleeping {sleep}s')
                time.sleep(sleep)
                continue
            # 400/401/403/404 는 transient 아님 — re-raise
            raise
        except errors.ServerError as e:
            # 5xx — backoff 으로 retry
            time.sleep(min(2 ** attempt, 30))
            continue
    raise RuntimeError(f'Gave up after {max_retries} retries')

External links

Exercise

Chat-loop CLI 만들어: stdin 에서 라인 읽고 chat.send_message_stream 으로 보냄, 응답 stdout 에 stream, 매 turn 후 full history 를 chat.jsonl 에 persist. 모든 API 호출을 위 robust_generate 패턴으로 wrap 해서 429 가 session 죽이지 않게. JSONL 에서 startup 시 reload 해서 conversation 이 restart 가로질러 유지되는지 확인.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.