Skip to content

Commit

Permalink
Merge branch 'main' of github.com:djthorpe/go-whisper
Browse files Browse the repository at this point in the history
  • Loading branch information
djthorpe committed Aug 10, 2024
2 parents 76fd81c + d4b7fdc commit 3444bd8
Show file tree
Hide file tree
Showing 56 changed files with 570 additions and 570 deletions.
23 changes: 15 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ BUILD_DIR := build

# Build flags
BUILD_MODULE := $(shell cat go.mod | head -1 | cut -d ' ' -f 2)
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/whisper/version.GitSource=${BUILD_MODULE}
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/whisper/version.GitTag=$(shell git describe --tags --always)
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/whisper/version.GitBranch=$(shell git name-rev HEAD --name-only --always)
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/whisper/version.GitHash=$(shell git rev-parse HEAD)
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/whisper/version.GoBuildTime=$(shell date -u '+%Y-%m-%dT%H:%M:%SZ')
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitSource=${BUILD_MODULE}
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitTag=$(shell git describe --tags --always)
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitBranch=$(shell git name-rev HEAD --name-only --always)
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GitHash=$(shell git rev-parse HEAD)
BUILD_LD_FLAGS += -X $(BUILD_MODULE)/pkg/version.GoBuildTime=$(shell date -u '+%Y-%m-%dT%H:%M:%SZ')
BUILD_FLAGS = -ldflags "-s -w $(BUILD_LD_FLAGS)"

# If GGML_CUDA is set, then add a cuda tag for the go ${BUILD FLAGS}
Expand All @@ -30,7 +30,7 @@ ifeq ($(GGML_CUDA),1)
endif

# Targets
all: whisper
all: whisper api

# Generate the pkg-config files
generate: mkdir go-tidy
Expand All @@ -42,6 +42,11 @@ whisper: mkdir generate go-tidy libwhisper libggml
@echo "Building whisper"
@PKG_CONFIG_PATH=${ROOT_PATH}/${BUILD_DIR} ${GO} build ${BUILD_FLAGS} -o ${BUILD_DIR}/whisper ./cmd/whisper

# Make api
api: mkdir go-tidy
@echo "Building api"
@${GO} build ${BUILD_FLAGS} -o ${BUILD_DIR}/api ./cmd/api

# Build docker container
docker: docker-dep submodule
@echo build docker image: ${BUILD_TAG} for ${OS}/${ARCH}
Expand All @@ -51,14 +56,16 @@ docker: docker-dep submodule
--build-arg OS=${OS} \
--build-arg SOURCE=${BUILD_MODULE} \
--build-arg VERSION=${VERSION} \
-f etc/Dockerfile.${OS}-${ARCH} .
-f etc/Dockerfile .

# Test whisper bindings
test: generate libwhisper libggml
@echo "Running tests (sys)"
@PKG_CONFIG_PATH=${ROOT_PATH}/${BUILD_DIR} ${GO} test -v ./sys/whisper/...
@echo "Running tests (pkg)"
@PKG_CONFIG_PATH=${ROOT_PATH}/${BUILD_DIR} ${GO} test -v ./pkg/whisper/...
@PKG_CONFIG_PATH=${ROOT_PATH}/${BUILD_DIR} ${GO} test -v ./pkg/...
@echo "Running tests (whisper)"
@PKG_CONFIG_PATH=${ROOT_PATH}/${BUILD_DIR} ${GO} test -v ./

# Build whisper-static-library
libwhisper: submodule
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Speech-to-Text in golang. This is an early development version.

* `cmd` contains an OpenAI-API compatible server
* `cmd` contains an OpenAI-API compatible service
* `pkg` contains the `whisper` service and client
* `sys` contains the `whisper` bindings to the `whisper.cpp` library
* `third_party` is a submodule for the whisper.cpp source
Expand All @@ -11,6 +11,7 @@ Speech-to-Text in golang. This is an early development version.

(Note: Docker images are not created yet - this is some forward planning!)

You can either run the whisper service as a CLI command or in a docker container.
There are docker images for arm64 and amd64 (Intel). The arm64 image is built for
Jetson GPU support specifically, but it will also run on Raspberry Pi's.

Expand All @@ -19,14 +20,15 @@ In order to utilize a NVIDIA GPU, you'll need to install the

