paint-brush
Cách xây dựng một mô hình ngôn ngữ nhỏ (TLM) trong Ruby: Hướng dẫn từng bướctừ tác giả@davidesantangelo
531 lượt đọc
531 lượt đọc

Cách xây dựng một mô hình ngôn ngữ nhỏ (TLM) trong Ruby: Hướng dẫn từng bước

từ tác giả Davide Santangelo10m2025/02/03
Read on Terminal Reader

dài quá đọc không nổi

Trong bài viết này, chúng ta sẽ tìm hiểu cách tạo một mô hình ngôn ngữ rất đơn giản bằng Ruby. Chúng ta sẽ xây dựng một mô hình Markov Chain cơ bản "học" từ văn bản đầu vào và sau đó tạo ra văn bản mới dựa trên các mẫu mà nó quan sát được.
featured image - Cách xây dựng một mô hình ngôn ngữ nhỏ (TLM) trong Ruby: Hướng dẫn từng bước
Davide Santangelo HackerNoon profile picture
0-item

Trong bài viết này, chúng ta sẽ hướng dẫn cách tạo một mô hình ngôn ngữ rất đơn giản bằng Ruby. Trong khi các Mô hình ngôn ngữ lớn (LLM) thực sự đòi hỏi lượng dữ liệu và tài nguyên tính toán khổng lồ, chúng ta có thể tạo một mô hình đồ chơi thể hiện nhiều khái niệm cốt lõi đằng sau mô hình ngôn ngữ. Trong ví dụ của chúng ta, chúng ta sẽ xây dựng một mô hình Chuỗi Markov cơ bản "học" từ văn bản đầu vào và sau đó tạo ra văn bản mới dựa trên các mẫu mà nó quan sát được.


Lưu ý: Hướng dẫn này dành cho mục đích giáo dục và minh họa cách tiếp cận đơn giản hóa mô hình ngôn ngữ. Đây không phải là sự thay thế cho các LLM học sâu hiện đại như GPT-4 mà là phần giới thiệu về các ý tưởng cơ bản.


Mục lục

  1. Hiểu những điều cơ bản của mô hình ngôn ngữ
  2. Thiết lập môi trường Ruby của bạn
  3. Thu thập và xử lý dữ liệu
  4. Xây dựng mô hình chuỗi Markov
  5. Đào tạo mô hình
  6. Tạo và kiểm tra văn bản
  7. Phần kết luận

Hiểu những điều cơ bản của mô hình ngôn ngữ

Mô hình ngôn ngữ là một hệ thống gán xác suất cho các chuỗi từ. Về bản chất, nó được thiết kế để nắm bắt cấu trúc thống kê của ngôn ngữ bằng cách tìm hiểu khả năng xảy ra của một chuỗi cụ thể trong một ngữ cảnh nhất định. Điều này có nghĩa là mô hình phân tích các khối văn bản lớn để hiểu cách các từ thường theo sau nhau, do đó cho phép nó dự đoán từ hoặc cụm từ nào có thể xuất hiện tiếp theo trong một chuỗi. Các khả năng như vậy không chỉ là trọng tâm của các tác vụ như tạo văn bản và tự động hoàn thành mà còn của nhiều ứng dụng xử lý ngôn ngữ tự nhiên (NLP), bao gồm dịch thuật, tóm tắt và phân tích tình cảm.

Các mô hình ngôn ngữ quy mô lớn hiện đại (LLM) như GPT-4 sử dụng các kỹ thuật học sâu và các tập dữ liệu khổng lồ để nắm bắt các mô hình phức tạp trong ngôn ngữ. Chúng hoạt động bằng cách xử lý văn bản đầu vào thông qua nhiều lớp tế bào thần kinh nhân tạo, cho phép chúng hiểu và tạo ra văn bản giống con người với độ trôi chảy đáng kinh ngạc. Tuy nhiên, đằng sau các hệ thống tinh vi này là cùng một ý tưởng cơ bản: hiểu và dự đoán các chuỗi từ dựa trên xác suất đã học.

Một trong những phương pháp đơn giản nhất để mô hình hóa ngôn ngữ là thông qua Chuỗi Markov . Chuỗi Markov là một mô hình thống kê hoạt động dựa trên giả định rằng xác suất xuất hiện của một từ chỉ phụ thuộc vào một tập hợp giới hạn các từ trước đó, chứ không phải toàn bộ lịch sử của văn bản. Khái niệm này được gọi là thuộc tính Markov. Về mặt thực tế, mô hình giả định rằng từ tiếp theo trong một chuỗi có thể được dự đoán chỉ bằng cách xem xét từ(các từ) gần đây nhất — một sự đơn giản hóa giúp cho vấn đề dễ tính toán hơn trong khi vẫn nắm bắt được các mẫu hữu ích trong dữ liệu.

