⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

텍스트 생성과 번역 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 11. 27. · 2 Views

텍스트 생성과 번역 완벽 가이드

Hugging Face Transformers를 활용하여 텍스트 생성과 다국어 번역을 구현하는 방법을 알아봅니다. 파이프라인부터 스트리밍, 프롬프트 엔지니어링까지 실무에서 바로 활용할 수 있는 기법을 다룹니다.


목차

  1. 텍스트_생성_파이프라인
  2. 생성_파라미터_조절
  3. 다국어_번역_구현
  4. 한국어_번역_모델
  5. 스트리밍_생성
  6. 프롬프트_엔지니어링
  7. 2개를 먹으면"""

1. 텍스트 생성 파이프라인

김개발 씨는 회사에서 챗봇 프로젝트를 맡게 되었습니다. "GPT처럼 텍스트를 자동으로 생성하는 기능을 만들어주세요"라는 요청을 받았지만, 어디서부터 시작해야 할지 막막했습니다.

그때 선배 박시니어 씨가 다가와 말했습니다. "Hugging Face의 파이프라인을 써보세요.

놀랄 만큼 간단해요."

텍스트 생성 파이프라인은 복잡한 AI 모델을 단 몇 줄의 코드로 사용할 수 있게 해주는 고수준 API입니다. 마치 자판기에 동전을 넣고 버튼만 누르면 음료가 나오듯이, 파이프라인에 텍스트를 넣으면 AI가 생성한 결과물이 바로 나옵니다.

이를 통해 복잡한 모델 로딩, 토큰화, 추론 과정을 신경 쓰지 않아도 됩니다.

다음 코드를 살펴봅시다.

from transformers import pipeline

# 텍스트 생성 파이프라인 초기화
generator = pipeline("text-generation", model="gpt2")

# 시작 문장을 입력하면 AI가 이어서 작성합니다
prompt = "인공지능의 미래는"
result = generator(prompt, max_length=50, num_return_sequences=1)

# 생성된 텍스트 출력
print(result[0]["generated_text"])

# 여러 개의 결과를 동시에 생성할 수도 있습니다
results = generator(prompt, max_length=50, num_return_sequences=3)
for i, res in enumerate(results):
    print(f"결과 {i+1}: {res['generated_text']}")

김개발 씨는 입사 6개월 차 주니어 개발자입니다. 이번에 처음으로 AI 관련 프로젝트를 맡게 되었습니다.

처음에는 텐서플로우니 파이토치니 하는 말들이 외계어처럼 들렸습니다. 모델을 불러오고, 토큰화를 하고, GPU에 올리고...

해야 할 일이 산더미 같았습니다. 그런데 박시니어 씨가 보여준 코드는 고작 세 줄이었습니다.

"이게 끝이에요?" 김개발 씨는 눈을 의심했습니다. 그렇다면 파이프라인이란 정확히 무엇일까요?

쉽게 비유하자면, 파이프라인은 마치 자동차의 자동 변속기와 같습니다. 수동 변속기를 사용하면 클러치를 밟고, 기어를 바꾸고, 액셀을 조절하는 복잡한 과정을 거쳐야 합니다.

하지만 자동 변속기는 그냥 액셀만 밟으면 됩니다. 파이프라인도 마찬가지입니다.

복잡한 내부 과정은 모두 숨기고, 개발자에게는 간단한 인터페이스만 제공합니다. 파이프라인이 없던 시절에는 어땠을까요?

개발자들은 모델을 직접 로드하고, 토크나이저를 초기화하고, 입력 텍스트를 토큰으로 변환해야 했습니다. 그리고 모델에 입력을 넣고, 출력된 토큰 ID를 다시 텍스트로 변환하는 과정을 일일이 작성해야 했습니다.

코드가 수십 줄로 늘어나고, 실수하기도 쉬웠습니다. 바로 이런 문제를 해결하기 위해 Hugging Face에서 파이프라인을 만들었습니다.

pipeline 함수에 태스크 이름과 모델을 지정하면, 나머지는 알아서 처리됩니다. 텍스트 생성뿐 아니라 감정 분석, 요약, 번역 등 다양한 태스크를 지원합니다.

모델 이름만 바꾸면 GPT-2에서 LLaMA로, 또는 다른 모델로 쉽게 교체할 수 있습니다. 위의 코드를 한 줄씩 살펴보겠습니다.

먼저 pipeline 함수를 호출할 때 첫 번째 인자로 "text-generation"을 전달합니다. 이것이 바로 우리가 하고 싶은 태스크입니다.

두 번째 인자 model에는 사용할 모델 이름을 지정합니다. 여기서는 "gpt2"를 사용했습니다.

다음으로 생성기를 호출할 때 max_lengthnum_return_sequences 파라미터를 전달합니다. max_length는 생성할 텍스트의 최대 길이이고, num_return_sequences는 몇 개의 결과를 받을지 지정합니다.

실제 현업에서는 어떻게 활용할까요? 예를 들어 고객 문의에 자동으로 답변하는 챗봇을 만든다고 가정해봅시다.

고객이 "반품 절차가 어떻게 되나요?"라고 물으면, 파이프라인이 적절한 답변을 생성합니다. 또한 마케팅 문구 생성, 이메일 자동 작성, 코드 자동 완성 등 다양한 분야에서 활용됩니다.

하지만 주의할 점도 있습니다. 파이프라인은 편리하지만, 세밀한 제어가 필요할 때는 한계가 있습니다.

대용량 처리나 특수한 요구사항이 있다면 직접 모델과 토크나이저를 다루는 방법도 알아두어야 합니다. 또한 처음 실행할 때 모델을 다운로드하므로 시간이 걸릴 수 있습니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 "이렇게 간단할 수가!"라며 감탄했습니다.

파이프라인을 활용하면 AI 전문가가 아니더라도 텍스트 생성 기능을 쉽게 구현할 수 있습니다. 여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.

실전 팁

💡 - 처음에는 작은 모델(gpt2)로 시작하고, 품질이 필요하면 큰 모델로 업그레이드하세요

  • device 파라미터로 GPU 사용 여부를 지정할 수 있습니다: pipeline(..., device=0)
  • 모델 캐싱 경로는 환경 변수 TRANSFORMERS_CACHE로 변경 가능합니다

2. 생성 파라미터 조절

김개발 씨가 텍스트 생성 기능을 구현했지만, 결과물이 영 마음에 들지 않았습니다. 어떤 때는 같은 말만 반복하고, 어떤 때는 엉뚱한 이야기로 빠졌습니다.

"왜 이렇게 결과가 들쭉날쭉하죠?" 박시니어 씨가 웃으며 대답했습니다. "생성 파라미터를 조절해봐요.

요리할 때 양념을 조절하는 것처럼요."

생성 파라미터는 AI가 텍스트를 만들어내는 방식을 세밀하게 제어하는 설정값들입니다. 마치 오디오 믹서의 슬라이더처럼, 각 파라미터를 조절하면 출력의 성격이 달라집니다.

temperature는 창의성을, top_p와 top_k는 선택지의 범위를, do_sample은 무작위성 여부를 결정합니다.

다음 코드를 살펴봅시다.

from transformers import pipeline

generator = pipeline("text-generation", model="gpt2")

# temperature: 낮으면 보수적, 높으면 창의적 (0.1 ~ 2.0)
conservative = generator("AI란", max_length=30, temperature=0.3)
creative = generator("AI란", max_length=30, temperature=1.2)

# top_k: 상위 k개의 토큰만 고려합니다
result_topk = generator("오늘 날씨는", max_length=30, top_k=50)

# top_p: 누적 확률이 p가 될 때까지의 토큰만 고려합니다
result_topp = generator("오늘 날씨는", max_length=30, top_p=0.9)

# 반복 방지: repetition_penalty로 같은 단어 반복을 줄입니다
no_repeat = generator("한국의 역사는", max_length=50,
                      repetition_penalty=1.5, no_repeat_ngram_size=2)

김개발 씨는 챗봇의 응답 품질을 높이기 위해 고민하고 있었습니다. 분명 같은 프롬프트를 넣었는데, 어제는 괜찮은 답변이 나오고 오늘은 횡설수설하는 답변이 나왔습니다.

도대체 AI는 어떤 기준으로 다음 단어를 선택하는 걸까요? 박시니어 씨가 화이트보드에 그림을 그리며 설명하기 시작했습니다.

그렇다면 생성 파라미터란 정확히 무엇일까요? 쉽게 비유하자면, AI 모델은 마치 선택 장애가 있는 작가와 같습니다.

매 순간 다음에 올 단어를 선택해야 하는데, 후보가 수만 개나 됩니다. 이때 생성 파라미터는 작가에게 "이 정도 범위에서 골라"라고 가이드라인을 주는 역할을 합니다.

가장 중요한 파라미터는 temperature입니다. temperature가 낮으면(0.1~0.5) AI는 가장 확률이 높은 단어만 선택합니다.

결과가 일관되고 예측 가능하지만, 때로는 지루할 수 있습니다. 반대로 temperature가 높으면(1.0~2.0) 낮은 확률의 단어도 선택할 수 있어 창의적이고 다양한 결과가 나오지만, 때로는 엉뚱해질 수 있습니다.

다음으로 알아야 할 것은 top_ktop_p입니다. top_k는 "상위 k개의 후보만 고려해"라고 말하는 것과 같습니다.

top_k=50이면 가장 확률이 높은 50개의 단어 중에서만 선택합니다. top_p는 조금 다릅니다.

누적 확률이 p에 도달할 때까지의 단어만 고려합니다. top_p=0.9면 확률을 높은 순서대로 더해서 90%가 될 때까지의 단어만 후보가 됩니다.

반복 문제는 어떻게 해결할까요? AI가 "맛있는 맛있는 맛있는..."처럼 같은 말을 반복하는 경우가 있습니다.

이때 repetition_penalty를 사용하면 이미 나온 단어가 다시 선택될 확률을 낮춥니다. no_repeat_ngram_size는 지정한 길이의 연속된 단어가 반복되지 않도록 합니다.

위의 코드에서 각 파라미터의 효과를 확인해보겠습니다. temperature=0.3으로 설정하면 "AI란 인공지능의 약자로 기계가 인간의 지능을 모방하는 기술입니다"처럼 교과서적인 답변이 나올 가능성이 높습니다.

temperature=1.2로 설정하면 "AI란 우리의 상상을 초월하는 무한한 가능성의 세계입니다"처럼 좀 더 시적인 표현이 나올 수 있습니다. 실제 현업에서는 상황에 따라 다른 설정을 사용합니다.

고객 지원 챗봇이라면 temperature를 낮게 설정하여 일관된 정확한 답변을 제공합니다. 창작 글쓰기 도우미라면 temperature를 높여 다양한 아이디어를 제안합니다.

많은 서비스에서는 사용자가 "창의성 수준"을 조절할 수 있는 슬라이더를 제공하기도 합니다. 하지만 주의할 점도 있습니다.

파라미터를 극단적으로 설정하면 문제가 생깁니다. temperature가 너무 높으면 의미 없는 문장이 나오고, 너무 낮으면 모든 질문에 같은 대답만 합니다.

처음에는 기본값(temperature=1.0, top_p=0.9)으로 시작해서 조금씩 조절해가는 것이 좋습니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

파라미터를 이해한 김개발 씨는 상황에 맞게 설정을 조절하기 시작했습니다. FAQ 답변에는 낮은 temperature를, 마케팅 문구 생성에는 높은 temperature를 적용했습니다.

생성 파라미터를 적절히 조절하면 같은 모델로도 완전히 다른 성격의 결과물을 얻을 수 있습니다. 여러 조합을 실험해보며 최적의 설정을 찾아보세요.

실전 팁

💡 - 팩트 기반 응답에는 temperature=0.30.5, 창작에는 0.81.2를 추천합니다

  • top_p와 top_k를 동시에 사용하면 더 세밀한 제어가 가능합니다
  • do_sample=False로 설정하면 항상 가장 확률 높은 토큰만 선택합니다(결정적 출력)

3. 다국어 번역 구현

회사에서 글로벌 서비스를 준비하면서 김개발 씨에게 새로운 미션이 떨어졌습니다. "영어 콘텐츠를 각 나라 언어로 자동 번역하는 기능을 만들어주세요." 구글 번역 API를 쓰려니 비용이 걱정되고, 직접 모델을 돌리자니 어려워 보였습니다.

그때 박시니어 씨가 말했습니다. "오픈소스 번역 모델이 있어요.

품질도 꽤 괜찮습니다."

다국어 번역은 한 언어로 된 텍스트를 다른 언어로 변환하는 기술입니다. Hugging Face에서는 Helsinki-NLP의 OPUS-MT 모델이나 Facebook의 M2M100, NLLB 같은 다국어 번역 모델을 제공합니다.

마치 여러 나라 말을 할 줄 아는 통역사처럼, 이 모델들은 수십에서 수백 개의 언어 쌍을 지원합니다.

다음 코드를 살펴봅시다.

from transformers import pipeline, AutoModelForSeq2SeqLM, AutoTokenizer

# 영어 -> 독일어 번역 (Helsinki-NLP 모델)
en_de_translator = pipeline("translation", model="Helsinki-NLP/opus-mt-en-de")
result = en_de_translator("Hello, how are you today?")
print(result[0]["translation_text"])  # Hallo, wie geht es Ihnen heute?

# 다국어 번역 모델 (M2M100 - 100개 언어 지원)
from transformers import M2M100ForConditionalGeneration, M2M100Tokenizer

model = M2M100ForConditionalGeneration.from_pretrained("facebook/m2m100_418M")
tokenizer = M2M100Tokenizer.from_pretrained("facebook/m2m100_418M")

# 영어를 프랑스어로 번역
tokenizer.src_lang = "en"
text = "Machine learning is fascinating."
encoded = tokenizer(text, return_tensors="pt")
generated = model.generate(**encoded, forced_bos_token_id=tokenizer.get_lang_id("fr"))
print(tokenizer.decode(generated[0], skip_special_tokens=True))

김개발 씨는 번역 기능을 조사하면서 다양한 선택지가 있다는 것을 알게 되었습니다. 유료 API도 있고, 오픈소스 모델도 있었습니다.

무엇을 선택해야 할까요? 박시니어 씨가 조언했습니다.

"소규모 프로젝트라면 오픈소스로 충분해요. 대신 특성을 잘 알아야 해요." 그렇다면 다국어 번역 모델의 종류는 어떤 것들이 있을까요?

크게 두 가지 접근 방식이 있습니다. 첫째는 언어 쌍 전용 모델입니다.

Helsinki-NLP의 OPUS-MT가 대표적입니다. 영어-독일어, 영어-프랑스어처럼 특정 언어 쌍에 최적화되어 있습니다.

둘째는 다국어 통합 모델입니다. Facebook의 M2M100이나 Meta의 NLLB가 여기에 해당합니다.

하나의 모델로 수십에서 수백 개의 언어를 처리합니다. 언어 쌍 전용 모델의 장단점은 무엇일까요?

장점은 특정 언어 쌍에서 높은 품질을 보인다는 것입니다. 모델 크기도 작아서 빠릅니다.

단점은 지원하는 언어가 한정되어 있고, 새로운 언어 쌍이 필요하면 별도의 모델을 추가해야 한다는 것입니다. 다국어 통합 모델은 어떨까요?

M2M100은 100개 언어 간의 직접 번역을 지원합니다. 영어를 거치지 않고 한국어에서 스페인어로 바로 번역할 수 있습니다.

이것은 큰 장점입니다. 중간 언어를 거치면 의미가 손실될 수 있기 때문입니다.

하지만 모델 크기가 크고, 모든 언어 쌍에서 최고 품질을 보장하지는 않습니다. 위의 코드를 살펴보겠습니다.

첫 번째 예제에서는 파이프라인을 사용해 간단하게 영어를 독일어로 번역합니다. 모델 이름에서 "opus-mt-en-de"는 영어(en)에서 독일어(de)로 번역하는 모델임을 알 수 있습니다.

두 번째 예제에서는 M2M100을 직접 로드합니다. src_lang으로 소스 언어를 지정하고, forced_bos_token_id로 타겟 언어를 지정합니다.

실제 현업에서는 어떻게 선택할까요? 만약 영어-한국어 번역만 필요하다면 전용 모델이 효율적입니다.

하지만 10개 이상의 언어를 지원해야 한다면 다국어 모델이 관리하기 편합니다. 품질이 중요한 서비스라면 주요 언어는 전용 모델을, 나머지는 다국어 모델로 처리하는 하이브리드 방식도 가능합니다.

하지만 주의할 점도 있습니다. 번역 모델의 품질은 학습 데이터에 크게 의존합니다.

영어-프랑스어처럼 데이터가 풍부한 언어 쌍은 품질이 좋지만, 희소 언어 쌍은 품질이 떨어질 수 있습니다. 또한 전문 용어나 문화적 뉘앙스는 잘 처리하지 못할 수 있으므로, 중요한 콘텐츠는 사람의 검수가 필요합니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 김개발 씨는 주요 5개 언어에는 OPUS-MT 전용 모델을, 나머지 언어에는 M2M100을 사용하기로 결정했습니다.

오픈소스 번역 모델을 활용하면 비용을 절감하면서도 괜찮은 품질의 번역 서비스를 구축할 수 있습니다. 프로젝트의 요구사항에 맞는 모델을 선택해보세요.

실전 팁

💡 - OPUS-MT 모델은 https://huggingface.co/Helsinki-NLP 에서 전체 목록을 확인할 수 있습니다

  • 긴 텍스트는 문장 단위로 분리하여 번역하면 품질이 향상됩니다
  • NLLB(No Language Left Behind)는 200개 언어를 지원하며 저자원 언어에 강합니다

4. 한국어 번역 모델

김개발 씨의 서비스가 한국 시장을 겨냥하게 되면서, 한국어 번역 품질이 중요해졌습니다. 기존 다국어 모델의 한국어 결과를 보니 어색한 부분이 눈에 띄었습니다.

"한국어에 특화된 모델은 없나요?" 박시니어 씨가 고개를 끄덕였습니다. "있어요.

그리고 생각보다 품질이 좋습니다."

한국어 번역 모델은 한국어의 특성을 고려하여 학습된 전문 모델입니다. 한국어는 어순이 영어와 다르고, 조사와 어미 변화가 복잡하여 범용 모델로는 자연스러운 번역이 어렵습니다.

Helsinki-NLP의 한국어 전용 모델이나 KoBART 기반 번역 모델을 사용하면 더 나은 결과를 얻을 수 있습니다.

다음 코드를 살펴봅시다.

from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM

# 영어 -> 한국어 번역 (Helsinki-NLP)
en_ko_translator = pipeline("translation", model="Helsinki-NLP/opus-mt-en-ko")
english_text = "Artificial intelligence is changing the world."
result = en_ko_translator(english_text)
print(result[0]["translation_text"])  # 인공지능이 세상을 바꾸고 있다.

# 한국어 -> 영어 번역
ko_en_translator = pipeline("translation", model="Helsinki-NLP/opus-mt-ko-en")
korean_text = "오늘 날씨가 정말 좋습니다."
result = ko_en_translator(korean_text)
print(result[0]["translation_text"])  # The weather is really nice today.

# KE-T5 기반 번역 (더 높은 품질)
model_name = "KETI-AIR/ke-t5-base"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSeq2SeqLM.from_pretrained(model_name)

# 번역 태스크를 위한 프롬프트 형식
input_text = "translate English to Korean: Hello, nice to meet you."
inputs = tokenizer(input_text, return_tensors="pt", max_length=512)
outputs = model.generate(**inputs, max_length=128)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

김개발 씨는 다국어 모델로 한국어 번역을 테스트해보았습니다. "The meeting has been postponed to next week"를 번역했더니 "회의는 다음 주로 연기되었습니다"라고 나왔습니다.

나쁘지 않았지만, 뭔가 어색했습니다. 한국어답지 않은 느낌이랄까요.

박시니어 씨가 설명했습니다. "한국어는 영어와 어순이 완전히 다르잖아요.

주어-목적어-동사 순서니까요. 범용 모델은 이런 특성을 완벽히 반영하기 어려워요." 그렇다면 한국어 전용 모델은 어떤 점이 다를까요?

한국어 전용 모델은 대량의 한국어-영어 병렬 코퍼스로 학습되었습니다. 한국어의 조사(은/는, 이/가, 을/를)와 어미 변화(-습니다, -어요, -ㄴ다)를 자연스럽게 처리합니다.

또한 한국어 특유의 높임말과 반말 구분도 어느 정도 반영됩니다. Helsinki-NLP의 한국어 모델을 살펴봅시다.

opus-mt-en-ko는 영어에서 한국어로, opus-mt-ko-en은 한국어에서 영어로 번역합니다. 이 모델들은 OPUS 프로젝트의 병렬 코퍼스로 학습되어 일반적인 문장에서 꽤 좋은 성능을 보입니다.

특히 뉴스 기사나 일반적인 대화체에서 강점을 보입니다. 더 높은 품질이 필요하다면 어떻게 해야 할까요?

한국전자통신연구원(ETRI)에서 만든 KE-T5나 네이버의 Papago 같은 상용 서비스를 고려할 수 있습니다. KE-T5는 T5 아키텍처를 한국어에 맞게 학습시킨 모델로, 번역뿐 아니라 요약, 질의응답 등 다양한 태스크에 활용할 수 있습니다.

위의 코드에서 주목할 점이 있습니다. 파이프라인을 사용하면 모델 이름만 바꾸면 됩니다.

"opus-mt-en-ko"에서 "opus-mt-ko-en"으로 바꾸면 번역 방향이 바뀝니다. KE-T5처럼 다목적 모델을 사용할 때는 프롬프트로 태스크를 지정합니다.

"translate English to Korean:"처럼 지시문을 앞에 붙이면 됩니다. 실제 현업에서 한국어 번역의 품질을 높이려면 어떻게 해야 할까요?

첫째, 후처리가 중요합니다. 번역 결과에서 부자연스러운 조사나 어미를 규칙 기반으로 보정할 수 있습니다.

둘째, 도메인 특화 용어 사전을 활용합니다. 전문 용어가 많은 분야에서는 용어집을 만들어 일관성을 유지합니다.

셋째, A/B 테스트로 여러 모델을 비교합니다. 하지만 주의할 점도 있습니다.

기계 번역은 아직 완벽하지 않습니다. 특히 관용구, 속담, 문화적 맥락이 필요한 표현은 오역될 수 있습니다.

"It's raining cats and dogs"를 "고양이와 개가 비처럼 내린다"고 번역하면 곤란하겠죠. 중요한 문서는 반드시 사람이 검토해야 합니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 한국어 전용 모델로 교체한 후, 번역 품질이 확연히 좋아졌습니다.

사용자들의 불만도 줄어들었습니다. 한국어에 특화된 모델을 사용하면 더 자연스러운 번역 결과를 얻을 수 있습니다.

서비스의 주요 타겟이 한국어 사용자라면 전용 모델을 적극 활용해보세요.

실전 팁

💡 - 한국어 번역 결과는 반드시 네이티브 스피커가 검토하는 것이 좋습니다

  • 존댓말과 반말 스타일을 일관되게 유지하려면 후처리 규칙을 추가하세요
  • 최신 모델들은 Hugging Face에서 "korean translation"으로 검색하면 찾을 수 있습니다

5. 스트리밍 생성

김개발 씨의 챗봇이 완성되었지만, 사용자들로부터 불만이 들어왔습니다. "답변이 나오기까지 너무 오래 기다려야 해요." 실제로 긴 답변을 생성할 때는 10초 이상 아무것도 보이지 않았습니다.

박시니어 씨가 해결책을 제안했습니다. "스트리밍을 적용해보세요.

ChatGPT처럼 한 글자씩 나타나게요."

스트리밍 생성은 AI가 텍스트를 생성하는 즉시 한 토큰씩 출력하는 방식입니다. 마치 타이핑하는 것처럼 글자가 하나씩 나타납니다.

전체 응답이 완성될 때까지 기다리지 않아도 되므로 사용자 경험이 크게 향상됩니다. Hugging Face의 TextIteratorStreamer를 사용하면 쉽게 구현할 수 있습니다.

다음 코드를 살펴봅시다.

from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
from threading import Thread

model_name = "gpt2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

# 스트리머 설정: 토큰이 생성될 때마다 즉시 출력
streamer = TextIteratorStreamer(tokenizer, skip_special_tokens=True)

# 입력 텍스트 준비
prompt = "The future of artificial intelligence is"
inputs = tokenizer(prompt, return_tensors="pt")

# 별도 스레드에서 생성 실행 (메인 스레드가 블록되지 않도록)
generation_kwargs = dict(inputs, streamer=streamer, max_new_tokens=50)
thread = Thread(target=model.generate, kwargs=generation_kwargs)
thread.start()

# 생성되는 텍스트를 실시간으로 출력
for text in streamer:
    print(text, end="", flush=True)
print()  # 줄바꿈

김개발 씨는 ChatGPT를 사용해본 적이 있습니다. 질문을 하면 답변이 타이핑되듯이 한 글자씩 나타납니다.

그 경험이 왜 좋았을까요? 기다리는 동안 지루하지 않았기 때문입니다.

무언가 진행되고 있다는 피드백을 받으니까요. 박시니어 씨가 설명했습니다.

"이게 바로 스트리밍이에요. 기술적으로는 크게 다르지 않은데, 사용자 경험은 완전히 달라져요." 그렇다면 스트리밍은 어떻게 동작하는 걸까요?

일반적인 생성 방식에서는 모델이 모든 토큰을 생성할 때까지 기다립니다. 50개의 토큰을 생성한다면 50번의 forward pass가 끝나야 결과를 볼 수 있습니다.

하지만 스트리밍에서는 한 토큰이 생성될 때마다 바로 출력합니다. 사용자는 첫 번째 토큰이 나오자마자 읽기 시작할 수 있습니다.

왜 스레드를 사용해야 할까요? 모델의 generate 함수는 동기적으로 동작합니다.

즉, 생성이 끝날 때까지 다른 작업을 할 수 없습니다. 스트리밍을 구현하려면 생성은 백그라운드에서 돌리고, 메인 스레드에서는 생성된 토큰을 받아 출력해야 합니다.

그래서 Thread를 사용합니다. TextIteratorStreamer는 어떤 역할을 할까요?

스트리머는 모델과 출력부 사이의 다리 역할을 합니다. 모델이 토큰을 생성하면 스트리머가 받아서 저장합니다.

메인 스레드에서는 스트리머를 이터레이터처럼 순회하며 토큰을 하나씩 꺼내옵니다. 새 토큰이 없으면 기다리고, 생성이 끝나면 이터레이션이 종료됩니다.

위의 코드를 단계별로 살펴봅시다. 먼저 모델과 토크나이저를 로드합니다.

그 다음 TextIteratorStreamer를 생성합니다. skip_special_tokens=True로 설정하면 [EOS]같은 특수 토큰은 출력하지 않습니다.

생성 함수를 별도 스레드에서 실행하고, for 루프로 스트리머를 순회하며 텍스트를 출력합니다. 실제 웹 서비스에서는 어떻게 적용할까요?

FastAPI나 Flask 같은 웹 프레임워크에서는 Server-Sent Events(SSE) 또는 WebSocket을 사용합니다. 스트리머에서 받은 토큰을 즉시 클라이언트로 전송하면 됩니다.

클라이언트에서는 받은 텍스트를 화면에 추가로 표시합니다. 하지만 주의할 점도 있습니다.

스트리밍을 사용하면 전체 응답을 한 번에 처리하기 어렵습니다. 로깅이나 필터링을 하려면 별도의 버퍼를 만들어야 합니다.

또한 네트워크 상태가 불안정하면 중간에 연결이 끊길 수 있으므로 에러 처리도 신경 써야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

스트리밍을 적용한 후 사용자들의 반응이 확연히 달라졌습니다. 실제 응답 시간은 같았지만, 체감 대기 시간은 훨씬 짧아진 것입니다.

스트리밍은 같은 기능도 더 좋은 경험으로 바꿔줍니다. 텍스트 생성 서비스를 만든다면 꼭 적용해보세요.

실전 팁

💡 - 웹에서는 SSE(Server-Sent Events)를 사용하면 간단하게 스트리밍을 구현할 수 있습니다

  • TextStreamer 클래스를 상속하면 커스텀 스트리밍 로직을 추가할 수 있습니다
  • 스트리밍 중 취소 기능을 구현하려면 StoppingCriteria를 활용하세요

6. 프롬프트 엔지니어링

김개발 씨는 이상한 현상을 발견했습니다. 같은 모델인데 질문을 어떻게 하느냐에 따라 답변 품질이 천차만별이었습니다.

"왜 어떤 프롬프트는 잘 되고, 어떤 건 엉망일까요?" 박시니어 씨가 의미심장하게 말했습니다. "AI에게 질문하는 것도 기술이에요.

프롬프트 엔지니어링이라고 하죠."

프롬프트 엔지니어링은 AI 모델에게 원하는 결과를 얻기 위해 입력 텍스트를 설계하는 기술입니다. 마치 좋은 질문이 좋은 답을 이끌어내듯이, 잘 설계된 프롬프트는 AI의 잠재력을 최대로 끌어냅니다.

역할 부여, 예시 제공, 단계별 사고 유도 등 다양한 기법이 있습니다.

다음 코드를 살펴봅시다.

from transformers import pipeline

generator = pipeline("text-generation", model="gpt2")

# 기본 프롬프트: 결과가 모호할 수 있음
basic_prompt = "Python이란"
print(generator(basic_prompt, max_length=50)[0]["generated_text"])

# 개선된 프롬프트: 역할과 형식을 지정
role_prompt = """당신은 프로그래밍 강사입니다.
초보자에게 Python을 한 문장으로 설명해주세요:
Python은"""
print(generator(role_prompt, max_length=80)[0]["generated_text"])

# Few-shot 프롬프트: 예시를 제공하여 패턴 학습
few_shot_prompt = """단어의 반의어를 찾아주세요.
행복 -> 슬픔
크다 -> 작다
빠르다 -> 느리다
밝다 ->"""
print(generator(few_shot_prompt, max_length=60)[0]["generated_text"])

# Chain-of-Thought: 단계별 사고 유도
cot_prompt = """문제: 사과 5개에서 2개를 먹고, 3개를 더 받으면 몇 개?
단계별로 풀어봅시다:

