mirror of
https://github.com/ggerganov/llama.cpp.git
synced 2024-12-28 12:24:35 +00:00
bae6b125f6
* Add LLAMA_DEFAULT_RMS_EPS so we can change the default (#2384) Co-authored-by: Iwan Kawrakow <iwan.kawrakow@gmail.com> * WIP: python class to write GGUF, incomplete C apı for reading --------- Co-authored-by: Kawrakow <48489457+ikawrakow@users.noreply.github.com> Co-authored-by: Iwan Kawrakow <iwan.kawrakow@gmail.com>
193 lines
5.9 KiB
C
193 lines
5.9 KiB
C
// TODO: convert to proper gguf.h gguf.c structure, now I'm trying to be fast as much as possible,
|
|
// and everything is in this file for quick debugging.
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
|
|
|
|
enum ggml_type {
|
|
GGML_TYPE_F32 = 0,
|
|
GGML_TYPE_F16 = 1,
|
|
GGML_TYPE_Q4_0 = 2,
|
|
GGML_TYPE_Q4_1 = 3,
|
|
// GGML_TYPE_Q4_2 = 4, support has been removed
|
|
// GGML_TYPE_Q4_3 (5) support has been removed
|
|
GGML_TYPE_Q5_0 = 6,
|
|
GGML_TYPE_Q5_1 = 7,
|
|
GGML_TYPE_Q8_0 = 8,
|
|
GGML_TYPE_Q8_1 = 9,
|
|
// k-quantizations
|
|
GGML_TYPE_Q2_K = 10,
|
|
GGML_TYPE_Q3_K = 11,
|
|
GGML_TYPE_Q4_K = 12,
|
|
GGML_TYPE_Q5_K = 13,
|
|
GGML_TYPE_Q6_K = 14,
|
|
GGML_TYPE_Q8_K = 15,
|
|
GGML_TYPE_I8,
|
|
GGML_TYPE_I16,
|
|
GGML_TYPE_I32,
|
|
GGML_TYPE_COUNT,
|
|
};
|
|
|
|
enum gguf_metadata_value_type {
|
|
GGUF_METADATA_VALUE_TYPE_UINT8 = 0,
|
|
GGUF_METADATA_VALUE_TYPE_INT8 = 1,
|
|
GGUF_METADATA_VALUE_TYPE_UINT16 = 2,
|
|
GGUF_METADATA_VALUE_TYPE_INT16 = 3,
|
|
GGUF_METADATA_VALUE_TYPE_UINT32 = 4,
|
|
GGUF_METADATA_VALUE_TYPE_INT32 = 5,
|
|
GGUF_METADATA_VALUE_TYPE_FLOAT32 = 6,
|
|
GGUF_METADATA_VALUE_TYPE_BOOL = 7,
|
|
GGUF_METADATA_VALUE_TYPE_STRING = 8,
|
|
GGUF_METADATA_VALUE_TYPE_ARRAY = 9,
|
|
};
|
|
|
|
struct gguf_string_t {
|
|
uint32_t len;
|
|
char * string;
|
|
};
|
|
|
|
union gguf_metadata_value_t;
|
|
|
|
// Union definition for gguf_metadata_value_t
|
|
union gguf_metadata_value_t {
|
|
uint8_t uint8;
|
|
int8_t int8;
|
|
uint16_t uint16;
|
|
int16_t int16;
|
|
uint32_t uint32;
|
|
int32_t int32;
|
|
float float32;
|
|
bool bool_;
|
|
struct gguf_string_t string;
|
|
struct {
|
|
uint32_t len;
|
|
enum gguf_metadata_value_type type;
|
|
union gguf_metadata_value_t * array;
|
|
} array;
|
|
};
|
|
|
|
|
|
struct gguf_metadata_kv_t {
|
|
struct gguf_string_t key;
|
|
uint32_t value_len;
|
|
enum gguf_metadata_value_type value_type;
|
|
union gguf_metadata_value_t* value;
|
|
};
|
|
|
|
struct gguf_header_t {
|
|
uint32_t magic;
|
|
uint32_t version;
|
|
uint32_t tensor_count;
|
|
uint32_t metadata_kv_count;
|
|
struct gguf_metadata_kv_t * metadata_kv;
|
|
};
|
|
|
|
struct gguf_tensor_info_t {
|
|
struct gguf_string_t name;
|
|
uint32_t n_dimensions;
|
|
uint32_t dimensions[];
|
|
};
|
|
|
|
struct gguf_file_t {
|
|
struct gguf_header_t header;
|
|
uint8_t tensor_data[];
|
|
};
|
|
|
|
void read_gguf_file(const char * file_path, struct gguf_file_t * gguf_file) {
|
|
FILE* file = fopen(file_path, "rb");
|
|
if (file == NULL) {
|
|
printf("Error opening the file.\n");
|
|
return;
|
|
}
|
|
|
|
fread(&gguf_file->header.magic, sizeof(uint32_t), 1, file);
|
|
|
|
// Verify magic and version
|
|
if (gguf_file->header.magic != 0x47475546) {
|
|
printf("Invalid magic number. Not a valid GGUF file.\n");
|
|
fclose(file);
|
|
return;
|
|
}
|
|
|
|
fread(&gguf_file->header.version, sizeof(uint32_t), 1, file);
|
|
|
|
if (gguf_file->header.version != 1) {
|
|
printf("Unsupported version. Expected version 1.\n");
|
|
fclose(file);
|
|
return;
|
|
}
|
|
|
|
fread(&gguf_file->header.tensor_count, sizeof(uint32_t), 1, file);
|
|
fread(&gguf_file->header.metadata_kv_count, sizeof(uint32_t), 1, file);
|
|
|
|
printf("Magic: %x\n", gguf_file->header.magic);
|
|
printf("Version: %d\n", gguf_file->header.version);
|
|
printf("Tensor Count: %d\n", gguf_file->header.tensor_count);
|
|
printf("Metadata Key-Value Count: %d\n", gguf_file->header.metadata_kv_count);
|
|
|
|
gguf_file->header.metadata_kv = (struct gguf_metadata_kv_t*)malloc(gguf_file->header.metadata_kv_count * sizeof(struct gguf_metadata_kv_t));
|
|
|
|
for (int i = 0; i < gguf_file->header.metadata_kv_count; i++) {
|
|
struct gguf_metadata_kv_t* kv = &gguf_file->header.metadata_kv[i];
|
|
fread(&kv->key.len, sizeof(uint32_t), 1, file);
|
|
kv->key.string = (char*)malloc(kv->key.len ); // Allocate memory for the key string
|
|
fread(kv->key.string, sizeof(char), kv->key.len, file);
|
|
//kv->key.string[kv->key.len] = '\0'; // Null-terminate the key string
|
|
|
|
fread(&kv->value_type, sizeof(uint32_t), 1, file);
|
|
|
|
printf("Metadata Value Type: %d\n", kv->value_type);
|
|
printf("Metadata Key: %s\n", kv->key.string);
|
|
|
|
// Read metadata value according to its type using reinterpret_cast
|
|
switch (kv->value_type) {
|
|
case GGUF_METADATA_VALUE_TYPE_UINT32:
|
|
kv->value = (uint32_t *) malloc(sizeof(uint32_t));
|
|
fread(kv->value, sizeof(uint32_t), 1, file);
|
|
printf("value: %d\n", kv->value->uint32);
|
|
break;
|
|
case GGUF_METADATA_VALUE_TYPE_FLOAT32:
|
|
kv->value = (float *)malloc(sizeof(float));
|
|
fread(kv->value, sizeof(float), 1, file);
|
|
printf("value: %f\n", (float)kv->value->float32);
|
|
break;
|
|
case GGUF_METADATA_VALUE_TYPE_STRING:
|
|
fread(&kv->value_len, sizeof(uint32_t), 1, file);
|
|
printf("value len: %d\n", kv->value_len);
|
|
kv->value = (char *)malloc(sizeof(char) * kv->value_len); // Allocate memory for the value string
|
|
fread(kv->value, sizeof(char), kv->value_len, file);
|
|
printf("value: %s\n", (char *)kv->value);
|
|
break;
|
|
// ... (handle other types in a similar manner)
|
|
default:
|
|
printf("Unsupported metadata value type.\n");
|
|
fclose(file);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// TODO: handle reading tensor data
|
|
|
|
fclose(file);
|
|
}
|
|
|
|
void gguf_free(struct gguf_file_t * gguf_file) {
|
|
// Free allocated memory for key strings avd values
|
|
for (int i = 0; i < gguf_file->header.metadata_kv_count; i++) {
|
|
free(gguf_file->header.metadata_kv[i].key.string);
|
|
free(gguf_file->header.metadata_kv[i].value);
|
|
}
|
|
free(gguf_file->header.metadata_kv);
|
|
}
|
|
|
|
int main() {
|
|
const char* file_path = "example.gguf";
|
|
struct gguf_file_t gguf_file;
|
|
read_gguf_file(file_path, &gguf_file);
|
|
gguf_free(&gguf_file);
|
|
return 0;
|
|
}
|