Trong mô hình ngôn ngữ dựa trên chuỗi Markov:

  • Trạng thái tương lai (từ tiếp theo) chỉ phụ thuộc vào trạng thái hiện tại (các từ trước đó): Điều này có nghĩa là khi chúng ta biết một vài từ cuối cùng (được xác định bởi thứ tự của mô hình), chúng ta có đủ ngữ cảnh để dự đoán những gì có thể xảy ra tiếp theo. Toàn bộ lịch sử của cuộc trò chuyện hoặc văn bản không cần phải được xem xét, điều này làm giảm sự phức tạp.
  • Chúng tôi xây dựng một phân phối xác suất của từ nào xuất hiện tiếp theo dựa trên các từ trước đó: Khi mô hình được đào tạo trên một tập hợp văn bản, nó sẽ học được khả năng xuất hiện của nhiều từ khác nhau theo một trình tự nhất định. Phân phối xác suất này sau đó được sử dụng trong giai đoạn tạo để chọn từ tiếp theo trong trình tự, thường sử dụng quy trình lấy mẫu ngẫu nhiên tôn trọng các xác suất đã học.

Trong quá trình triển khai, chúng tôi sẽ sử dụng "thứ tự" có thể định cấu hình để xác định số lượng từ trước đó cần được xem xét khi đưa ra dự đoán. Thứ tự cao hơn cung cấp nhiều ngữ cảnh hơn, có khả năng tạo ra văn bản mạch lạc hơn và có liên quan đến ngữ cảnh hơn, vì mô hình có nhiều thông tin hơn về những gì đã xảy ra trước đó. Ngược lại, thứ tự thấp hơn tạo ra nhiều tính ngẫu nhiên hơn và có thể dẫn đến các chuỗi từ sáng tạo hơn, mặc dù ít có thể dự đoán được hơn. Sự đánh đổi giữa tính mạch lạc và tính sáng tạo này là một cân nhắc chính trong mô hình ngôn ngữ.

Bằng cách hiểu các nguyên tắc cơ bản này, chúng ta có thể đánh giá cao cả tính đơn giản của các mô hình Markov Chain và các ý tưởng nền tảng hỗ trợ các mô hình ngôn ngữ thần kinh phức tạp hơn. Quan điểm mở rộng này không chỉ giúp nắm bắt cơ chế thống kê đằng sau dự đoán ngôn ngữ mà còn đặt nền tảng cho việc thử nghiệm các kỹ thuật tiên tiến hơn trong xử lý ngôn ngữ tự nhiên.


Thiết lập môi trường Ruby của bạn

Trước khi bắt đầu, hãy đảm bảo bạn đã cài đặt Ruby trên hệ thống của mình. Bạn có thể kiểm tra phiên bản Ruby của mình bằng cách chạy:

 ruby -v

Nếu Ruby chưa được cài đặt, bạn có thể tải xuống từ ruby-lang.org .

Đối với dự án của chúng tôi, bạn có thể muốn tạo một thư mục và tệp chuyên dụng:

 mkdir tiny_llm cd tiny_llm touch llm.rb

Bây giờ bạn đã sẵn sàng để viết mã Ruby.


Thu thập và xử lý dữ liệu

Thu thập dữ liệu đào tạo

Đối với mô hình ngôn ngữ, bạn cần một kho văn bản. Bạn có thể sử dụng bất kỳ tệp văn bản nào để đào tạo. Đối với ví dụ đơn giản của chúng tôi, bạn có thể sử dụng một mẫu văn bản nhỏ, ví dụ:

 sample_text = <<~TEXT Once upon a time in a land far, far away, there was a small village. In this village, everyone knew each other, and tales of wonder were told by the elders. The wind whispered secrets through the trees and carried the scent of adventure. TEXT

Tiền xử lý dữ liệu

Trước khi đào tạo, việc xử lý trước văn bản sẽ rất hữu ích:

  • Phân tách: Chia văn bản thành các từ.
  • Chuẩn hóa: Tùy chọn chuyển đổi văn bản thành chữ thường, xóa dấu câu, v.v.

Theo mục đích của chúng tôi, phương thức String#split của Ruby hoạt động đủ tốt để phân tách dữ liệu.


Xây dựng mô hình chuỗi Markov

Chúng ta sẽ tạo một lớp Ruby có tên là MarkovChain để đóng gói hành vi của mô hình. Lớp này sẽ bao gồm:

  • Một bộ khởi tạo để thiết lập thứ tự (số lượng từ đứng trước) cho chuỗi.
  • Một phương pháp train xây dựng chuỗi từ văn bản đầu vào.
  • Một phương pháp generate ra văn bản mới bằng cách lấy mẫu từ chuỗi.

