Text Generation
English
nsfw
pretrained
gpt

bytestalkai/SmallNSFW-28.8M_pretrained β€” A Lightweight Language Model for Adult Content Generation

bytestalkai/Small-28.8M_pretrained is a small, autoregressive language model trained specifically for generating fluent, story-driven adult content. This model is intended for research and creative applications where mature themes are required, and it aims to deliver NSFW text with natural pacing, realistic dialogue, and structured narratives.


What is bytestalkai/SmallNSFW-28.8M_pretrained?

bytestalkai/SmallNSFW-28.8M_pretrained is a compact GPT-style model trained from scratch to understand and generate adult-themed fiction. Unlike general-purpose LLMs, the model was trained on NSFW datasets only.


How It Was Trained

  • Training Objective: Causal language modeling (next-token prediction)
  • Dataset Size: ~50 million tokens total (train + validation)
  • Parameter Count: ~28.8M
  • Language: English
  • Data Sources:
    • A mixture of publicly available NSFW story datasets

The model was trained on multiple datasets containing user-submitted erotic fiction.


Intended Use

bytestalkai/SmallNSFW-28.8M_pretrained is designed for:

  • Erotic and adult story generation
  • Character-based dialogue simulations
  • Interactive fiction

This model is not intended for commercial use where platform policy or local laws restrict the distribution or generation of adult content.


Disclaimer

This model is not safe for use by minors or in environments where NSFW content is prohibited. The authors are not responsible for misuse. Always respect applicable laws and community guidelines.


Metadata

  • License: MIT
  • Pipeline: text-generation
  • Language: English
  • Tags: nsfw, pretrained, gpt
  • Datasets Used:
    • bluuwhale/nsfwstory2
    • bluuwhale/scrappednsfwstory
    • bluuwhale/nsfwstory

License

MIT License β€” free for personal and research use.


πŸ”§ How to Run the Model

You can run the model locally using the following Python script. Make sure the files 28m_model.pt and model_config.pt are in the same directory.

import torch
import torch.nn as nn
from torch.nn import functional as F
import math
import tiktoken
import time
import os

device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(f"Using device: {device}")

PROMPT = "INSERT YOUR PROMPT HERE"

n_embd = 384
n_head = 6
n_layer = 8
block_size = 128
dropout = 0.20

enc = tiktoken.get_encoding("gpt2")
vocab_size = enc.n_vocab

class MultiHeadAttention(nn.Module):
    def __init__(self, n_embd, n_head, block_size, dropout=0.1):
        super().__init__()
        assert n_embd % n_head == 0
        self.n_head = n_head
        self.head_size = n_embd // n_head

        self.qkv = nn.Linear(n_embd, 3 * n_embd, bias=False)
        self.proj = nn.Linear(n_embd, n_embd, bias=False)
        self.dropout = nn.Dropout(dropout)

        self.register_buffer("bias", torch.tril(torch.ones(block_size, block_size))
                                     .view(1, 1, block_size, block_size))

    def forward(self, x):
        B, T, C = x.size()
        qkv = self.qkv(x).view(B, T, 3, self.n_head, self.head_size).permute(2, 0, 3, 1, 4)
        q, k, v = qkv[0], qkv[1], qkv[2]

        att = (q @ k.transpose(-2, -1)) * (1.0 / math.sqrt(self.head_size))
        att = att.masked_fill(self.bias[:,:,:T,:T] == 0, float('-inf'))
        att = F.softmax(att, dim=-1)
        att = self.dropout(att)

        y = att @ v
        y = y.transpose(1, 2).contiguous().view(B, T, C)
        y = self.proj(y)
        return y

class FeedForward(nn.Module):
    def __init__(self, n_embd, dropout=0.1):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(n_embd, 2 * n_embd, bias=False),
            nn.GELU(),
            nn.Linear(2 * n_embd, n_embd, bias=False),
            nn.Dropout(dropout),
        )

    def forward(self, x):
        return self.net(x)

class Block(nn.Module):
    def __init__(self, n_embd, n_head, block_size, dropout=0.1):
        super().__init__()
        self.ln1 = nn.LayerNorm(n_embd, bias=False)
        self.attn = MultiHeadAttention(n_embd, n_head, block_size, dropout)
        self.ln2 = nn.LayerNorm(n_embd, bias=False)
        self.mlp = FeedForward(n_embd, dropout)

    def forward(self, x):
        x = x + self.attn(self.ln1(x))
        x = x + self.mlp(self.ln2(x))
        return x

