]> git.djapps.eu Git - pkg/ggml/sources/whisper.cpp/commitdiff
go : bindings updated so they can be used in third party packages. (#379)
authorDavid Thorpe <redacted>
Fri, 6 Jan 2023 17:32:28 +0000 (17:32 +0000)
committerGitHub <redacted>
Fri, 6 Jan 2023 17:32:28 +0000 (19:32 +0200)
* Updated bindings so they can be used in third pary packages.

* Updated makefiles to set FMA flag on optionally, for xeon E5 on Darwin

CMakeLists.txt
Makefile
bindings/go/.gitignore
bindings/go/Makefile
bindings/go/README.md
bindings/go/examples/go-model-download/main.go
bindings/go/go.sum [new file with mode: 0644]
bindings/go/params.go
bindings/go/whisper.go
bindings/go/whisper_test.go

index ee437399d493c0f60a740967d2e64ab23872835a..5233459ee5ace17a80ce29aa7d6388c36e8a637b 100644 (file)
@@ -53,6 +53,7 @@ if (APPLE)
     option(WHISPER_NO_ACCELERATE       "whisper: disable Accelerate framework" OFF)
     option(WHISPER_NO_AVX              "whisper: disable AVX" OFF)
     option(WHISPER_NO_AVX2             "whisper: disable AVX2" OFF)
+    option(WHISPER_NO_FMA              "whisper: disable FMA" OFF)
 else()
     option(WHISPER_SUPPORT_OPENBLAS    "whisper: support for OpenBLAS" OFF)
 endif()
@@ -166,7 +167,10 @@ else()
             if(NOT WHISPER_NO_AVX2)
                 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx2")
             endif()
-            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfma -mf16c")
+            if(NOT WHISPER_NO_FMA)
+                set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfma")
+            endif()
+            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mf16c")
         endif()
     endif()
 endif()
index a9d205a7fe1a26ed606628304f61aadf4df0b2c9..b7edea8f5c2700a18f12ce4ca51aedfcc52762a3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -58,8 +58,11 @@ endif
 #       feel free to update the Makefile for your architecture and send a pull request or issue
 ifeq ($(UNAME_M),$(filter $(UNAME_M),x86_64 i686))
        ifeq ($(UNAME_S),Darwin)
-               CFLAGS += -mfma -mf16c
+               CFLAGS += -mf16c
                AVX1_M := $(shell sysctl machdep.cpu.features)
+               ifneq (,$(findstring FMA,$(AVX1_M)))
+                       CFLAGS += -mfma
+               endif
                ifneq (,$(findstring AVX1.0,$(AVX1_M)))
                        CFLAGS += -mavx
                endif
index b4e10840359f688b7960eff2343f3e12d7f4ec1b..036df1d3b0d5dc58847078850c8b62ebb12b2b1d 100644 (file)
@@ -1,3 +1,2 @@
 build
 models
-go.sum
index 420981ac4f4dbb26dac4c93474666c3dccd117cd..6be2979948e1b82b1430813e062ee96f95b12fa2 100644 (file)
@@ -1,28 +1,27 @@
-CMAKE := $(shell which cmake)
-BUILD_DIR := "build"
-MODELS_DIR := "models"
+BUILD_DIR := build
+MODELS_DIR := models
 EXAMPLES_DIR := $(wildcard examples/*)
-C_INCLUDE_PATH := "../.."
+INCLUDE_PATH := $(abspath ../..)
+LIBRARY_PATH := $(abspath ../..)
 
 all: clean whisper examples
 
 whisper: mkdir
        @echo Build whisper
-       @${CMAKE} -S ../.. -B ${BUILD_DIR} -D BUILD_SHARED_LIBS=off -D WHISPER_NO_AVX2=on
-       @${CMAKE} --build ${BUILD_DIR} --target whisper
+       @${MAKE} -C ../.. libwhisper.a
 
 test: model-small whisper modtidy
-       @go test -v .
-       @go test -v ./pkg/whisper/...
+       @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} go test -v .
+       @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} go test -v ./pkg/whisper/...
 
 examples: $(EXAMPLES_DIR)
 
 model-small: mkdir examples/go-model-download
-       @${BUILD_DIR}/go-model-download -out models small.en
+       @${BUILD_DIR}/go-model-download -out models ggml-small.en.bin
 
 $(EXAMPLES_DIR): mkdir whisper modtidy
        @echo Build example $(notdir $@)
-       @go build ${BUILD_FLAGS} -o ${BUILD_DIR}/$(notdir $@) ./$@
+       @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} go build ${BUILD_FLAGS} -o ${BUILD_DIR}/$(notdir $@) ./$@
 
 mkdir:
        @echo Mkdir ${BUILD_DIR}
index 8ae89c7741a7c8c702ebdac8a9c5f8e78062def3..2b14c30930fa861a76aad282461aabf5e2139582 100644 (file)
@@ -74,4 +74,27 @@ And you can then test a model against samples with the following command:
 ./build/go-whisper -model models/ggml-tiny.en.bin samples/jfk.wav 
 ```
 
+## Using the bindings
+
+To use the bindings in your own software,
+
+  1. Import `github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper` (or `github.com/ggerganov/whisper.cpp/bindings/go` into your package;
+  2. Compile `libwhisper.a` (you can use `make whisper` in the `bindings/go` directory);
+  3. Link your go binary against whisper by setting the environment variables `C_INCLUDE_PATH` and `LIBRARY_PATH`
+     to point to the `whisper.h` file directory and `libwhisper.a` file directory respectively.
+
+Look at the `Makefile` in the `bindings/go` directory for an example.
+
+The API Documentation:
+
+  * https://pkg.go.dev/github.com/ggerganov/whisper.cpp/bindings/go
+  * https://pkg.go.dev/github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper
+
+Getting help:
+
+  * Follow the discussion for the go bindings [here](https://github.com/ggerganov/whisper.cpp/discussions/312)
+
+## License
+
+The license for the Go bindings is the same as the license for the rest of the whisper.cpp project, which is the MIT License. See the `LICENSE` file for more details.
 
index 841a2c65ff52a881248d849a6bc8ee333929d52f..91d016acc03e600325d5c840a505a6ee09647803 100644 (file)
@@ -17,15 +17,14 @@ import (
 // CONSTANTS
 
 const (
-       srcUrl        = "https://huggingface.co/"                           // The location of the models
-       srcPathPrefix = "/datasets/ggerganov/whisper.cpp/resolve/main/ggml" // Filename prefix
-       srcExt        = ".bin"                                              // Filename extension
-       bufSize       = 1024 * 64                                           // Size of the buffer used for downloading the model
+       srcUrl  = "https://huggingface.co/datasets/ggerganov/whisper.cpp/resolve/main" // The location of the models
+       srcExt  = ".bin"                                                               // Filename extension
+       bufSize = 1024 * 64                                                            // Size of the buffer used for downloading the model
 )
 
 var (
        // The models which will be downloaded, if no model is specified as an argument
-       modelNames = []string{"tiny.en", "tiny", "base.en", "base", "small.en", "small", "medium.en", "medium", "large-v1", "large"}
+       modelNames = []string{"ggml-tiny.en", "ggml-tiny", "ggml-base.en", "ggml-base", "ggml-small.en", "ggml-small", "ggml-medium.en", "ggml-medium", "ggml-large-v1", "ggml-large"}
 )
 
 var (
@@ -123,11 +122,14 @@ func GetModels() []string {
 
 // URLForModel returns the URL for the given model on huggingface.co
 func URLForModel(model string) (string, error) {
+       if filepath.Ext(model) != srcExt {
+               model += srcExt
+       }
        url, err := url.Parse(srcUrl)
        if err != nil {
                return "", err
        } else {
-               url.Path = srcPathPrefix + "-" + model + srcExt
+               url.Path = filepath.Join(url.Path, model)
        }
        return url.String(), nil
 }
diff --git a/bindings/go/go.sum b/bindings/go/go.sum
new file mode 100644 (file)
index 0000000..870ebdc
--- /dev/null
@@ -0,0 +1,23 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-audio/audio v1.0.0 h1:zS9vebldgbQqktK4H0lUqWrG8P0NxCJVqcj7ZpNnwd4=
+github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
+github.com/go-audio/riff v1.0.0 h1:d8iCGbDvox9BfLagY94fBynxSPHO80LmZCaOsmKxokA=
+github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
+github.com/go-audio/wav v1.1.0 h1:jQgLtbqBzY7G+BM8fXF7AHUk1uHUviWS4X39d5rsL2g=
+github.com/go-audio/wav v1.1.0/go.mod h1:mpe9qfwbScEbkd8uybLuIpTgHyrISw/OTuvjUW2iGtE=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
index 7f4c509c44114bbac286790ff238c71815f6536e..c67a7299b8557bb57fdd980abd4fecee796840c3 100644 (file)
@@ -1,8 +1,5 @@
 package whisper
 
-// This file defines the whisper_token, whisper_token_data and whisper_full_params
-// structures, which are used by the whisper_full() function.
-
 import (
        "fmt"
 )
index 2584f7bb9caa16ca05b38db2b9cf1c6a37dd823f..9381879c25dfb46225d6249779ad011197386fe2 100644 (file)
@@ -9,8 +9,7 @@ import (
 // CGO
 
 /*
-#cgo CFLAGS: -I${SRCDIR}/../..
-#cgo LDFLAGS: -L${SRCDIR}/build -lwhisper -lm -lstdc++
+#cgo LDFLAGS: -lwhisper -lm -lstdc++
 #cgo darwin LDFLAGS: -framework Accelerate
 #include <whisper.h>
 #include <stdlib.h>
@@ -171,6 +170,10 @@ func (ctx *Context) Whisper_tokenize(text string, tokens []Token) (int, error) {
 }
 
 // Return the id of the specified language, returns -1 if not found
+// Examples:
+//
+//     "de" -> 2
+//     "german" -> 2
 func (ctx *Context) Whisper_lang_id(lang string) int {
        return int(C.whisper_lang_id(C.CString(lang)))
 }
@@ -211,6 +214,10 @@ func (ctx *Context) Whisper_n_text_ctx() int {
        return int(C.whisper_n_text_ctx((*C.struct_whisper_context)(ctx)))
 }
 
+func (ctx *Context) Whisper_n_audio_ctx() int {
+       return int(C.whisper_n_audio_ctx((*C.struct_whisper_context)(ctx)))
+}
+
 func (ctx *Context) Whisper_is_multilingual() int {
        return int(C.whisper_is_multilingual((*C.struct_whisper_context)(ctx)))
 }
index d7b8caefdebf4fbcf37ffa52e6904c88f15269cc..2c95c81ff0a4f3833467d04f3f0379fef4a62b06 100644 (file)
@@ -50,7 +50,10 @@ func Test_Whisper_001(t *testing.T) {
        ctx := whisper.Whisper_init(ModelPath)
        assert.NotNil(ctx)
        defer ctx.Whisper_free()
-       assert.NoError(ctx.Whisper_full(ctx.Whisper_full_default_params(whisper.SAMPLING_GREEDY), buf.AsFloat32Buffer().Data, nil, nil))
+       params := ctx.Whisper_full_default_params(whisper.SAMPLING_GREEDY)
+       data := buf.AsFloat32Buffer().Data
+       err = ctx.Whisper_full(params, data, nil, nil)
+       assert.NoError(err)
 
        // Print out tokens
        num_segments := ctx.Whisper_full_n_segments()