Skip to content

Commit 47a3c89

Browse files
authored
go : bindings updated so they can be used in third party packages. (ggml-org#379)
* Updated bindings so they can be used in third pary packages. * Updated makefiles to set FMA flag on optionally, for xeon E5 on Darwin
1 parent 8a90b17 commit 47a3c89

File tree

10 files changed

+85
-25
lines changed

10 files changed

+85
-25
lines changed

CMakeLists.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ if (APPLE)
5353
option(WHISPER_NO_ACCELERATE "whisper: disable Accelerate framework" OFF)
5454
option(WHISPER_NO_AVX "whisper: disable AVX" OFF)
5555
option(WHISPER_NO_AVX2 "whisper: disable AVX2" OFF)
56+
option(WHISPER_NO_FMA "whisper: disable FMA" OFF)
5657
else()
5758
option(WHISPER_SUPPORT_OPENBLAS "whisper: support for OpenBLAS" OFF)
5859
endif()
@@ -166,7 +167,10 @@ else()
166167
if(NOT WHISPER_NO_AVX2)
167168
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx2")
168169
endif()
169-
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfma -mf16c")
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")
170174
endif()
171175
endif()
172176
endif()

Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,11 @@ endif
5858
# feel free to update the Makefile for your architecture and send a pull request or issue
5959
ifeq ($(UNAME_M),$(filter $(UNAME_M),x86_64 i686))
6060
ifeq ($(UNAME_S),Darwin)
61-
CFLAGS += -mfma -mf16c
61+
CFLAGS += -mf16c
6262
AVX1_M := $(shell sysctl machdep.cpu.features)
63+
ifneq (,$(findstring FMA,$(AVX1_M)))
64+
CFLAGS += -mfma
65+
endif
6366
ifneq (,$(findstring AVX1.0,$(AVX1_M)))
6467
CFLAGS += -mavx
6568
endif

bindings/go/.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
build
22
models
3-
go.sum

bindings/go/Makefile

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
1-
CMAKE := $(shell which cmake)
2-
BUILD_DIR := "build"
3-
MODELS_DIR := "models"
1+
BUILD_DIR := build
2+
MODELS_DIR := models
43
EXAMPLES_DIR := $(wildcard examples/*)
5-
C_INCLUDE_PATH := "../.."
4+
INCLUDE_PATH := $(abspath ../..)
5+
LIBRARY_PATH := $(abspath ../..)
66

77
all: clean whisper examples
88

99
whisper: mkdir
1010
@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
11+
@${MAKE} -C ../.. libwhisper.a
1312

1413
test: model-small whisper modtidy
15-
@go test -v .
16-
@go test -v ./pkg/whisper/...
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/...
1716

1817
examples: $(EXAMPLES_DIR)
1918

2019
model-small: mkdir examples/go-model-download
21-
@${BUILD_DIR}/go-model-download -out models small.en
20+
@${BUILD_DIR}/go-model-download -out models ggml-small.en.bin
2221

2322
$(EXAMPLES_DIR): mkdir whisper modtidy
2423
@echo Build example $(notdir $@)
25-
@go build ${BUILD_FLAGS} -o ${BUILD_DIR}/$(notdir $@) ./$@
24+
@C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} go build ${BUILD_FLAGS} -o ${BUILD_DIR}/$(notdir $@) ./$@
2625

2726
mkdir:
2827
@echo Mkdir ${BUILD_DIR}

bindings/go/README.md

+23
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,27 @@ And you can then test a model against samples with the following command:
7474
./build/go-whisper -model models/ggml-tiny.en.bin samples/jfk.wav
7575
```
7676

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.
77100

bindings/go/examples/go-model-download/main.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@ import (
1717
// CONSTANTS
1818

1919
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
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
2423
)
2524

2625
var (
2726
// 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"}
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"}
2928
)
3029

3130
var (
@@ -123,11 +122,14 @@ func GetModels() []string {
123122

124123
// URLForModel returns the URL for the given model on huggingface.co
125124
func URLForModel(model string) (string, error) {
125+
if filepath.Ext(model) != srcExt {
126+
model += srcExt
127+
}
126128
url, err := url.Parse(srcUrl)
127129
if err != nil {
128130
return "", err
129131
} else {
130-
url.Path = srcPathPrefix + "-" + model + srcExt
132+
url.Path = filepath.Join(url.Path, model)
131133
}
132134
return url.String(), nil
133135
}

bindings/go/go.sum

+23
Original file line numberDiff line numberDiff line change
@@ -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

-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
package whisper
22

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-
63
import (
74
"fmt"
85
)

bindings/go/whisper.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ import (
99
// CGO
1010

1111
/*
12-
#cgo CFLAGS: -I${SRCDIR}/../..
13-
#cgo LDFLAGS: -L${SRCDIR}/build -lwhisper -lm -lstdc++
12+
#cgo LDFLAGS: -lwhisper -lm -lstdc++
1413
#cgo darwin LDFLAGS: -framework Accelerate
1514
#include <whisper.h>
1615
#include <stdlib.h>
@@ -171,6 +170,10 @@ func (ctx *Context) Whisper_tokenize(text string, tokens []Token) (int, error) {
171170
}
172171

173172
// Return the id of the specified language, returns -1 if not found
173+
// Examples:
174+
//
175+
// "de" -> 2
176+
// "german" -> 2
174177
func (ctx *Context) Whisper_lang_id(lang string) int {
175178
return int(C.whisper_lang_id(C.CString(lang)))
176179
}
@@ -211,6 +214,10 @@ func (ctx *Context) Whisper_n_text_ctx() int {
211214
return int(C.whisper_n_text_ctx((*C.struct_whisper_context)(ctx)))
212215
}
213216

217+
func (ctx *Context) Whisper_n_audio_ctx() int {
218+
return int(C.whisper_n_audio_ctx((*C.struct_whisper_context)(ctx)))
219+
}
220+
214221
func (ctx *Context) Whisper_is_multilingual() int {
215222
return int(C.whisper_is_multilingual((*C.struct_whisper_context)(ctx)))
216223
}

bindings/go/whisper_test.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ func Test_Whisper_001(t *testing.T) {
5050
ctx := whisper.Whisper_init(ModelPath)
5151
assert.NotNil(ctx)
5252
defer ctx.Whisper_free()
53-
assert.NoError(ctx.Whisper_full(ctx.Whisper_full_default_params(whisper.SAMPLING_GREEDY), buf.AsFloat32Buffer().Data, nil, nil))
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)
5457

5558
// Print out tokens
5659
num_segments := ctx.Whisper_full_n_segments()

0 commit comments

Comments
 (0)