class BigramLanguageModel(nn.Module):
    def __init__(self, vocab_size, n_embd, n_head, n_layer, block_size, dropout=0.1):
        super().__init__()
        self.block_size = block_size

        self.token_embedding_table = nn.Embedding(vocab_size, n_embd)
        self.position_embedding_table = nn.Embedding(block_size, n_embd)
        self.blocks = nn.Sequential(*[Block(n_embd, n_head, block_size, dropout) for _ in range(n_layer)])
        self.ln_f = nn.LayerNorm(n_embd, bias=False)
        self.lm_head = nn.Linear(n_embd, vocab_size, bias=False)

        self.lm_head.weight = self.token_embedding_table.weight

        self.apply(self._init_weights)

    def _init_weights(self, module):
        if isinstance(module, nn.Linear):
            torch.nn.init.normal_(module.weight, mean=0.0, std=0.02)
        elif isinstance(module, nn.Embedding):
            torch.nn.init.normal_(module.weight, mean=0.0, std=0.02)

    def forward(self, idx, targets=None):
        B, T = idx.shape

        tok_emb = self.token_embedding_table(idx)
        pos_emb = self.position_embedding_table(torch.arange(T, device=idx.device))
        x = tok_emb + pos_emb
        x = self.blocks(x)
        x = self.ln_f(x)
        logits = self.lm_head(x)

        if targets is None:
            loss = None
        else:
            B, T, C = logits.shape
            logits = logits.view(B*T, C)
            targets = targets.view(B*T)
            loss = F.cross_entropy(logits, targets)

        return logits, loss

def encode(text):
    return enc.encode(text)

def decode(tokens):
    return enc.decode(tokens)

def generate_text(model, prompt="", max_tokens=500, temperature=0.8, top_k=50):
    model.eval()

    if prompt:
        context = torch.tensor([encode(prompt)], dtype=torch.long, device=device)
    else:
        context = torch.zeros((1, 1), dtype=torch.long, device=device)

    generated_tokens = []

    with torch.no_grad():
        for i in range(max_tokens):
            idx_cond = context if context.size(1) <= block_size else context[:, -block_size:]
            logits, _ = model(idx_cond)
            logits = logits[:, -1, :] / temperature

            if top_k is not None:
                v, _ = torch.topk(logits, min(top_k, logits.size(-1)))
                logits[logits < v[:, [-1]]] = -float('Inf')

            probs = F.softmax(logits, dim=-1)
            idx_next = torch.multinomial(probs, num_samples=1)
            context = torch.cat((context, idx_next), dim=1)
            generated_tokens.append(idx_next.item())

    return decode(generated_tokens)

def load_model():
    if not os.path.exists('model_config.pt'):
        print("❌ Model config file not found: model_config.pt")
        return None
        
    if not os.path.exists('28m_model.pt'):
        print("❌ Model weights file not found: 28m_model.pt")
        return None
        
    config = torch.load('model_config.pt', map_location=device)
    print("βœ“ Configuration loaded")

    model = BigramLanguageModel(
        vocab_size=vocab_size,
        n_embd=n_embd,
        n_head=n_head,
        n_layer=n_layer,
        block_size=block_size,
        dropout=dropout
    )

    checkpoint = torch.load('28m_model.pt', map_location=device)
    model.load_state_dict(checkpoint['model_state_dict'])
    model = model.to(device)
    model.eval()

    print(f"βœ“ Model loaded successfully!")
    
    return model

if __name__ == "__main__":
    print("Loading model...")
    
    try:
        model = load_model()
        if model is None:
            exit()
        
        start_time = time.time()
        generated_text = generate_text(
            model, 
            prompt=PROMPT, 
            max_tokens=150, 
            temperature=0.8, 
            top_k=50
        )
        generation_time = time.time() - start_time
        
        print(f"\n GENERATED TEXT ({generation_time:.1f}s):")
        print("-" * 50)
        print(f"{PROMPT}{generated_text}")
        print("-" * 50)
        
    except Exception as e:
        print(f"❌ Error: {e}")
        print("Please make sure:")
        print("1. The model files (28m_model.pt and model_config.pt) are in the same directory")
        print("2. The model architecture matches the code")
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Datasets used to train bytestalkai/SmallNSFW-28.8M_pretrained