-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
163 lines (148 loc) · 4.5 KB
/
main.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package main
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strconv"
dialogflow "cloud.google.com/go/dialogflow/apiv2"
"github.com/golang/protobuf/ptypes/struct"
"google.golang.org/api/option"
dialogflowpb "google.golang.org/genproto/googleapis/cloud/dialogflow/v2"
)
// DialogflowProcessor has all the information for connecting with Dialogflow
type DialogflowProcessor struct {
projectID string
authJSONFilePath string
lang string
timeZone string
sessionClient *dialogflow.SessionsClient
ctx context.Context
}
// NLPResponse is the struct for the response
type NLPResponse struct {
Intent string `json:"intent"`
Confidence float32 `json:"confidence"`
Entities map[string]string `json:"entities"`
}
var dp DialogflowProcessor
func main() {
dp.init("tutorialchatbot-d4db0", "tutorialchatbot-d4db0-0fea9ca7f682.json", "en", "America/Montevideo")
http.HandleFunc("/", requestHandler)
fmt.Println("Started listening...")
http.ListenAndServe(":5000", nil)
}
func requestHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
//POST method, receives a json to parse
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Error reading request body",
http.StatusInternalServerError)
}
type inboundMessage struct {
Message string
}
var m inboundMessage
err = json.Unmarshal(body, &m)
if err != nil {
panic(err)
}
// Use NLP
response := dp.processNLP(m.Message, "testUser")
fmt.Printf("%#v", response)
w.Header().Set("Content-Type", "application/json")
//json.NewEncoder(w).Encode(response)
json.NewEncoder(w).Encode(response)
}
}
func (dp *DialogflowProcessor) init(a ...string) (err error) {
dp.projectID = a[0]
dp.authJSONFilePath = a[1]
dp.lang = a[2]
dp.timeZone = a[3]
// Auth process: https://dialogflow.com/docs/reference/v2-auth-setup
dp.ctx = context.Background()
sessionClient, err := dialogflow.NewSessionsClient(dp.ctx, option.WithCredentialsFile(dp.authJSONFilePath))
if err != nil {
log.Fatal("Error in auth with Dialogflow")
}
dp.sessionClient = sessionClient
return
}
func (dp *DialogflowProcessor) processNLP(rawMessage string, username string) (r NLPResponse) {
sessionID := username
request := dialogflowpb.DetectIntentRequest{
Session: fmt.Sprintf("projects/%s/agent/sessions/%s", dp.projectID, sessionID),
QueryInput: &dialogflowpb.QueryInput{
Input: &dialogflowpb.QueryInput_Text{
Text: &dialogflowpb.TextInput{
Text: rawMessage,
LanguageCode: dp.lang,
},
},
},
QueryParams: &dialogflowpb.QueryParameters{
TimeZone: dp.timeZone,
},
}
response, err := dp.sessionClient.DetectIntent(dp.ctx, &request)
if err != nil {
log.Fatalf("Error in communication with Dialogflow %s", err.Error())
return
}
queryResult := response.GetQueryResult()
if queryResult.Intent != nil {
r.Intent = queryResult.Intent.DisplayName
r.Confidence = float32(queryResult.IntentDetectionConfidence)
}
r.Entities = make(map[string]string)
params := queryResult.Parameters.GetFields()
if len(params) > 0 {
for paramName, p := range params {
fmt.Printf("Param %s: %s (%s)", paramName, p.GetStringValue(), p.String())
extractedValue := extractDialogflowEntities(p)
r.Entities[paramName] = extractedValue
}
}
return
}
func extractDialogflowEntities(p *structpb.Value) (extractedEntity string) {
kind := p.GetKind()
switch kind.(type) {
case *structpb.Value_StringValue:
return p.GetStringValue()
case *structpb.Value_NumberValue:
return strconv.FormatFloat(p.GetNumberValue(), 'f', 6, 64)
case *structpb.Value_BoolValue:
return strconv.FormatBool(p.GetBoolValue())
case *structpb.Value_StructValue:
s := p.GetStructValue()
fields := s.GetFields()
extractedEntity = ""
for key, value := range fields {
if key == "amount" {
extractedEntity = fmt.Sprintf("%s%s", extractedEntity, strconv.FormatFloat(value.GetNumberValue(), 'f', 6, 64))
}
if key == "unit" {
extractedEntity = fmt.Sprintf("%s%s", extractedEntity, value.GetStringValue())
}
if key == "date_time" {
extractedEntity = fmt.Sprintf("%s%s", extractedEntity, value.GetStringValue())
}
// @TODO: Other entity types can be added here
}
return extractedEntity
case *structpb.Value_ListValue:
list := p.GetListValue()
if len(list.GetValues()) > 1 {
// @TODO: Extract more values
}
extractedEntity = extractDialogflowEntities(list.GetValues()[0])
return extractedEntity
default:
return ""
}
}