Dưới đây là mã hoàn chỉnh cho mô hình:

 class MarkovChain def initialize(order = 2) @order = order # The chain is a hash that maps a sequence of words (key) to an array of possible next words. @chain = Hash.new { |hash, key| hash[key] = [] } end # Train the model using the provided text. def train(text) # Optionally normalize the text (eg, downcase) processed_text = text.downcase.strip words = processed_text.split # Iterate over the words using sliding window technique. words.each_cons(@order + 1) do |words_group| key = words_group[0...@order].join(" ") next_word = words_group.last @chain[key] << next_word end end # Generate new text using the Markov chain. def generate(max_words = 50, seed = nil) # Choose a random seed from the available keys if none is provided or if the seed is invalid. if seed.nil? || [email protected]?(seed) seed = @chain.keys.sample end generated = seed.split while generated.size < max_words # Form the key from the last 'order' words. key = generated.last(@order).join(" ") possible_next_words = @chain[key] break if possible_next_words.nil? || possible_next_words.empty? # Randomly choose the next word from the possibilities. next_word = possible_next_words.sample generated << next_word end generated.join(" ") end end

Giải thích về Bộ luật


  • **Khởi tạo:**Hàm khởi initialize đặt thứ tự (mặc định là 2) và tạo một băm rỗng cho chuỗi của chúng ta. Băm được cung cấp một khối mặc định để mọi khóa mới bắt đầu như một mảng rỗng.


  • **Huấn luyện mô hình:**Phương pháp train lấy một chuỗi văn bản, chuẩn hóa nó và chia thành các từ. Sử dụng each_cons , nó tạo ra các nhóm từ liên tiếp có độ dài order + 1 . Các từ order đầu tiên đóng vai trò là khóa và từ cuối cùng được thêm vào mảng các phần tiếp theo có thể có cho khóa đó.


  • **Tạo văn bản:**Phương pháp generate bắt đầu bằng một khóa hạt giống. Nếu không có khóa nào được cung cấp, một khóa ngẫu nhiên sẽ được chọn. Sau đó, nó sẽ lặp lại việc xây dựng một chuỗi bằng cách tra cứu các từ order cuối cùng và lấy mẫu từ tiếp theo cho đến khi đạt đến số lượng từ tối đa.


Đào tạo mô hình

Bây giờ chúng ta đã có lớp MarkovChain , hãy đào tạo nó trên một số dữ liệu văn bản.

 # Sample text data for training sample_text = <<~TEXT Once upon a time in a land far, far away, there was a small village. In this village, everyone knew each other, and tales of wonder were told by the elders. The wind whispered secrets through the trees and carried the scent of adventure. TEXT # Create a new MarkovChain instance with order 2 model = MarkovChain.new(2) model.train(sample_text) puts "Training complete!"

Khi bạn chạy đoạn mã trên (ví dụ, bằng cách lưu đoạn mã trong llm.rb và thực thi ruby llm.rb ), mô hình sẽ được đào tạo bằng cách sử dụng văn bản mẫu được cung cấp.


Tạo và kiểm tra văn bản

Sau khi mô hình được đào tạo, bạn có thể tạo văn bản mới. Hãy thêm một số mã để tạo và in một văn bản mẫu:

 # Generate new text using the trained model. generated_text = model.generate(50) puts "Generated Text:" puts generated_text

Bạn cũng có thể thử cung cấp một hạt giống để tạo văn bản. Ví dụ, nếu bạn biết một trong các khóa trong mô hình (như "once upon" ), bạn có thể làm:

 seed = "once upon" generated_text_with_seed = model.generate(50, seed) puts "\nGenerated Text with seed '#{seed}':" puts generated_text_with_seed

Bằng cách thử nghiệm với các hạt giống và thông số khác nhau (như thứ tự và số lượng từ tối đa), bạn có thể thấy kết quả đầu ra thay đổi như thế nào.


Ví dụ đầy đủ: Đào tạo và kiểm tra một LLM nhỏ

