Huggingface.js documentation
@huggingface/gguf
@huggingface/gguf
์๊ฒฉ ํธ์คํ ํ์ผ์์ ์๋ํ๋ GGUF ํ์์ ๋๋ค.
์ฌ์
Spec: https://github.com/ggerganov/ggml/blob/master/docs/gguf.md
์ฐธ์กฐ ๊ตฌํ (Python): https://github.com/ggerganov/llama.cpp/blob/master/gguf-py/gguf/gguf_reader.py
์ค์น
npm install @huggingface/gguf
์ฌ์ฉ
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
import { GGMLQuantizationType, gguf } from "@huggingface/gguf";
// remote GGUF file from https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF
const URL_LLAMA = "https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/191239b/llama-2-7b-chat.Q2_K.gguf";
const { metadata, tensorInfos } = await gguf(URL_LLAMA);
console.log(metadata);
// {
// version: 2,
// tensor_count: 291n,
// kv_count: 19n,
// "general.architecture": "llama",
// "general.file_type": 10,
// "general.name": "LLaMA v2",
// ...
// }
console.log(tensorInfos);
// [
// {
// name: "token_embd.weight",
// shape: [4096n, 32000n],
// dtype: GGMLQuantizationType.Q2_K,
// },
// ... ,
// {
// name: "output_norm.weight",
// shape: [4096n],
// dtype: GGMLQuantizationType.F32,
// }
// ]
๋ก์ปฌ ํ์ผ ์ฝ๊ธฐ
// Reading a local file. (Not supported on browser)
const { metadata, tensorInfos } = await gguf(
'./my_model.gguf',
{ allowLocalFile: true },
);ํ์ ์ด ์ง์ ๋ ๋ฉํ๋ฐ์ดํฐ
typedMetadata: true๋ฅผ ์ค์ ํ๋ฉด ํ์
์ ๋ณด๊ฐ ํฌํจ๋ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์๋ณธ ๊ฐ๊ณผ ํด๋น GGUF ๋ฐ์ดํฐ ํ์
์ ๋ชจ๋ ์ ๊ณตํฉ๋๋ค:
import { GGMLQuantizationType, GGUFValueType, gguf } from "@huggingface/gguf";
const URL_LLAMA = "https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/191239b/llama-2-7b-chat.Q2_K.gguf";
const { metadata, typedMetadata } = await gguf(URL_LLAMA, { typedMetadata: true });
console.log(typedMetadata);
// {
// version: { value: 2, type: GGUFValueType.UINT32 },
// tensor_count: { value: 291n, type: GGUFValueType.UINT64 },
// kv_count: { value: 19n, type: GGUFValueType.UINT64 },
// "general.architecture": { value: "llama", type: GGUFValueType.STRING },
// "general.file_type": { value: 10, type: GGUFValueType.UINT32 },
// "general.name": { value: "LLaMA v2", type: GGUFValueType.STRING },
// "llama.attention.head_count": { value: 32, type: GGUFValueType.UINT32 },
// "llama.attention.layer_norm_rms_epsilon": { value: 9.999999974752427e-7, type: GGUFValueType.FLOAT32 },
// "tokenizer.ggml.tokens": { value: ["<unk>", "<s>", "</s>", ...], type: GGUFValueType.ARRAY, subType: GGUFValueType.STRING },
// "tokenizer.ggml.scores": { value: [0.0, -1000.0, -1000.0, ...], type: GGUFValueType.ARRAY, subType: GGUFValueType.FLOAT32 },
// ...
// }
// Access both value and type information
console.log(typedMetadata["general.architecture"].value); // "llama"
console.log(typedMetadata["general.architecture"].type); // GGUFValueType.STRING (8)
// For arrays, subType indicates the type of array elements
console.log(typedMetadata["tokenizer.ggml.tokens"].type); // GGUFValueType.ARRAY (9)
console.log(typedMetadata["tokenizer.ggml.tokens"].subType); // GGUFValueType.STRING (8)์๊ฒฉํ ํ์
๊ธฐ๋ณธ์ ์ผ๋ก metadata์ ์๋ ค์ง ํ๋๋ ํ์
์ด ์ง์ ๋ฉ๋๋ค. ์ฌ๊ธฐ์๋ llama.cpp, whisper.cpp ๋ฐ ggml์์ ๋ฐ๊ฒฌ๋๋ ๋ค์ํ ํ๋๊ฐ ํฌํจ๋ฉ๋๋ค.
const { metadata, tensorInfos } = await gguf(URL_MODEL);
// Type check for model architecture at runtime
if (metadata["general.architecture"] === "llama") {
// "llama.attention.head_count" is a valid key for llama architecture, this is typed as a number
console.log(model["llama.attention.head_count"]);
// "mamba.ssm.conv_kernel" is an invalid key, because it requires model architecture to be mamba
console.log(model["mamba.ssm.conv_kernel"]); // error
}strictly typed ๋นํ์ฑํ
GGUF ํ์์ ํ ์๋ฅผ ์ ์ฅํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก, ๊ธฐ์ ์ ์ผ๋ก ๋ค๋ฅธ ์ฉ๋๋ก๋ ํ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ปจํธ๋กค ๋ฒกํฐ, lora ๊ฐ์ค์น ๋ฑ์ ์ ์ฅํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์์ฒด์ ์ธ GGUF ๋ฉํ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด, ํ์ฑ ์ถ๋ ฅ์ GGUFParseOutput<{ strict: false }>์ผ๋ก ์บ์คํ
ํ์ฌ ์๊ฒฉํ ํ์
์ง์ (strict typing)์ ๋นํ์ฑํํ ์ ์์ต๋๋ค:
const { metadata, tensorInfos }: GGUFParseOutput<{ strict: false }> = await gguf(URL_LLAMA);๋ช ๋ น์ค ์ธํฐํ์ด์ค
์ด ํจํค์ง๋ gguf_dump.py ์คํฌ๋ฆฝํธ์ CLI ๋์์ ์ ๊ณตํฉ๋๋ค. ์ด ๋ช
๋ น์ ์ฌ์ฉํ์ฌ GGUF ๋ฉํ๋ฐ์ดํฐ์ ํ
์ ๋ชฉ๋ก์ ๋คํํ ์ ์์ต๋๋ค:
npx @huggingface/gguf my_model.gguf
# or, with a remote GGUF file:
# npx @huggingface/gguf https://huggingface.co/bartowski/Llama-3.2-1B-Instruct-GGUF/resolve/main/Llama-3.2-1B-Instruct-Q4_K_M.gguf์ถ๋ ฅ ์์:
* Dumping 36 key/value pair(s)
Idx | Count | Value
----|--------|----------------------------------------------------------------------------------
1 | 1 | version = 3
2 | 1 | tensor_count = 292
3 | 1 | kv_count = 33
4 | 1 | general.architecture = "llama"
5 | 1 | general.type = "model"
6 | 1 | general.name = "Meta Llama 3.1 8B Instruct"
7 | 1 | general.finetune = "Instruct"
8 | 1 | general.basename = "Meta-Llama-3.1"
[truncated]
* Dumping 292 tensor(s)
Idx | Num Elements | Shape | Data Type | Name
----|--------------|--------------------------------|-----------|--------------------------
1 | 64 | 64, 1, 1, 1 | F32 | rope_freqs.weight
2 | 525336576 | 4096, 128256, 1, 1 | Q4_K | token_embd.weight
3 | 4096 | 4096, 1, 1, 1 | F32 | blk.0.attn_norm.weight
4 | 58720256 | 14336, 4096, 1, 1 | Q6_K | blk.0.ffn_down.weight
[truncated]๋์ ์ด ํจํค์ง๋ฅผ ์ ์ญ์ผ๋ก ์ค์นํ ์ ์์ผ๋ฉฐ, ์ด๋ ๊ฒ ํ๋ฉด gguf-view ๋ช
๋ น์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
npm i -g @huggingface/gguf gguf-view my_model.gguf
Hugging Face Hub
Hub์ ๋ชจ๋ ํ์ผ ํ์์ ์ง์ํ๋ฉฐ GGUF ํ์์ ๋ํ ๋ด์ฅ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
์์ธํ ๋ด์ฉ์ http://hf.co/docs/hub/gguf์์ ํ์ธํ์ธ์.
๊ฐ์ฌ ๋ฐ ์๊ฐ
- @platypii์ https://github.com/hyparam/hyllama (MIT ๋ผ์ด์ ์ค)
- @biw @dkogut1996 @spencekim์ https://github.com/ahoylabs/gguf.js (MIT ๋ผ์ด์ ์ค)
๐ฅโค๏ธ
Update on GitHub