Skip to content

Commit 387757e

Browse files
authored
Merge pull request #13 from machinebox/feature-helpers
added feature helpers
2 parents 32458e2 + bba4f6d commit 387757e

File tree

2 files changed

+148
-20
lines changed

2 files changed

+148
-20
lines changed

suggestionbox/suggestionbox_model.go

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import (
44
"bytes"
55
"context"
66
"encoding/json"
7+
"fmt"
78
"net/http"
89
"net/url"
10+
"strings"
911
"time"
1012

1113
"github.com/pkg/errors"
@@ -16,35 +18,52 @@ type Model struct {
1618
// ID is the ID of the model.
1719
ID string `json:"id,omitempty"`
1820
// Name is the human readable name of the Model.
19-
Name string `json:"name,omitempty"`
21+
Name string `json:"name"`
2022
// Options are optional Model settings to adjust the behaviour
2123
// of this Model within Suggestionbox.
2224
Options *ModelOptions `json:"options,omitempty"`
2325
// Choices are the options this Model will select from.
2426
Choices []Choice `json:"choices,omitempty"`
2527
}
2628

29+
// NewModel makes a new Model.
30+
func NewModel(id, name string, choices ...Choice) Model {
31+
return Model{
32+
ID: id,
33+
Name: name,
34+
Choices: choices,
35+
}
36+
}
37+
2738
// Feature represents a single feature, to describe an input or a choice
2839
// for example age:28 or location:"London".
2940
type Feature struct {
3041
// Key is the name of the Feature.
31-
Key string `json:"key,omitempty"`
42+
Key string `json:"key"`
3243
// Value is the string value of this Feature.
33-
Value string `json:"value,omitempty"`
44+
Value string `json:"value"`
3445
// Type is the type of the Feature.
3546
// Can be "number", "text", "keyword", "list", "image_url" or "image_base64"..
36-
Type string `json:"type,omitempty"`
47+
Type string `json:"type"`
3748
}
3849

3950
// Choice is an option with features.
4051
type Choice struct {
4152
// ID is a unique ID for this choice.
42-
ID string `json:"id,omitempty"`
53+
ID string `json:"id"`
4354
// Features holds all the Feature objects that describe
4455
// this choice.
4556
Features []Feature `json:"features,omitempty"`
4657
}
4758

59+
// NewChoice creates a new Choice.
60+
func NewChoice(id string, features ...Feature) Choice {
61+
return Choice{
62+
ID: id,
63+
Features: features,
64+
}
65+
}
66+
4867
// ModelOptions describes the behaviours of a Model.
4968
type ModelOptions struct {
5069
// Expiration is the time to wait for the reward before it expires.
@@ -104,3 +123,60 @@ func (c *Client) CreateModel(ctx context.Context, model Model) (Model, error) {
104123
}
105124
return response.Model, nil
106125
}
126+
127+
// FeatureNumber makes a numerical Feature.
128+
func FeatureNumber(key string, value float64) Feature {
129+
return Feature{
130+
Type: "number",
131+
Key: key,
132+
Value: fmt.Sprintf("%v", value),
133+
}
134+
}
135+
136+
// FeatureText makes a textual Feature that will be tokenized.
137+
// Use FeatureKeyword for values that should not be tokenized.
138+
func FeatureText(key string, text string) Feature {
139+
return Feature{
140+
Type: "text",
141+
Key: key,
142+
Value: text,
143+
}
144+
}
145+
146+
// FeatureKeyword makes a textual Feature that will not be tokenized.
147+
// Use FeatureList to provide multiple keywords in a single Feature.
148+
// Use Text for bodies of text that should be tokenized.
149+
func FeatureKeyword(key string, keyword string) Feature {
150+
return Feature{
151+
Type: "keyword",
152+
Key: key,
153+
Value: keyword,
154+
}
155+
}
156+
157+
// FeatureList makes a Feature made up of multiple keywords.
158+
func FeatureList(key string, keywords ...string) Feature {
159+
return Feature{
160+
Type: "list",
161+
Key: key,
162+
Value: strings.Join(keywords, ","),
163+
}
164+
}
165+
166+
// FeatureImageURL makes a Feature that points to a hosted image.
167+
func FeatureImageURL(key string, url string) Feature {
168+
return Feature{
169+
Type: "image_url",
170+
Key: key,
171+
Value: url,
172+
}
173+
}
174+
175+
// FeatureImageBase64 makes a Feature that is base 64 encoded.
176+
func FeatureImageBase64(key string, data string) Feature {
177+
return Feature{
178+
Type: "image_base64",
179+
Key: key,
180+
Value: data,
181+
}
182+
}

suggestionbox/suggestionbox_model_test.go

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,75 @@ func TestCreateModel(t *testing.T) {
3434
}))
3535
defer srv.Close()
3636
sb := suggestionbox.New(srv.URL)
37-
inModel := suggestionbox.Model{
38-
Name: "My Model",
39-
Choices: []suggestionbox.Choice{
40-
{
41-
ID: "choice1",
42-
Features: []suggestionbox.Feature{
43-
{
44-
Key: "title",
45-
Type: "text",
46-
Value: "Machine Box releases new product",
47-
},
48-
},
49-
},
50-
},
51-
}
37+
inModel := suggestionbox.NewModel("", "My Model",
38+
suggestionbox.NewChoice("choice1",
39+
suggestionbox.FeatureText("title", "Machine Box releases new product"),
40+
),
41+
)
5242
outModel, err := sb.CreateModel(context.Background(), inModel)
5343
is.NoErr(err)
5444
is.Equal(apiCalls, 1) // apiCalls
5545
is.Equal(outModel.ID, "1") // outModel.ID
5646
}
47+
48+
func TestNewModel(t *testing.T) {
49+
is := is.New(t)
50+
51+
m := suggestionbox.NewModel("model1", "My Model",
52+
suggestionbox.NewChoice("choice1",
53+
suggestionbox.FeatureKeyword("city", "New York City"),
54+
),
55+
)
56+
is.Equal(m.ID, "model1")
57+
is.Equal(m.Name, "My Model")
58+
is.Equal(len(m.Choices), 1)
59+
is.Equal(m.Choices[0].ID, "choice1")
60+
}
61+
62+
func TestNewChoice(t *testing.T) {
63+
is := is.New(t)
64+
65+
c := suggestionbox.NewChoice("choice1",
66+
suggestionbox.FeatureKeyword("city", "New York City"),
67+
)
68+
is.Equal(c.ID, "choice1")
69+
is.Equal(len(c.Features), 1)
70+
is.Equal(c.Features[0].Key, "city")
71+
}
72+
73+
func TestFeatureHelpers(t *testing.T) {
74+
is := is.New(t)
75+
76+
var f suggestionbox.Feature
77+
78+
f = suggestionbox.FeatureNumber("age", 20)
79+
is.Equal(f.Type, "number")
80+
is.Equal(f.Key, "age")
81+
is.Equal(f.Value, "20")
82+
83+
f = suggestionbox.FeatureText("title", "Machine box releases new box")
84+
is.Equal(f.Type, "text")
85+
is.Equal(f.Key, "title")
86+
is.Equal(f.Value, "Machine box releases new box")
87+
88+
f = suggestionbox.FeatureKeyword("city", "New York City")
89+
is.Equal(f.Type, "keyword")
90+
is.Equal(f.Key, "city")
91+
is.Equal(f.Value, "New York City")
92+
93+
f = suggestionbox.FeatureList("categories", "one", "two", "three")
94+
is.Equal(f.Type, "list")
95+
is.Equal(f.Key, "categories")
96+
is.Equal(f.Value, "one,two,three")
97+
98+
f = suggestionbox.FeatureImageURL("pic", "http://url.com/path/to/pic.jpg")
99+
is.Equal(f.Type, "image_url")
100+
is.Equal(f.Key, "pic")
101+
is.Equal(f.Value, "http://url.com/path/to/pic.jpg")
102+
103+
f = suggestionbox.FeatureImageBase64("pic", "pretendthisisimagedata")
104+
is.Equal(f.Type, "image_base64")
105+
is.Equal(f.Key, "pic")
106+
is.Equal(f.Value, "pretendthisisimagedata")
107+
108+
}

0 commit comments

Comments
 (0)