djthorpe commited on
Commit
4030b6d
·
unverified ·
1 Parent(s): 6101321

go : bindings updated so they can be used in third party packages. (#379)

Browse files

* 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 CHANGED
@@ -53,6 +53,7 @@ if (APPLE)
53
  option(WHISPER_NO_ACCELERATE "whisper: disable Accelerate framework" OFF)
54
  option(WHISPER_NO_AVX "whisper: disable AVX" OFF)
55
  option(WHISPER_NO_AVX2 "whisper: disable AVX2" OFF)
 
56
  else()
57
  option(WHISPER_SUPPORT_OPENBLAS "whisper: support for OpenBLAS" OFF)
58
  endif()
@@ -166,7 +167,10 @@ else()
166
  if(NOT WHISPER_NO_AVX2)
167
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx2")
168
  endif()
169
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfma -mf16c")
 
 
 
170
  endif()
171
  endif()
172
  endif()
 
53
  option(WHISPER_NO_ACCELERATE "whisper: disable Accelerate framework" OFF)
54
  option(WHISPER_NO_AVX "whisper: disable AVX" OFF)
55
  option(WHISPER_NO_AVX2 "whisper: disable AVX2" OFF)
56
+ option(WHISPER_NO_FMA "whisper: disable FMA" OFF)
57
  else()
58
  option(WHISPER_SUPPORT_OPENBLAS "whisper: support for OpenBLAS" OFF)
59
  endif()
 
167
  if(NOT WHISPER_NO_AVX2)
168
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx2")
169
  endif()
170
+ if(NOT WHISPER_NO_FMA)
171
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfma")
172
+ endif()
173
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mf16c")
174
  endif()
175
  endif()
176
  endif()
Makefile CHANGED
@@ -58,8 +58,11 @@ endif
58
  # feel free to update the Makefile for your architecture and send a pull request or issue
59
  ifeq ($(UNAME_M),$(filter $(UNAME_M),x86_64 i686))
60
  ifeq ($(UNAME_S),Darwin)
61
- CFLAGS += -mfma -mf16c
62
  AVX1_M := $(shell sysctl machdep.cpu.features)
 
 
 
63
  ifneq (,$(findstring AVX1.0,$(AVX1_M)))
64
  CFLAGS += -mavx
65
  endif
 
58
  # feel free to update the Makefile for your architecture and send a pull request or issue
59
  ifeq ($(UNAME_M),$(filter $(UNAME_M),x86_64 i686))
60
  ifeq ($(UNAME_S),Darwin)
61
+ CFLAGS += -mf16c
62
  AVX1_M := $(shell sysctl machdep.cpu.features)
63
+ ifneq (,$(findstring FMA,$(AVX1_M)))
64
+ CFLAGS += -mfma
65
+ endif
66
  ifneq (,$(findstring AVX1.0,$(AVX1_M)))
67
  CFLAGS += -mavx
68
  endif
bindings/go/.gitignore CHANGED
@@ -1,3 +1,2 @@
1
  build
2
  models
3
- go.sum
 
1
  build
2
  models
 
bindings/go/Makefile CHANGED
@@ -1,28 +1,27 @@
1
- CMAKE := $(shell which cmake)
2
- BUILD_DIR := "build"
3
- MODELS_DIR := "models"
4
  EXAMPLES_DIR := $(wildcard examples/*)
5
- C_INCLUDE_PATH := "../.."
 
6
 
7
  all: clean whisper examples
8
 
9
  whisper: mkdir
10
  @echo Build whisper
11
- @${CMAKE} -S ../.. -B ${BUILD_DIR} -D BUILD_SHARED_LIBS=off -D WHISPER_NO_AVX2=on
12
- @${CMAKE} --build ${BUILD_DIR} --target whisper
13
 
14
  test: model-small whisper modtidy
15
- @go test -v .
16
- @go test -v ./pkg/whisper/...
17
 
18
  examples: $(EXAMPLES_DIR)
19
 
20
  model-small: mkdir examples/go-model-download
21
- @${BUILD_DIR}/go-model-download -out models small.en
22
 
23
  $(EXAMPLES_DIR): mkdir whisper modtidy
24
  @echo Build example $(notdir $@)
25
- @go build ${BUILD_FLAGS} -o ${BUILD_DIR}/$(notdir $@) ./$@
26
 
27
  mkdir:
28
  @echo Mkdir ${BUILD_DIR}
 
1
+ BUILD_DIR := build
2
+ MODELS_DIR := models
 
3
  EXAMPLES_DIR := $(wildcard examples/*)
4
+ INCLUDE_PATH := $(abspath ../..)
5
+ LIBRARY_PATH := $(abspath ../..)
6
 
7
  all: clean whisper examples
8
 
9
  whisper: mkdir
10
  @echo Build whisper
11
+ @${MAKE} -C ../.. libwhisper.a
 
12
 
13
  test: model-small whisper modtidy
14
+ @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} go test -v .
15
+ @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} go test -v ./pkg/whisper/...
16
 
17
  examples: $(EXAMPLES_DIR)
18
 
19
  model-small: mkdir examples/go-model-download
20
+ @${BUILD_DIR}/go-model-download -out models ggml-small.en.bin
21
 
22
  $(EXAMPLES_DIR): mkdir whisper modtidy
23
  @echo Build example $(notdir $@)
24
+ @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} go build ${BUILD_FLAGS} -o ${BUILD_DIR}/$(notdir $@) ./$@
25
 
26
  mkdir:
27
  @echo Mkdir ${BUILD_DIR}
bindings/go/README.md CHANGED
@@ -74,4 +74,27 @@ And you can then test a model against samples with the following command:
74
  ./build/go-whisper -model models/ggml-tiny.en.bin samples/jfk.wav
75
  ```
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
 
74
  ./build/go-whisper -model models/ggml-tiny.en.bin samples/jfk.wav
75
  ```
76
 
77
+ ## Using the bindings
78
+
79
+ To use the bindings in your own software,
80
+
81
+ 1. Import `github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper` (or `github.com/ggerganov/whisper.cpp/bindings/go` into your package;
82
+ 2. Compile `libwhisper.a` (you can use `make whisper` in the `bindings/go` directory);
83
+ 3. Link your go binary against whisper by setting the environment variables `C_INCLUDE_PATH` and `LIBRARY_PATH`
84
+ to point to the `whisper.h` file directory and `libwhisper.a` file directory respectively.
85
+
86
+ Look at the `Makefile` in the `bindings/go` directory for an example.
87
+
88
+ The API Documentation:
89
+
90
+ * https://pkg.go.dev/github.com/ggerganov/whisper.cpp/bindings/go
91
+ * https://pkg.go.dev/github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper
92
+
93
+ Getting help:
94
+
95
+ * Follow the discussion for the go bindings [here](https://github.com/ggerganov/whisper.cpp/discussions/312)
96
+
97
+ ## License
98
+
99
+ 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.
100
 
bindings/go/examples/go-model-download/main.go CHANGED
@@ -17,15 +17,14 @@ import (
17
  // CONSTANTS
18
 
19
  const (
20
- srcUrl = "https://huggingface.co/" // The location of the models
21
- srcPathPrefix = "/datasets/ggerganov/whisper.cpp/resolve/main/ggml" // Filename prefix
22
- srcExt = ".bin" // Filename extension
23
- bufSize = 1024 * 64 // Size of the buffer used for downloading the model
24
  )
25
 
26
  var (
27
  // The models which will be downloaded, if no model is specified as an argument
28
- modelNames = []string{"tiny.en", "tiny", "base.en", "base", "small.en", "small", "medium.en", "medium", "large-v1", "large"}
29
  )
30
 
31
  var (
@@ -123,11 +122,14 @@ func GetModels() []string {
123
 
124
  // URLForModel returns the URL for the given model on huggingface.co
125
  func URLForModel(model string) (string, error) {
 
 
 
126
  url, err := url.Parse(srcUrl)
127
  if err != nil {
128
  return "", err
129
  } else {
130
- url.Path = srcPathPrefix + "-" + model + srcExt
131
  }
132
  return url.String(), nil
133
  }
 
17
  // CONSTANTS
18
 
19
  const (
20
+ srcUrl = "https://huggingface.co/datasets/ggerganov/whisper.cpp/resolve/main" // The location of the models
21
+ srcExt = ".bin" // Filename extension
22
+ bufSize = 1024 * 64 // Size of the buffer used for downloading the model
 
23
  )
24
 
25
  var (
26
  // The models which will be downloaded, if no model is specified as an argument
27
+ 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"}
28
  )
29
 
30
  var (
 
122
 
123
  // URLForModel returns the URL for the given model on huggingface.co
124
  func URLForModel(model string) (string, error) {
125
+ if filepath.Ext(model) != srcExt {
126
+ model += srcExt
127
+ }
128
  url, err := url.Parse(srcUrl)
129
  if err != nil {
130
  return "", err
131
  } else {
132
+ url.Path = filepath.Join(url.Path, model)
133
  }
134
  return url.String(), nil
135
  }
bindings/go/go.sum ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4
+ github.com/go-audio/audio v1.0.0 h1:zS9vebldgbQqktK4H0lUqWrG8P0NxCJVqcj7ZpNnwd4=
5
+ github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
6
+ github.com/go-audio/riff v1.0.0 h1:d8iCGbDvox9BfLagY94fBynxSPHO80LmZCaOsmKxokA=
7
+ github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
8
+ github.com/go-audio/wav v1.1.0 h1:jQgLtbqBzY7G+BM8fXF7AHUk1uHUviWS4X39d5rsL2g=
9
+ github.com/go-audio/wav v1.1.0/go.mod h1:mpe9qfwbScEbkd8uybLuIpTgHyrISw/OTuvjUW2iGtE=
10
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
11
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
12
+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
13
+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
14
+ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
15
+ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
16
+ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
17
+ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
18
+ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
19
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
20
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
21
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
22
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
23
+ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
bindings/go/params.go CHANGED
@@ -1,8 +1,5 @@
1
  package whisper
2
 
3
- // This file defines the whisper_token, whisper_token_data and whisper_full_params
4
- // structures, which are used by the whisper_full() function.
5
-
6
  import (
7
  "fmt"
8
  )
 
1
  package whisper
2
 
 
 
 
3
  import (
4
  "fmt"
5
  )
bindings/go/whisper.go CHANGED
@@ -9,8 +9,7 @@ import (
9
  // CGO
10
 
11
  /*
12
- #cgo CFLAGS: -I${SRCDIR}/../..
13
- #cgo LDFLAGS: -L${SRCDIR}/build -lwhisper -lm -lstdc++
14
  #cgo darwin LDFLAGS: -framework Accelerate
15
  #include <whisper.h>
16
  #include <stdlib.h>
@@ -171,6 +170,10 @@ func (ctx *Context) Whisper_tokenize(text string, tokens []Token) (int, error) {
171
  }
172
 
173
  // Return the id of the specified language, returns -1 if not found
 
 
 
 
174
  func (ctx *Context) Whisper_lang_id(lang string) int {
175
  return int(C.whisper_lang_id(C.CString(lang)))
176
  }
@@ -211,6 +214,10 @@ func (ctx *Context) Whisper_n_text_ctx() int {
211
  return int(C.whisper_n_text_ctx((*C.struct_whisper_context)(ctx)))
212
  }
213
 
 
 
 
 
214
  func (ctx *Context) Whisper_is_multilingual() int {
215
  return int(C.whisper_is_multilingual((*C.struct_whisper_context)(ctx)))
216
  }
 
9
  // CGO
10
 
11
  /*
12
+ #cgo LDFLAGS: -lwhisper -lm -lstdc++
 
13
  #cgo darwin LDFLAGS: -framework Accelerate
14
  #include <whisper.h>
15
  #include <stdlib.h>
 
170
  }
171
 
172
  // Return the id of the specified language, returns -1 if not found
173
+ // Examples:
174
+ //
175
+ // "de" -> 2
176
+ // "german" -> 2
177
  func (ctx *Context) Whisper_lang_id(lang string) int {
178
  return int(C.whisper_lang_id(C.CString(lang)))
179
  }
 
214
  return int(C.whisper_n_text_ctx((*C.struct_whisper_context)(ctx)))
215
  }
216
 
217
+ func (ctx *Context) Whisper_n_audio_ctx() int {
218
+ return int(C.whisper_n_audio_ctx((*C.struct_whisper_context)(ctx)))
219
+ }
220
+
221
  func (ctx *Context) Whisper_is_multilingual() int {
222
  return int(C.whisper_is_multilingual((*C.struct_whisper_context)(ctx)))
223
  }
bindings/go/whisper_test.go CHANGED
@@ -50,7 +50,10 @@ func Test_Whisper_001(t *testing.T) {
50
  ctx := whisper.Whisper_init(ModelPath)
51
  assert.NotNil(ctx)
52
  defer ctx.Whisper_free()
53
- assert.NoError(ctx.Whisper_full(ctx.Whisper_full_default_params(whisper.SAMPLING_GREEDY), buf.AsFloat32Buffer().Data, nil, nil))
 
 
 
54
 
55
  // Print out tokens
56
  num_segments := ctx.Whisper_full_n_segments()
 
50
  ctx := whisper.Whisper_init(ModelPath)
51
  assert.NotNil(ctx)
52
  defer ctx.Whisper_free()
53
+ params := ctx.Whisper_full_default_params(whisper.SAMPLING_GREEDY)
54
+ data := buf.AsFloat32Buffer().Data
55
+ err = ctx.Whisper_full(params, data, nil, nil)
56
+ assert.NoError(err)
57
 
58
  // Print out tokens
59
  num_segments := ctx.Whisper_full_n_segments()