SONUB 홈 KO English 한국어 日本語 中文 हिन्दी বাংলা اردو Español Português Français Deutsch Русский العربية Bahasa Indonesia Tiếng Việt ไทย Türkçe

알림을 켜는 방법

이 브라우저 또는 주소에서는 알림을 사용할 수 없습니다. 지원되는 브라우저로 보안 연결된 SONUB 사이트에 접속해 주세요.

알림이 차단되어 있으면 브라우저 설정에서 허용해 주세요.

  1. 주소 표시줄 옆의 사이트 설정 또는 브라우저의 사이트 설정을 열고, 이 사이트의 알림을 허용으로 바꾸세요.
  2. 기기 설정에서 브라우저 알림을 허용하고 방해 금지 또는 집중 모드를 확인하세요.
  3. SONUB으로 돌아와 페이지를 새로고침한 뒤 벨을 눌러 알림을 켜세요.

iPhone 또는 iPad에서는 SONUB을 홈 화면에 추가하고 거기에서 연 뒤 알림을 허용하세요.

XSML · 첫 코드부터 나만의 대화까지

자, 이제 여러분들만의 인공지능을 만들어 봅시다.

이 브라우저에서 직접 타이핑하며 언어 모델을 만듭니다. 데이터를 준비하고 작은 GPT를 학습한 뒤, 내가 만든 Runner와 XChat으로 대화합니다. 미리 학습된 가중치나 외부 AI API는 쓰지 않습니다.

7

텍스트 생성

다음 토큰의 점수를 실제 생성 문장으로 바꿉니다.

생성은 최근 을 GPT에 넣고 예측한 토큰 하나를 붙이는 일을 반복합니다. 가 0이면 가장 높은 점수를 고릅니다. 양수면 점수를 조절한 뒤 무작위로 뽑으며, 높을수록 확률이 더 고르게 퍼집니다. top_k는 상위 후보만 남기고, 0이면 전부 씁니다.

seed는 무작위 선택을 재현하는 번호이며 정답을 보장하는 번호가 아닙니다. 줄바꿈이나 요청한 토큰 수에서 생성을 멈추고 새로 만든 글만 돌려줍니다. 입력은 학습 때의 Q:/A: 형식을 맞춥니다.

직접 타이핑하며 실습하기

generate.py를 작성하세요. 같은 체크포인트로 세 명령을 비교합니다. 먼저 temperature만 바꾸고, 다음에는 top_k와 seed를 바꾸어 보세요. 토크나이저와 모델 크기는 체크포인트에 저장된 값을 읽습니다.

cd ~/xsml
nano generate.py
python3 generate.py --temperature 0 --top-k 1
python3 generate.py --temperature 0.8 --top-k 8 --seed 7
python3 generate.py --temperature 1.2 --top-k 0 --seed 8
generate.py직접 작성할 전체 소스

load는 모델 구조를 다시 만들고 숫자를 복원합니다. generate는 문맥을 자르고 후보 점수를 계산해 반복해서 뽑습니다. 같은 seed로 비교 실험을 재현할 수 있습니다.

import argparse
import json
import math
import random
from pathlib import Path
from model import GPT
from tokenizer import BPE


def load():
    saved = json.loads(Path('checkpoints/model.json').read_text())
    cfg = saved['settings']
    tokenizer = BPE(**saved['tokenizer'])
    model = GPT(len(tokenizer.vocab), cfg['width'], cfg['context'], cfg['seed'])
    model.load(saved['weights'])
    return model, tokenizer, cfg


def generate(model, tokenizer, prompt, tokens=24, temperature=0.8, top_k=8, seed=7):
    if not prompt or tokens < 1 or temperature < 0 or not math.isfinite(temperature) or top_k < 0:
        raise ValueError('invalid sampling parameters')
    ids, result, rng = tokenizer.encode(prompt), [], random.Random(seed)
    for _ in range(tokens):
        logits = model.forward(ids[-model.context:])[-1]
        ranked = sorted(range(len(logits)), key=lambda i: logits[i].data, reverse=True)
        if temperature == 0:
            token = ranked[0]
        else:
            candidates = ranked[:top_k] if top_k else ranked
            peak = logits[candidates[0]].data
            weights = [math.exp((logits[i].data - peak) / temperature) for i in candidates]
            token = rng.choices(candidates, weights=weights)[0]
        ids.append(token)
        if tokenizer.vocab[token] == '\n':
            break
        result.append(token)
    return tokenizer.decode(result)


if __name__ == '__main__':
    model, tokenizer, cfg = load()
    parser = argparse.ArgumentParser()
    parser.add_argument('--prompt', default='Q: hi\nA:')
    parser.add_argument('--tokens', type=int, default=cfg['tokens'])
    parser.add_argument('--temperature', type=float, default=0.8)
    parser.add_argument('--top-k', type=int, default=8)
    parser.add_argument('--seed', type=int, default=cfg['seed'])
    args = parser.parse_args()
    assert 1 <= args.tokens <= cfg['max_tokens']
    print(generate(model, tokenizer, args.prompt, args.tokens,
                   args.temperature, args.top_k, args.seed))

여기까지 이해했나요?

같은 체크포인트·질문·seed·설정이면 같은 글이 나와야 합니다. 가중치를 읽는 것과 학습하는 것의 차이를 설명해 보세요. 첫 선택이 줄바꿈이면 빈 답이 될 수 있습니다.

막혔을 때 확인하기

작은 모델을 잠깐 학습하면 이상한 글이나 빈 답이 나올 수 있습니다. 자료 형식·모르는 문자·학습 손실부터 확인하세요. 무작위성을 높인다고 부족한 학습이 해결되지는 않습니다.