Class: Cohere::Transcribe::DenseConverter
- Inherits:
-
Object
- Object
- Cohere::Transcribe::DenseConverter
- Defined in:
- lib/cohere/transcribe/dense_converter.rb
Overview
Converts a native Transformers Cohere ASR dense checkpoint to the GGUF tensor contract consumed by CrispASR's Cohere backend.
The tensor naming contract is derived from CrispASR, MIT-licensed by the ggml authors. See licenses/crispasr.txt for the retained license notice.
Defined Under Namespace
Classes: Error, Mapping, Plan, PlannedTensor, Result
Constant Summary collapse
- FRONTEND_SOURCE_PATTERN =
/\A(?:model\.)?preprocessor\.featurizer\.(?:fb|window)\z/- COUNTER_SOURCE_PATTERN =
/\A(?:model\.)?encoder\.layers\.\d+\.conv\.batch_norm\.num_batches_tracked\z/- REQUIRED_PROMPT_TOKENS =
%w[ ▁ <|startofcontext|> <|startoftranscript|> <|emo:undefined|> <|ar|> <|pnc|> <|noitn|> <|notimestamp|> <|nodiarize|> <|endoftext|> ].freeze
- OUTPUT_TYPES =
%i[f16 f32 bf16].freeze
- REQUIRED_ARTIFACT_FILENAMES =
%w[config.json tokenizer.json].freeze
- WEIGHT_ARTIFACT_FILENAMES =
%w[ model.safetensors model.safetensors.index.json pytorch_model.bin pytorch_model.bin.index.json ].freeze
- SOURCE_ARTIFACT_FILENAMES =
( REQUIRED_ARTIFACT_FILENAMES + WEIGHT_ARTIFACT_FILENAMES ).freeze
- SOURCE_ARTIFACT_REQUIREMENTS =
{ required: REQUIRED_ARTIFACT_FILENAMES, one_weight_file: WEIGHT_ARTIFACT_FILENAMES }.freeze
Instance Attribute Summary collapse
-
#chunk_bytes ⇒ Object
readonly
Returns the value of attribute chunk_bytes.
-
#dtype_converter ⇒ Object
readonly
Returns the value of attribute dtype_converter.
-
#model_directory ⇒ Object
readonly
Returns the value of attribute model_directory.
-
#output_path ⇒ Object
readonly
Returns the value of attribute output_path.
-
#output_type ⇒ Object
readonly
Returns the value of attribute output_type.
-
#progress ⇒ Object
readonly
Returns the value of attribute progress.
Class Method Summary collapse
-
.convert(model_dir:, output_path:, overwrite: false, fsync: true) ⇒ Object
Stable integration entry point for model stores and CLI adapters.
- .required_source_artifacts ⇒ Object
-
.source_artifact_filenames ⇒ Object
Every filename a downloader may need to request.
- .tensor_mappings(encoder_layers:, decoder_layers:) ⇒ Object
Instance Method Summary collapse
- #convert(overwrite: false, fsync: true) ⇒ Object
-
#initialize(model_directory, output_path:, output_type: :f16, dtype_converter: Safetensors::DTypeConverter.default, chunk_bytes: Safetensors::DEFAULT_CHUNK_BYTES, progress: nil) ⇒ DenseConverter
constructor
A new instance of DenseConverter.
- #plan ⇒ Object
Constructor Details
#initialize(model_directory, output_path:, output_type: :f16, dtype_converter: Safetensors::DTypeConverter.default, chunk_bytes: Safetensors::DEFAULT_CHUNK_BYTES, progress: nil) ⇒ DenseConverter
Returns a new instance of DenseConverter.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 64 def initialize(model_directory, output_path:, output_type: :f16, dtype_converter: Safetensors::DTypeConverter.default, chunk_bytes: Safetensors::DEFAULT_CHUNK_BYTES, progress: nil) @model_directory = Pathname(model_directory). @output_path = Pathname(output_path). @output_type = output_type.to_sym @dtype_converter = dtype_converter @chunk_bytes = Integer(chunk_bytes) @progress = progress unless OUTPUT_TYPES.include?(@output_type) raise ArgumentError, "Unsupported dense GGUF output type #{@output_type.inspect}" end raise ArgumentError, "chunk_bytes must be positive" unless @chunk_bytes.positive? raise ArgumentError, "progress must respond to call" if progress && !progress.respond_to?(:call) end |
Instance Attribute Details
#chunk_bytes ⇒ Object (readonly)
Returns the value of attribute chunk_bytes.
47 48 49 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 47 def chunk_bytes @chunk_bytes end |
#dtype_converter ⇒ Object (readonly)
Returns the value of attribute dtype_converter.
47 48 49 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 47 def dtype_converter @dtype_converter end |
#model_directory ⇒ Object (readonly)
Returns the value of attribute model_directory.
47 48 49 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 47 def model_directory @model_directory end |
#output_path ⇒ Object (readonly)
Returns the value of attribute output_path.
47 48 49 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 47 def output_path @output_path end |
#output_type ⇒ Object (readonly)
Returns the value of attribute output_type.
47 48 49 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 47 def output_type @output_type end |
#progress ⇒ Object (readonly)
Returns the value of attribute progress.
47 48 49 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 47 def progress @progress end |
Class Method Details
.convert(model_dir:, output_path:, overwrite: false, fsync: true) ⇒ Object
Stable integration entry point for model stores and CLI adapters.
50 51 52 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 50 def self.convert(model_dir:, output_path:, overwrite: false, fsync: true, **) new(model_dir, output_path: output_path, **).convert(overwrite: overwrite, fsync: fsync) end |
.required_source_artifacts ⇒ Object
60 61 62 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 60 def self.required_source_artifacts SOURCE_ARTIFACT_REQUIREMENTS end |
.source_artifact_filenames ⇒ Object
Every filename a downloader may need to request. The safetensors file and its sharded index are alternatives; see required_source_artifacts.
56 57 58 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 56 def self.source_artifact_filenames SOURCE_ARTIFACT_FILENAMES end |
.tensor_mappings(encoder_layers:, decoder_layers:) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 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 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 101 def self.tensor_mappings(encoder_layers:, decoder_layers:) mappings = [] add_pair = lambda do |output, source, weight_precision = :f16| mappings << Mapping.new(output_name: "#{output}.weight", source_name: "#{source}.weight", precision: weight_precision) mappings << Mapping.new(output_name: "#{output}.bias", source_name: "#{source}.bias", precision: :f32) end [0, 2, 3, 5, 6].each do |index| add_pair.call("enc.pre.conv.#{index}", "encoder.pre_encode.conv.#{index}") end add_pair.call("enc.pre.out", "encoder.pre_encode.out") encoder_layers.times do |index| source = "encoder.layers.#{index}" output = "enc.blk.#{index}" add_pair.call("#{output}.ff1.norm", "#{source}.norm_feed_forward1", :f32) add_pair.call("#{output}.ff1.up", "#{source}.feed_forward1.linear1") add_pair.call("#{output}.ff1.down", "#{source}.feed_forward1.linear2") add_pair.call("#{output}.attn.norm", "#{source}.norm_self_att", :f32) add_pair.call("#{output}.attn.q", "#{source}.self_attn.linear_q") add_pair.call("#{output}.attn.k", "#{source}.self_attn.linear_k") add_pair.call("#{output}.attn.v", "#{source}.self_attn.linear_v") add_pair.call("#{output}.attn.out", "#{source}.self_attn.linear_out") mappings << Mapping.new(output_name: "#{output}.attn.pos.weight", source_name: "#{source}.self_attn.linear_pos.weight", precision: :f16) mappings << Mapping.new(output_name: "#{output}.attn.pos_bias_u", source_name: "#{source}.self_attn.pos_bias_u", precision: :f32) mappings << Mapping.new(output_name: "#{output}.attn.pos_bias_v", source_name: "#{source}.self_attn.pos_bias_v", precision: :f32) add_pair.call("#{output}.conv.norm", "#{source}.norm_conv", :f32) add_pair.call("#{output}.conv.pw1", "#{source}.conv.pointwise_conv1") add_pair.call("#{output}.conv.dw", "#{source}.conv.depthwise_conv") add_pair.call("#{output}.conv.bn", "#{source}.conv.batch_norm", :f32) mappings << Mapping.new(output_name: "#{output}.conv.bn.mean", source_name: "#{source}.conv.batch_norm.running_mean", precision: :f32) mappings << Mapping.new(output_name: "#{output}.conv.bn.var", source_name: "#{source}.conv.batch_norm.running_var", precision: :f32) add_pair.call("#{output}.conv.pw2", "#{source}.conv.pointwise_conv2") add_pair.call("#{output}.ff2.norm", "#{source}.norm_feed_forward2", :f32) add_pair.call("#{output}.ff2.up", "#{source}.feed_forward2.linear1") add_pair.call("#{output}.ff2.down", "#{source}.feed_forward2.linear2") add_pair.call("#{output}.out_norm", "#{source}.norm_out", :f32) end add_pair.call("enc.proj", "encoder_decoder_proj") mappings << Mapping.new(output_name: "dec.emb.weight", source_name: "transf_decoder._embedding.token_embedding.weight", precision: :f16) mappings << Mapping.new(output_name: "dec.pos.weight", source_name: "transf_decoder._embedding.position_embedding.pos_enc", precision: :f16) add_pair.call("dec.emb_ln", "transf_decoder._embedding.layer_norm", :f32) decoder_layers.times do |index| source = "transf_decoder._decoder.layers.#{index}" output = "dec.blk.#{index}" add_pair.call("#{output}.attn_ln", "#{source}.layer_norm_1", :f32) add_pair.call("#{output}.attn_q", "#{source}.first_sub_layer.query_net") add_pair.call("#{output}.attn_k", "#{source}.first_sub_layer.key_net") add_pair.call("#{output}.attn_v", "#{source}.first_sub_layer.value_net") add_pair.call("#{output}.attn_o", "#{source}.first_sub_layer.out_projection") add_pair.call("#{output}.cross_ln", "#{source}.layer_norm_2", :f32) add_pair.call("#{output}.cross_q", "#{source}.second_sub_layer.query_net") add_pair.call("#{output}.cross_k", "#{source}.second_sub_layer.key_net") add_pair.call("#{output}.cross_v", "#{source}.second_sub_layer.value_net") add_pair.call("#{output}.cross_o", "#{source}.second_sub_layer.out_projection") add_pair.call("#{output}.ffn_ln", "#{source}.layer_norm_3", :f32) add_pair.call("#{output}.ffn_up", "#{source}.third_sub_layer.dense_in") add_pair.call("#{output}.ffn_down", "#{source}.third_sub_layer.dense_out") end add_pair.call("dec.out_ln", "transf_decoder._decoder.final_layer_norm", :f32) add_pair.call("dec.head", "log_softmax.mlp.layer0") mappings.freeze end |
Instance Method Details
#convert(overwrite: false, fsync: true) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 81 def convert(overwrite: false, fsync: true) conversion_plan = plan writer = build_writer(conversion_plan) written_path = writer.write(output_path, overwrite: overwrite, fsync: fsync) Result.new( path: written_path, tensor_count: conversion_plan.tensors.length, source_dtype_counts: conversion_plan.source_dtype_counts, output_dtype_counts: conversion_plan.output_dtype_counts ) rescue Safetensors::Error, PyTorchCheckpoint::Error, GGUF::Error => e raise Error, e. end |
#plan ⇒ Object
95 96 97 98 99 |
# File 'lib/cohere/transcribe/dense_converter.rb', line 95 def plan @plan ||= build_plan rescue Safetensors::Error, PyTorchCheckpoint::Error => e raise Error, e. end |