EOS ํ ํฐ ์ฒ๋ฆฌ ์ ์ ๊ฐ์ฌ ๋ณด๊ณ ์
๋ ์ง: 2026-02-26
๊ฐ์ฌ ๋์: /PROJECT/0325120031_A/ghong/taketimes/llm-bang/
๋ฌธ์ : SFT ๋ชจ๋ธ์ด "### ๋ต๋ณ:" ์ดํ "### ์ง๋ฌธ:"์ ๋ฐ๋ณต (๋ฐ๋ณต๋ฅ 57%)
๊ฒฐ๋ก ์์ฝ
๐ด ๊ทผ๋ณธ ์์ธ: ์ถ๋ก ์ ํ๋กฌํํธ ํ ํ๋ฆฟ ๋ถ์ผ์น (EOS ๋ฒ๊ทธ ์๋)
| ํญ๋ชฉ | ํ์ต ํ ํ๋ฆฟ | ์ถ๋ก ํ ํ๋ฆฟ (test_generation_params.py) |
|---|---|---|
| ์ฌ์ฉ์ ํ๊ทธ | <|user|>\n{instruction}\n |
### ์ง๋ฌธ: {instruction}\n |
| ์ด์์คํดํธ ํ๊ทธ | <|assistant|>\n |
### ๋ต๋ณ: |
| ์ข ๋ฃ ํ ํฐ | </s> (EOS, id=2) |
์์ (stop_strings๋ก ๋์ฒด ์๋) |
๋ชจ๋ธ์ <|user|> / <|assistant|> ํฌ๋งท์ผ๋ก ํ์ต๋์ผ๋, ์ถ๋ก ์ ### ์ง๋ฌธ: / ### ๋ต๋ณ: ํฌ๋งท์ผ๋ก ํธ์ถ๋จ.
๋ชจ๋ธ ์
์ฅ์์ ### ์ง๋ฌธ: ### ๋ต๋ณ:์ ์ผ๋ฐ ํ
์คํธ โ EOS๋ฅผ ์ถ๋ ฅํ ์ด์ ๊ฐ ์์ผ๋ฏ๋ก ๋ฌดํ ๋ฐ๋ณต.
์์ธ ๊ฐ์ฌ ๊ฒฐ๊ณผ
โ ์ฒดํฌํฌ์ธํธ 1: SFTDataset โ response ๋ EOS ํ ํฐ ๋ถ์ฐฉ
๊ฒฐ๊ณผ: ์ ์
sft_dataset.py Line ~52, ~87:
response = f"{output}{_EOS_STRING}" # _EOS_STRING = "</s>"
response = f"{content}{_EOS_STRING}" # conversation format๋ ๋์ผ
์ค์ ๊ฒ์ฆ: response_ids[-1] == 2 (EOS) โ
โ ์ฒดํฌํฌ์ธํธ 2: EOS ํ ํฐ label = ํ์ต ๋์
๊ฒฐ๊ณผ: ์ ์
sft_dataset.py Line ~144-152:
resp_label_start = max(0, resp_start - 1) # 1์นธ ์ผ์ชฝ ์ํํธ (causal LM ๊ด๋ก)
resp_label_end = resp_label_start + len(response_ids)
labels[resp_label_start:resp_label_end] = response_ids
labels[resp_label_end - 1] = EOS (2)โ EOS๊ฐ ํ์ต ๋์์ ํฌํจ๋จ โ- logits[๋ง์ง๋ง ์๋ต ํ ํฐ ์์น] โ EOS ์์ธกํ๋๋ก ํ์ต๋จ โ
โ ์ฒดํฌํฌ์ธํธ 3: prompt ๋ถ๋ถ label = -1 (๋ฌด์)
๊ฒฐ๊ณผ: ์ ์
labels ์ด๊ธฐ๊ฐ์ด -1์ด๊ณ , response ์์ญ๋ง ๋ฎ์ด์ฐ๋ฏ๋ก prompt ์ ์ฒด๋ -1 โ
โ ์ฒดํฌํฌ์ธํธ 4: ํธ๋ ์ผ์ด์ ์ผ๋ก EOS ์์ค
๊ฒฐ๊ณผ: ๋ฌด์ ๊ฐ๋ฅ ์์ค
- ์ ์ฒด 159,125 ์ํ ์ค 61๊ฐ (0.04%)๋ง max_seq_len=4096 ์ด๊ณผ
- ์ด 61๊ฐ์์๋ง EOS๊ฐ ์๋ฆด ์ ์์ โ ๋ฐ๋ณต๋ฅ 57%์ ๋ฌด๊ด
โ ๏ธ ์ฒดํฌํฌ์ธํธ 5: ํ ํฌ๋์ด์ ํน์ ํ ํฐ ๋ฏธ๋ฑ๋ก
๊ฒฐ๊ณผ: ๊ฒฝ๋ฏธํ ๋ฌธ์
<|user|>โtoken_to_id()= None (ํน์ ํ ํฐ ์๋, ์๋ธ์๋๋ก ๋ถํ ๋จ)<|assistant|>โ None (๋์ผ)</s>โ id=2 โ (์ ์ ๋ฑ๋ก)
<|user|> / <|assistant|>๊ฐ ๋จ์ผ ํ ํฐ์ด ์๋๋ผ ์๋ธ์๋ ์กฐ๊ฐ์ผ๋ก ๋ถํ ๋จ.
ํ์ต/์ถ๋ก ๋ชจ๋ ๊ฐ์ ํ ํฌ๋์ด์ ๋ฅผ ์ฐ๋ฉด ๋์์ ํ์ง๋ง, ๋จ์ผ ํน์ ํ ํฐ์ผ๋ก ๋ฑ๋กํ๋ ๊ฒ์ด ๋ robust.
๐ด ์ฒดํฌํฌ์ธํธ 6: ์ถ๋ก ํ๋กฌํํธ ํฌ๋งท ๋ถ์ผ์น (๊ทผ๋ณธ ์์ธ)
eval/test_generation_params.py:
"### ์ง๋ฌธ: ํ๊ตญ์ ์๋๋ ์ด๋์ธ๊ฐ์?\n### ๋ต๋ณ:",
eval/comprehensive_eval.py:
"ํ๊ตญ์ ์๋๋", # ํ
ํ๋ฆฟ ์์ด raw text
ํ์ต๋ ํฌ๋งท:
<|user|>
ํ๊ตญ์ ์๋๋ ์ด๋์ธ๊ฐ์?
<|assistant|>
์์ธ์
๋๋ค.</s>
์ถ๋ก ์ ์ฌ๋ฐ๋ฅธ ํ๋กฌํํธ:
<|user|>
ํ๊ตญ์ ์๋๋ ์ด๋์ธ๊ฐ์?
<|assistant|>
์์ ์ฌํญ
Fix 1: ์ถ๋ก ํ๋กฌํํธ ํ ํ๋ฆฟ ์์ (ํ์, ์ฌํ์ต ๋ถํ์)
eval/test_generation_params.py์ eval/comprehensive_eval.py์์ ํ๋กฌํํธ๋ฅผ SFT ํ์ต ํ
ํ๋ฆฟ์ ๋ง๊ฒ ๋ณ๊ฒฝ:
# Before (WRONG)
prompt = "### ์ง๋ฌธ: ํ๊ตญ์ ์๋๋ ์ด๋์ธ๊ฐ์?\n### ๋ต๋ณ:"
# After (CORRECT)
prompt = "<|user|>\nํ๊ตญ์ ์๋๋ ์ด๋์ธ๊ฐ์?\n<|assistant|>\n"
Fix 2: ํธ๋ ์ผ์ด์ ์ EOS ๋ณด์ฅ (๊ถ์ฅ, ์ฌํ์ต ํ์)
sft_dataset.py์์ truncation ํ EOS๋ฅผ ๊ฐ์ ์ฝ์
:
# ํ์ฌ (truncation ์ EOS ์์ค ๊ฐ๋ฅ)
response_ids = response_ids[:allowed_response]
# ์์ ์ (truncation ํ EOS ๊ฐ์ )
response_ids = response_ids[:allowed_response]
if response_ids and response_ids[-1] != self.eos_token_id:
response_ids[-1] = self.eos_token_id # ๋ง์ง๋ง ํ ํฐ์ EOS๋ก ๊ต์ฒด
Fix 3: <|user|> / <|assistant|> ํน์ ํ ํฐ ๋ฑ๋ก (์ ํ, ์ฌํ์ต ํ์)
ํ ํฌ๋์ด์ ์ ํน์ ํ ํฐ์ผ๋ก ์ถ๊ฐํ๋ฉด ๋จ์ผ ํ ํฐ์ผ๋ก ์ธ์ฝ๋ฉ๋์ด ๋ ์์ ์ :
tokenizer.add_special_tokens(["<|user|>", "<|assistant|>"])
์ฌํ์ต ํ์ ์ฌ๋ถ
| ์์ | ์ฌํ์ต ํ์ | ํจ๊ณผ |
|---|---|---|
| Fix 1: ์ถ๋ก ํ ํ๋ฆฟ ์์ | โ | ๋ฐ๋ณต ๋ฌธ์ ํด๊ฒฐ ์์ (๊ทผ๋ณธ ์์ธ) |
| Fix 2: ํธ๋ ์ผ์ด์ EOS ๋ณด์ฅ | โญ (0.04%๋ง ํด๋น) | ๋ฏธ๋ฏธ |
| Fix 3: ํน์ ํ ํฐ ๋ฑ๋ก | โญ | ์ฅ๊ธฐ์ ์์ ์ฑ ํฅ์ |
์ฆ์ ์กฐ์น: Fix 1๋ง์ผ๋ก ๋ฐ๋ณต ๋ฌธ์ ํด๊ฒฐ ๊ฐ๋ฅ. ์ฌํ์ต ๋ถํ์.
๊ฒ์ฆ ๋ฐฉ๋ฒ
python eval/generate.py \
--checkpoint checkpoints/korean_1b_sft \
--prompt $'<|user|>\nํ๊ตญ์ ์๋๋ ์ด๋์ธ๊ฐ์?\n<|assistant|>\n' \
--max_new_tokens 200 \
--temperature 0.7
๋ฐ๋ณต์ด ๋ฉ์ถ๊ณ </s> (EOS)์์ ์ ์ ์ข
๋ฃ๋๋ฉด Fix 1 ์ฑ๊ณต.