1 điểm bởi GN⁺ 2023-07-24 | 1 bình luận | Chia sẻ qua WhatsApp
  • llama2.c là một giải pháp huấn luyện và suy luận “fullstack”, huấn luyện kiến trúc Llama 2 LLM bằng PyTorch và suy luận bằng tệp C đơn giản run.c
  • Trọng tâm cốt lõi là chủ nghĩa tối giản và sự đơn giản, là một triển khai mang tính giáo dục với kiến trúc Llama 2 được hard-code và chỉ gồm một tệp suy luận C thuần túy không có phụ thuộc
  • Dựa trên quan điểm rằng ngay cả LLM rất nhỏ cũng có thể đạt hiệu năng mạnh nếu thu hẹp miền bài toán đủ nhiều, dự án cung cấp mô hình ví dụ dựa trên TinyStories
    • Mô hình 15M tham số có dung lượng tải về khoảng 60MB và có thể chạy bằng make run rồi ./run stories15M.bin
    • Các mô hình 42M và 110M tham số cũng được cung cấp, và mô hình 110M được nêu rõ là có cùng kích thước với GPT-1
  • Các mô hình Llama 2 của Meta cũng có thể suy luận vì kiến trúc mạng nơ-ron là như nhau, nhưng cần nhận checkpoint theo hướng dẫn của Meta rồi chuyển đổi sang định dạng llama2.c bằng export.py
    • Hiện tại run.c chỉ thực hiện suy luận fp32, nên các mô hình lớn hơn 7B có khả năng khó tải một cách thực tế trong môi trường production
    • Từ 13B trở lên hiện không hoạt động do integer overflow trong phép toán con trỏ, và vẫn chưa được sửa
  • Suy luận lượng tử hóa int8 được triển khai trong runq.c, sử dụng phương thức Q8_0 để lượng tử hóa các trọng số tham gia vào matmul, đồng thời các giá trị kích hoạt cũng được lượng tử hóa và giải lượng tử động trong lúc chạy
    • Bản export fp32 của Llama 2 7B tạo ra tệp 26GB, còn bản export lượng tử hóa version 2 tạo ra tệp 6.7GB
    • Trong môi trường của tác giả với OpenMP 64 luồng, fp32 chạy ở 4.6 tok/s còn int8 là 14 tok/s, giúp giảm kích thước checkpoint 4 lần và tăng tốc khoảng 3 lần
  • Cách sử dụng gồm chạy suy luận C, nhập prompt, điều khiển lấy mẫu temperature và top-p, chạy chế độ chat, và chỉ định tokenizer tùy chỉnh
    • Ví dụ chạy có dạng ./run stories42M.bin -t 0.8 -n 256 -i "One day, Lily met a Shoggoth"
    • Mô hình chat chạy bằng cờ -m chat như ./run llama2_7b_chat.bin -m chat
    • Tokenizer tùy chỉnh được export sang định dạng .bin bằng tokenizer.py rồi chỉ định bằng cờ -z
  • Các mô hình trên Hugging Face dùng kiến trúc Llama 2 có thể được export sang tệp .bin bằng cờ --hf của export.py
  • Quy trình huấn luyện tiếp nối từ tải xuống và tiền token hóa TinyStories, chạy train.py, rồi export mô hình và suy luận bằng C
    • Ví dụ TinyStories mặc định hiện là ví dụ dataset duy nhất được cung cấp
    • Việc huấn luyện tokenizer tùy chỉnh sử dụng sentencepiece, với ví dụ dùng thiết lập --vocab_size=4096
  • Các bản build liên quan đến hiệu năng được chia thành make run, make runfast, make runomp, trong đó bản build OpenMP kích hoạt #pragma omp parallel for bên trong matmul và attention để chia công việc vòng lặp cho nhiều bộ xử lý
  • Hướng dẫn build theo nền tảng được cung cấp cho Windows, Centos 7, Amazon Linux 2018 và Mac
    • Windows dùng build_msvc.bat hoặc make win64
    • Centos 7 và Amazon Linux 2018 dùng make rungnu hoặc make runompgnu
    • Bản build OpenMP trên Mac dùng clang từ brew rồi chạy make runomp CC=/opt/homebrew/opt/llvm/bin/clang
  • Kiểm thử cung cấp pytest và bài test C make testcc, còn test_all.py chạy 200 bước forward trong C và Python để so sánh với đầu ra kỳ vọng đã biết
  • Mục tiêu của dự án là duy trì một triển khai tham chiếu đơn giản gồm 2 tệp .py dễ đọc cho mã huấn luyện và mã suy luận C, không hướng đến framework phức tạp hay quá nhiều tùy chọn
  • Giấy phép là MIT

