Class: Cohere::Transcribe::Runtime::ModelProvider
- Inherits:
-
Object
- Object
- Cohere::Transcribe::Runtime::ModelProvider
- Defined in:
- lib/cohere/transcribe/runtime/model_provider.rb
Overview
Resolves native Transformers Dense checkpoints, downloads only their required artifacts, converts them once to CrispASR GGUF, and retains no Python-side state.
Constant Summary collapse
- CACHE_LAYOUT_VERSION =
Increment whenever conversion semantics or the native tensor types written to GGUF change. Version 2 adds first-class BF16 artifacts.
2
Instance Attribute Summary collapse
-
#cache_dir ⇒ Object
readonly
Returns the value of attribute cache_dir.
-
#hub ⇒ Object
readonly
Returns the value of attribute hub.
Instance Method Summary collapse
- #converted_model_path(identity, options) ⇒ Object
-
#initialize(hub: Hub.new, cache_dir: nil, native_session_class: nil, converter: nil) ⇒ ModelProvider
constructor
A new instance of ModelProvider.
- #materialize_source(identity) ⇒ Object
- #open(identity, options) ⇒ Object
-
#resolve(options, verify_model_weights: false) ⇒ Object
Planning may discover that every requested output can be resumed from a checkpoint.
Constructor Details
#initialize(hub: Hub.new, cache_dir: nil, native_session_class: nil, converter: nil) ⇒ ModelProvider
Returns a new instance of ModelProvider.
21 22 23 24 25 26 27 28 29 |
# File 'lib/cohere/transcribe/runtime/model_provider.rb', line 21 def initialize(hub: Hub.new, cache_dir: nil, native_session_class: nil, converter: nil) @hub = hub root = cache_dir || ENV["COHERE_TRANSCRIBE_CACHE"] || File.join(ENV.fetch("XDG_CACHE_HOME", File.("~/.cache")), "cohere-transcribe") @cache_dir = Pathname(root). @native_session_class = native_session_class @converter = converter end |
Instance Attribute Details
#cache_dir ⇒ Object (readonly)
Returns the value of attribute cache_dir.
19 20 21 |
# File 'lib/cohere/transcribe/runtime/model_provider.rb', line 19 def cache_dir @cache_dir end |
#hub ⇒ Object (readonly)
Returns the value of attribute hub.
19 20 21 |
# File 'lib/cohere/transcribe/runtime/model_provider.rb', line 19 def hub @hub end |
Instance Method Details
#converted_model_path(identity, options) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/cohere/transcribe/runtime/model_provider.rb', line 63 def converted_model_path(identity, ) model_directory = materialize_source(identity) output_type = { "fp32" => :f32, "bf16" => :bf16 }.fetch(.dtype, :f16) fingerprint = source_fingerprint(identity, model_directory, output_type) directory = conversion_cache_directory output = directory.join("#{fingerprint}-#{output_type}.gguf") return output if valid_gguf?(output, fingerprint: fingerprint, output_type: output_type) lock_path = Pathname("#{output}.lock") open_conversion_lock(lock_path) do |lock| raise TranscriptionRuntimeError, "Cannot acquire Dense conversion lock for #{output}" unless lock.flock(File::LOCK_EX) return output if valid_gguf?(output, fingerprint: fingerprint, output_type: output_type) cleanup_conversion_temporaries(output) remove_cache_entry(output) remove_cache_entry(conversion_marker(output)) begin converter.convert( model_dir: model_directory, output_path: output, output_type: output_type, overwrite: false, fsync: true ) unless source_fingerprint(identity, model_directory, output_type) == fingerprint raise TranscriptionRuntimeError, "Dense checkpoint changed during Dense conversion; retry with a stable model directory" end write_conversion_marker(output, fingerprint: fingerprint, output_type: output_type) rescue Exception # rubocop:disable Lint/RescueException -- clean partial artifacts before propagating interrupts remove_cache_entry(output) remove_cache_entry(conversion_marker(output)) raise end end unless valid_gguf?(output, fingerprint: fingerprint, output_type: output_type) raise TranscriptionRuntimeError, "Dense conversion did not produce a valid GGUF file at #{output}" end output rescue DenseConverter::Error, Safetensors::Error, PyTorchCheckpoint::Error, GGUF::Error => e raise TranscriptionRuntimeError, "Cannot convert Dense Cohere checkpoint: #{e.}" rescue Hub::Error => e raise TranscriptionRuntimeError, e. rescue SystemCallError => e raise TranscriptionRuntimeError, "Cannot prepare native Dense model: #{e.}" end |
#materialize_source(identity) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/cohere/transcribe/runtime/model_provider.rb', line 112 def materialize_source(identity) local = Pathname(identity.model_id). return local.realpath if local.directory? revision = identity.model_revision raise TranscriptionRuntimeError, "Remote model identity has no immutable revision" unless revision DenseConverter::REQUIRED_ARTIFACT_FILENAMES.each do |filename| hub.download(identity.model_id, filename, revision: revision) end snapshot = hub.snapshot_path(identity.model_id, revision) return snapshot if hub.cached_file(identity.model_id, "model.safetensors", revision: revision) return snapshot if hub.cached_file(identity.model_id, "pytorch_model.bin", revision: revision) safetensors_index = hub.cached_file( identity.model_id, "model.safetensors.index.json", revision: revision ) if safetensors_index download_index_shards(identity, safetensors_index, extension: ".safetensors", label: "Safetensors") return snapshot end pytorch_index = hub.cached_file( identity.model_id, "pytorch_model.bin.index.json", revision: revision ) if pytorch_index download_index_shards(identity, pytorch_index, extension: ".bin", label: "PyTorch") return snapshot end files = hub.list_files(identity.model_id, revision: revision) if files.include?("model.safetensors") hub.download(identity.model_id, "model.safetensors", revision: revision) elsif files.include?("model.safetensors.index.json") index = hub.download(identity.model_id, "model.safetensors.index.json", revision: revision) download_index_shards(identity, index, extension: ".safetensors", label: "Safetensors") elsif files.include?("pytorch_model.bin") hub.download(identity.model_id, "pytorch_model.bin", revision: revision) elsif files.include?("pytorch_model.bin.index.json") index = hub.download(identity.model_id, "pytorch_model.bin.index.json", revision: revision) download_index_shards(identity, index, extension: ".bin", label: "PyTorch") else raise TranscriptionRuntimeError, "#{identity.model_id}@#{revision} has no supported Dense Safetensors or PyTorch weights" end snapshot end |
#open(identity, options) ⇒ Object
55 56 57 58 59 60 61 |
# File 'lib/cohere/transcribe/runtime/model_provider.rb', line 55 def open(identity, ) ModelIdentity.verify_model_weight_artifacts(identity, hub: hub) path = converted_model_path(identity, ) (@native_session_class || ASR::NativeSession).new(path, ) rescue ArgumentError, TypeError, Hub::Error => e raise TranscriptionRuntimeError, e. end |
#resolve(options, verify_model_weights: false) ⇒ Object
Planning may discover that every requested output can be resumed from a checkpoint. Defer multi-gigabyte weight discovery until #open unless a caller explicitly asks to validate inference artifacts now.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/cohere/transcribe/runtime/model_provider.rb', line 34 def resolve(, verify_model_weights: false) identity = ModelIdentity.resolve( path_text(.model), .model_revision, path_text(.adapter), .adapter_revision, hub: hub, verify_weight_artifacts: verify_model_weights ) unless identity.model_format == :dense raise TranscriptionConfigurationError, "Saved #{identity.model_format} checkpoints are outside the core Dense Ruby inference path" end if identity.adapter_id raise TranscriptionConfigurationError, "PEFT/LoRA adapters are not supported by the native Ruby Dense runtime" end identity end |