|
| 1 | +# Firefox-local: load Parakeet GGUF models from an already-open file |
| 2 | +# descriptor, for the sandboxed HWInference utility process which cannot |
| 3 | +# open paths. |
| 4 | +# Upstreamable to https://github.com/mudler/parakeet.cpp |
| 5 | +# |
| 6 | +--- a/src/model_loader.hpp |
| 7 | ++++ b/src/model_loader.hpp |
| 8 | +@@ -77,6 +77,8 @@ |
| 9 | + ModelLoader() = default; |
| 10 | + ~ModelLoader(); |
| 11 | + bool load(const std::string& path); |
| 12 | ++ // Firefox-local: load from an already-open fd (sandboxed process). |
| 13 | ++ bool load_fd(int fd); |
| 14 | + const ParakeetConfig& config() const { return cfg_; } |
| 15 | + const std::vector<std::string>& tokenizer_pieces() const { return cfg_.tokenizer_pieces; } |
| 16 | + ggml_tensor* tensor(const std::string& name) const; // nullptr if absent |
| 17 | +@@ -94,6 +96,9 @@ |
| 18 | + bool realize_weights(ggml_backend_t backend); |
| 19 | + bool weights_realized() const { return weights_buf_ != nullptr; } |
| 20 | + private: |
| 21 | ++ // Parse metadata + tensors from an already-opened gguf_. Shared by load() |
| 22 | ++ // and load_fd(). |
| 23 | ++ bool parse_gguf(); |
| 24 | + ParakeetConfig cfg_; |
| 25 | + gguf_context* gguf_ = nullptr; |
| 26 | + ggml_context* ctx_ = nullptr; |
| 27 | +--- a/src/model_loader.cpp |
| 28 | ++++ b/src/model_loader.cpp |
| 29 | +@@ -6,6 +6,7 @@ |
| 30 | + #include "ggml-cpu.h" |
| 31 | + #include "gguf.h" |
| 32 | + #include <cstring> |
| 33 | ++#include <cstdio> |
| 34 | + #include <vector> |
| 35 | + #include <utility> |
| 36 | + #include <stdexcept> |
| 37 | +@@ -125,6 +126,24 @@ |
| 38 | + struct gguf_init_params p{ /*no_alloc*/false, /*ctx*/&ctx_ }; |
| 39 | + gguf_ = gguf_init_from_file(path.c_str(), p); |
| 40 | + if(!gguf_){ PK_LOG("gguf open failed: %s", path.c_str()); return false; } |
| 41 | ++ return parse_gguf(); |
| 42 | ++} |
| 43 | ++ |
| 44 | ++// Firefox-local addition (upstreamable): load the GGUF from an already-open |
| 45 | ++// file descriptor. The sandboxed HWInference utility process is handed an fd by |
| 46 | ++// the broker and cannot open paths itself. The fd stays owned by the caller. |
| 47 | ++bool ModelLoader::load_fd(int fd){ |
| 48 | ++ struct gguf_init_params p{ /*no_alloc*/false, /*ctx*/&ctx_ }; |
| 49 | ++ FILE* f = fdopen(fd, "rb"); |
| 50 | ++ if(!f){ PK_LOG("fdopen failed for parakeet model fd"); return false; } |
| 51 | ++ // gguf reads the whole file (no_alloc=false). Do NOT fclose(f): that would |
| 52 | ++ // close the caller-owned fd. |
| 53 | ++ gguf_ = gguf_init_from_file_ptr(f, p); |
| 54 | ++ if(!gguf_){ PK_LOG("gguf open from fd failed"); return false; } |
| 55 | ++ return parse_gguf(); |
| 56 | ++} |
| 57 | ++ |
| 58 | ++bool ModelLoader::parse_gguf(){ |
| 59 | + cfg_.arch = kv_str(gguf_, "parakeet.arch"); |
| 60 | + cfg_.feat_in = kv_u32(gguf_, "parakeet.encoder.feat_in"); |
| 61 | + cfg_.d_model = kv_u32(gguf_, "parakeet.encoder.d_model"); |
| 62 | +--- a/src/model.hpp |
| 63 | ++++ b/src/model.hpp |
| 64 | +@@ -24,6 +24,10 @@ |
| 65 | + // Loads the GGUF at `gguf_path`. Returns nullptr on failure (no throw). |
| 66 | + static std::unique_ptr<Model> load(const std::string& gguf_path); |
| 67 | + |
| 68 | ++ // Firefox-local: load the GGUF from an already-open fd, for the sandboxed |
| 69 | ++ // HWInference process. Returns nullptr on failure (no throw). |
| 70 | ++ static std::unique_ptr<Model> load_fd(int fd); |
| 71 | ++ |
| 72 | + // Transcribe raw mono float PCM. If `sample_rate != 16000` the audio is |
| 73 | + // linearly resampled to 16 kHz (via pk::resample_linear) before inference. |
| 74 | + // `target_lang` selects the language prompt for multilingual (nemotron) |
| 75 | +--- a/src/model.cpp |
| 76 | ++++ b/src/model.cpp |
| 77 | +@@ -52,6 +52,18 @@ |
| 78 | + return m; |
| 79 | + } |
| 80 | + |
| 81 | ++// Firefox-local: identical to load() but reads the GGUF from an already-open |
| 82 | ++// file descriptor (the sandboxed HWInference process cannot open paths). |
| 83 | ++std::unique_ptr<Model> Model::load_fd(int fd) { |
| 84 | ++ std::unique_ptr<Model> m(new (std::nothrow) Model()); |
| 85 | ++ if (!m) return nullptr; |
| 86 | ++ if (!m->loader_.load_fd(fd)) { |
| 87 | ++ return nullptr; |
| 88 | ++ } |
| 89 | ++ ensure_weights_realized(m->loader_); |
| 90 | ++ return m; |
| 91 | ++} |
| 92 | ++ |
| 93 | + // Forward declarations: subsampling-tiling helpers are defined below (after the |
| 94 | + // batched staging helpers) but used by the single-clip transcribe entry points. |
| 95 | + static int safe_mel_window(const pk::ParakeetConfig& cfg); |
| 96 | +--- a/include/parakeet_capi.h |
| 97 | ++++ b/include/parakeet_capi.h |
| 98 | +@@ -46,6 +46,11 @@ |
| 99 | + // The returned context must be released with parakeet_capi_free. |
| 100 | + parakeet_ctx* parakeet_capi_load(const char* gguf_path); |
| 101 | + |
| 102 | ++// Firefox-local: load a GGUF model from an already-open file descriptor (for |
| 103 | ++// sandboxed hosts that cannot open paths). The fd remains owned by the caller. |
| 104 | ++// Returns an owning context, or NULL on failure. |
| 105 | ++parakeet_ctx* parakeet_capi_load_fd(int fd); |
| 106 | ++ |
| 107 | + // Free a context obtained from parakeet_capi_load. Safe on NULL. |
| 108 | + void parakeet_capi_free(parakeet_ctx* ctx); |
| 109 | + |
| 110 | +--- a/src/parakeet_capi.cpp |
| 111 | ++++ b/src/parakeet_capi.cpp |
| 112 | +@@ -225,6 +225,21 @@ |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | ++// Firefox-local: load from an already-open fd (sandboxed host). |
| 117 | ++extern "C" parakeet_ctx* parakeet_capi_load_fd(int fd) { |
| 118 | ++ if (fd < 0) return nullptr; |
| 119 | ++ try { |
| 120 | ++ std::unique_ptr<pk::Model> model = pk::Model::load_fd(fd); |
| 121 | ++ if (!model) return nullptr; |
| 122 | ++ auto* ctx = new (std::nothrow) parakeet_ctx(); |
| 123 | ++ if (!ctx) return nullptr; |
| 124 | ++ ctx->model = std::move(model); |
| 125 | ++ return ctx; |
| 126 | ++ } catch (...) { |
| 127 | ++ return nullptr; |
| 128 | ++ } |
| 129 | ++} |
| 130 | ++ |
| 131 | + extern "C" void parakeet_capi_free(parakeet_ctx* ctx) { |
| 132 | + delete ctx; // safe on nullptr; ~unique_ptr releases the model. |
| 133 | + } |
0 commit comments