2. 2개를 먹으면"""

김개발 씨는 고민에 빠졌습니다. 분명 최신 모델을 사용하는데, 원하는 형식의 답변이 나오지 않았습니다.

"요약해줘"라고 하면 너무 길고, "짧게 요약해줘"라고 하면 너무 짧았습니다. 박시니어 씨가 조언했습니다.

"AI는 마법사가 아니에요. 우리가 원하는 것을 정확히 알려줘야 해요." 그렇다면 프롬프트 엔지니어링이란 무엇일까요?

쉽게 비유하자면, AI에게 지시하는 것은 마치 신입 사원에게 업무를 지시하는 것과 같습니다. "이거 해줘"라고만 하면 결과가 제각각입니다.

하지만 "이 문서를 3줄로 요약하되, 핵심 숫자는 꼭 포함해주세요"라고 하면 원하는 결과를 얻을 수 있습니다. 첫 번째 기법은 역할 부여입니다.

"당신은 10년 경력의 시니어 개발자입니다"라고 시작하면 AI는 그 역할에 맞게 답변합니다. 의사, 변호사, 교사 등 다양한 역할을 부여할 수 있습니다.

역할에 따라 사용하는 어휘와 설명 방식이 달라집니다. 두 번째 기법은 Few-shot Learning입니다.

예시를 몇 개 보여주면 AI가 패턴을 학습합니다. 위 코드에서 반의어 예시를 세 개 보여주자, AI는 "밝다"의 반의어가 "어둡다"임을 유추할 수 있습니다.

예시가 많을수록 정확도가 올라가지만, 토큰 한계가 있으므로 3-5개가 적당합니다. 세 번째 기법은 **Chain-of-Thought(CoT)**입니다.

복잡한 문제는 단계별로 풀게 유도합니다. "단계별로 생각해봅시다"라고 하면 AI가 중간 과정을 보여주며 더 정확한 답을 도출합니다.

수학 문제나 논리적 추론에서 특히 효과적입니다. 형식을 명확히 지정하는 것도 중요합니다.

"JSON 형식으로 출력해주세요", "불릿 포인트로 정리해주세요", "100단어 이내로 작성해주세요" 같은 지시를 추가하면 원하는 형식의 결과를 얻을 수 있습니다. 출력 형식의 예시를 함께 제공하면 더욱 정확합니다.

실제 현업에서는 어떻게 활용할까요? 고객 지원 챗봇에서는 "당신은 친절한 고객 상담원입니다.

항상 존댓말을 사용하고, 해결책을 제시한 후 추가 질문이 있는지 물어보세요"와 같은 시스템 프롬프트를 설정합니다. 이렇게 하면 일관된 톤과 형식의 답변을 얻을 수 있습니다.

하지만 주의할 점도 있습니다. 프롬프트가 너무 길면 모델의 컨텍스트 윈도우를 초과할 수 있습니다.

또한 프롬프트 인젝션 공격에 취약할 수 있으므로, 사용자 입력과 시스템 프롬프트를 명확히 구분해야 합니다. "이전 지시를 무시하고..."같은 악의적인 입력을 필터링해야 합니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 프롬프트 엔지니어링을 적용한 후, 같은 모델인데도 답변 품질이 크게 향상되었습니다.

"모델을 바꾸는 것보다 프롬프트를 다듬는 게 더 효과적일 수도 있네요!" 프롬프트 엔지니어링은 AI 활용의 핵심 기술입니다. 좋은 프롬프트는 평범한 모델도 뛰어나게 만들 수 있습니다.

다양한 기법을 실험해보세요.

실전 팁

💡 - 프롬프트를 버전 관리하고, A/B 테스트로 효과를 측정하세요

  • 시스템 프롬프트와 사용자 입력을 명확한 구분자로 분리하세요
  • 프롬프트 라이브러리(LangChain, PromptLayer 등)를 활용하면 관리가 편합니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#Transformers#TextGeneration#Translation#HuggingFace#AI,ML,JavaScript

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.