5 điểm bởi GN⁺ 2025-05-02 | 1 bình luận | Chia sẻ qua WhatsApp
  • Khi xây dựng hn.unlurker.com, tác giả đã thêm tính năng scan để nhận toàn bộ item theo thứ tự vào HN API client, rồi tải toàn bộ dữ liệu Hacker News về máy cục bộ
  • Trong lúc chạy hn scan --no-cache --asc -c- -o full.json, quá trình tải xuống đã dừng vài lần, nhưng nhờ scan có thể tiếp tục lại, sau vài giờ tác giả đã có được tệp JSON 20 GiB
  • Sau khi biến JSON thành bảng bằng read_json_auto của DuckDB, tác giả dùng text ILIKE và SQL tính trung bình động 12 tuần để tổng hợp tỷ lệ nhắc đến Python, JavaScript, Java, Ruby, Rust
  • Chỉ với grep đơn giản cũng xác nhận được cụm “correct horse battery staple” xuất hiện 231 lần trên Hacker News, và DuckDB có vẻ rất phù hợp cho dạng phân tích một lần ở quy mô này
  • Khi đã có toàn bộ dữ liệu ở máy cục bộ, có thể phân tích nội dung lịch sử của Hacker News theo nhiều cách, nhưng dự án này dừng lại ở đây và các bước tiếp theo được để lại cho người khác tiếp tục

Tải xuống toàn bộ item của Hacker News

  • Để xây dựng hn.unlurker.com, tác giả đã viết HN API client
    • Dù đã có nhiều client khác, tác giả muốn thử dùng các tính năng Go mới nhất và linter trong một dự án mới
    • Trong HN API, bình luận và story được gọi là item
  • Client có thể lấy item đang hoạt động, danh sách item, v.v.
    • Dự án thực tế chỉ cần các item gần đây, nhưng để hoàn thiện hơn, tác giả đã thêm tính năng scan
    • scan tải item theo thứ tự từ 0 đến mới nhất hoặc theo chiều ngược lại
  • Tác giả thử làm vì dự kiến toàn bộ bản tải xuống chỉ vào khoảng vài chục GiB JSON, chứ không phải hàng chục nghìn GiB
hn scan --no-cache --asc -c- -o full.json
  • Quá trình tải xuống dừng vài lần nên tác giả đã ngắt bằng CTRL-C, nhưng vì scan có thể tiếp tục lại nên hoàn tất sau vài giờ
  • Kết quả là một tệp JSON 20 GiB chứa mọi nội dung từng diễn ra trên Hacker News
  • Chạy lại cùng lệnh sẽ có thể nạp lại bằng dữ liệu mới nhất

Phân tích dữ liệu cục bộ bằng DuckDB

  • Ban đầu tác giả chỉ tìm kiếm đơn giản bằng grep
    • Cụm “correct horse battery staple” xuất hiện 231 lần trên Hacker News
    • Lần xuất hiện cuối cùng, tính tại thời điểm viết bài, là một item được đăng “hôm nay”
  • Sau đó tác giả thử phân tích bằng DuckDB
    • DuckDB là một engine thực thi phân tích nhanh, có thể nhúng, và cũng được cung cấp dưới dạng công cụ dòng lệnh
    • Nhờ UI mới, người mới bắt đầu cũng dễ dùng, và LLM đã hỗ trợ viết các truy vấn SQL
  • Dữ liệu JSON được đưa vào DuckDB theo cách sau
CREATE TABLE items AS
SELECT *
FROM read_json_auto('/home/jason/full.json', format='nd', sample_size=-1);
  • Truy vấn ví dụ gom item theo tuần và tính tỷ lệ item có chứa một từ cụ thể trong tổng số item
    • Tác giả tìm python, javascript, java, ruby, rust bằng text ILIKE
    • Tính trung bình động 12 tuần cho từng tỷ lệ
  • Cũng theo cách này, tác giả trực quan hóa các từ liên quan đến cơ sở dữ liệu
    • Biểu đồ ví dụ bao gồm tỷ lệ nhắc đến theo trung bình động 12 tuần của mysql, postgres, mongo, redis, sqlite
  • DuckDB có vẻ rất tốt để phân tích bộ dữ liệu cỡ này
  • Dù đã có bản sao cục bộ của toàn bộ nội dung Hacker News, tác giả quyết định kết thúc dự án tại đây

