來試著用 mise

應該是前幾天在 Mastodon 上看到 (但找不到了) 有人提到 mise 這個套件,可以不用每個程式語言都裝各自的 version manager (以 Node.js 這邊的話就像是 nvmfnm 的東西),剛剛先開個獨立的 user 丟進去測,測試的情況還可以接受,就換起來用看看...

官網提供的安裝方式有不少選項可以選,除了 ... | bash 的方法以外,還有自己抓 binary 下來,丟到任何可以跑的目錄下,或是透過 apt 安裝與更新。

有了 mise 後,接著把這段 code 放到每次 login 執行的地方:(PS:裡面 bash 的欄位也可以改成 zsh)

if command -v mise > /dev/null; then
    eval "$(mise activate bash)"
fi

然後重新登入讓他生效,接著就是裝一堆東西,參數可以自己用 --help 看說明:

mise ls
mise use -g go
mise use java@11
mise use java@17
mise use -g java@lts
mise use node@16
mise use node@18
mise use -g node@lts
mise use -g perl
mise use -g python@3.12
mise use -g ruby
mise use -g rust

在裝的時候發現有些是吃 asdf 社群的資源。

另外一個我自己很需要的功能是支援 .nvmrc 切版本的功能,切進目錄後用 node -v 會看到版本切過去了。

Russ Cox 從 Go 的 tech lead 身分交棒出來

在「Russ Cox is stepping down as the Go tech lead (groups.google.com)」看到的,Russ Cox 要將 tech lead 身分交棒出來,原討論串在 Google Groups 上面:「passing torches to Austin and Cherry」。

交棒本身算是階段性任務,倒是沒什麼特別的,讓人討論起來的是這段,批評 BDFL 模式並且直接點名 Python 的情況:

In particular, I don’t believe that the “BDFL” (benevolent dictator for life) model is healthy for a person or a project. It doesn’t create space for new leaders. It’s a single point of failure. It doesn’t give the project room to grow. I think Python benefited greatly from Guido stepping down in 2018 and letting other people lead, and I’ve had in the back of my mind for many years that we should have a Go leadership change eventually.

Go 從一開始就是很純正的由商業公司開發出來的程式語言,所以本來就不會有 BDFL 的角色,這樣的批評其實蠻有趣的...

Node.js 實驗性支援 type 的語法 (但不會檢查)

Hacker News 上看到「Node.js adds experimental support for TypeScript (github.com/nodejs)」這個,標題有點誤導就是了,GitHub 上面的標題比較正確:「module: add --experimental-strip-types」。

從說明可以看到 --experimental-strip-types 參數只是接受 type 語法,但不會檢查:

It is possible to execute TypeScript files by setting the experimental flag --experimental-strip-types.

Node.js will transpile TypeScript source code into JavaScript source code.

During the transpilation process, no type checking is performed, and types are discarded.

目前的版本離跑 TypeScript 還有段距離,不過算是個有趣的開頭:

At least initially in this PR no trasformation is performed, meaning that using Enum, namespaces etc... will not be possible.

不確定官方打算要支援 TypeScript,還是只是個人作個實驗看看?

用 2024 年的技術花 US$20 嘗試重建當年 OpenAI 的 GPT-2 (124M)

GPT-2 出來的 2019 年 Nvidia 的家用顯卡應該是 2080 Ti (2018/09/27),抓一下感覺。

在「Reproducing GPT-2 in llm.c (github.com/karpathy)」這邊看到 Andrej Karpathy 試著重建 GPT-2 的計畫,雖然是最小的 model (124M),不過這邊可以注意到當年最小是 117M,其實有一點差距 (大約多了 6%):

Two other smaller releases of GPT-2 are available, including the small version of 117M parameters and the medium size of 355M parameters. Both are available to download from Huggingface.

另外維基百科上面可以看到 OpenAI 發表 GPT-2 的時候他不在 OpenAI

OpenAI (2015–2017, 2023-2024)

但畢竟曾經是 OpenAI 裡面的老大,能看到的資料總是比外面的人多不少 (加上 GPT-2 屬於過時的技術,管制上應該會鬆不少?),這也是為什麼大家會關注的原因。

這次的嘗試不是完全重現,因為當初 GPT-2 的 training data 並沒有公開,所以他只能找個接近的 data set 訓練,這代表這次不是完全與 GPT-2 相同的情況下重建:

it was trained on the never released "WebText" dataset

雖然知道軟硬體的成長速度頗快 (畢竟整個產業的錢都往這邊丟進去),不過發現用現在的技術只要 US$20 就可以重現最小的 model 還是讓人有點驚訝:

