Spaces:
Running
Running
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 +5 -1
- Makefile +4 -1
- bindings/go/.gitignore +0 -1
- bindings/go/Makefile +9 -10
- bindings/go/README.md +23 -0
- bindings/go/examples/go-model-download/main.go +8 -6
- bindings/go/go.sum +23 -0
- bindings/go/params.go +0 -3
- bindings/go/whisper.go +9 -2
- bindings/go/whisper_test.go +4 -1
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 |
-
|
|
|
|
|
|
|
|
|
|
| 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 += -
|
| 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 |
-
|
| 2 |
-
|
| 3 |
-
MODELS_DIR := "models"
|
| 4 |
EXAMPLES_DIR := $(wildcard examples/*)
|
| 5 |
-
|
|
|
|
| 6 |
|
| 7 |
all: clean whisper examples
|
| 8 |
|
| 9 |
whisper: mkdir
|
| 10 |
@echo Build whisper
|
| 11 |
-
@${
|
| 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
|
| 21 |
-
|
| 22 |
-
|
| 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 =
|
| 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
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
| 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()
|