Skip to content

Commit 05ffbf4

Browse files
committed
fix(ai): sanitize response strings
1 parent 446bb91 commit 05ffbf4

File tree

5 files changed

+37
-4
lines changed

5 files changed

+37
-4
lines changed

filter_ollama.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
var (
1717
OllamaSystemPrompt = `You will carefully evaluate a message to
1818
determine if it matches specific criteria. Provide a very short explanation
19-
for your reasoning.
19+
for your reasoning. Return as JSON.
2020
`
2121
OllamaTimeout = 120
2222
OllamaMaxPredictionTokens = 512
@@ -103,6 +103,8 @@ func OllamaFilter(m string) bool {
103103
Options: map[string]interface{}{
104104
// Hopefully minimizes the model timing out
105105
"num_predict": OllamaMaxPredictionTokens,
106+
// Make output deterministic
107+
"temperature": 0,
106108
},
107109
}
108110

@@ -120,6 +122,7 @@ func OllamaFilter(m string) bool {
120122
start, end := matches[len(matches)-1][0], matches[len(matches)-1][1]
121123
content := resp.Response[start:end]
122124

125+
content = SanitizeJSONString(content)
123126
err = json.Unmarshal([]byte(content), &r)
124127
if err != nil {
125128
err = fmt.Errorf("%w, ollama full response: %s", err, resp.Response)

filter_openai.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import (
1010
log "github.com/sirupsen/logrus"
1111
)
1212

13-
var OpenAISystemPrompt string = `You are an API that only responds in
14-
valid JSON objects. You will carefully evaluate a message to determine if it
15-
matches specific criteria.
13+
var OpenAISystemPrompt string = `You will carefully evaluate a message to
14+
determine if it matches specific criteria. Return as JSON.
1615
1716
If the message matches the criteria, "decision" will ALWAYS be true:
1817
{"decision": true, "reasoning": "REASON"}
@@ -45,6 +44,7 @@ func OpenAIFilter(m string) bool {
4544
if config.OpenAIModel != "" {
4645
openAIModel = config.OpenAIModel
4746
}
47+
4848
log.Debugf("calling OpenAI model %s", openAIModel)
4949
chatCompletion, err := client.Chat.Completions.New(context.TODO(),
5050
openai.ChatCompletionNewParams{
@@ -54,6 +54,8 @@ func OpenAIFilter(m string) bool {
5454
openai.UserMessage(m),
5555
}),
5656
Model: openai.F(openAIModel),
57+
// Make it deterministic
58+
Temperature: openai.Float(0),
5759
})
5860
if err != nil {
5961
log.Errorf("error using OpenAI: %s", err)
@@ -74,6 +76,7 @@ func OpenAIFilter(m string) bool {
7476
}
7577
start, end := matches[len(matches)-1][0], matches[len(matches)-1][1]
7678
content := chatCompletion.Choices[0].Message.Content[start:end]
79+
content = SanitizeJSONString(content)
7780
err = json.Unmarshal([]byte(content), &r)
7881

7982
if err != nil {

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@ require (
1414

1515
require (
1616
github.com/BurntSushi/toml v1.2.1 // indirect
17+
github.com/bahlo/generic-list-go v0.2.0 // indirect
18+
github.com/buger/jsonparser v1.1.1 // indirect
1719
github.com/golobby/cast v1.3.3 // indirect
1820
github.com/golobby/dotenv v1.3.2 // indirect
1921
github.com/golobby/env/v2 v2.2.4 // indirect
22+
github.com/invopop/jsonschema v0.13.0 // indirect
23+
github.com/mailru/easyjson v0.7.7 // indirect
2024
github.com/tidwall/gjson v1.14.4 // indirect
2125
github.com/tidwall/match v1.1.1 // indirect
2226
github.com/tidwall/pretty v1.2.1 // indirect
2327
github.com/tidwall/sjson v1.2.5 // indirect
28+
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
2429
golang.org/x/sys v0.30.0 // indirect
2530
gopkg.in/yaml.v3 v3.0.1 // indirect
2631
)

go.sum

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
22
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
3+
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
4+
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
5+
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
6+
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
37
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
48
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
59
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -14,15 +18,20 @@ github.com/golobby/env/v2 v2.2.4 h1:sjdTe+bScPRWUIA1AQH95RHv52jM5Mns2XHwLyEbkzk=
1418
github.com/golobby/env/v2 v2.2.4/go.mod h1:HDJW+dHHwLxkb8FZMjBTBiZUFl1iAA4F9YX15kBC84c=
1519
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
1620
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
21+
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
22+
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
1723
github.com/jftuga/geodist v1.0.0 h1:PFPQlZtj10u8ETAYTyxE0DWMl1bwA+Xzrqb4+oLkkC0=
1824
github.com/jftuga/geodist v1.0.0/go.mod h1:BohEDxpZ8S5ADAxW/9EKPSKWOVl0+3wHENIT40m4UO4=
25+
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
1926
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
2027
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
2128
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
2229
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
2330
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
2431
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
2532
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
33+
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
34+
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
2635
github.com/newrelic/newrelic-telemetry-sdk-go v0.8.1 h1:6OX5VXMuj2salqNBc41eXKz6K+nV6OB/hhlGnAKCbwU=
2736
github.com/newrelic/newrelic-telemetry-sdk-go v0.8.1/go.mod h1:2kY6OeOxrJ+RIQlVjWDc/pZlT3MIf30prs6drzMfJ6E=
2837
github.com/ollama/ollama v0.6.1 h1:M+wxOCuC1hKhHd6a8zNuJl6jYiRPsi/JFd4QoU0P5BQ=
@@ -57,6 +66,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
5766
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
5867
github.com/tidwall/words v0.0.0-20181116223016-6463671b7759 h1:y3CDYT8Qw7Gmll8W8OvgVdRX3Va70xJqSBaKaeILSAY=
5968
github.com/tidwall/words v0.0.0-20181116223016-6463671b7759/go.mod h1:calX3QB7ABamqPLok6zrdMw6kcIsxErDVuPEHCETil8=
69+
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
70+
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
6071
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6172
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
6273
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

util.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,14 @@ func AircraftOrTower(s string) (r string) {
6666
}
6767
return "Tower"
6868
}
69+
70+
// Fixes AI output bullshit
71+
func SanitizeJSONString(s string) string {
72+
replacer := strings.NewReplacer(
73+
"“", "\"",
74+
"”", "\"",
75+
"‘", "'",
76+
"’", "'",
77+
)
78+
return replacer.Replace(s)
79+
}

0 commit comments

Comments
 (0)