-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Embed yolo files #831
base: master
Are you sure you want to change the base?
Embed yolo files #831
Conversation
Is it really necessary to a new type of object to the GGUF format to do this? The file data could be stored either as an array metadata or as a tensor. |
I agree with @slaren - don't think it's necessary to introduce named object. But the rest of the idea to embed the data in the GGUF file is nice |
Thanks for prompt checking, @slaren and @ggerganov . But, I think embedding files need 3 elements, such as path name string(GGUF string 2 part as length and string byte stream), length of data, data stream. |
You can store the data in an UINT8 array, |
You can for example store a KV string array with filenames and for each filename have a U8 tensor for each file containing the binary data:
|
Thanks comments, and sorry for my late response because of my hard working days. |
finally, I added file data as follows;
So, I deleted all NAMEDOBJECT part. |
I also removed dump code from gguf-addfile.py script. this script usage example: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you try to update ci/run.sh
to use the new script in the tests?
Adding the files as tensors instead of KV can have some advantages, because the GGUF header remains small. For example, I'm not sure how the GGUF viewer on HuggingFace would handle big data in the header. So it's an option that might be worth exploring
examples/yolo/yolov3-tiny.cpp
Outdated
@@ -30,6 +30,7 @@ struct yolo_model { | |||
int height = 416; | |||
std::vector<conv2d_layer> conv2d_layers; | |||
struct ggml_context * ctx; | |||
struct gguf_context * ggufctx; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
struct gguf_context * ggufctx; | |
struct gguf_context * ctx_gguf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
applied
include/ggml/ggml.h
Outdated
GGML_API uint8_t gguf_get_val_u8 (const struct gguf_context * ctx, int key_id); | ||
GGML_API int8_t gguf_get_val_i8 (const struct gguf_context * ctx, int key_id); | ||
GGML_API uint16_t gguf_get_val_u16 (const struct gguf_context * ctx, int key_id); | ||
GGML_API int16_t gguf_get_val_i16 (const struct gguf_context * ctx, int key_id); | ||
GGML_API uint32_t gguf_get_val_u32 (const struct gguf_context * ctx, int key_id); | ||
GGML_API int32_t gguf_get_val_i32 (const struct gguf_context * ctx, int key_id); | ||
GGML_API float gguf_get_val_f32 (const struct gguf_context * ctx, int key_id); | ||
GGML_API uint64_t gguf_get_val_u64 (const struct gguf_context * ctx, int key_id); | ||
GGML_API int64_t gguf_get_val_i64 (const struct gguf_context * ctx, int key_id); | ||
GGML_API double gguf_get_val_f64 (const struct gguf_context * ctx, int key_id); | ||
GGML_API bool gguf_get_val_bool (const struct gguf_context * ctx, int key_id); | ||
GGML_API const char * gguf_get_val_str (const struct gguf_context * ctx, int key_id); | ||
GGML_API uint64_t gguf_get_val_str_len(const struct gguf_context * ctx, int key_id); | ||
GGML_API const void * gguf_get_val_data (const struct gguf_context * ctx, int key_id); | ||
GGML_API int gguf_get_arr_n (const struct gguf_context * ctx, int key_id); | ||
GGML_API const void * gguf_get_arr_data (const struct gguf_context * ctx, int key_id); | ||
GGML_API const char * gguf_get_arr_str (const struct gguf_context * ctx, int key_id, int i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GGML_API uint8_t gguf_get_val_u8 (const struct gguf_context * ctx, int key_id); | |
GGML_API int8_t gguf_get_val_i8 (const struct gguf_context * ctx, int key_id); | |
GGML_API uint16_t gguf_get_val_u16 (const struct gguf_context * ctx, int key_id); | |
GGML_API int16_t gguf_get_val_i16 (const struct gguf_context * ctx, int key_id); | |
GGML_API uint32_t gguf_get_val_u32 (const struct gguf_context * ctx, int key_id); | |
GGML_API int32_t gguf_get_val_i32 (const struct gguf_context * ctx, int key_id); | |
GGML_API float gguf_get_val_f32 (const struct gguf_context * ctx, int key_id); | |
GGML_API uint64_t gguf_get_val_u64 (const struct gguf_context * ctx, int key_id); | |
GGML_API int64_t gguf_get_val_i64 (const struct gguf_context * ctx, int key_id); | |
GGML_API double gguf_get_val_f64 (const struct gguf_context * ctx, int key_id); | |
GGML_API bool gguf_get_val_bool (const struct gguf_context * ctx, int key_id); | |
GGML_API const char * gguf_get_val_str (const struct gguf_context * ctx, int key_id); | |
GGML_API uint64_t gguf_get_val_str_len(const struct gguf_context * ctx, int key_id); | |
GGML_API const void * gguf_get_val_data (const struct gguf_context * ctx, int key_id); | |
GGML_API int gguf_get_arr_n (const struct gguf_context * ctx, int key_id); | |
GGML_API const void * gguf_get_arr_data (const struct gguf_context * ctx, int key_id); | |
GGML_API const char * gguf_get_arr_str (const struct gguf_context * ctx, int key_id, int i); | |
GGML_API uint8_t gguf_get_val_u8 (const struct gguf_context * ctx, int key_id); | |
GGML_API int8_t gguf_get_val_i8 (const struct gguf_context * ctx, int key_id); | |
GGML_API uint16_t gguf_get_val_u16 (const struct gguf_context * ctx, int key_id); | |
GGML_API int16_t gguf_get_val_i16 (const struct gguf_context * ctx, int key_id); | |
GGML_API uint32_t gguf_get_val_u32 (const struct gguf_context * ctx, int key_id); | |
GGML_API int32_t gguf_get_val_i32 (const struct gguf_context * ctx, int key_id); | |
GGML_API float gguf_get_val_f32 (const struct gguf_context * ctx, int key_id); | |
GGML_API uint64_t gguf_get_val_u64 (const struct gguf_context * ctx, int key_id); | |
GGML_API int64_t gguf_get_val_i64 (const struct gguf_context * ctx, int key_id); | |
GGML_API double gguf_get_val_f64 (const struct gguf_context * ctx, int key_id); | |
GGML_API bool gguf_get_val_bool (const struct gguf_context * ctx, int key_id); | |
GGML_API const char * gguf_get_val_str (const struct gguf_context * ctx, int key_id); | |
GGML_API uint64_t gguf_get_val_str_len(const struct gguf_context * ctx, int key_id); | |
GGML_API const void * gguf_get_val_data (const struct gguf_context * ctx, int key_id); | |
GGML_API int gguf_get_arr_n (const struct gguf_context * ctx, int key_id); | |
GGML_API const void * gguf_get_arr_data (const struct gguf_context * ctx, int key_id); | |
GGML_API const char * gguf_get_arr_str (const struct gguf_context * ctx, int key_id, int i); |
src/ggml.c
Outdated
case GGUF_TYPE_UINT8: ok = ok && gguf_fread_el (file, &kv->value.uint8, sizeof(kv->value.uint8), &offset); break; | ||
case GGUF_TYPE_INT8: ok = ok && gguf_fread_el (file, &kv->value.int8, sizeof(kv->value.int8), &offset); break; | ||
case GGUF_TYPE_UINT16: ok = ok && gguf_fread_el (file, &kv->value.uint16, sizeof(kv->value.uint16), &offset); break; | ||
case GGUF_TYPE_INT16: ok = ok && gguf_fread_el (file, &kv->value.int16, sizeof(kv->value.int16), &offset); break; | ||
case GGUF_TYPE_UINT32: ok = ok && gguf_fread_el (file, &kv->value.uint32, sizeof(kv->value.uint32), &offset); break; | ||
case GGUF_TYPE_INT32: ok = ok && gguf_fread_el (file, &kv->value.int32, sizeof(kv->value.int32), &offset); break; | ||
case GGUF_TYPE_FLOAT32: ok = ok && gguf_fread_el (file, &kv->value.float32, sizeof(kv->value.float32), &offset); break; | ||
case GGUF_TYPE_UINT64: ok = ok && gguf_fread_el (file, &kv->value.uint64, sizeof(kv->value.uint64), &offset); break; | ||
case GGUF_TYPE_INT64: ok = ok && gguf_fread_el (file, &kv->value.int64, sizeof(kv->value.int64), &offset); break; | ||
case GGUF_TYPE_FLOAT64: ok = ok && gguf_fread_el (file, &kv->value.float64, sizeof(kv->value.float64), &offset); break; | ||
case GGUF_TYPE_BOOL: ok = ok && gguf_fread_el (file, &kv->value.bool_, sizeof(kv->value.bool_), &offset); break; | ||
case GGUF_TYPE_STRING: ok = ok && gguf_fread_str (file, &kv->value.str, &offset); break; | ||
case GGUF_TYPE_ARRAY: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
case GGUF_TYPE_UINT8: ok = ok && gguf_fread_el (file, &kv->value.uint8, sizeof(kv->value.uint8), &offset); break; | |
case GGUF_TYPE_INT8: ok = ok && gguf_fread_el (file, &kv->value.int8, sizeof(kv->value.int8), &offset); break; | |
case GGUF_TYPE_UINT16: ok = ok && gguf_fread_el (file, &kv->value.uint16, sizeof(kv->value.uint16), &offset); break; | |
case GGUF_TYPE_INT16: ok = ok && gguf_fread_el (file, &kv->value.int16, sizeof(kv->value.int16), &offset); break; | |
case GGUF_TYPE_UINT32: ok = ok && gguf_fread_el (file, &kv->value.uint32, sizeof(kv->value.uint32), &offset); break; | |
case GGUF_TYPE_INT32: ok = ok && gguf_fread_el (file, &kv->value.int32, sizeof(kv->value.int32), &offset); break; | |
case GGUF_TYPE_FLOAT32: ok = ok && gguf_fread_el (file, &kv->value.float32, sizeof(kv->value.float32), &offset); break; | |
case GGUF_TYPE_UINT64: ok = ok && gguf_fread_el (file, &kv->value.uint64, sizeof(kv->value.uint64), &offset); break; | |
case GGUF_TYPE_INT64: ok = ok && gguf_fread_el (file, &kv->value.int64, sizeof(kv->value.int64), &offset); break; | |
case GGUF_TYPE_FLOAT64: ok = ok && gguf_fread_el (file, &kv->value.float64, sizeof(kv->value.float64), &offset); break; | |
case GGUF_TYPE_BOOL: ok = ok && gguf_fread_el (file, &kv->value.bool_, sizeof(kv->value.bool_), &offset); break; | |
case GGUF_TYPE_STRING: ok = ok && gguf_fread_str (file, &kv->value.str, &offset); break; | |
case GGUF_TYPE_ARRAY: | |
case GGUF_TYPE_UINT8: ok = ok && gguf_fread_el (file, &kv->value.uint8, sizeof(kv->value.uint8), &offset); break; | |
case GGUF_TYPE_INT8: ok = ok && gguf_fread_el (file, &kv->value.int8, sizeof(kv->value.int8), &offset); break; | |
case GGUF_TYPE_UINT16: ok = ok && gguf_fread_el (file, &kv->value.uint16, sizeof(kv->value.uint16), &offset); break; | |
case GGUF_TYPE_INT16: ok = ok && gguf_fread_el (file, &kv->value.int16, sizeof(kv->value.int16), &offset); break; | |
case GGUF_TYPE_UINT32: ok = ok && gguf_fread_el (file, &kv->value.uint32, sizeof(kv->value.uint32), &offset); break; | |
case GGUF_TYPE_INT32: ok = ok && gguf_fread_el (file, &kv->value.int32, sizeof(kv->value.int32), &offset); break; | |
case GGUF_TYPE_FLOAT32: ok = ok && gguf_fread_el file, &kv->value.float32, sizeof(kv->value.float32), &offset); break; | |
case GGUF_TYPE_UINT64: ok = ok && gguf_fread_el (file, &kv->value.uint64, sizeof(kv->value.uint64), &offset); break; | |
case GGUF_TYPE_INT64: ok = ok && gguf_fread_el (file, &kv->value.int64, sizeof(kv->value.int64), &offset); break; | |
case GGUF_TYPE_FLOAT64: ok = ok && gguf_fread_el (file, &kv->value.float64, sizeof(kv->value.float64), &offset); break; | |
case GGUF_TYPE_BOOL: ok = ok && gguf_fread_el (file, &kv->value.bool_, sizeof(kv->value.bool_), &offset); break; | |
case GGUF_TYPE_STRING: ok = ok && gguf_fread_str(file, &kv->value.str, &offset); break; | |
case GGUF_TYPE_ARRAY: |
src/ggml.c
Outdated
case GGUF_TYPE_UINT8: gguf_bwrite_el (buf, &kv->value.uint8, sizeof(kv->value.uint8) ); break; | ||
case GGUF_TYPE_INT8: gguf_bwrite_el (buf, &kv->value.int8, sizeof(kv->value.int8) ); break; | ||
case GGUF_TYPE_UINT16: gguf_bwrite_el (buf, &kv->value.uint16, sizeof(kv->value.uint16) ); break; | ||
case GGUF_TYPE_INT16: gguf_bwrite_el (buf, &kv->value.int16, sizeof(kv->value.int16) ); break; | ||
case GGUF_TYPE_UINT32: gguf_bwrite_el (buf, &kv->value.uint32, sizeof(kv->value.uint32) ); break; | ||
case GGUF_TYPE_INT32: gguf_bwrite_el (buf, &kv->value.int32, sizeof(kv->value.int32) ); break; | ||
case GGUF_TYPE_FLOAT32: gguf_bwrite_el (buf, &kv->value.float32, sizeof(kv->value.float32)); break; | ||
case GGUF_TYPE_UINT64: gguf_bwrite_el (buf, &kv->value.uint64, sizeof(kv->value.uint64) ); break; | ||
case GGUF_TYPE_INT64: gguf_bwrite_el (buf, &kv->value.int64, sizeof(kv->value.int64) ); break; | ||
case GGUF_TYPE_FLOAT64: gguf_bwrite_el (buf, &kv->value.float64, sizeof(kv->value.float64)); break; | ||
case GGUF_TYPE_BOOL: gguf_bwrite_el (buf, &kv->value.bool_, sizeof(kv->value.bool_) ); break; | ||
case GGUF_TYPE_STRING: gguf_bwrite_str (buf, &kv->value.str ); break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
case GGUF_TYPE_UINT8: gguf_bwrite_el (buf, &kv->value.uint8, sizeof(kv->value.uint8) ); break; | |
case GGUF_TYPE_INT8: gguf_bwrite_el (buf, &kv->value.int8, sizeof(kv->value.int8) ); break; | |
case GGUF_TYPE_UINT16: gguf_bwrite_el (buf, &kv->value.uint16, sizeof(kv->value.uint16) ); break; | |
case GGUF_TYPE_INT16: gguf_bwrite_el (buf, &kv->value.int16, sizeof(kv->value.int16) ); break; | |
case GGUF_TYPE_UINT32: gguf_bwrite_el (buf, &kv->value.uint32, sizeof(kv->value.uint32) ); break; | |
case GGUF_TYPE_INT32: gguf_bwrite_el (buf, &kv->value.int32, sizeof(kv->value.int32) ); break; | |
case GGUF_TYPE_FLOAT32: gguf_bwrite_el (buf, &kv->value.float32, sizeof(kv->value.float32)); break; | |
case GGUF_TYPE_UINT64: gguf_bwrite_el (buf, &kv->value.uint64, sizeof(kv->value.uint64) ); break; | |
case GGUF_TYPE_INT64: gguf_bwrite_el (buf, &kv->value.int64, sizeof(kv->value.int64) ); break; | |
case GGUF_TYPE_FLOAT64: gguf_bwrite_el (buf, &kv->value.float64, sizeof(kv->value.float64)); break; | |
case GGUF_TYPE_BOOL: gguf_bwrite_el (buf, &kv->value.bool_, sizeof(kv->value.bool_) ); break; | |
case GGUF_TYPE_STRING: gguf_bwrite_str (buf, &kv->value.str ); break; | |
case GGUF_TYPE_UINT8: gguf_bwrite_el (buf, &kv->value.uint8, sizeof(kv->value.uint8) ); break; | |
case GGUF_TYPE_INT8: gguf_bwrite_el (buf, &kv->value.int8, sizeof(kv->value.int8) ); break; | |
case GGUF_TYPE_UINT16: gguf_bwrite_el (buf, &kv->value.uint16, sizeof(kv->value.uint16) ); break; | |
case GGUF_TYPE_INT16: gguf_bwrite_el (buf, &kv->value.int16, sizeof(kv->value.int16) ); break; | |
case GGUF_TYPE_UINT32: gguf_bwrite_el (buf, &kv->value.uint32, sizeof(kv->value.uint32) ); break; | |
case GGUF_TYPE_INT32: gguf_bwrite_el (buf, &kv->value.int32, sizeof(kv->value.int32) ); break; | |
case GGUF_TYPE_FLOAT32: gguf_bwrite_el (buf, &kv->value.float32, sizeof(kv->value.float32)); break; | |
case GGUF_TYPE_UINT64: gguf_bwrite_el (buf, &kv->value.uint64, sizeof(kv->value.uint64) ); break; | |
case GGUF_TYPE_INT64: gguf_bwrite_el (buf, &kv->value.int64, sizeof(kv->value.int64) ); break; | |
case GGUF_TYPE_FLOAT64: gguf_bwrite_el (buf, &kv->value.float64, sizeof(kv->value.float64)); break; | |
case GGUF_TYPE_BOOL: gguf_bwrite_el (buf, &kv->value.bool_, sizeof(kv->value.bool_) ); break; | |
case GGUF_TYPE_STRING: gguf_bwrite_str(buf, &kv->value.str ); break; |
I revised code as to add files to tensor data. I try to update ci/run.sh later. |
include/ggml/ggml.h
Outdated
GGML_API char * gguf_get_tensor_name (const struct gguf_context * ctx, int i); | ||
GGML_API enum ggml_type gguf_get_tensor_type (const struct gguf_context * ctx, int i); | ||
GGML_API size_t gguf_get_tensor_size (const struct gguf_context * ctx, int i); | ||
GGML_API int gguf_find_and_get_tensor(const struct gguf_context * ctx, const char * name, char ** data, size_t * size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking better, but still needs some work. Neither of the changes to gguf
are needed, so try to avoid them and do the same using the existing API. The final PR should not contain any modifications to ggml.h
. The only one that can remain is the gguf_get_tensor_size()
helper function
I added two functions to ggml.c, gguf_get_tensor_size and gguf_find_key_array. |
I also revised ci/run.sh. |
I fixed script gguf-addfile.py
|
include/ggml/ggml.h
Outdated
@@ -2305,6 +2305,7 @@ extern "C" { | |||
|
|||
GGML_API int gguf_get_n_kv(const struct gguf_context * ctx); | |||
GGML_API int gguf_find_key(const struct gguf_context * ctx, const char * key); | |||
GGML_API int gguf_find_key_array(const struct gguf_context * ctx, const char * key, const char * val); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to add gguf_find_key_array()
- it's result is never used for anything, so we can simply remove it
deleted gguf_find_key_array() and related code from examples/yolo/yolov3-tiny.cpp. |
examples/yolo/yolov3-tiny.cpp
Outdated
return false; | ||
} | ||
const size_t offset = gguf_get_tensor_offset(ctx, tensor); | ||
const size_t len = gguf_get_tensor_size(ctx, tensor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somehow I didn't notice this before: gguf_get_tensor_size()
is not needed too. You can instead use:
const size_t len = gguf_get_tensor_size(ctx, tensor); | |
const size_t len = ggml_nelements(tensor); |
So remove gguf_get_tensor_size
all together
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, i removed gguf_get_tensor_size from ggml.h, ggml.c, yolov3-tiny.cpp.
Thank you for checking the code. I applied minor changes. please check. |
62be398
to
2859244
Compare
Some app like yolov3-tiny needs additional files to execute such as label(coco.names) and alphabet labels(100_0.png, ...) files.
If these files are embedded to a model(gguf) file and the app read them from the model file, the app is more portable.
I added below
NAMEDOBJECT constructed from name(file path) and value(file body)
function usage:
call gguf_find_name_nobj() with const struct gguf_context *ctx and const char *name.
ctx is gguf_context pointer. name is string encoded UTF8 like filename.
search 'name' NAMEDOBJECT and return struct nobj.
if not found, return struct nobj(0, NULL, 0, NULL). so if nobj.n == 0 means 'not found'.
if found, return nobj with nobj.name has name, nobj.n has length of nobj.data, nobj.data has byte stream of data.
script usage: