สรุปย่อ (TL;DR)
การสร้างแบบจำลองภาษาขนาดเล็ก (minimal language model) ตั้งแต่เริ่มต้นใช้โค้ด Python ไม่ถึง 300 บรรทัด กระบวนการนี้เผยให้เห็นอย่างชัดเจนว่าการ Tokenization, Attention และ Inference ทำงานอย่างไร ซึ่งจะทำให้คุณเป็นผู้ใช้ API ที่ดีขึ้นมากเมื่อคุณต้องรวม LLM สำหรับการผลิตเข้ากับแอปพลิเคชันของคุณ
บทนำ
นักพัฒนาส่วนใหญ่ปฏิบัติต่อแบบจำลองภาษาเหมือนกล่องดำ คุณส่งข้อความเข้าไป ได้โทเค็นออกมา และในระหว่างนั้นก็เกิดความมหัศจรรย์ขึ้น โมเดลทางความคิดนี้ใช้ได้ดีจนกว่าคุณจะต้องแก้ไขข้อบกพร่องของการรวม API ที่เสีย, ปรับแต่งพารามิเตอร์การสุ่มตัวอย่าง หรือหาสาเหตุว่าทำไมโมเดลของคุณยังคงสร้างข้อมูลที่มีโครงสร้างผิดๆ
GuppyLM ซึ่งเป็นโปรเจกต์ที่เพิ่งติดหน้าแรกของ HackerNews ด้วยคะแนน 842 คะแนน ทำให้การทำงานภายในเป็นที่มองเห็นได้ มันคือหม้อแปลงขนาด 8.7 ล้านพารามิเตอร์ที่เขียนขึ้นตั้งแต่เริ่มต้นด้วย Python มันสามารถฝึกฝนได้ในเวลาไม่ถึงหนึ่งชั่วโมงบน GPU สำหรับผู้บริโภค โค้ดทั้งหมดอยู่ในไฟล์เดียว เป้าหมายไม่ใช่การแข่งขันกับ GPT-4 แต่เป็นการขจัดความลึกลับว่า LLM ทำอะไรจริงๆ
บทความนี้จะอธิบายถึงวิธีการสร้าง LLM ขนาดเล็ก สิ่งที่ส่วนประกอบแต่ละชิ้นทำ และสิ่งที่การทำความเข้าใจการทำงานภายในสอนคุณเมื่อคุณทำงานกับ AI API อย่างมืออาชีพ
อะไรทำให้แบบจำลองภาษา "เล็ก"?
LLM สำหรับการผลิตอย่าง GPT-4 มีพารามิเตอร์หลายแสนล้านตัว LLM "ขนาดเล็ก" อยู่ในช่วง 1 ล้านถึง 25 ล้านพารามิเตอร์ โปรเจกต์อย่าง GuppyLM (8.7M), nanoGPT ของ Karpathy (124M) และ MicroLM (1-2M) ล้วนอยู่ในหมวดหมู่นี้
LLM ขนาดเล็กสามารถ: - ฝึกฝนบนแล็ปท็อปหรือ Google Colab - พอดีกับหน่วยความจำ CPU ทั้งหมด - สามารถตรวจสอบ, ปรับเปลี่ยน และแก้ไขข้อบกพร่องในระดับน้ำหนักได้
แต่ไม่สามารถ: - จัดการกับการให้เหตุผลที่ซับซ้อน - สร้างข้อความยาวๆ ที่สอดคล้องกันได้อย่างน่าเชื่อถือ - ตรงกับความลึกของข้อมูลที่เป็นข้อเท็จจริงของโมเดลสำหรับการผลิต
คุณค่าไม่ได้อยู่ที่ผลลัพธ์ แต่อยู่ที่ความเข้าใจที่คุณได้รับจากการสร้างมันขึ้นมา
ส่วนประกอบหลัก: LLM ทำงานอย่างไรจริงๆ
ก่อนที่จะเขียนโค้ดใดๆ คุณต้องรู้ว่าส่วนประกอบหลักทั้งสี่ชิ้นทำอะไร
ตัวแบ่งโทเค็น (Tokenizer)
ตัวแบ่งโทเค็นจะแปลงข้อความดิบให้เป็น ID แบบจำนวนเต็ม "Hello, world!" กลายเป็นบางอย่างเช่น [15496, 11, 995, 0] จำนวนเต็มแต่ละตัวจะแมปกับหน่วยย่อยคำจากคำศัพท์ที่กำหนดไว้
ทำไมเรื่องนี้ถึงสำคัญสำหรับการทำงานกับ API: จำนวนโทเค็นส่งผลโดยตรงต่อความล่าช้าและต้นทุน การทำความเข้าใจว่าตัวแบ่งโทเค็นแบ่งข้อความอย่างไรช่วยให้คุณเขียนพร้อมต์ที่พอดีกับหน้าต่างบริบทและหลีกเลี่ยงการตัดข้อความที่ไม่คาดคิด
GuppyLM ใช้ตัวแบ่งโทเค็นระดับอักขระที่เรียบง่าย โมเดลสำหรับการผลิตอย่าง GPT-4 ใช้ BPE (byte-pair encoding) ที่มีคำศัพท์ 50K-100K โทเค็น
เลเยอร์การฝัง (Embedding layer)
เลเยอร์การฝังจะแปลง ID โทเค็นให้เป็นเวกเตอร์หนาแน่น โทเค็นแต่ละตัวจะได้รับเวกเตอร์ที่เรียนรู้มา (เช่น 384 มิติใน GuppyLM) เวกเตอร์เหล่านี้มีความหมายทางความหมาย: โทเค็นที่คล้ายกันจะอยู่ใกล้กันในพื้นที่เวกเตอร์
มีการเพิ่มตำแหน่งการฝัง (Position embeddings) เพื่อให้โมเดลทราบลำดับโทเค็น
บล็อก Transformer
นี่คือการคำนวณหลัก แต่ละบล็อกมีสองส่วน:
Self-attention: ทำให้โทเค็นแต่ละตัวสามารถมองเห็นโทเค็นอื่นๆ ทั้งหมดในลำดับและตัดสินใจว่าโทเค็นใดมีความสำคัญสำหรับการคาดการณ์โทเค็นถัดไป GuppyLM ใช้หัว Attention 6 หัวใน 6 เลเยอร์
Feed-forward network: MLP สองเลเยอร์ที่นำไปใช้กับตัวแทนของโทเค็นแต่ละตัวหลังจากการ Attention GuppyLM ใช้การเปิดใช้งาน ReLU ซึ่งง่ายกว่า SwiGLU ที่ใช้ในสถาปัตยกรรมใหม่ๆ
ส่วนหัวเอาต์พุต (Output head)
หลังจากบล็อก Transformer สุดท้าย เลเยอร์เชิงเส้นจะฉายภาพตัวแทนของโทเค็นแต่ละตัวไปยังเวกเตอร์ที่มีขนาดเท่ากับคำศัพท์ ใช้ Softmax เพื่อรับความน่าจะเป็น เลือกโทเค็นถัดไปที่มีแนวโน้มมากที่สุด (หรือสุ่มตัวอย่าง) และทำซ้ำ
การสร้าง LLM ขนาดเล็กใน Python
นี่คือ LLM ขนาดเล็กที่ทำงานได้โดยใช้วิธีการของ GuppyLM ซึ่งสามารถรันได้ใน PyTorch มาตรฐาน
import torch
import torch.nn as nn
import torch.nn.functional as F
# Hyperparameters
VOCAB_SIZE = 256 # character-level: one slot per ASCII char
D_MODEL = 128 # embedding dimension
N_HEADS = 4 # attention heads
N_LAYERS = 3 # transformer blocks
SEQ_LEN = 64 # context window
DROPOUT = 0.1
class SelfAttention(nn.Module):
def __init__(self, d_model, n_heads):
super().__init__()
self.n_heads = n_heads
self.head_dim = d_model // n_heads
self.qkv = nn.Linear(d_model, 3 * d_model, bias=False)
self.proj = nn.Linear(d_model, d_model, bias=False)
self.dropout = nn.Dropout(DROPOUT)
def forward(self, x):
B, T, C = x.shape
qkv = self.qkv(x).reshape(B, T, 3, self.n_heads, self.head_dim)
q, k, v = qkv.unbind(dim=2)
q = q.transpose(1, 2)
k = k.transpose(1, 2)
v = v.transpose(1, 2)
# Causal mask: each token can only attend to previous tokens
scale = self.head_dim ** -0.5
attn = (q @ k.transpose(-2, -1)) * scale
mask = torch.triu(torch.ones(T, T, device=x.device), diagonal=1).bool()
attn = attn.masked_fill(mask, float('-inf'))
attn = F.softmax(attn, dim=-1)
attn = self.dropout(attn)
out = (attn @ v).transpose(1, 2).reshape(B, T, C)
return self.proj(out)
class TransformerBlock(nn.Module):
def __init__(self, d_model, n_heads):
super().__init__()
self.attn = SelfAttention(d_model, n_heads)
self.ff = nn.Sequential(
nn.Linear(d_model, 4 * d_model),
nn.ReLU(),
nn.Linear(4 * d_model, d_model),
nn.Dropout(DROPOUT),
)
self.ln1 = nn.LayerNorm(d_model)
self.ln2 = nn.LayerNorm(d_model)
def forward(self, x):
x = x + self.attn(self.ln1(x))
x = x + self.ff(self.ln2(x))
return x
class TinyLLM(nn.Module):
def __init__(self):
super().__init__()
self.embed = nn.Embedding(VOCAB_SIZE, D_MODEL)
self.pos_embed = nn.Embedding(SEQ_LEN, D_MODEL)
self.blocks = nn.ModuleList([
TransformerBlock(D_MODEL, N_HEADS) for _ in range(N_LAYERS)
])
self.ln_f = nn.LayerNorm(D_MODEL)
self.head = nn.Linear(D_MODEL, VOCAB_SIZE, bias=False)
def forward(self, idx):
B, T = idx.shape
tok_emb = self.embed(idx)
pos = torch.arange(T, device=idx.device)
pos_emb = self.pos_embed(pos)
x = tok_emb + pos_emb
for block in self.blocks:
x = block(x)
x = self.ln_f(x)
logits = self.head(x)
return logits
# Initialize and count parameters
model = TinyLLM()
total_params = sum(p.numel() for p in model.parameters())
print(f"Model size: {total_params:,} parameters") # ~1.2M
ลูปการฝึกฝน (Training loop)
import torch.optim as optim
def train(model, data, epochs=100, lr=3e-4):
optimizer = optim.AdamW(model.parameters(), lr=lr)
model.train()
for epoch in range(epochs):
# data: tensor of token IDs, shape [batch, seq_len+1]
x = data[:, :-1] # input: all tokens except last
y = data[:, 1:] # target: all tokens shifted by 1
logits = model(x)
loss = F.cross_entropy(logits.reshape(-1, VOCAB_SIZE), y.reshape(-1))
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 10 == 0:
print(f"Epoch {epoch}, loss: {loss.item():.4f}")
การอนุมาน (การสร้างข้อความ)
@torch.no_grad()
def generate(model, prompt_ids, max_new_tokens=50, temperature=1.0, top_k=10):
model.eval()
ids = torch.tensor([prompt_ids])
for _ in range(max_new_tokens):
idx_cond = ids[:, -SEQ_LEN:] # crop to context window
logits = model(idx_cond)
logits = logits[:, -1, :] / temperature # last token only
# top-k sampling
v, _ = torch.topk(logits, min(top_k, logits.size(-1)))
logits[logits < v[:, [-1]]] = float('-inf')
probs = F.softmax(logits, dim=-1)
next_id = torch.multinomial(probs, num_samples=1)
ids = torch.cat([ids, next_id], dim=1)
return ids[0].tolist()
สิ่งนี้สอนอะไรคุณเกี่ยวกับพฤติกรรมของ AI API
การสร้างสิ่งนี้เผยให้เห็นหลายสิ่งที่จะทำให้คุณเป็นผู้ใช้งาน API ที่ดีขึ้น
อุณหภูมิและการสุ่มตัวอย่างเป็นเชิงกลไก ไม่ใช่เวทมนตร์
อุณหภูมิจะแบ่ง logits ก่อน Softmax อุณหภูมิที่สูงขึ้น = การกระจายที่ราบเรียบขึ้น = ผลลัพธ์ที่สุ่มมากขึ้น อุณหภูมิที่ต่ำลง = การกระจายที่คมชัดขึ้น = ผลลัพธ์ที่กำหนดได้มากขึ้น เมื่อ API การผลิตของคุณส่งคืนผลลัพธ์ที่ไม่สอดคล้องกันด้วย temperature=0.0 นี่ไม่ใช่ข้อผิดพลาด อุณหภูมิศูนย์จริงคือ argmax แบบ greedy และ API จำนวนมากจะปัดเศษขึ้นเล็กน้อยเพื่อหลีกเลี่ยงผลลัพธ์ที่เสื่อมสภาพ
หน้าต่างบริบทเป็นขีดจำกัดที่แน่นอน ไม่ใช่คำแนะนำแบบยืดหยุ่น
บรรทัด idx_cond = ids[:, -SEQ_LEN:] ในลูปการอนุมานแสดงให้เห็นอย่างชัดเจนว่าเกิดอะไรขึ้นที่ขีดจำกัดบริบท โมเดลจะทิ้งโทเค็นเก่าอย่างเงียบๆ หากการรวม API ของคุณสมมติว่าโมเดลจดจำประวัติการสนทนาทั้งหมด มันจะไม่เป็นเช่นนั้นหลังจากจุดหนึ่ง ดู [internal: how-ai-agent-memory-works] สำหรับวิธีที่เอเจนต์จัดการปัญหานี้
การสตรีมโทเค็นเป็นเพียงขั้นตอนการอนุมานที่ทำให้มองเห็นได้
API แบบสตรีมมิ่งไม่ได้ทำอะไรที่แตกต่างกันในเชิงสถาปัตยกรรม พวกมันรันลูปการอนุมานและส่งโทเค็นแต่ละตัวไปยังสตรีมการตอบกลับเมื่อมันถูกสร้างขึ้นมา การทำความเข้าใจสิ่งนี้ช่วยได้เมื่อคุณเขียนตรรกะการลองใหม่: สตรีมที่หยุดชะงักระหว่างการสร้างไม่สามารถดำเนินการต่อได้ ต้องเริ่มต้นใหม่
Logits อธิบายว่าทำไมการสร้างเอาต์พุตที่มีโครงสร้างจึงเป็นเรื่องยาก
โมเดลจะกำหนดความน่าจะเป็นให้กับโทเค็นทุกตัวในคำศัพท์ในแต่ละขั้นตอน การสร้าง JSON ที่ถูกต้องนั้นต้องใช้โทเค็นที่เหมาะสมเพื่อให้ชนะในแต่ละตำแหน่ง ไลบรารีเช่น Outlines และ Guidance จะจำกัดการกระจาย logit เพื่อบังคับใช้ไวยากรณ์ในเวลาอนุมาน เมื่อคุณเห็น AI API เสนอโหมด "Structured output" นี่คือสิ่งที่พวกมันกำลังทำอยู่ภายใน
วิธีทดสอบการรวม AI API ด้วย Apidog
เมื่อคุณเข้าใจว่า LLM inference ทำงานอย่างไร คุณก็สามารถเขียนการทดสอบ API ที่ดีขึ้นมาก Test Scenarios ของ Apidog ช่วยให้คุณสามารถเชื่อมโยงการเรียก API และตรวจสอบโครงสร้างของการตอบกลับจาก AI ได้
ตัวอย่างเช่น เมื่อทดสอบ API แชทแบบสตรีมมิ่ง:
- สร้าง Test Scenario ใน Apidog ด้วย
/v1/chat/completionsendpoint ของคุณ - ตั้งค่า assertions เพื่อตรวจสอบโครงสร้างการตอบกลับ:
response.choices[0].finish_reason == "stop",response.usage.total_tokens < 4096 - เพิ่มขั้นตอนติดตามผลที่ส่งการตอบกลับเป็นบริบทไปยังการสนทนาครั้งต่อไป เพื่อจำลองการสนทนาแบบหลายเทิร์น
- ใช้ Smart Mock ของ Apidog เพื่อจำลอง AI endpoint และทดสอบการจัดการข้อผิดพลาดของแอปคุณ: จำลอง
finish_reason: "length"(เอาต์พุตถูกตัด),finish_reason: "content_filter"และ network timeout กลางสตรีม
นี่คือวิธีที่คุณจะทดสอบการรวม AI โดยไม่ต้องเผาผลาญเครดิต API ทุกครั้งที่รัน CI ดู [internal: api-testing-tutorial] สำหรับภาพรวมที่กว้างขึ้นของแนวทางการทดสอบ API
การทดสอบการยืนยันจำนวนโทเค็น
{
"assertions": [
{
"field": "response.usage.completion_tokens",
"operator": "less_than",
"value": 512
},
{
"field": "response.choices[0].finish_reason",
"operator": "equals",
"value": "stop"
},
{
"field": "response.choices[0].message.content",
"operator": "not_empty"
}
]
}
รันสิ่งนี้กับโมเดลหลายตัว (GPT-4o, Claude 3.5 Sonnet, Gemini 1.5 Pro) ใน Test Scenario เดียวกัน เพื่อจับความแตกต่างของ API Schema ก่อนที่จะเข้าสู่การผลิต
ขั้นสูง: การหาปริมาณและการเพิ่มประสิทธิภาพการอนุมาน
เมื่อคุณมี LLM ขนาดเล็กที่ใช้งานได้แล้ว มีเทคนิคสองอย่างที่ควรทำความเข้าใจเพราะมันนำไปใช้โดยตรงกับวิธีการให้บริการโมเดลสำหรับการผลิต
การหาปริมาณ (Quantization)
น้ำหนักในโมเดลของเราเป็น floating-point 32 บิตโดยค่าเริ่มต้น การหาปริมาณจะลดขนาดลงเหลือจำนวนเต็ม 8 บิต (INT8) หรือแม้แต่ 4 บิต (INT4) ซึ่งช่วยลดการใช้หน่วยความจำลง 4-8 เท่าโดยมีการสูญเสียความแม่นยำเล็กน้อย
# Example: dynamic INT8 quantization in PyTorch
import torch.quantization
quantized_model = torch.quantization.quantize_dynamic(
model, {nn.Linear}, dtype=torch.qint8
)
API สำหรับการผลิตจะรันโมเดลที่ผ่านการหาปริมาณ เมื่อคุณเห็นคุณภาพเอาต์พุตที่แตกต่างกันใน "เวอร์ชัน" ต่างๆ ของโมเดลเดียวกัน การหาปริมาณมักจะเกี่ยวข้องด้วย
แคช KV (KV cache)
ในลูปการอนุมานของเรา เราจะคำนวณ Attention ใหม่ตลอดทั้งลำดับในแต่ละขั้นตอน ระบบการผลิตจะแคชคู่คีย์-ค่าจากโทเค็นก่อนหน้า (KV cache) ดังนั้นโทเค็นใหม่แต่ละตัวต้องการการคำนวณ Attention ใหม่เพียงครั้งเดียว นี่คือสาเหตุที่โทเค็นแรกในการตอบสนองแบบสตรีมมิ่งใช้เวลานานกว่าโทเค็นถัดไป
Tiny LLM vs. API สำหรับการผลิต: จะใช้เมื่อใด
| กรณีการใช้งาน | Tiny LLM | API สำหรับการผลิต |
|---|---|---|
| เรียนรู้การทำงานภายในของโมเดล | ดีที่สุดสำหรับ | เกินความจำเป็น |
| สร้างแอปต้นแบบใหม่ | คุณภาพไม่เพียงพอ | ดีที่สุดสำหรับ |
| ข้อมูลส่วนตัว/ละเอียดอ่อน | ตัวเลือกที่ดี | ขึ้นอยู่กับผู้ให้บริการ |
| การปรับใช้แบบออฟไลน์/Edge | เป็นไปได้ | ไม่สามารถทำได้ |
| ต้นทุนต่ำ, ปริมาณมาก | เป็นไปได้โดยมีการแลกเปลี่ยน | แพงเมื่อขยายขนาด |
| งานที่เน้นการให้เหตุผล | ไม่สามารถทำได้ | จำเป็น |
คำตอบที่แท้จริงสำหรับนักพัฒนาส่วนใหญ่: ใช้ API สำหรับการผลิตสำหรับแอปพลิเคชันของคุณ แต่รันโมเดลขนาดเล็กเพื่อทำความเข้าใจว่าเกิดอะไรขึ้นภายใต้การทำงาน ทั้งสองไม่ได้แข่งขันกัน บทความ [internal: open-source-coding-assistants-2026] ครอบคลุมเครื่องมือที่ทำให้เส้นแบ่งนี้เบลอด้วยการตั้งค่า "bring-your-own-model"
สรุป
การสร้าง LLM ขนาดเล็กตั้งแต่เริ่มต้นใช้เวลาช่วงวันหยุดสุดสัปดาห์ สิ่งที่คุณได้รับไม่ใช่ระบบสำหรับการผลิต แต่มันคือโมเดลความคิดที่ใช้งานได้จริงว่าแบบจำลองภาษาทุกตัว ตั้งแต่ GuppyLM ไปจนถึง GPT-4o ทำงานอย่างไร ความเข้าใจนั้นคุ้มค่าทุกครั้งที่คุณแก้ไขข้อบกพร่องของการรวมระบบแบบสตรีมมิ่ง, ปรับแต่งพารามิเตอร์การสุ่มตัวอย่าง หรือออกแบบการยืนยันสำหรับการทดสอบ AI API ของคุณ
โปรเจกต์ GuppyLM เป็นจุดเริ่มต้นที่ดี คลอนมันมา ฝึกฝนด้วยชุดข้อมูลข้อความใดก็ได้ และใช้เวลาช่วงบ่ายอ่านลูปการอนุมาน จากนั้นกลับไปดูการรวม API สำหรับการผลิตของคุณ แล้วคุณจะเห็นมันในมุมมองที่แตกต่างออกไป
ลองใช้ Test Scenarios ของ Apidog เพื่อนำความเข้มงวดแบบเดียวกันมาใช้กับการทดสอบ AI API ของคุณ เหมือนที่คุณใช้กับระบบแบ็กเอนด์อื่นๆ
คำถามที่พบบ่อย
LLM "ขนาดเล็ก" ต้องการพารามิเตอร์จำนวนเท่าใดจึงจะสร้างข้อความที่สอดคล้องกันได้? ประมาณ 10M-50M พารามิเตอร์พร้อมชุดข้อมูลการฝึกที่ดีสามารถสร้างประโยคที่สอดคล้องกันในท้องถิ่นได้ ต่ำกว่า 1M คุณจะได้คำพูดที่ไร้สาระในงานส่วนใหญ่ GuppyLM ที่ 8.7M ใช้ได้ดีสำหรับการสนทนาสั้นๆ ในโดเมนการฝึก (60 หัวข้อ)
ฉันสามารถรัน LLM ขนาดเล็กโดยไม่มี GPU ได้หรือไม่? ได้ โมเดลที่มีพารามิเตอร์น้อยกว่า 100M ทำงานได้ดีบน CPU แม้ว่าการอนุมานจะช้ากว่าก็ตาม โมเดลข้างต้น (1.2M พารามิเตอร์) สร้างโทเค็นในเวลาไม่กี่มิลลิวินาทีบน CPU ของแล็ปท็อป
ฉันควรฝึกฝนด้วยชุดข้อมูลใด? โมเดลระดับอักขระทำงานได้ดีกับข้อความจาก Project Gutenberg, ชุดย่อยของ Wikipedia หรือคอร์ปัสข้อความธรรมดาใดๆ GuppyLM ใช้ชุดข้อมูลการสนทนา 60K รายการบน HuggingFace (arman-bd/guppylm-60k-generic) สำหรับการสร้างโค้ด ให้ใช้ The Stack หรือ CodeParrot
ความแตกต่างระหว่าง temperature และ top-k sampling คืออะไร? Temperature จะปรับขนาดการกระจาย logit (ควบคุมความสุ่มโดยรวม) Top-k จำกัดการสุ่มตัวอย่างให้เหลือเพียง k โทเค็นที่มีแนวโน้มมากที่สุดก่อนที่จะใช้ temperature ทั้งสองจะถูกนำมาใช้ร่วมกัน: ขั้นแรก top-k จะกรองผู้สมัคร จากนั้น temperature จะปรับรูปร่างความน่าจะเป็นภายในชุดนั้น
ทำไม LLM ของฉันจึงบางครั้งพูดซ้ำๆ? การพูดซ้ำเป็นโหมดความล้มเหลวที่โมเดลกำหนดความน่าจะเป็นสูงให้กับโทเค็นที่เพิ่งสร้างขึ้นมาเพราะมันปรากฏอยู่ในบริบท API สำหรับการผลิตใช้การลงโทษการพูดซ้ำ (การปรับ logit ที่ลดค่าโทเค็นที่เพิ่งสร้างขึ้นมา) เพิ่ม repetition_penalty=1.1 ในการเรียก API ของคุณเพื่อลดปัญหานี้
ใช้เวลาเท่าไหร่ในการฝึกฝน LLM ขนาดเล็ก? โมเดลข้างต้นฝึกฝนจนได้ผลลัพธ์ที่สอดคล้องกันภายใน 2 ชั่วโมงบน GPU ตัวเดียว (RTX 3060 หรือเทียบเท่า) GuppyLM ฝึกฝนใน Colab ใช้เวลาประมาณเท่ากัน โมเดลที่ใหญ่กว่า (100M+) ต้องการการตั้งค่าแบบ Multi-GPU และใช้เวลาฝึกฝนหลายวัน
วิธีที่เร็วที่สุดในการเปลี่ยนจาก LLM ขนาดเล็กไปเป็น API endpoint จริงคืออะไร? ส่งออกเป็นรูปแบบ GGUF โดยใช้สคริปต์การแปลงของ llama.cpp จากนั้นให้บริการด้วย llama-server ซึ่งจะให้ API endpoint ที่เข้ากันได้กับ OpenAI ที่รันในเครื่อง จากนั้นคุณสามารถชี้ Apidog ไปยังมันเพื่อทดสอบ ดู [internal: rest-api-best-practices]
LLM สำหรับการผลิตจัดการบริบทที่ยาวกว่าหน้าต่างการฝึกฝนของมันได้อย่างไร? เทคนิคต่างๆ เช่น RoPE (Rotary Position Embedding) พร้อมการปรับขนาดที่ขยายออก, sliding window attention และ retrieval-augmented generation ล้วนช่วยขยายบริบทที่มีประสิทธิภาพ สถาปัตยกรรม Transformer หลักไม่ได้เปลี่ยนแปลงไป สิ่งเหล่านี้เป็นการปรับเปลี่ยนวิธีการเข้ารหัสข้อมูลตำแหน่งและวิธีการนำหน้าต่าง attention มาใช้