With llm.c, which is quite efficient at up to ~60% model flops utilization, reproducing this model on one 8X A100 80GB SXM node takes ~90 minutes.

理論上同樣的 code 改一些參數也就可以訓練出比較大的幾個 model?

Vector embedding

最近累積起來的東西,都跟 vector embedding 有關,第二篇甚至有提到透過 embedding 切入可以找到不少 LLM 有趣的使用方式:

自己編 llama.cpp 的時候會產生出 embeeding 這隻程式,就可以測試把文字轉成 vector 的功能,接著就可以套用高維空間的數學運算了,像是最常被提到的是利用兩個 vector 的夾角來判斷相似度。

因為是對一堆 vector 處理,就不太需要去管輸出格式的問題 (像是 ChatGPT 會自由輸出任何東西),對程式開發上會方便不少...

AMD 推出 16GB 的 RX 7600 XT

看到「AMD Unveils AMD Radeon RX 7600 XT Graphics Card – Incredible Gaming at 1080p and Beyond for Under $350」這篇,16GB VRAM 官方的定價在 US$329...

剛好昨天寫的「Mixtral 8x7B 的論文出來了」提到了 Nvidia 的 3060 Ti 的 16GB 版本是跑 LLM 的窮人選擇,因為 12GB VRAM 的卡官方訂在 US$329,目前售價大約在 NT$9000 (~US$300) 左右。

這次 AMD 這張 16GB VRAM 美國定價是 US$329,剛好跟 3060 Ti 12GB 版本相同,這下 entry level 的市場就瞬間變得有趣了起來,雖然說 AMD 這邊的軟體支援度是差了一些,但最近算是急起直追,對於想要追求 CP 值的群眾來說還蠻有吸引力的?

後續來追看看台灣的售價...

Mixtral 8x7B 的論文出來了

Hacker News 上看到 Mixtral-8x7B-v0.1 以及 Mixtral-8x7B-Instruct-v0.1 的論文出來了:「Mixtral 8x7B: A sparse Mixture of Experts language model (arxiv.org)」,arXiv 上的連結:「Mixtral of Experts」。

跟先前大家從公開資料研究的差不多,這個研究成果主要不是降低參數的大小,而是降低運算的量:

As a result, each token has access to 47B parameters, but only uses 13B active parameters during inference.

然後仍然是超越 GPT-3.5 的水準:

Mixtral was trained with a context size of 32k tokens and it outperforms or matches Llama 2 70B and GPT-3.5 across all evaluated benchmarks.

先看計算量的問題,Mixtral 8x7B 的 model 對 VRAM 要求仍然不是消費級 GPU 可以達到的,對一般家用電腦來說,還是需要 quantisation 降低精度換取對 VRAM 空間的壓力下降。

這點可以在 TheBloke/Mixtral-8x7B-v0.1-GGUF 這邊看到各種 quantisation 後需要的 VRAM 大小。

如果用 CPU 計算的話目前應該不是大問題,目前 LLM 的大小對於一般主機的 RAM 來說還不是問題 (單條 32GB,四條就有 128GB 了),加上現在 llama.cpp 主力已經是用 mmap 的方式在存取檔案,filesystem cache 可以在多次執行中重複使用,只是用 CPU 就不能對速度有太多想法了。

但如果往 GPU 這邊看的話就得取捨了,目前 GPU 中能跑 Mixtral 8x7B 最便宜的方案應該是兩張 3060 12GB 組成 24GB VRAM,一張約 NT$9k (~US$300),兩張約 NT$18k (~US$600),這樣的話有機會跑 mixtral-8x7b-v0.1.Q3_K_M.gguf,不過這邊寫「very small, high quality loss」。

如果 mixtral-8x7b-v0.1.Q3_K_M.gguf 的品質不能接受,希望計算品質好一點的話,三張 3060 Ti 12GB 組 36GB VRAM 的方案約 NT$27000 (~US$900),不過主機板可能要挑一下;這樣就有機會用需求 34.73 GB VRAM 的 mixtral-8x7b-v0.1.Q5_K_M.gguf 了,評語是「large, very low quality loss - recommended」。

最後岔題,剛剛算了一下成本,發現 3060 Ti 12GB 這張還是穩穩的 LLM 窮人卡,先前在「雲端上面的 GPU 資源費用,以及地端的 GPU 決策圖」這邊提到的決策圖,即使在 2023 年七月 4060 Ti 16GB 出了以後還是很好用... (約 NT$15k,~US$500)

微軟 Phi-2 model 的授權改成 MIT License

