개발자가 될래요
[플레이데이터 SK네트웍스 Family AI 캠프 23기] 10주차 회고 본문
회고 방식
The four Fs
- FACTS(사실, 객관) : 이번 일주일 동안 있었던 일, 내가 한 일
- FEELINGS(느낌, 주관) : 나의 감정적인 반응, 느낌
- FINDINGS(배운 것) : 그 상황으로부터 내가 배운 것, 얻은 것
- FUTURE(미래) : 배운 것을 미래에는 어떻게 적용할 지
FACTS
이번 주는 LLM에 대해 배우며, LLM을 이해하고, OpenAI의 API를 이용해 어떻게 프롬프트를 작성해보고 그 구성에 대해 공부했다.
LLM 개념 정리
- LLM이 “다음 토큰을 확률적으로 예측”하는 모델이라는 점, 그리고 거대한 파라미터가 지식을 ‘압축’한 형태라는 점을 정리했다.
- In-context learning(프롬프트 안의 예시로 즉석에서 문제를 푸는 방식)과 창발 능력 같은 키워드를 정리했다.
프롬프트 엔지니어링
- temperature, top_p, max_completion_tokens 같은 하이퍼파라미터가 출력에 어떤 영향을 주는지 실습으로 확인했다.
- 프롬프트를 “역할/규칙/출력 포맷(특히 JSON)” 중심으로 설계하는 연습을 했다.
Chat Completion 코드 작성
- .env로 키 관리하고, OpenAI() 클라이언트로 호출하는 기본 뼈대를 만들었다.
- system / user / assistant 역할을 섞어서 대화 히스토리를 유지하는 방식으로 챗봇 형태를 만들어봤다.
- 토큰 카운팅(tiktoken)으로 “같은 문장도 모델별로 토큰 수가 달라질 수 있다”는 점을 확인했다.
- 스트리밍 응답을 받아서 실시간으로 출력되는 콘솔 챗봇 형태도 실습했다.
FEELINGS
이번 주는 특별한 이론이나 개념에 집중하기보다는 “써먹는 방법”는 방법을 배우면서 재밋게 공부했던 것 같다.
특히 OpenAI의 API를 사용하거나, 프롬프트 엔지니어링을 하는 것은, 예전에 팀 프로젝트를 하면서 겉핥기 식으로 해보았던 것들이기에, 큰 거부감이나 어려움 없이 학습할 수 있었던 것 같다.
오랜만에 OpenAI API를 사용하면서 프롬프트 엔지니어링을 한 느낌은 이렇다.
- 프롬프트는 조금만 애매해도 출력이 흔들린다. “내가 원하는 출력”을 얻기 위해 지시문을 다듬는 과정이 역시나 중요하다.
- 특히 JSON 출력 강제는, 모델이 한 번만 삐끗해도 파싱이 깨져버리니 “안정성”에 대한 압박이 있었다.
- 그래도 TTS/STT까지 연결되니까, 이전의 텍스트로만 이루어진 챗봇 뿐만 아니라, 음성 인식을 넣은 챗봇을 구현하는 것도 생각해 볼 수 있겠다.
FINDINGS
1) “LLM을 잘 쓴다”는 건, 결국 입력과 출력을 설계하는 일
LLM 자체를 다 외우는 것보다, 프롬프트로 역할을 고정하고 출력 포맷을 통제하는 게 더 중요하다.
특히 JSON 형태로 결과를 받으면, 그 다음 파이프라인(저장/분석/화면 렌더링)이 쉬워진다.
예를 들어 함수 시그니처도 이렇게 잡아두면, 호출 실수를 줄일 수 있었다(위치 인자 강제 + 키워드 인자 강제).
def correct_headline_json(headline, /, *, model='gpt-4.1-mini', temperature=1, top_p=1, max_completion_tokens=2048):
...
2) 하이퍼파라미터
- temperature를 낮추면 출력이 안정적이고 반복 가능해지지만, 너무 낮추면 표현이 딱딱해진다.
- top_p도 비슷하게 “후보 폭”을 조절하는 느낌.
- 그래서 작업 성격에 맞게 “창의성 vs 안정성”을 선택해야 한다는 기준이 중요.
3) Chat Completions에서 중요한 건 ‘대화 로그’
대화형 서비스는 한 번의 질문/답변이 아니라, 이전 맥락(messages 배열) 을 어떻게 유지하느냐가 핵심.
response = client.chat.completions.create(
model="gpt-4.1-mini",
messages=[
{"role": "system", "content": "너는 친절한 챗봇입니다."},
{"role": "user", "content": "안녕"},
# 이전 대화가 있으면 assistant/user를 계속 쌓아감
],
max_completion_tokens=2048
)
그리고 OpenAI API에 충전되어 있는 요금을 매번 확인해보고, 토큰 카운팅을 해보니, 운영 관점에서 “대화가 길어질수록 비용/지연이 커질 수 있다”는 점이 확실히 느껴졌다.
4) TTS/STT
음성을 만드는 것은 별개로 더 어려울 줄 알았는데, 해보니까 결국 모델의 차이만 존재하고, 큰 어려움은 없을 것이라고 '아직은' 생각된다.
# TTS: text -> mp3
with client.audio.speech.with_streaming_response.create(
model="gpt-4o-mini-tts",
voice="nova",
input="오늘은 날씨가 꽤 춥습니다. 감기 조심하세요!"
) as resp:
resp.stream_to_file("output.mp3")
# STT: mp3 -> text
with open("output.mp3", "rb") as f:
transcription = client.audio.transcriptions.create(
model="whisper-1",
file=f,
)
print(transcription.text)
FUTURE
대화 로그 저장(DB) + 스트리밍 출력 + (가능하면) TTS/STT까지 붙여서, 이후 팀 프로젝트을 고려한 작은 토이 프로젝트를 해보고 싶긴하다. 아직 LLM에 대해 배울 기간이 많이 남기도 했고, 이후에 RAG도 배우겠지만, 지금 이 재밌는 느낌을 끝까지 가져가고 싶다.
'SKN_Family_AI' 카테고리의 다른 글
| [플레이데이터 SK네트웍스 Family AI 캠프 23기] 12주차 회고 (0) | 2026.02.18 |
|---|---|
| [플레이데이터 SK네트웍스 Family AI 캠프 23기] 11주차 회고 (0) | 2026.02.08 |
| [플레이데이터 SK네트웍스 Family AI 캠프 23기] 9주차 회고 (0) | 2026.01.25 |
| [플레이데이터 SK네트웍스 Family AI 캠프 23기] 8주차 회고 (0) | 2026.01.19 |
| [플레이데이터 SK네트웍스 Family AI 캠프 23기] 7주차 회고 (0) | 2026.01.16 |