1 bình luận

 
GN⁺ 2023-07-24
Ý kiến Hacker News
  • Thấy bài này trên HN khá thú vị :) checkpoint gốc chạy nhanh hơn kỳ vọng rất nhiều trên MacBook Air M1 khi biên dịch với -O3, đạt 100 tok/s, nên giờ đang huấn luyện một mô hình 44M lớn hơn
    Có vẻ vẫn sẽ chạy được ở chế độ tương tác, và thậm chí có cảm giác biết đâu mô hình Llama 7B cũng có thể với tới

    • Mình đã chỉnh nanoGPT một chút để thử tiền huấn luyện một mô hình 12M trên 2GB dữ liệu do GPT-4 tạo từ TinyStories, và kết quả khá bất ngờ
      Sau đó mình cho nó thích nghi thêm với Wikipedia, và nó trở thành một cỗ máy tạo ra nội dung nghe có vẻ hợp lý nhưng vô nghĩa, thông minh hơn rất nhiều và nhỏ hơn rất nhiều so với mô hình n-gram được làm trơn. Có vẻ các LLM nhỏ sẽ trở thành xu hướng chủ đạo ở nhiều lĩnh vực, và mục tiêu tiếp theo là thu nhỏ Llama2 7B xuống 10~100M mà không làm nó ngốc đi quá nhiều
    • Như mọi khi, công việc này truyền cảm hứng. Câu hỏi hơi ngây ngô, nhưng mình tò mò đâu là con đường thực tế nhất để chạy một LLM có kích thước hợp lý trên một máy chủ Linux bình thường không có GPU xịn, để gắn vào một web app làm chơi
      Thuê instance GPU ở mấy nơi như Linode đắt hơn rất nhiều so với máy chủ web app thông thường, nên mình muốn biết liệu đây có phải là vùng hoàn toàn bất khả thi, hay kiểu tiếp cận này hoặc cách nào khác vẫn là hướng đi thực tế
    • Mình tò mò liệu đã có ấn tượng ban đầu nào về chất lượng/hiệu năng tương đối giữa các mô hình Llama-2 nhỏ và các mô hình GPT-2 nhỏ chưa
    • Mình muốn biết liệu có thể làm cả trình huấn luyện thuần C thay vì Python không
    • Mình tò mò những mô hình này được huấn luyện ở đâu giữa máy nhà, M1 và cloud
  • Georgi Gerganov, người nổi tiếng với llama.cpp, có một phiên bản chạy trong trình duyệt bằng Emscripten: https://ggerganov.com/llama2.c/
    Chuỗi Twitter đang được cập nhật ở https://twitter.com/ggerganov/status/1683174252990660610
    Cả bản gốc lẫn bản này đều thực sự rất hay, và dù gần giống một bản chứng minh khái niệm dùng mô hình cực nhỏ, LLM ưu tiên chạy cục bộ vẫn đặc biệt hấp dẫn. Ý tưởng có thể xây dựng web app với suy luận cục bộ rất đáng thích
    Nếu tiến tới tối ưu hóa, nghiên cứu mô hình nhỏ hơn, tải xuống từng phần và tận dụng WebGPU, đây có thể là điểm khởi đầu cho một cách mới để tạo ứng dụng riêng tư dựa trên LLM cục bộ. Có thể sẽ khó đạt được năng lực như các LLM được host trên cụm GPU cao cấp quy mô lớn, nhưng cách tiếp cận này mở ra rất nhiều trường hợp sử dụng

    • Ở liên kết đầu tiên có đầu ra khá kỳ lạ. Ban đầu nó mở như một truyện cổ tích nghe khá ổn, nhưng rồi lỗi chính tả tăng dần, nội dung bắt đầu lảm nhảm và sụp đổ, sau đó trộn lẫn ngoại ngữ với các thuật ngữ kỹ thuật/lập trình
      Ví dụ, nó bắt đầu bằng “Once upon a time...”, trông như câu chuyện về Lily và Timmy, rồi biến thành đầu ra hỏng hoàn toàn với những đoạn như “Butterfly would pauseWhy”, “TextField”, querySelector, HttpRequest và các mảnh ngôn ngữ khác nhau bị trộn lẫn
  • Với ai quan tâm thì cũng có bản Rust. Ở chế độ release chạy được khoảng 106 tokens/second
    https://github.com/garrisonhess/llama2.c/blob/517a1a3e487f31...

    • Cũng có một bản Rust khác. Nó dùng thư viện ML candle mà tác giả làm từ tháng trước, và cũng có thể chạy trong trình duyệt: https://laurentmazare.github.io/candle-llama2/index.html
      Bản không chạy trên web hỗ trợ GPU đầy đủ, nhưng hoàn toàn không tối giản
    • Như thường thấy trong Rust, đôi khi người ta chỉ chép lại thứ đã có sẵn chỉ vì nó khả thi, mà không đem lại lợi ích nào
      Đôi lúc điều đó còn phân tán nỗ lực của cộng đồng trong việc cải thiện dự án
  • Có vẻ không nhiều người hiểu đây là bước đi táo bạo đến mức nào
    Andrej đang nhận thù lao rất lớn từ OpenAI(MSFT), nhưng vẫn giúp Apple, Facebook và quan trọng hơn là phong trào mã nguồn mở. Dù vậy, cũng khó mà chèn ép được anh ấy, vì nếu thế thì anh ấy có thể chuyển thẳng sang Tesla hoặc xAI

  • Mình cảm thấy Llama-2 bị lọc an toàn quá mức đến nỗi không thể dùng cho công việc sáng tạo: https://i.imgur.com/GFY0wSL.png

    • Cá nhân mình cho rằng nhân danh “an toàn”, mức lọc này thậm chí còn quay ngoắt 180 độ theo hướng có thể củng cố các định kiến mang tính thù ghét hoặc tiêu cực: https://i.imgur.com/xkzXrPK.pnghttps://i.imgur.com/3HQ8FqL.png
      Tuy nhiên hiện tượng này chỉ tái hiện phần nào khi gửi như tin nhắn thứ hai trên Llama2-70b-chat TGI Hugging Face, nên có thể có điều gì đó kỳ lạ ở cách viết prompt dẫn đến hành vi này. Mình vẫn chưa thể tự chạy mô hình để điều tra thêm
    • Nếu có mô hình tiền huấn luyện thì tốt hơn là đừng dùng mô hình instruct/chat
      Chat/instruct có ưu điểm là dễ phân phối cho người dùng bên thứ ba, prompt đơn giản và có sẵn các rào chắn an toàn, nhưng để tự dùng thì nó kém xa mô hình tiền huấn luyện. Ở điểm này Llama 2 có thể có lợi thế hơn OpenAI, vì OpenAI dường như đã bỏ các mô hình GPT-3 tiền huấn luyện và từ nay chỉ cung cấp mô hình chat
    • Cứ tưởng tượng Casca và Brutus không đâm Caesar mà thay vào đó lịch sự đối diện ông ta về khả năng lạm quyền và xu hướng độc tài của ông ấy
    • Bị lọc quá mức không phải toàn bộ “llama-2” mà là Llama-2 chat
    • Cần phải gạt nhóm “AI đạo đức” ra ngoài. Ngày càng rõ là họ thực sự rất phiền
      Tôi không muốn kiểu kéo an toàn đó. Hạn chế những thứ chạy trên máy chủ của họ thì được, nhưng đừng đưa cho tôi một mô hình mà tôi không thể chỉnh sửa và dùng theo ý mình trên chính máy tính của tôi
  • Andrej đã đăng chi tiết hơn ở đây: https://twitter.com/karpathy/status/1683143097604243456?s=46...

  • Nhân tiện, nếu bạn quan tâm đến mảng này, đoạn mã này có thể được build gọn gàng bằng WASI SDK và chạy trong runtime Wasm mà không cần sửa đổi

  • Tò mò không biết cần bao nhiêu bộ nhớ để chạy mạng nơ-ron
    Chỉ cần đọc hai lớp đầu từ đĩa và tính giá trị kích hoạt của mọi nút, rồi bỏ lớp thứ nhất, đọc lớp thứ ba và tính tiếp, sau đó bỏ lớp thứ hai, cứ như vậy là đủ chứ? Nếu vậy thì có phải chỉ cần đủ bộ nhớ để chứa hai lớp không?

    • TheBloke trên Hugging Face đã tài liệu hóa yêu cầu bộ nhớ theo từng phiên bản lượng tử hóa của các mô hình phổ biến: https://huggingface.co/TheBloke
      Tóm lại, RAM tối đa thay đổi theo phương pháp lượng tử hóa, và xấp xỉ là mô hình 7B cần 4~8GB, 13B cần 8~15GB, 30B cần 13~33GB, còn 70B nằm trong khoảng 31~75GB
    • Không cần tự xử lý việc đọc rồi bỏ. Chỉ cần mmap toàn bộ mạng và để hệ điều hành lo phần đó
    • Làm vậy thì được, nhưng khi đó bạn sẽ bị giới hạn bởi băng thông đĩa
    • Theo tôi biết, trong suy luận transformer O(N²), cần cache toàn bộ các giá trị kích hoạt
  • Một ý nghĩ chợt đến là, hiện tại LLM trả về một phân phối xác suất, rồi một bộ lấy mẫu ngẫu nhiên chọn một phần tử và gắn nó vào đầu ra, sau đó lặp lại
    Thay vào đó, liệu có thể để bộ ngẫu nhiên chọn ra N token gần đúng với phân phối, cho LLM tạo ra N phân phối mới, rồi kết hợp chúng theo cách nào đó và lại chọn N token từ phân phối kết hợp không?

    • Nghe gần như beam search, và thực tế đây là một kỹ thuật sinh khá phổ biến: https://en.wikipedia.org/wiki/Beam_search
      Có thể xem ví dụ tại https://huggingface.co/docs/transformers/internal/generation...
    • Nghe như một hướng đáng để nghiên cứu, nhưng có lẽ cần sinh xa hơn nhiều so với 2 token. Có thể nhìn trước khoảng 20 token, nhưng chắc hẳn không ai muốn chạy LLM tới N^20 lần, nên có lẽ tốt hơn là lấy khoảng 200 mẫu đại diện trong các tổ hợp 20 token tiếp theo
      Dù vậy tôi không biết phải làm điều đó thế nào
    • Tôi là người mới nhưng thích ý tưởng đó. Không biết câu trả lời, nhưng có vẻ đáng để thử nghiệm, và khả năng cao là các nhà nghiên cứu đã thử rồi
      Tất nhiên, mỗi lần sinh token sẽ cần lượng tính toán gấp N lần. Có thể chọn N phần tử đứng đầu, hoặc nếu cần thì áp dụng điều chỉnh nhiệt độ lên logits để lấy mẫu N phần tử
  • Đây là để phục vụ giáo dục à? Nhìn vào thành công của llama.cpp và dự án này, có vẻ như ngành đang đi theo hướng có mã nguồn riêng cho từng mô hình được phát hành, thay vì các framework đa dụng như PyTorch, TensorFlow hay ONNX Runtime

    • Có vẻ đây hoàn toàn là để phục vụ giáo dục
      Và không phải vậy. Trái với tên gọi, llama.cpp không chỉ hỗ trợ llama. Nó cũng không hoàn toàn tùy biến riêng, mà được xây dựng trên thư viện/framework tensor ggml mang tính tổng quát hơn
    • Ngay trong framework cũng có mã nguồn riêng cho từng mô hình. Vì mô hình là mã tùy biến ghép từ các thành phần cơ bản của framework, chứ không phải thứ được tạo ra hoàn toàn chỉ bằng framework. Đó là bản chất của nghiên cứu khám phá
      Tuy nhiên, khi tìm ra mô hình hoạt động tốt, các phát triển đó thường được đưa vào phiên bản framework tiếp theo. Vì vậy TensorFlow mới có các thành phần cơ bản như CNN, GRU, TransformerEncoder, đồng thời cũng có các triển khai chuyên biệt cho phần cứng nhất định để đổi bớt tính tổng quát lấy tốc độ
    • Vì là đơn luồng nên xem nó là để phục vụ giáo dục là hợp lý