Hacker News 的「Microsoft Phi-2 model changes licence to MIT (huggingface.co)」這邊看到的消息,連結是改成 MIT License 的 commit:「Upload 3 files · microsoft/phi-2 at 7e10f3e」。

看了一下 model 的參數是 2.7B,宣稱在 13B 以下 model 中是前段班:

Phi-2 showcased a nearly state-of-the-art performance among models with less than 13 billion parameters.

再回頭查一下這段宣稱的時間,當初發表的時間是 2023/12/12:「Phi-2: The surprising power of small language models」。

應該是希望在行動裝置上用更少的運算量達到效果...

另外找了一下 GGUF 格式,看起來 TheBloke/phi-2-GGUF 這邊已經有轉好的了,可以直接上 llama.cpp 跑。

JavaScript 的分號,以及 ASI (Automatic Semicolon Insertion)

目前 community 的主流跟我理出來的期望不一樣... 所以記錄一下。

先提一下背景,在 JavaScript 程式語言裡面,在大多數的情境下是可以省略掉分號 (;) 的,也就是說這兩種寫法都是合法的 JavaScript 語法:

console.log('Hello, world.')
console.log('Hello, world.');

這是因為在 ECMA-262 裡面有 ASI (Automatic Semicolon Insertion) 的設計:「Automatic Semicolon Insertion」。

ASI 設計本身是好的,可以讓開發者少處理 ;,但偏偏 EMCA-262 又允許千變萬化的換行,於是就造成了各種奇怪的現象。

因此早期在 community 上都是推薦無條件加上分號,這可以避免各種奇怪的 bug 與 error,像是「Do you recommend using semicolons after every statement in JavaScript?」以及「Should I use semicolons in JavaScript?」這些問答。

大家會推薦加上分號主要的原因是因為,不加上分號遇到的 error 與 bug 不是那種你知道很雷,所以會主動查詢 & 避開的問題:

而是各種平常寫就會遇到的情況,最容易中獎的是第二組敘述是 ([ 開頭的,像是 ECMA-262 文件裡面提到的 case 就算常見了:

a = b + c
(d + e).print()

// 等價於:
a = b + c(d + e).print();

而且不因為註解受到影響:

// blahblah
a = b + c

// blahblah
(d + e).print()

// 還是等價於:
a = b + c(d + e).print();

另外一個常見的情況是我們會利用 anonymous function 包出一個 block,避免變數污染到外面:

// I want to do blahblahblah...
(() => {
  const a = '';
  // ...
})()

// I want to do another blahblahblah...
(() => {
  const a = '';
  // ...
})()

大多數的情況應該會 error,除非第一個 anonymous function 傳回一個 callable,而這種情況跑出來的結果就更慘了...

另外這種 case 也是常見的情況:

// ...
[1, 2, 3].forEach(...)

// ...
[4, 5, 6].forEach(...)

// 等價於:
[1, 2, 3].forEach(...)[4, 5, 6].forEach(...)

這邊省略分號最大的問題是你無法知道「自己這行需不需要加上分號」,因為註解可能很長有個 30 行,所以依照這些現況,比較好的方法應該是全部加上分號,保持一致性。

但這幾年所有的 frontend framework 都是推動拿掉分號,這可以從各家的文件看到,就搞不懂 community 是怎麼推導出來的... 在全部都拿掉分號的情況下,遇到上面的情況就得寫成不一致的 style:

// ...
[1, 2, 3].forEach(...);

// ...
[4, 5, 6].forEach(...)

查了目前可行的 workaround,大多都是透過 ESLint 類的工具來擋可能會出現 bug 的地方,也只能先這樣做了...

漢字字形的處理

Hacker News 上看到「Your Code Displays Japanese Wrong (heistak.github.io)」這篇,原文是「Your Code Displays Japanese Wrong」。

這個算是 CJK 族群的經典問題,主要的問題是有不同的團體都在使用漢字,但雖然都是 U+5203 的「刃」,在不同的地區的「標準寫法」是不一樣的,像是「國家教育研究院 - 教育部國語小字典-刃」這邊就有 SVG 版本的「圖」可以看:

我在 different-lang.html 這邊把他提到的「刃直海角骨入」給放了進去,指定不同的 lang,像是這樣:

<dt>lang="jp"</dt><dd lang="jp">刃直海角骨入</dd>

如果你的電腦裡面有 Noto Sans CJK 的話,應該可以看出不同的字形。

在 HTML 網頁上可以利用 html 內的 lang 資訊告訴瀏覽器去抓取對應的字形,當然,系統有沒有這個字形又是另外一回事了,不過市場上至少有 open source license 的 Noto CJK 系列,算是個低標的答案可以用。

至於要更多樣的話,應該是要分不同語言下去找...