10 điểm bởi GN⁺ 2025-02-28 | 2 bình luận | Chia sẻ qua WhatsApp
  • Trong vài năm gần đây, Elixir đang mở rộng năng lực trong lĩnh vực machine learning và dữ liệu thông qua dự án Nx (Numerical Elixir)
  • Các dự án như Nx, Explorer, Axon, Bumblebee và Scholar đã xuất hiện, phát triển dựa trên những bài học rút ra từ hệ sinh thái Python và R
  • Ban đầu, nhóm đã quyết định không phụ thuộc trực tiếp vào các thư viện Python, nhằm theo đuổi thiết kế tối ưu cho Elixir và tránh sự phức tạp trong việc thiết lập môi trường Python
  • Tuy nhiên, hiện nay thứ đang dẫn dắt việc áp dụng Elixir trong lĩnh vực này lại là Livebook
    • Một nền tảng notebook ở tuyến đầu về khả năng tái lập, thực thi phân tán và phát triển ứng dụng, dựa trên các thế mạnh của Elixir và Erlang
    • Sự quan tâm từ các đội ngũ và doanh nghiệp muốn lần đầu bước vào hệ sinh thái Elixir thông qua Livebook đang ngày càng tăng
  • Nhưng vẫn có rào cản
    • Phần lớn các công ty muốn đưa Elixir và Livebook vào hạ tầng của mình đều đã sử dụng workflow, package và repository dựa trên Python
    • Điều này đồng nghĩa hoặc phải tìm các package tương đương trong Elixir, hoặc phải viết lại từ đầu, làm tăng rủi ro và chi phí khi bổ sung Elixir vào data stack
  • Để giải quyết điều này, nhóm công bố Pythonx, công cụ nhúng trình thông dịch Python vào bên trong Erlang VM

Pythonx

  • Pythonx cung cấp tính năng chuyển đổi dữ liệu tự động giữa Elixir và Python, đánh giá mã và quản lý virtual environment
  • Có thể sử dụng package pytesseract để thực hiện Optical Character Recognition (OCR)
  • Sau khi tải ảnh bằng req, gọi Pythonx.uv_init/1 để tải xuống và khởi tạo Python cùng các dependency
  • Dùng Pythonx.eval/2 để chạy mã Python và chuyển kết quả thành chuỗi Elixir

Cấu trúc bên trong

  • Bản triển khai tham chiếu CPython của Python có thể được nhúng vào ứng dụng khác
  • Chức năng cốt lõi của trình thông dịch Python được cung cấp dưới dạng thư viện C
  • Ứng dụng C/C++ có thể liên kết với thư viện đó và dùng API để chạy mã cũng như tương tác với đối tượng
  • Elixir cung cấp khả năng tương tác với C/C++ thông qua Erlang NIFs
  • Pythonx tận dụng NIFs để nhúng Python và chạy trong cùng một tiến trình OS
  • Việc truyền dữ liệu giữa Python và Elixir được thực hiện hiệu quả

Hỗ trợ đa ngôn ngữ của Livebook

  • Dựa trên Pythonx, hỗ trợ Python đang được bổ sung vào Livebook
  • Elixir và Python sẽ có thể tương tác trong cùng một notebook
  • Livebook tự động cài đặt Python và các dependency, đồng thời quản lý việc chuyển đổi giữa biến Elixir và Python
  • Đảm bảo môi trường có thể tái lập
  • Hiện vẫn đang tiếp tục bổ sung các phần như hoàn thành mã, tài liệu hóa..., và đã có thể tải về cũng như sử dụng Livebook nightly

Những điểm cần cân nhắc khi sử dụng và các lựa chọn thay thế

  • Mục đích chính của Pythonx là tích hợp workflow Python trong Livebook và trong script
  • Do Global Interpreter Lock (GIL) của Python, có thể tồn tại giới hạn về đồng thời khi gọi Pythonx từ nhiều tiến trình Elixir
  • Cần gọi từ một tiến trình Elixir duy nhất, hoặc xác nhận thư viện Python có thể xử lý các lời gọi đồng thời hay không
  • Một lựa chọn khác là dùng System.cmd/3 hoặc Port để quản lý nhiều tiến trình Python
  • Với workflow AI, có thể chạy các mô hình đã huấn luyện trước thông qua Bumblebee
  • Có thể chạy mô hình ONNX bằng Ortex
  • Với LLM, có thể dùng API bên thứ ba hoặc chạy container Docker Llama.cpp on-premises
  • Khi dùng giao diện dựa trên HTTP, có thể tận dụng các công cụ như InstructorLangChain của Elixir

Dự án Fine

  • Pythonx được triển khai bằng NIFs
  • NIFs là các hàm Elixir được triển khai bằng C và đòi hỏi khá nhiều mã boilerplate
  • Tồn tại sự phức tạp trong quản lý bộ nhớ và xử lý lỗi
  • Để giải quyết điều này, thư viện Fine dựa trên C++ đã được phát triển
  • Fine cung cấp khả năng tự động xử lý chuyển đổi cấu trúc dữ liệu, quản lý an toàn resource object và phát sinh ngoại lệ
  • Có thể giảm đáng kể lượng mã cần viết khi tạo NIF

