Bỏ qua tới nội dung chính
Quay lại tin tức

microgpt

Andrej Karpathy Blog· 12/2/2026models

Đây là hướng dẫn ngắn gọn về dự án nghệ thuật mới microgpt của tôi, một tệp gồm 200 dòng Python thuần túy không có phần phụ thuộc giúp đào tạo và suy luận GPT. Tệp này chứa nội dung thuật toán đầy đủ về những thứ cần thiết: tập dữ liệu tài liệu, mã thông báo, công cụ tự động chuyển đổi, kiến ​​trúc mạng thần kinh giống GPT-2, trình tối ưu hóa Adam, vòng lặp đào tạo và vòng suy luận. Mọi thứ khác chỉ là hiệu quả. Tôi không thể đơn giản hóa điều này hơn nữa. Kịch bản này là đỉnh cao của nhiều dự án (micrograd, makemore, nanogpt, v.v.) và nỗi ám ảnh kéo dài hàng thập kỷ nhằm đơn giản hóa LLM thành những điều cơ bản nhất của chúng và

Đây là hướng dẫn ngắn gọn về dự án nghệ thuật mới microgpt của tôi, một tệp gồm 200 dòng Python thuần túy không có phần phụ thuộc giúp đào tạo và suy luận GPT. Tệp này chứa nội dung thuật toán đầy đủ về những thứ cần thiết: tập dữ liệu tài liệu, mã thông báo, công cụ tự động chuyển đổi, kiến ​​trúc mạng thần kinh giống GPT-2, trình tối ưu hóa Adam, vòng lặp đào tạo và vòng suy luận. Mọi thứ khác chỉ là hiệu quả. Tôi không thể đơn giản hóa điều này hơn nữa. Kịch bản này là đỉnh cao của nhiều dự án (micrograd, makemore, nanogpt, v.v.) và nỗi ám ảnh kéo dài hàng thập kỷ nhằm đơn giản hóa LLM thành những điều cơ bản nhất của chúng và tôi nghĩ nó thật đẹp 🥹. Nó thậm chí còn phá vỡ hoàn hảo trên 3 cột: Tìm nó ở đâu: Ý chính GitHub này có mã nguồn đầy đủ: microgpt.py Nó cũng có sẵn trên trang web này: https://karpathy.ai/microgpt.html Cũng có sẵn dưới dạng sổ ghi chép Google Colab MỚI: mua microgpt dưới dạng bộ ba trên cửa hàng nghệ thuật của tôi tại karpathy.art :) Sau đây là hướng dẫn của tôi về cách hướng dẫn người đọc quan tâm thực hiện mã. Tập dữ liệu Nguồn nhiên liệu của các mô hình ngôn ngữ lớn là luồng dữ liệu văn bản, được phân tách tùy ý thành một bộ tài liệu. Trong các ứng dụng cấp sản xuất, mỗi tài liệu sẽ là một trang web internet nhưng đối với microgpt, chúng tôi sử dụng một ví dụ đơn giản hơn gồm 32.000 tên, mỗi tên một dòng: # Giả sử có một tập dữ liệu đầu vào `docs`: list[str] các tài liệu (ví dụ: tập dữ liệu về tên) nếu không phải os.path.exists('input.txt'): nhập urllib.request name_url = 'https://raw.githubusercontent.com/karpathy/makemore/refs/heads/master/names.txt' urllib.request.urlretrieve(names_url, 'input.txt') docs = [l.strip() for l in open('input.txt').read().strip().split('\n') if l.strip()] # list[str] của tài liệu ngẫu nhiên.shuffle(docs) print(f"num docs: {len(docs)}") Tập dữ liệu trông như thế này. Mỗi tên là một tài liệu: emma Olivia ava Isabella sophia charlotte Mia amelia người chơi đàn hạc ... (~32.000 tên theo dõi) Mục tiêu của mô hình là tìm hiểu các mẫu trong dữ liệu và sau đó tạo ra các tài liệu mới tương tự có chung các mẫu thống kê bên trong. Ở dạng xem trước, ở cuối tập lệnh, mô hình của chúng tôi sẽ tạo ra những cái tên mới (“ảo giác”!) mới, nghe có vẻ hợp lý. Bỏ qua phía trước, chúng ta sẽ nhận được: mẫu 1: kamon mẫu 2: ann mẫu 3: karai mẫu 4: jaire mẫu 5: vialan mẫu 6: karia mẫu 7: yeran mẫu 8: anna mẫu 9: areli mẫu 10: kaina mẫu 11: kona mẫu 12: keylen mẫu 13: liole mẫu 14: alerin mẫu 15: tai mẫu 16: lenne mẫu 17: kana mẫu 18: lara mẫu 19: alela mẫu 20: anton Trông thì không nhiều nhưng dưới góc nhìn của một mô hình như ChatGPT, cuộc trò chuyện của bạn với nó chỉ là một “tài liệu” trông buồn cười. Khi bạn khởi tạo tài liệu bằng lời nhắc của mình, phản hồi của mô hình từ góc độ của nó chỉ là việc hoàn thành tài liệu thống kê. Mã thông báo Về cơ bản, mạng lưới thần kinh hoạt động với các con số chứ không phải ký tự, vì vậy chúng ta cần một cách để chuyển đổi văn bản thành một chuỗi các id mã thông báo số nguyên và ngược lại. Các mã thông báo sản xuất như tiktoken (được GPT-4 sử dụng) hoạt động trên các khối ký tự để đạt hiệu quả, nhưng mã thông báo đơn giản nhất có thể chỉ gán một số nguyên cho mỗi ký tự duy nhất trong tập dữ liệu: # Hãy có một Tokenizer để dịch các chuỗi thành các ký hiệu rời rạc và ngược lại uchars = được sắp xếp(set(''.join(docs))) # ký tự duy nhất trong tập dữ liệu trở thành id mã thông báo 0..n-1 BOS = len(uchars) # mã thông báo id cho mã thông báo Bắt đầu chuỗi (BOS) đặc biệt vocab_size = len(uchars) + 1 # tổng số mã thông báo duy nhất, +1 dành cho BOS print(f"kích thước từ vựng: {vocab_size}") Trong đoạn mã trên, chúng tôi thu thập tất cả các ký tự duy nhất trên tập dữ liệu (chỉ là tất cả các chữ cái viết thường từ a đến z), sắp xếp chúng và mỗi chữ cái sẽ nhận được một id theo chỉ mục của nó. Lưu ý rằng bản thân các giá trị số nguyên không có ý nghĩa gì cả; mỗi mã thông báo chỉ là một biểu tượng riêng biệt. Thay vì 0, 1, 2, chúng có thể là các biểu tượng cảm xúc khác nhau. Ngoài ra, chúng tôi tạo thêm một mã thông báo đặc biệt gọi là BOS (Bắt đầu chuỗi), hoạt động như một dấu phân cách: nó cho mô hình biết “một tài liệu mới bắt đầu/kết thúc tại đây”. Sau này trong quá trình đào tạo, mỗi tài liệu sẽ được bọc BOS trên cả hai mặt: [BOS, e, m, m, a, BOS]. Mô hình biết rằng BOS đặt tên mới và BOS khác kết thúc tên đó. Do đó, chúng tôi có từ vựng cuối cùng là 27 (26 ký tự chữ thường có thể có từ a-z và +1 cho mã thông báo BOS). Tự động tốt nghiệp Việc đào tạo mạng nơ-ron yêu cầu độ dốc: đối với mỗi tham số trong mô hình, chúng ta cần biết “nếu tôi nâng con số này lên một chút thì tổn thất sẽ tăng hay giảm và tăng bao nhiêu?”. Biểu đồ tính toán có nhiều đầu vào (tham số mô hình và mã thông báo đầu vào) nhưng chuyển xuống một đầu ra vô hướng duy nhất: tổn thất (chúng tôi sẽ xác định chính xác tổn thất bên dưới). Lan truyền ngược bắt đầu ở đầu ra duy nhất đó và hoạt động ngược lại thông qua biểu đồ, tính toán độ dốc của tổn thất đối với mọi đầu vào. Nó dựa vào quy tắc dây chuyền từ phép tính. Trong quá trình sản xuất, các thư viện như PyTorch tự động xử lý việc này. Ở đây, chúng tôi triển khai nó từ đầu trong một lớp duy nhất có tên là Value: Giá trị lớp: __slots__ = ('dữ liệu', 'grad', '_children', '_local_grads') def __init__(self, data, Children=(), local_grads=()): self.data = data # giá trị vô hướng của nút này được tính toán trong quá trình chuyển tiếp self.grad = 0 # phái sinh của tổn thất w.r.t. nút này, được tính theo đường truyền ngược self._children = con # con của nút này trong biểu đồ tính toán self._local_grads = local_grads # đạo hàm cục bộ của nút này w.r.t. con cái của nó def __add__(bản thân, người khác): other = other if isinstance(other, Value) else Value(other) trả về Giá trị(self.data + other.data, (self, other), (1, 1)) def __mul__(bản thân, người khác): other = other if isinstance(other, Value) else Value(other) trả về Giá trị(self.data * other.data, (self, other), (other.data, self.data)) def __pow__(self, other): trả về Giá trị(self.data**other, (self,), (other * self.data**(other-1),)) def log(self): trả về Giá trị(math.log(self.data), (self,), (1/self.data,)) def exp(self): trả về Giá trị(math.exp(self.data), (self,), (math.exp(se

Nguồn tin: Andrej Karpathy Blog. Bản dịch tiếng Việt do AI thực hiện, có thể có sai sót.