-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgo_wabbit.go
111 lines (91 loc) · 2.3 KB
/
go_wabbit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Package gowabbit is a utility wrapper for Vowpal Wabbit.
package gowabbit
import (
"errors"
"fmt"
"strconv"
"strings"
"time"
)
var (
NoVwError = errors.New("Could not find VW on this box at the specified path.")
CheckDuration = time.Duration(time.Microsecond * 500)
)
type Wabbit struct {
tcpPort, children int
modelPath, binpath string
quiet bool
}
// What is returned from VW after calling Predict. If no class is given, it will return an empty string.
type Prediction struct {
val float64
class string
}
// Initialise a new Wabbit object. This controls VWP.
func NewWabbit(tcpPort, children int, binPath, modelPath string, quiet bool) *Wabbit {
return &Wabbit{
tcpPort: tcpPort,
children: children,
binpath: binPath,
modelPath: modelPath,
quiet: quiet,
}
}
// If continous, runs a goroutine in the background that checks that VW is still up. If not, it panics.
func (w *Wabbit) StartDaemonWabbit(continualCheck bool) error {
err := w.checkPresence()
if err != nil {
return err
}
comm := fmt.Sprintf("vw --daemon -i %s -t --port %d", w.modelPath, w.tcpPort)
if w.quiet {
comm += " --quiet"
}
_, err = runCommand(comm, false)
if err != nil {
return err
}
if continualCheck {
go checkRunning(w)
}
return nil
}
// Stops the daemon by killing it completely.
func (w *Wabbit) KillDaemonWabbit() error {
_, err := runCommand("killall vw", false)
if err != nil {
return err
}
return nil
}
// Takes a VW formatted string and returns the raw output as a string.
// @todo: Write parser to split apart tag and prediction.
// @todo: Deal with cluster.
// @todo: Use TCP socket, not command line cruft.
// @todo: Deal with multiple predictions.
func (w *Wabbit) Predict(command string) (*Prediction, error) {
comm := ` echo "` + command + fmt.Sprintf(`" | nc localhost %v`, w.tcpPort)
val, err := runCommand(comm, true)
if err != nil {
return nil, err
}
splitString := strings.Split(string(val), " ")
flt, _ := strconv.ParseFloat(string(splitString[0]), 64)
var class string
if len(splitString) == 1 {
class = ""
} else {
class = strings.TrimSpace(splitString[1])
}
pred := &Prediction{
val: flt,
class: class,
}
return pred, nil
}
func (p *Prediction) Class() string {
return p.class
}
func (p *Prediction) Val() string {
return p.val
}