Skip to content
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

ruby : Add more API #2551

Merged
merged 17 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions bindings/ruby/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,63 @@ whisper.transcribe("path/to/audio.wav", params)

```

You can see model information:

```ruby
whisper = Whisper::Context.new("path/to/model.bin")
model = whisper.model

model.n_vocab # => 51864
model.n_audio_ctx # => 1500
model.n_audio_state # => 512
model.n_audio_head # => 8
model.n_audio_layer # => 6
model.n_text_ctx # => 448
model.n_text_state # => 512
model.n_text_head # => 8
model.n_text_layer # => 6
model.n_mels # => 80
model.ftype # => 1
model.type # => "base"

```

You can set log callback:

```ruby
prefix = "[MyApp] "
log_callback = ->(level, buffer, user_data) {
case level
when Whisper::LOG_LEVEL_NONE
puts "#{user_data}none: #{buffer}"
when Whisper::LOG_LEVEL_INFO
puts "#{user_data}info: #{buffer}"
when Whisper::LOG_LEVEL_WARN
puts "#{user_data}warn: #{buffer}"
when Whisper::LOG_LEVEL_ERROR
puts "#{user_data}error: #{buffer}"
when Whisper::LOG_LEVEL_DEBUG
puts "#{user_data}debug: #{buffer}"
when Whisper::LOG_LEVEL_CONT
puts "#{user_data}same to previous: #{buffer}"
end
}
Whisper.log_set log_callback, prefix
```

Using this feature, you are also able to suppress log:

```ruby
Whisper.log_set ->(level, buffer, user_data) {
# do nothing
}, nil
Whisper::Context.new(MODEL)
```

License
-------

The same to [whisper.cpp][].

[whisper.cpp]: https://github.com/ggerganov/whisper.cpp
[models]: https://github.com/ggerganov/whisper.cpp/tree/master/models
29 changes: 19 additions & 10 deletions bindings/ruby/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,39 @@ CLEAN.include FileList[
"ext/depend"
]

task build: SOURCES + FileList[
"ext/extconf.rb",
"ext/ruby_whisper.h",
"ext/ruby_whisper.cpp",
"whispercpp.gemspec",
]
task build: FileList[
"ext/Makefile",
"ext/ruby_whisper.h",
"ext/ruby_whisper.cpp",
"whispercpp.gemspec",
]

directory "pkg"
CLOBBER.include "pkg"

TEST_MODEL = "../../models/ggml-base.en.bin"
LIB_NAME = "whisper".ext(RbConfig::CONFIG["DLEXT"])
SO_FILE = File.join("ext", LIB_NAME)
LIB_FILE = File.join("lib", LIB_NAME)

directory "lib"
task LIB_FILE => SOURCES + ["lib"] do |t|
file "ext/Makefile" => ["ext/extconf.rb", "ext/ruby_whisper.h", "ext/ruby_whisper.cpp"] + SOURCES do |t|
Dir.chdir "ext" do
ruby "extconf.rb"
end
end

file SO_FILE => "ext/Makefile" do |t|
Dir.chdir "ext" do
sh "ruby extconf.rb"
sh "make"
end
mv "ext/#{LIB_NAME}", t.name
end
CLEAN.include LIB_FILE

directory "lib"
file LIB_FILE => [SO_FILE, "lib"] do |t|
copy t.source, t.name
end

Rake::TestTask.new do |t|
t.test_files = FileList["tests/test_*.rb"]
end
Expand Down
79 changes: 21 additions & 58 deletions bindings/ruby/ext/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

# need to use c++ compiler flags
$CXXFLAGS << ' -std=c++11'

$LDFLAGS << ' -lstdc++'

# Set to true when building binary gems
if enable_config('static-stdlib', false)
$LDFLAGS << ' -static-libgcc -static-libstdc++'
Expand All @@ -12,34 +15,6 @@
$CXXFLAGS << ' -march=native -mtune=native'
end

def with_disabling_unsupported_files
disabled_files = []

unless $GGML_METAL
disabled_files << 'ggml-metal.h' << 'ggml-metal.m'
end

unless $GGML_METAL_EMBED_LIBRARY
disabled_files << 'ggml-metal.metal'
end

unless $OBJ_ALL&.include? 'ggml-blas.o'
disabled_files << 'ggml-blas.h' << 'ggml-blas.cpp'
end

disabled_files.filter! {|file| File.exist? file}

disabled_files.each do |file|
File.rename file, "#{file}.disabled"
end

yield

disabled_files.each do |file|
File.rename "#{file}.disabled", file
end
end

if ENV['WHISPER_METAL']
$GGML_METAL ||= true
$DEPRECATE_WARNING ||= true
Expand All @@ -66,10 +41,10 @@ def with_disabling_unsupported_files
$MK_NVCCFLAGS = '-std=c++11'
$MK_LDFLAGS = ''

$OBJ_GGML = ''
$OBJ_WHISPER = ''
$OBJ_COMMON = ''
$OBJ_SDL = ''
$OBJ_GGML = []
$OBJ_WHISPER = []
$OBJ_COMMON = []
$OBJ_SDL = []

$MK_CPPFLAGS << ' -D_XOPEN_SOURCE=600'

Expand Down Expand Up @@ -152,50 +127,51 @@ def with_disabling_unsupported_files
$MK_CPPFLAGS << ' -DACCELERATE_NEW_LAPACK'
$MK_CPPFLAGS << ' -DACCELERATE_LAPACK_ILP64'
$MK_LDFLAGS << ' -framework Accelerate'
$OBJ_GGML << ' ggml-blas.o'
$OBJ_GGML << 'ggml-blas.o'
end
end

if ENV['GGML_OPENBLAS']
$MK_CPPFLAGS << " -DGGML_USE_BLAS #{`pkg-config --cflags-only-I openblas`.chomp}"
$MK_CFLAGS << " #{`pkg-config --cflags-only-other openblas)`.chomp}"
$MK_LDFLAGS << " #{`pkg-config --libs openblas`}"
$OBJ_GGML << ' ggml-blas.o'
$OBJ_GGML << 'ggml-blas.o'
end

if ENV['GGML_OPENBLAS64']
$MK_CPPFLAGS << " -DGGML_USE_BLAS #{`pkg-config --cflags-only-I openblas64`.chomp}"
$MK_CFLAGS << " #{`pkg-config --cflags-only-other openblas64)`.chomp}"
$MK_LDFLAGS << " #{`pkg-config --libs openblas64`}"
$OBJ_GGML << ' ggml-blas.o'
$OBJ_GGML << 'ggml-blas.o'
end

if $GGML_METAL
$MK_CPPFLAGS << ' -DGGML_USE_METAL'
$MK_LDFLAGS << ' -framework Foundation -framework Metal -framework MetalKit'
$OBJ_GGML << ' ggml-metal.o'
$OBJ_GGML << 'ggml-metal.o'

if ENV['GGML_METAL_NDEBUG']
$MK_CPPFLAGS << ' -DGGML_METAL_NDEBUG'
end

if $GGML_METAL_EMBED_LIBRARY
$MK_CPPFLAGS << ' -DGGML_METAL_EMBED_LIBRARY'
$OBJ_GGML << ' ggml-metal-embed.o'
$OBJ_GGML << 'ggml-metal-embed.o'
end
end

$OBJ_GGML <<
' ggml.o' <<
' ggml-alloc.o' <<
' ggml-backend.o' <<
' ggml-quants.o' <<
' ggml-aarch64.o'
'ggml.o' <<
'ggml-alloc.o' <<
'ggml-backend.o' <<
'ggml-quants.o' <<
'ggml-aarch64.o'

$OBJ_WHISPER <<
' whisper.o'
'whisper.o'

$OBJ_ALL = "#{$OBJ_GGML} #{$OBJ_WHISPER} #{$OBJ_COMMON} #{$OBJ_SDL}"
$objs = $OBJ_GGML + $OBJ_WHISPER + $OBJ_COMMON + $OBJ_SDL
$objs << "ruby_whisper.o"

$CPPFLAGS = "#{$MK_CPPFLAGS} #{$CPPFLAGS}"
$CFLAGS = "#{$CPPFLAGS} #{$MK_CFLAGS} #{$GF_CFLAGS} #{$CFLAGS}"
Expand All @@ -204,26 +180,13 @@ def with_disabling_unsupported_files
$NVCCFLAGS = "#{$MK_NVCCFLAGS} #{$NVCCFLAGS}"
$LDFLAGS = "#{$MK_LDFLAGS} #{$LDFLAGS}"

if $GGML_METAL_EMBED_LIBRARY
File.write 'depend', "$(OBJS): $(OBJS) ggml-metal-embed.o\n"
end

with_disabling_unsupported_files do

create_makefile('whisper')

end
create_makefile('whisper')

File.open 'Makefile', 'a' do |file|
file.puts 'include get-flags.mk'

if $GGML_METAL
if $GGML_METAL_EMBED_LIBRARY
# mkmf determines object files to compile dependent on existing *.{c,cpp,m} files
# but ggml-metal-embed.c doesn't exist on creating Makefile.
file.puts "objs := $(OBJS)"
file.puts "OBJS = $(objs) 'ggml-metal-embed.o'"

file.puts 'include metal-embed.mk'
end
end
Expand Down
Loading
Loading