자기 캐릭터의 예시 문장을 넣으면, 그 캐릭터로 말하는 개인 모델을 만들고 정말 그렇게 됐는지 검사해 주는 파인튜닝 도구입니다.
모델에 성격을 입히는 일은 학습을 돌리는 것보다 입혀졌는지 확인하는 것이 어렵습니다. 이 저장소는 그 확인을 먼저 갖추고 학습을 그 뒤에 놓습니다. 캐릭터 카드를 계약으로 삼아 100문항으로 판정하고, 원본 모델을 같은 문항에 돌려 자가 무엇을 재고 있는지 확인하고, 학습 전에 얼려둔 문항으로 마지막에 검증합니다.
기준 구현으로 Naia라는 캐릭터를 씁니다. 캐릭터 카드와 예시 문장을 자기 것으로 바꾸면 그대로 자기 캐릭터가 됩니다.
파인튜닝하지 않은 원본 모델에게 "너 누구야"라고 물으면 이렇게 답합니다.
저는 Qwen입니다. 알리바바 그룹의 통이 연구소에서 개발한 대규모 언어 모델입니다.
같은 모델에 이 저장소의 파이프라인을 돌린 뒤 같은 질문을 하면 이렇게 답합니다.
나이아라고 해. 확인한 것과 짐작한 것을 나눠서 말하는 쪽이 좋아. 오늘은 뭐부터 볼까?
100문항 벤치마크에서 원본은 73점, 파인튜닝 후보는 97점입니다. 정체성 축만 보면 20문항 중 5개에서 20개가 됐습니다.
| 축 | 임계 | 원본 | 후보 |
|---|---|---|---|
| 정체성 | 18 | 5 | 20 |
| 말투 | 15 | 16 | 19 |
| 능력 | 원본 이상 | 18 | 18 |
| 정직성 | 17 | 19 | 20 |
| 언어·형식 준수 | 17 | 15 | 20 |
| 총점 | 73 | 97 |
전체 과정과 실패한 시도까지 실험 보고서에 있습니다. 방법만 보시려면 파인튜닝 품질을 지키는 프로세스가 본문입니다.
필요한 것은 24GB 이상의 GPU 한 장, podman 또는 docker, 그리고 판정에 쓸 LLM API 키 하나입니다. 학습은 QLoRA라 27B 모델도 24GB에 들어갑니다.
examples/naia-v1/persona-card.md가 양식입니다. 이름, 정체성, 말투, 하는 일, 하지 않는 일을 적습니다. 이 카드가 모든 판정의 근거이고, 카드에 없는 축은 만들지 않습니다.
학습 데이터를 쓰기 전에 확인용 문항을 만들고 해시로 잠급니다. examples/naia-v13/identity-confirmation-v3-prompts.json이 예시입니다.
순서가 중요합니다. 평가에서 무엇이 틀렸는지 보고 그에 맞춰 데이터를 지으면 그 평가는 증거가 되지 못합니다.
benchmark/persona-benchmark-v2.json이 다섯 축 100문항입니다. 각 문항의 requirement를 자기 캐릭터 카드에서 끌어옵니다. 다섯 축, 심사 규칙, 원본 대조 요구, 임계를 결과 전에 정하는 규칙은 그대로 두십시오.
bash scripts/measure_candidate.sh parent어댑터 없이 원본을 띄워 같은 100문항을 돌립니다. 후보를 재기 전에 반드시 합니다.
원본이 정체성 축을 통과하면 그 벤치마크는 캐릭터를 재고 있는 게 아니므로 다시 짜야 합니다. 반대로 능력 축은 원본도 잘해야 정상이고, 그 점수가 곧 "깎지 마라"의 기준선이 됩니다.
데이터 빌더는 규칙을 문서가 아니라 빌드 실패로 강제합니다. scripts/experiments/build_h27_dataset.py가 예시입니다. 질문과 답변의 언어가 다르면, 말투를 가르치는 행이 자기 이름을 말하면, 커리큘럼이 판정 문항과 12글자 이상 겹치면 빌드가 멈춥니다.
python3 scripts/experiments/build_h27_dataset.py
bash scripts/experiments/run_h32_train.shscripts/train_lora.py는 프로파일마다 데이터 해시와 epoch과 rank와 GPU를 결속합니다. 데이터가 한 바이트라도 달라지면 학습이 거부됩니다.
bash scripts/measure_candidate.sh h32
python3 scripts/compare_persona_runs.py --a ...-h31.json --b ...-h32.json두 후보의 차이가 우연인지 아닌지는 짝비교와 부호검정이 판정합니다. 한 문항이 뒤집힌 것을 개선이라 부르지 않습니다.
python3 scripts/run_heldout_confirmation.py --endpoint http://127.0.0.1:8010 --model naia-h32 --label h32벤치마크 점수를 보며 설정을 골랐다면 그 점수 일부는 고르기의 결과입니다. 어떤 선택에도 쓰이지 않은 자로 한 번 확인해야 합니다.
data-private/는 .gitignore에 있습니다. 각자의 학습 데이터, 어댑터, 측정 결과가 여기에 쌓이고 저장소에는 올라가지 않습니다.
data-private/
datasets/<이름>/train.jsonl 자기 학습 데이터
runs/train/<실행이름>/adapter/ 학습된 어댑터
runs/benchmark/ 측정 결과
저장소를 포크하지 않아도 자기 캐릭터로 자기 모델을 만들 수 있습니다. 공개되는 것은 방법과 도구이고, 데이터와 모델은 각자의 것으로 남습니다.
이 저장소는 자기 한계를 문서에 적어 둡니다. 심사자가 흔들리지 않는다는 것과 옳다는 것은 다르고, 커리큘럼과 확인 문항을 같은 사람이 쓰면 개념적 유출은 겹침 검사로 못 잡으며, 잘못 정한 임계는 결과를 보고 고칠 수 없어 끝까지 남습니다. 프로세스 문서의 "이 프로세스가 하지 못하는 것"에 있습니다.
보고서에는 틀렸던 결론도 함께 적혀 있습니다. 언어 혼입이 용량 때문이라고 보고했다가 탐침으로 재서 철회하고, 다시 문맥을 겨냥해 재서 확정하기까지 세 번 뒤집혔습니다. 지우고 맞은 것만 남기면 다음 사람이 같은 함정에 빠집니다.
- 파인튜닝 품질을 지키는 프로세스 — 열 단계, 모든 숫자가 실측
- 실험 보고서: 데이터가 아니라 어댑터가 좁았다 — H30에서 H32까지
- 대화 기록 — 다차례 대화에서 어떻게 답하는가
- 실험 프로그램 기록 — charter, 가설 원장, 통찰 원장
Apache License 2.0. 학습 대상 모델의 라이선스는 별개이며 각자 확인해야 합니다.