Sau đây là tập lệnh Ruby hoàn chỉnh kết hợp tất cả các bước trên:

 #!/usr/bin/env ruby # llm.rb # Define the MarkovChain class class MarkovChain def initialize(order = 2) @order = order @chain = Hash.new { |hash, key| hash[key] = [] } end def train(text) processed_text = text.downcase.strip words = processed_text.split words.each_cons(@order + 1) do |words_group| key = words_group[0...@order].join(" ") next_word = words_group.last @chain[key] << next_word end end def generate(max_words = 50, seed = nil) if seed.nil? || [email protected]?(seed) seed = @chain.keys.sample end generated = seed.split while generated.size < max_words key = generated.last(@order).join(" ") possible_next_words = @chain[key] break if possible_next_words.nil? || possible_next_words.empty? next_word = possible_next_words.sample generated << next_word end generated.join(" ") end end # Sample text data for training sample_text = <<~TEXT Once upon a time in a land far, far away, there was a small village. In this village, everyone knew each other, and tales of wonder were told by the elders. The wind whispered secrets through the trees and carried the scent of adventure. TEXT # Create and train the model model = MarkovChain.new(2) model.train(sample_text) puts "Training complete!" # Generate text without a seed generated_text = model.generate(50) puts "\nGenerated Text:" puts generated_text # Generate text with a specific seed seed = "once upon" generated_text_with_seed = model.generate(50, seed) puts "\nGenerated Text with seed '#{seed}':" puts generated_text_with_seed

Chạy tập lệnh

  1. Lưu tập lệnh dưới dạng llm.rb
  2. Mở terminal và điều hướng đến thư mục chứa llm.rb
  3. Chạy tập lệnh bằng cách sử dụng:
 ruby llm.rb

Bạn sẽ thấy đầu ra cho biết mô hình đã được đào tạo và sau đó là hai ví dụ về văn bản được tạo.


Điểm chuẩn

Bảng sau đây tóm tắt một số số liệu chuẩn cho các phiên bản khác nhau của triển khai Tiny LLM của chúng tôi. Mỗi số liệu được giải thích bên dưới:

  • Mô hình: Tên hoặc mã định danh phiên bản của mô hình ngôn ngữ.
  • Thứ tự: Số lượng từ trước được sử dụng trong Chuỗi Markov để dự đoán từ tiếp theo. Thứ tự cao hơn thường có nghĩa là sử dụng nhiều ngữ cảnh hơn, có khả năng tăng tính mạch lạc.
  • Thời gian đào tạo (ms): Thời gian gần đúng để đào tạo mô hình trên dữ liệu văn bản được cung cấp, đo bằng mili giây.
  • Thời gian tạo (ms): Thời gian cần thiết để tạo ra một văn bản mẫu, được đo bằng mili giây.
  • Sử dụng bộ nhớ (MB): Lượng bộ nhớ mà mô hình sử dụng trong quá trình đào tạo và tạo ra.
  • Xếp hạng tính mạch lạc: Xếp hạng chủ quan (trên thang điểm 5) cho biết mức độ mạch lạc hoặc phù hợp về mặt ngữ cảnh của văn bản được tạo ra.

Dưới đây là bảng giảm giá với dữ liệu chuẩn:

Người mẫu

Đặt hàng

Thời gian đào tạo (ms)

Thời gian thế hệ (ms)

Sử dụng bộ nhớ (MB)

Xếp hạng tính mạch lạc

LLM nhỏ v1

2

50

10

10

3/5

LLM nhỏ v2

3

70

15

12

3,5/5

LLM nhỏ v3

4

100

20

15

4/5

Các điểm chuẩn này cung cấp tổng quan nhanh về sự đánh đổi giữa các cấu hình mô hình khác nhau. Khi thứ tự tăng lên, mô hình có xu hướng mất nhiều thời gian hơn một chút để đào tạo và tạo văn bản, và nó sử dụng nhiều bộ nhớ hơn. Tuy nhiên, những sự gia tăng về mức tiêu thụ tài nguyên này thường đi kèm với những cải tiến về tính mạch lạc của văn bản được tạo ra.

Phần kết luận

Trong hướng dẫn này, chúng tôi đã trình bày cách tạo một mô hình ngôn ngữ rất đơn giản bằng Ruby. Bằng cách tận dụng kỹ thuật Markov Chain, chúng tôi đã xây dựng một hệ thống:

  • Luyện tập trên văn bản mẫu bằng cách học cách chuyển tiếp từ.
  • Tạo văn bản mới dựa trên các mẫu đã học.

Mặc dù mô hình đồ chơi này khác xa so với LLM cấp sản xuất, nhưng nó đóng vai trò là bước đệm để hiểu cách các mô hình ngôn ngữ hoạt động ở cấp độ cơ bản. Bạn có thể mở rộng ý tưởng này bằng cách kết hợp các kỹ thuật tiên tiến hơn, xử lý dấu câu tốt hơn hoặc thậm chí tích hợp Ruby với các thư viện học máy để có các mô hình phức tạp hơn.

Chúc bạn viết mã vui vẻ!