A docker volume should be created called "whisper" can be used for storing the Whisper language
models. You can see which models are available to download locally [here](https://huggingface.co/ggerganov/whisper.cpp).
The following command will run the server on port 8080:

The following command will run the server on port 8080 for an NVIDIA GPU:

```bash
docker run \
--name whisper-server --rm \
--runtime nvidia --gpus all \ # When using a NVIDIA GPU
-v whisper:/models -p 8080:8080 -e WHISPER_DATA=/models \
ghcr.io/mutablelogic/go-whisper:latest
ghcr.io/mutablelogic/go-whisper
```

If you include a `-debug` flag at the end, you'll get more verbose output. The API is then
Expand Down Expand Up @@ -92,6 +94,10 @@ The following `Makefile` targets can be used:

See all the other targets in the `Makefile` for more information.

## Developing

TODO

## Status

Still in development. See this [issue](https://github.com/mutablelogic/go-whisper/issues/1) for
Expand Down
12 changes: 12 additions & 0 deletions cmd/api/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

type DeleteCmd struct {
Model string `arg:"" name:"model" help:"Model to delete"`
}

func (cmd *DeleteCmd) Run(ctx *Globals) error {
if err := ctx.client.DeleteModel(ctx.ctx, cmd.Model); err != nil {
return err
}
return nil
}
22 changes: 22 additions & 0 deletions cmd/api/download.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package main

import (
"fmt"

"github.com/djthorpe/go-tablewriter"
)

type DownloadCmd struct {
Model string `arg:"" name:"model" help:"Model to download (must end in .bin)"`
}

func (cmd *DownloadCmd) Run(ctx *Globals) error {
model, err := ctx.client.DownloadModel(ctx.ctx, cmd.Model, func(status string, cur, total int64) {
pct := fmt.Sprintf("%02d%%", int(100*float64(cur)/float64(total)))
ctx.writer.Writeln(pct, status)
})
if err != nil {
return err
}
return ctx.writer.Write(model, tablewriter.OptHeader())
}
104 changes: 104 additions & 0 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package main

import (
"context"
"os"
"path/filepath"
"syscall"

// Packages
kong "github.com/alecthomas/kong"
tablewriter "github.com/djthorpe/go-tablewriter"
opt "github.com/mutablelogic/go-client"
ctx "github.com/mutablelogic/go-server/pkg/context"
client "github.com/mutablelogic/go-whisper/pkg/client"
)

////////////////////////////////////////////////////////////////////////////////
// TYPES

type Globals struct {
Url string `name:"url" help:"URL of whisper service (can be set from WHISPER_URL env)" default:"${WHISPER_URL}"`
Debug bool `name:"debug" help:"Enable debug output"`

// Writer, service and context
writer *tablewriter.Writer
client *client.Client
ctx context.Context
}

type CLI struct {
Globals

Ping PingCmd `cmd:"ping" help:"Ping the whisper service"`
Models ModelsCmd `cmd:"models" help:"List models"`
Download DownloadCmd `cmd:"download" help:"Download a model"`
Delete DeleteCmd `cmd:"delete" help:"Delete a model"`
}

////////////////////////////////////////////////////////////////////////////////
// GLOBALS

const (
defaultEndpoint = "http://localhost:8080/api/v1"
)

////////////////////////////////////////////////////////////////////////////////
// MAIN

func main() {
// The name of the executable
name, err := os.Executable()
if err != nil {
panic(err)
} else {
name = filepath.Base(name)
}

// Create a cli parser
cli := CLI{}
cmd := kong.Parse(&cli,
kong.Name(name),
kong.Description("speech transcription and translation service client"),
kong.UsageOnError(),
kong.ConfigureHelp(kong.HelpOptions{Compact: true}),
kong.Vars{
"WHISPER_URL": envOrDefault("WHISPER_URL", defaultEndpoint),
},
)

// Set whisper client options
opts := []opt.ClientOpt{}
if cli.Globals.Debug {
opts = append(opts, opt.OptTrace(os.Stderr, true))
}

// Create a whisper client
client, err := client.New(cli.Globals.Url, opts...)
if err != nil {
cmd.FatalIfErrorf(err)
return
} else {
cli.Globals.client = client
}

// Create a tablewriter object with text output
writer := tablewriter.New(os.Stdout, tablewriter.OptOutputText())
cli.Globals.writer = writer

// Create a context
cli.Globals.ctx = ctx.ContextForSignal(os.Interrupt, syscall.SIGQUIT)

// Run the command
if err := cmd.Run(&cli.Globals); err != nil {
cmd.FatalIfErrorf(err)
}
}

func envOrDefault(name, def string) string {
if value := os.Getenv(name); value != "" {
return value
} else {
return def
}
}
13 changes: 13 additions & 0 deletions cmd/api/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import "github.com/djthorpe/go-tablewriter"

type ModelsCmd struct{}

func (cmd *ModelsCmd) Run(ctx *Globals) error {
if models, err := ctx.client.ListModels(ctx.ctx); err != nil {
return err
} else {
return ctx.writer.Write(models, tablewriter.OptHeader())
}
}
10 changes: 10 additions & 0 deletions cmd/api/ping.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

type PingCmd struct{}

func (cmd *PingCmd) Run(ctx *Globals) error {
if err := ctx.client.Ping(ctx.ctx); err != nil {
return err
}
return ctx.writer.Writeln("OK")
}
13 changes: 0 additions & 13 deletions cmd/cli/delete.go

This file was deleted.

34 changes: 0 additions & 34 deletions cmd/cli/download.go

This file was deleted.

Loading

0 comments on commit 3444bd8

Please sign in to comment.