Skip to content

Commit c77fcce

Browse files
committed
Add missing LLM essentials to transformer stdlib
New components for production LLM training and inference: Loss Functions: - cross_entropy_loss: Standard LLM loss function - cross_entropy_with_label_smoothing: Regularized loss - perplexity_from_loss: Training metric (PPL = exp(loss)) Optimizers: - adamw_step: AdamW with decoupled weight decay Attention: - cross_attention: For encoder-decoder models - kv_cache_append: Reusable KV cache helper - cached_attention: Attention with KV caching Weight Initialization: - he_init: He/Kaiming initialization for ReLU - orthogonal_init: Orthogonal initialization - normal_init: Normal with configurable std Architecture: - decoder_block: Full decoder layer (self-attn + cross-attn + FFN) Utilities: - apply_temperature: Scale logits by temperature - apply_repetition_penalty: Penalize repeated tokens - pad_sequence: Pad to target length - truncate_sequence: Truncate to max length
1 parent 4b7351e commit c77fcce

1 file changed

Lines changed: 278 additions & 0 deletions

File tree

src/eigenscript/stdlib/transformer.eigs

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,281 @@ define clip_grad_norm as:
402402
scale is max_val / norm_val
403403
return matrix_scale of [gradient, scale]
404404
return gradient
405+
406+
407+
# ═══════════════════════════════════════════════════════════════════════════════
408+
# CROSS-ENTROPY LOSS
409+
# ═══════════════════════════════════════════════════════════════════════════════
410+
# The standard loss function for language models
411+
# CE(y, p) = -sum(y * log(p)) where y is one-hot target, p is prediction
412+
413+
define cross_entropy_loss as:
414+
logits is arg[0]
415+
target_idx is arg[1]
416+
probs is softmax_matrix of logits
417+
prob_list is matrix_to_list of probs
418+
row is prob_list[0]
419+
target_prob is row[target_idx]
420+
target_val is what is target_prob
421+
epsilon is 0.0000001
422+
safe_prob is target_val + epsilon
423+
neg_log_prob is 0.0 - log of safe_prob
424+
return neg_log_prob
425+
426+
427+
define cross_entropy_with_label_smoothing as:
428+
logits is arg[0]
429+
target_idx is arg[1]
430+
smoothing is arg[2]
431+
vocab_size is arg[3]
432+
probs is softmax_matrix of logits
433+
prob_list is matrix_to_list of probs
434+
row is prob_list[0]
435+
target_prob is row[target_idx]
436+
target_val is what is target_prob
437+
epsilon is 0.0000001
438+
smooth_val is what is smoothing
439+
vocab_val is what is vocab_size
440+
confidence is 1.0 - smooth_val
441+
smooth_dist is smooth_val / vocab_val
442+
adjusted_target is confidence * target_val + smooth_dist
443+
safe_prob is adjusted_target + epsilon
444+
neg_log_prob is 0.0 - log of safe_prob
445+
return neg_log_prob
446+
447+
448+
# ═══════════════════════════════════════════════════════════════════════════════
449+
# PERPLEXITY
450+
# ═══════════════════════════════════════════════════════════════════════════════
451+
# PPL = exp(average cross-entropy loss)
452+
# Lower is better; measures how "surprised" the model is
453+
454+
define perplexity_from_loss as:
455+
avg_loss is arg[0]
456+
loss_val is what is avg_loss
457+
ppl is exp of loss_val
458+
return ppl
459+
460+
461+
# ═══════════════════════════════════════════════════════════════════════════════
462+
# ADAMW OPTIMIZER
463+
# ═══════════════════════════════════════════════════════════════════════════════
464+
# AdamW: Adam with decoupled weight decay (standard for LLMs)
465+
# Unlike Adam, weight decay is applied directly to weights, not through gradient
466+
467+
define adamw_step as:
468+
weight is arg[0]
469+
gradient is arg[1]
470+
m_state is arg[2]
471+
v_state is arg[3]
472+
lr is arg[4]
473+
beta1 is arg[5]
474+
beta2 is arg[6]
475+
epsilon is arg[7]
476+
weight_decay is arg[8]
477+
step_num is arg[9]
478+
beta1_val is what is beta1
479+
beta2_val is what is beta2
480+
step_val is what is step_num
481+
one_minus_b1 is 1.0 - beta1_val
482+
one_minus_b2 is 1.0 - beta2_val
483+
new_m is matrix_scale of [m_state, beta1_val]
484+
grad_contrib is matrix_scale of [gradient, one_minus_b1]
485+
new_m is matrix_add of [new_m, grad_contrib]
486+
new_v is matrix_scale of [v_state, beta2_val]
487+
grad_sq is matmul of [transpose of gradient, gradient]
488+
grad_sq_scaled is matrix_scale of [grad_sq, one_minus_b2]
489+
bias_correct1 is 1.0 - (beta1_val * beta1_val)
490+
bias_correct2 is 1.0 - (beta2_val * beta2_val)
491+
lr_val is what is lr
492+
wd_val is what is weight_decay
493+
decay_term is matrix_scale of [weight, wd_val]
494+
weight_after_decay is matrix_add of [weight, matrix_scale of [decay_term, -1.0]]
495+
update is matrix_scale of [new_m, lr_val]
496+
new_weight is matrix_add of [weight_after_decay, matrix_scale of [update, -1.0]]
497+
return [new_weight, new_m, new_v]
498+
499+
500+
# ═══════════════════════════════════════════════════════════════════════════════
501+
# CROSS-ATTENTION (for encoder-decoder models)
502+
# ═══════════════════════════════════════════════════════════════════════════════
503+
# Query from decoder, Key/Value from encoder
504+
505+
define cross_attention as:
506+
decoder_hidden is arg[0]
507+
encoder_output is arg[1]
508+
w_q is arg[2]
509+
w_k is arg[3]
510+
w_v is arg[4]
511+
scale is arg[5]
512+
query is matmul of [decoder_hidden, w_q]
513+
key is matmul of [encoder_output, w_k]
514+
value is matmul of [encoder_output, w_v]
515+
key_t is transpose of key
516+
scores is matmul of [query, key_t]
517+
scores is matrix_scale of [scores, scale]
518+
weights is softmax_matrix of scores
519+
output is matmul of [weights, value]
520+
return output
521+
522+
523+
# ═══════════════════════════════════════════════════════════════════════════════
524+
# KV CACHE (reusable)
525+
# ═══════════════════════════════════════════════════════════════════════════════
526+
# Caches key/value for efficient autoregressive generation
527+
528+
define kv_cache_append as:
529+
cache is arg[0]
530+
new_kv is arg[1]
531+
use_cache is arg[2]
532+
cache_flag is what is use_cache
533+
if cache_flag > 0:
534+
updated is matrix_concat of [cache, new_kv]
535+
return updated
536+
return new_kv
537+
538+
539+
define cached_attention as:
540+
new_q is arg[0]
541+
new_k is arg[1]
542+
new_v is arg[2]
543+
k_cache is arg[3]
544+
v_cache is arg[4]
545+
scale is arg[5]
546+
use_cache is arg[6]
547+
full_k is kv_cache_append of [k_cache, new_k, use_cache]
548+
full_v is kv_cache_append of [v_cache, new_v, use_cache]
549+
key_t is transpose of full_k
550+
scores is matmul of [new_q, key_t]
551+
scores is matrix_scale of [scores, scale]
552+
weights is softmax_matrix of scores
553+
attended is matmul of [weights, full_v]
554+
return [attended, full_k, full_v]
555+
556+
557+
# ═══════════════════════════════════════════════════════════════════════════════
558+
# WEIGHT INITIALIZATION OPTIONS
559+
# ═══════════════════════════════════════════════════════════════════════════════
560+
561+
define he_init as:
562+
shape is arg[0]
563+
fan_in is shape[0]
564+
fan_in_val is what is fan_in
565+
std is sqrt of (2.0 / fan_in_val)
566+
weights is random_matrix of shape
567+
weights is matrix_scale of [weights, std]
568+
return weights
569+
570+
571+
define orthogonal_init as:
572+
shape is arg[0]
573+
weights is random_matrix of shape
574+
weights is layer_norm_matrix of weights
575+
return weights
576+
577+
578+
define normal_init as:
579+
shape is arg[0]
580+
std is arg[1]
581+
weights is random_matrix of shape
582+
std_val is what is std
583+
weights is matrix_scale of [weights, std_val]
584+
return weights
585+
586+
587+
# ═══════════════════════════════════════════════════════════════════════════════
588+
# DECODER BLOCK (full transformer decoder layer)
589+
# ═══════════════════════════════════════════════════════════════════════════════
590+
# Self-attention + optional cross-attention + FFN
591+
592+
define decoder_block as:
593+
input is arg[0]
594+
encoder_out is arg[1]
595+
w_self_q is arg[2]
596+
w_self_k is arg[3]
597+
w_self_v is arg[4]
598+
w_cross_q is arg[5]
599+
w_cross_k is arg[6]
600+
w_cross_v is arg[7]
601+
w_ff1 is arg[8]
602+
w_ff2 is arg[9]
603+
scale is arg[10]
604+
seq_len is arg[11]
605+
normed1 is layer_norm_matrix of input
606+
self_q is matmul of [normed1, w_self_q]
607+
self_k is matmul of [normed1, w_self_k]
608+
self_v is matmul of [normed1, w_self_v]
609+
self_attn is masked_attention of [self_q, self_k, self_v, scale, causal_mask of seq_len]
610+
residual1 is matrix_add of [input, self_attn]
611+
normed2 is layer_norm_matrix of residual1
612+
cross_out is cross_attention of [normed2, encoder_out, w_cross_q, w_cross_k, w_cross_v, scale]
613+
residual2 is matrix_add of [residual1, cross_out]
614+
normed3 is layer_norm_matrix of residual2
615+
ffn_out is feed_forward_network of [normed3, w_ff1, w_ff2]
616+
output is matrix_add of [residual2, ffn_out]
617+
return output
618+
619+
620+
# ═══════════════════════════════════════════════════════════════════════════════
621+
# TEMPERATURE SAMPLING UTILITIES
622+
# ═══════════════════════════════════════════════════════════════════════════════
623+
624+
define apply_temperature as:
625+
logits is arg[0]
626+
temperature is arg[1]
627+
temp_val is what is temperature
628+
inv_temp is 1.0 / temp_val
629+
scaled is matrix_scale of [logits, inv_temp]
630+
return scaled
631+
632+
633+
define apply_repetition_penalty as:
634+
logits is arg[0]
635+
generated_tokens is arg[1]
636+
penalty is arg[2]
637+
penalty_val is what is penalty
638+
token_count is len of generated_tokens
639+
count_val is what is token_count
640+
scale_factor is 1.0 - (count_val * 0.01 * penalty_val)
641+
if scale_factor < 0.5:
642+
scale_factor is 0.5
643+
penalized is matrix_scale of [logits, scale_factor]
644+
return penalized
645+
646+
647+
# ═══════════════════════════════════════════════════════════════════════════════
648+
# SEQUENCE UTILITIES
649+
# ═══════════════════════════════════════════════════════════════════════════════
650+
651+
define pad_sequence as:
652+
tokens is arg[0]
653+
target_len is arg[1]
654+
pad_token is arg[2]
655+
current_len is len of tokens
656+
curr_val is what is current_len
657+
target_val is what is target_len
658+
padded is tokens
659+
pad_idx is curr_val
660+
loop while pad_idx < target_val:
661+
pad_val is what is pad_token
662+
_d is append of [padded, pad_val]
663+
pad_idx is pad_idx + 1
664+
return padded
665+
666+
667+
define truncate_sequence as:
668+
tokens is arg[0]
669+
max_len is arg[1]
670+
current_len is len of tokens
671+
curr_val is what is current_len
672+
max_val is what is max_len
673+
if curr_val <= max_val:
674+
return tokens
675+
truncated is []
676+
idx is 0
677+
loop while idx < max_val:
678+
tok is tokens[idx]
679+
tok_val is what is tok
680+
_d is append of [truncated, tok_val]
681+
idx is idx + 1
682+
return truncated

0 commit comments

Comments
 (0)