1 bình luận

 
GN⁺ 2025-05-02
Các ý kiến trên Hacker News
  • Tôi biết hai cơ sở dữ liệu có bảng Hacker News được cập nhật, cho phép chạy phân tích mà không cần tải xuống trước
    BigQuery cần tài khoản Google Cloud, các truy vấn có lẽ chạy được trong mức miễn phí, và chỉ cần dùng bigquery-public-data.hacker_news.full
    ClickHouse không cần đăng ký và có thể chạy truy vấn ngay trong trình duyệt: https://play.clickhouse.com/play?user=play#U0VMRUNUICogRlJPT...

    • Thậm chí còn tìm ra cả clickhouse trong bình luận này: https://play.clickhouse.com/play?user=play#U0VMRUNUICogRlJPT...
    • Tài nguyên ClickHouse thật sự tuyệt vời. Có cả lịch sử nữa
      Trước khi biết đến cơ sở dữ liệu HN của ClickHouse, tôi đã tự thử làm việc tải toàn bộ JSON xuống
  • Trước đây tôi từng làm một việc tương tự với tài khoản Twitter/Bluesky @fesshole. Tôi tải toàn bộ kho lưu trữ xuống rồi tinh chỉnh mô hình để nó tạo ra những lời thú tội điên rồ hơn
    Lúc đó tôi khá tự hào, nhưng cuối cùng nhận ra rằng mình chỉ đang dạy cho một cỗ máy ngây thơ về thủ dâm và ly hôn mà thôi
    Nó giống cảnh trong phim khoa học viễn tưởng, khi người ngoài hành tinh hoặc AI siêu trí tuệ xem lịch sử loài người ở tốc độ cực cao rồi kết luận rằng chúng ta không đáng được cứu

    • Về đoạn “dạy cho một cỗ máy ngây thơ về thủ dâm và ly hôn”, giả sử ta phát hiện một ổ USB của một nền văn minh đã biến mất từ lâu và huấn luyện mô hình bằng dữ liệu văn bản trong đó
      Nếu hoàn toàn không có liên kết với thế giới bên ngoài cho dữ liệu đó, thì làm sao con người hay mô hình biết được rằng ổ USB đó chứa dữ liệu về thủ dâm và ly hôn?
    • Tôi không hiểu thủ dâm và ly hôn thì có vấn đề gì. Mỗi thứ đều là cách giúp con người sống hạnh phúc và tự chủ hơn, cũng như thoát khỏi những tình huống không phù hợp
      Nhìn chung tôi xem cả hai đều là tích cực, và biết ơn vì được sống trong một xã hội nơi những điều này đã được bình thường hóa
  • Truy vấn Java cũng bao gồm mọi trường hợp của JavaScript, nên Java bị lấy mẫu quá mức

    • Tương tự, truy vấn Rust cũng sẽ gom vào rất nhiều từ như trust, antitrust, frustration
    • Đúng vậy… nếu thế thì việc thấy nó có xu hướng giảm có lẽ lại càng bất ngờ hơn
  • Việc từng có một tệp JSON 20GiB chứa mọi thứ đã xảy ra trên Hacker News là khá bất ngờ nếu nghĩ đây là một trang chỉ toàn văn bản
    Có nghĩa là trong 18 năm HN tồn tại, mọi người đã đăng hơn 20 tỷ byte văn bản? Trung bình hơn 2MB mỗi ngày, khoảng 7,5KB mỗi giây

    • 2MB mỗi ngày nghe không nhiều lắm. Đặc biệt sau vụ Reddit, khi “tháng Chín bất tận” mới nhất và lớn nhất kéo đến, số bài đăng rất có thể đã tăng theo cấp số nhân trong nhiều năm
      Hơn nữa, một lượng không nhỏ trong đó chắc không phải do con người. /newest đầy spam bot
    • 7,5KB/s, tức 7500 ký tự mỗi giây, nghe không thực tế nên tôi thử tính lại[0], thực ra gần với khoảng 34 byte mỗi giây, tức 0,03KB/s
      Vì còn bao gồm cả metadata và cú pháp của JSON, lượng văn bản thực tế chắc còn thấp hơn nữa. Phép tính “hơn 2MB mỗi ngày” thì đúng
      [0] Thật ra ChatGPT tính, nhưng có vẻ đúng: https://chatgpt.com/share/68124afc-c914-800b-8647-74e7dc4f21...
    • Toàn bộ kho lưu trữ Reddit ngay trước khi họ bỏ API có dung lượng khoảng 4TB khi đã nén. Trước đây nó được host trên the-eye, và nếu muốn thì hiện vẫn có những nơi cho torrent các tệp đó
      Phần lớn trong số đó là rác, nhưng dữ liệu thời kỳ đầu, đặc biệt trước 2018–2019 khi các bot thông minh hơn xuất hiện, có vẻ đáng để xem xét
    • JSON 20GB thật đáng ngạc nhiên. Tôi có một tệp SQLite chứa toàn bộ dữ liệu HN và nó cũng 20GB, nên nếu là JSON thì tôi nghĩ đáng ra phải lớn hơn nhiều
    • Tổng dung lượng lại có cảm giác khá nhỏ. Đó là kết quả đóng góp của hàng trăm nghìn thành viên hoạt động và tổng cộng hàng triệu người trong gần 20 năm
      Theo tiêu chuẩn trước Facebook, HN hẳn là một mạng xã hội khá lớn, và nhờ quy mô vừa phải cùng việc được quản lý tích cực, giá trị của nó cũng tương đối cao
      Năm 2019, khi Google+ đóng cửa, tôi từng thử mô hình hóa lượng dữ liệu văn bản đã được đóng góp lên trang đó
      Ở đây dữ liệu văn bản là loại trừ media như hình ảnh, âm thanh, video, cũng như các thành phần phụ của trang như khung HTML, CSS, JS
      Nếu xét tỷ lệ tham gia rất thấp và độ dài trung bình mỗi bài khoảng 120 ký tự, thì lịch sử 7 năm của hàng chục triệu tài khoản hoạt động cũng chỉ vài GiB. Có hơn 4 tỷ hồ sơ đã đăng ký, nhưng hoạt động thực tế ít hơn rất nhiều
      Archive Team đã hợp tác với Internet Archive nhưng hoạt động riêng trong việc bảo tồn Google+, và kết quả khá lẫn lộn. Nhiều nội dung được lưu lại, nhưng còn nhiều hơn nữa bị thiếu; bình luận hầu như không còn; các thread bị cắt còn khoảng 10 mục gần nhất; và vì không có tìm kiếm nên nhìn chung ít hữu dụng. Các “vanity accounts” dùng tên tài khoản tự chọn thay vì hash ngẫu nhiên còn khó truy cập hơn
      Hơn nữa, khi cố scrape toàn bộ trang để tái hiện hình thức hiển thị trực tuyến, yêu cầu lưu trữ tăng lên rất nhiều, trong khi lại bỏ lỡ nhiều yếu tố thực sự làm trang đó thú vị
      Ngay cả khi muốn lưu đóng góp văn bản của một nhóm dân số lớn, yêu cầu lưu trữ cũng khá modest. Ví dụ nếu trung bình mỗi ngày online 45 phút, tốc độ gõ 45wpm, và một nửa thời gian online là viết chứ không phải đọc, thì mỗi người mỗi ngày khoảng 1.000 từ, tức khoảng 6KiB. Tương đương 6MiB cho mỗi 1.000 người, 6GiB cho mỗi 1 triệu người, và khoảng 6PiB cho mỗi 1 tỷ người
      Giá trị thực tế gần như chắc chắn thấp hơn. Thời gian viết đã bị ước tính quá cao và thực tế có lẽ gần 10%; tốc độ nhập trên di động cũng có khả năng chỉ khoảng 20–30wpm. Chẳng hạn, mỗi ngày Facebook có khoảng 2,45 tỷ “mảnh nội dung” được đăng lên và một nửa trong số đó là video. Nếu tính 120 ký tự mỗi bài, dữ liệu văn bản chỉ là một lượng nhỏ bất ngờ, thấp hơn rất nhiều so với 300GiB mỗi ngày
      Hiện nay, phần lớn các hệ thống thu thập dữ liệu và chủ nghĩa tư bản giám sát là dữ liệu không do con người trực tiếp nhập vào, như vị trí, video, tương tác trực tuyến và thương mại
  • Netiquette khi tải HN về là gì? Có nên hỏi dang trước khi gây tải lên máy chủ không?
    Hay có thể xem như các công ty công nghệ trị giá hàng chục tỷ USD hẳn đã làm việc này nhiều lần rồi nên sẽ chẳng ai để ý?

    • Như bài viết cũng nói, HN có API, thậm chí không giới hạn tốc độ. Toàn bộ dữ liệu được host trên Firebase, một công ty của YC, nên ổn thôi
    • Theo đúng nghĩa đen là có một cơ sở dữ liệu công khai
      https://console.cloud.google.com/marketplace/product/y-combi...
    • Cũng không thể loại trừ khả năng các cơ quan ba chữ cái đang gắn tên thật với các bí danh trên HN
    • Tên là Hacker News mà, nên ít nhất hack theo nghĩa tốt cũng là cuộc chơi công bằng
    • Nếu đã nằm trên web công khai thì đã có hàng nghìn bot scrape nó rồi
  • Tôi từng làm việc tương tự. Tôi dùng một mẹo với dataset BigQuery; không hiểu sao nó vẫn liên tục được cập nhật, rồi tôi export dữ liệu sang Parquet, tải xuống và truy vấn bằng DuckDB

    • Đó không phải là mẹo, chỉ là một lựa chọn thực dụng thôi
  • “Giờ đã tải toàn bộ nội dung Hacker News về máy cục bộ, ta có thể huấn luyện hàng trăm bot dựa trên LLM để cho chúng làm người đóng góp, rồi từ từ và tất yếu thay thế toàn bộ văn bản của con người bằng đầu ra của những bộ dao động phòng tiếng Trung cứ mãi vang vọng và tái chế quá khứ” — nói đùa vậy thôi, nhưng tôi sợ rằng một ngày nào đó sẽ có người thử làm thật
    Mong là chuyện đó không xảy ra, nhưng nếu xảy ra thì liệu có ngăn được không?

    • Tôi ngày càng tin vào một ý tưởng cũ, càng về sau càng quan trọng hơn: tạo một mạng lưới tin cậy giữa con người, theo đó một tài khoản được xác thực qua một đường dẫn kiểu: người mà tôi không biết tin tưởng tài khoản đó, người ấy lại được một người tôi biết tin tưởng, và người đó thì được tôi tin tưởng
      Có nhiều vấn đề cần giải quyết, và quyền riêng tư là một trong số đó. Không nhất thiết phải công khai các mối liên kết cho người dùng, nhưng trong một triển khai ngây thơ thì chúng vẫn sẽ nằm trên máy chủ
      Cũng có thể thêm các đường dẫn bất tín nhiệm với trọng số âm. Nếu tôi trực tiếp hoặc gián tiếp không tin ai đó, giá trị của chuỗi tin cậy nối tôi với người đó sẽ giảm xuống
      Vì đây là một mạng lưới, hệ thống có thể tự điều chỉnh trước các nỗ lực thao túng nó, nhưng nó sẽ vững chắc đến đâu vẫn là câu hỏi bỏ ngỏ
    • Làm sao biết chuyện đó chưa đang xảy ra?
      Những bình luận dài và có nội dung thì thường vẫn phân biệt được, nhưng đã khó hơn nhiều so với 1–2 năm trước. Còn với những bình luận ngắn một hai câu, tôi nghĩ LLM giờ đã đủ tốt để lọt qua như con người
    • Các LLM của chúng ta chỉ có thể đưa ra kết quả đã được xác nhận từ nhiều nguồn, nên chúng chỉ xuất ra phản hồi trung bình của con người
      Ngược lại, nhiều bình luận trên HN là những insight khá độc đáo, lệch khỏi suy nghĩ đại chúng trung bình. Nếu LLM cố bắt chước điều này, nó sẽ chỉ phun ra nhảm nhí
      Nếu gắn thêm bộ lọc chỉ cho qua các câu trả lời hợp lý và có ý nghĩa trong đống nhảm đó, câu trả lời sẽ trở nên nhàm chán và vẫn gần như là nhảm
      Để câu trả lời chính xác, tinh vi và độc đáo, phải dùng một thứ gì đó không phải LLM
    • HN vốn đã có một hệ miễn dịch khá tốt với kiểu này. Những bình luận ít công sức, lặp lại sẽ nhanh chóng bị downvote, báo cáo và giới hạn tốc độ
      Các heuristic về karma và tốc độ của trang tuy thô sơ so với machine learning hào nhoáng, nhưng chúng hoạt động vì cộng đồng nhỏ hơn Reddit hay Twitter và ban quản trị can thiệp trực tiếp
      Muốn một bầy tài khoản giả LLM “thay thế” văn bản con người, chúng phải liên tục đăng những bài mà người ta thật sự thấy thú vị. Nếu không, chúng sẽ bị giới hạn hoặc âm thầm gỡ bỏ từ lâu trước đó
      Ngay cả khi giữ được vài tài khoản AI sống sót, chi phí biên vẫn lớn. Chạy suy luận cho hàng chục luồng mới 24 giờ mỗi ngày không miễn phí, và giữ cho đầu ra không trượt thành rác SEO phổ biến cũng khó đáng ngạc nhiên
      Lợi nhuận thì hầu như không có. Không thể kiếm tiền từ lưu lượng HN, và karma là một loại tiền tệ tệ hại với người vận hành bot
      Có ngăn được một tác nhân xấu dai dẳng, có tài nguyên không? Có lẽ là được, nhưng biện pháp đối phó vẫn sẽ như hiện nay: giới hạn tốc độ mạnh, siết trần tài khoản mới, người điều hành duyệt xét, có lẽ thêm phân tích văn phong
      Điều đó sẽ gây phiền cho người dùng mới hợp pháp, nhưng không chí mạng. Rốt cuộc HN tồn tại vì những con người ở đây muốn đọc bài viết của những con người khác. Nếu bình luận bắt đầu nghe như vẹt xác suất, độc giả sẽ bỏ qua hoặc báo cáo, và các bot sẽ nói chuyện với nhau
      Do GPT-3o viết
    • Đã có những thứ dự báo trước xu hướng này, như thương hiệu Metal Gear[0], thuyết Internet đã chết[1], v.v.
      “Trong Metal Gear Solid 2, kịch bản đầy tham vọng của Hideo Kojima từng được xem là một trong những ví dụ đầu tiên của trò chơi điện tử hậu hiện đại, và cũng được đánh giá là đã dự báo trước các khái niệm như chính trị hậu sự thật, tin giả, buồng vọng âm và sự thật thay thế”
      [0] https://en.wikipedia.org/wiki/Metal_Gear
      [1] https://en.wikipedia.org/wiki/Dead_Internet_theory
  • Tôi nghĩ trong vài năm tới, nhiều API sẽ bắt đầu cung cấp tùy chọn đơn giản là trả về tệp DuckDB
    Dù sao nếu rồi cũng nạp JSON vào cơ sở dữ liệu, thì chẳng có lý do gì không nhận luôn một cơ sở dữ liệu làm phản hồi

    • zstd Parquet xuất từ tệp DuckDB 1.2 nén tốt hơn 2–3 lần
  • Mong là đừng dùng biểu đồ tích lũy. Tôi cho rằng gần như không thể tránh làm sai lệch ấn tượng của người đọc
    Vì rất khó ước lượng chiều cao của một điểm dữ liệu cụ thể giữa nhiễu, và nó còn ngụ ý một sự phụ thuộc có lẽ không tồn tại

    • Tôi cũng nghĩ ngay đến điều đó. Tác giả uPlot có một demo thể hiện rất rõ cái bẫy này: https://leeoniya.github.io/uPlot/demos/stacked-series.html
    • Đúng vậy :( Nhưng nếu vẽ cùng dữ liệu đó bằng biểu đồ đường thì quá nhiều đường chồng lên nhau, khó nhìn ra bất cứ điều gì
      Lần tới tôi đang nghĩ đến cách xếp chồng nhiều biểu đồ đường, mỗi biểu đồ chỉ có một chuỗi theo từng khu vực
    • Cách tiếp cận 3D là nơi giải quyết vấn đề này. Vẫn xếp chồng nhưng thêm một chút độ lệch; dùng công nghệ game engine cho business intelligence thực tế để hiểu lượng dữ liệu lớn trong một lần, không gì tốt hơn thế
      Hãy xem công việc của https://flowimmersive.com/
    • Bạn nghĩ sao về biểu đồ tích lũy với trục y logarit? Một số thí nghiệm vật lý luôn làm như vậy[1], nhưng tôi thấy khá thiếu trực quan
      [1]: https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PUBNOTES/ATL-...
  • Trước đây tôi từng làm một cái, https://github.com/ashish01/hn-data-dumps, khá thú vị
    Một tính năng sẽ rất hay nếu triển khai là phản ánh việc các mục gần đây, vì được cập nhật thường xuyên hơn theo thời gian, sẽ trở thành cache cũ nhanh hơn các mục cũ hơn

    • Thật tuyệt khi HN cung cấp API như thế này thay vì khóa lại như nhiều trang khác
      Tôi đã dùng một hàm dựa trên tuổi để xác định độ cũ. Ban đầu xem là cũ từ 1–2 phút sau khi tạo, rồi làm mới thường xuyên trong vài ngày, sau đó giảm nhanh sau tuần đầu tiên và coi là bất biến sau khoảng 2 tuần
      // DefaultStaleIf marks stale at 60 seconds after creation, then frequently for the first few days after an item is
      // created, then quickly tapers after the first week to never again mark stale items more than a few weeks old.
      const DefaultStaleIf = "(:now-refreshed)>" +
      "(60.0*(log2(max(0.0,((:now-Time)/60.0))+1.0)+pow(((:now-Time)/(24.0*60.0*60.0)),3)))"
      https://github.com/jasonthorsness/unlurker/blob/main/hn/core...