Kết luận

  • Mục tiêu của dự án Numerical Elixir là giúp Elixir có được bản sắc riêng trong hệ sinh thái dữ liệu và machine learning
  • Giờ đây, khả năng tương tác đang trở thành mục tiêu trọng yếu
  • Pythonx nhúng Python vào Elixir, cho phép chuyển đổi qua lại minh bạch giữa hai ngôn ngữ

2 bình luận

 
aer0700 2025-03-01

Numpy thực sự rất tuyệt...

 
GN⁺ 2025-02-28
Ý kiến trên Hacker News
  • Tính năng của Livebook rất ấn tượng. Việc gọi trực tiếp CPython từ Elixir thông qua C++ NIFs và trả về các cấu trúc dữ liệu native của Elixir là một cách làm gọn gàng

    • Trên máy chủ production, dùng Pythonx có thể hơi rủi ro. Vì nó chạy trong cùng tiến trình OS với ứng dụng Elixir nên sẽ bỏ qua khả năng phục hồi sau lỗi mạnh mẽ của ứng dụng Elixir/BEAM
    • Thông thường, ứng dụng Elixir có cây giám sát có thể xử lý lỗi của chính các tiến trình BEAM một cách uyển chuyển, và đây là một ưu điểm lớn của các ngôn ngữ như Elixir, Erlang và Gleam
    • Khi dùng NIFs, nếu xảy ra ngoại lệ chưa được xử lý trong Pythonx thì có thể làm dừng toàn bộ tiến trình OS và mọi tiến trình BEAM
    • Rustler là trình bao NIF phổ biến cho Rust trong Elixir; có những trường hợp NIFs rất hữu ích, nhưng cần cân nhắc rủi ro có thể làm dừng toàn bộ ứng dụng
    • Dùng Ports để chạy mã native khác như Python hoặc Rust sẽ ít rủi ro hơn ở điểm này
  • Thật tốt khi thấy những người "có tiếng" trong cộng đồng Elixir ủng hộ và tích cực phát triển hướng tiếp cận này

    • VM và runtime rất phù hợp để điều phối các ngôn ngữ và công nghệ khác, khiến nó giống như có cả lộ trình tiêu chuẩn lẫn lộ trình offload
    • Sự khác biệt giữa những ý tưởng offload "có vẻ nguy hiểm" và việc thực thi an toàn thường chỉ là khối lượng công việc, nhưng runtime lại khuyến khích điều đó
    • Vì là NIF nên có chút rủi ro, nhưng có thể tạo một instance BEAM riêng và phân tán thông qua đó
  • Có những bình luận khác đã chỉ ra vấn đề an toàn khi dùng NIFs

    • Bộ lập lịch của Erlang VM không thể preempt NIF, nên các lệnh gọi Python chạy lâu có nguy cơ làm VM bị đình trệ
    • GIL ngăn việc thực thi Python đồng thời, nhưng bên gọi Erlang có thể chạy nhiều trình thông dịch Python, nên đây không phải vấn đề với Ports
  • Đây là một bài viết rất bổ ích. Thật tốt khi bài viết nêu rõ rằng Pythonx không chỉ gọi subprocess đơn thuần mà chạy trong cùng một tiến trình

    • Sẽ tốt hơn nếu có thêm ví dụ gọi một hàm được định nghĩa trong Python từ Elixir
  • Thật vui khi thấy Elixir đang bắt kịp, dù nó phù hợp với cuộc chiến AI hơn JavaScript và Python nhưng lại bị chậm chân

    • Tôi thích quyết định ban đầu là mở rộng nền tảng ML của Elixir từ gốc, nhưng cũng rất tốt khi giờ đã có cách tận dụng các thư viện Python đang phát triển rất nhanh
  • Trước đây tôi thấy việc chuyển từ Python sang hệ sinh thái Elixir/Erlang quá khó, nhưng với Pythonx thì việc học dần dần có vẻ khả thi hơn nhiều

    • Tôi tự hỏi họ có thử nghiệm free-threading cho vấn đề GIL của Python hay chưa
  • Elixir có một số tính năng mà tôi ước Python có

    • atom, hầu hết mọi thứ đều là macro, pipe |>, tính bất biến thực sự, song song và đồng thời thực sự nhờ cây giám sát, hot code reloading, khả năng chịu lỗi
  • Với tư cách là người đã tham gia sâu vào Elixir và cũng dùng Python rất nhiều, tôi thấy điều này rất thực tế

    • Tôi còn quan tâm hơn đến thư viện Fine, vốn giúp tạo C++ NIFs dễ dàng
  • Dự án này và bài đăng blog này có cảm giác như được tạo ra riêng cho tôi. Tôi muốn thử nó, cảm ơn