Part 1 — In this article, we will try out their /query service.
Api.ai is a service which provides a nice combination of both voice recognition and machine learning for developers. We shall use their free tier.
Api.ai has “Domains”. Domains are a whole collection of knowledge and data structures from Api.ai that are ready for use in every Api.ai agent (apps are called “agents” in Api.ai).
Api.ai has SDKs for most languages except Golang. Nevertheless, we shall use Go to write a program called “apiai.go” which will query the weather for a particular place and display the result.
I have created a folder “apiai” which will hold the Go source code “apiai.go”.
C:\go_projects\go\src\github.com\SatishTalim\apiai
We shall be running our program at the command prompt in the folder “apiai” as follows:
go run apiai.go
apiai.go
As mentioned in their docs, a sample query response is:
{ "id": "cfcbd337-6b66-4393-a6a3-74fc5487cedb", "timestamp": "2016-02-16T00:30:13.529Z", "result": { "source": "agent", "resolvedQuery": "hi my name is Sam", "action": "greetings", "actionIncomplete": false, "parameters": { "name": "Sam" }, "contexts": [ { "name": "user_name", "parameters": { "name": "Sam" }, "lifespan": 5 }, { "name": "greetings", "parameters": { "name": "Sam" }, "lifespan": 5 } ], "metadata": { "intentId": "c251ef97-0c43-404d-bf75-98e806f942be", "intentName": "Greetings" }, "fulfillment": { "speech": "Hi Sam! How can I help you?" } }, "status": { "code": 200, "errorType": "success" } }
JSON-to-Go is an excellent tool that instantly converts JSON into a Go type definition. Using it, I get:
type QResponse struct { ID string `json:"id"` Timestamp time.Time `json:"timestamp"` Result struct { Source string `json:"source"` ResolvedQuery string `json:"resolvedQuery"` Action string `json:"action"` ActionIncomplete bool `json:"actionIncomplete"` Parameters struct { Name string `json:"name"` } `json:"parameters"` Contexts []struct { Name string `json:"name"` Parameters struct { Name string `json:"name"` } `json:"parameters"` Lifespan int `json:"lifespan"` } `json:"contexts"` Metadata struct { IntentID string `json:"intentId"` IntentName string `json:"intentName"` } `json:"metadata"` Fulfillment struct { Speech string `json:"speech"` } `json:"fulfillment"` } `json:"result"` Status struct { Code int `json:"code"` ErrorType string `json:"errorType"` } `json:"status"` }
Here’s the complete “apiai.go” program:
package main import ( "encoding/json" "fmt" "log" "net/http" "time" ) type QResponse struct { ID string `json:"id"` Timestamp time.Time `json:"timestamp"` Result struct { Source string `json:"source"` ResolvedQuery string `json:"resolvedQuery"` Action string `json:"action"` ActionIncomplete bool `json:"actionIncomplete"` Parameters struct { Name string `json:"name"` } `json:"parameters"` Contexts []struct { Name string `json:"name"` Parameters struct { Name string `json:"name"` } `json:"parameters"` Lifespan int `json:"lifespan"` } `json:"contexts"` Metadata struct { IntentID string `json:"intentId"` IntentName string `json:"intentName"` } `json:"metadata"` Fulfillment struct { Speech string `json:"speech"` } `json:"fulfillment"` } `json:"result"` Status struct { Code int `json:"code"` ErrorType string `json:"errorType"` } `json:"status"` } func main() { url := fmt.Sprintf("https://api.api.ai/v1/query?v=20150910&query=weather&lang=en&latitude=35.925&longitude=-86.8688889&sessionId=1234567890") // Build the request req, err := http.NewRequest("GET", url, nil) if err != nil { log.Fatal("NewRequest: ", err) return } // Replace 9ea93023b7274cfbb392b289658cff0b by your Client access token req.Header.Add("Authorization", "Bearer 9ea93023b7274cfbb392b289658cff0b") // For control over HTTP client headers, // redirect policy, and other settings, // create a Client // A Client is an HTTP client client := &http.Client{} // Send the request via a client // Do sends an HTTP request and // returns an HTTP response resp, err := client.Do(req) if err != nil { log.Fatal("Do: ", err) return } // Callers should close resp.Body // when done reading from it // Defer the closing of the body defer resp.Body.Close() // Fill the record with the data from the JSON var record QResponse // Use json.Decode for reading streams of JSON data if err := json.NewDecoder(resp.Body).Decode(&record); err != nil { log.Println(err) } fmt.Println("Status = ", record.Status.Code) fmt.Println("Response = ", record.Result.Fulfillment.Speech) }
https://docs.api.ai/docs/reference allow you to submit queries and get text-to-speech results.
All the URLs have the following base:
https://api.api.ai/v1/
The query endpoint is used to process natural language, either in the form of text or a sound file. The query requests return structured data in JSON format with an action and parameters for that action. Get /query — Takes natural language text and information as query parameters and returns information as JSON.
We are going to find out the weather at Franklin, Tennessee, USA.
Query parameters
https://api.api.ai/v1/query?v=20150910&query=weather&lang=en&latitude=35.925&longitude=-86.8688889&sessionId=1234567890
With the parameters in the above table, our URL is as shown above.
fmt.Sprintf
“Sprintf” formats and returns a string without printing it anywhere.
func NewRequest(method, urlStr string, body io.Reader) (*Request, error)
“NewRequest” returns a new “Request” given a method, URL, and an optional body. “NewRequest” returns a “Request” suitable for use with “Client.Do”.
func (h Header) Add(key, value string)
“Add” adds the key, value pair to the header. It appends to any existing values associated with key.
// Replace 9ea93023b7274cfbb392b289658cff0b by your Client access token req.Header.Add(“Authorization”, “Bearer 9ea93023b7274cfbb392b289658cff0b”)
For each API request, include the above HTTP header.
client := &http.Client{}
A “Client” is an HTTP client.
resp, err := client.Do(req)
“Do” sends an HTTP request and returns an HTTP response. When “err” is nil, “resp” always contains a non-nil “resp.Body”. Callers should close “resp.Body” when done reading from it. Use “Defer” for closing the body. “resp.Body” is of type “io.Reader”.
defer resp.Body.Close()
Next, “NewDecoder” returns a new decoder that reads from “io.Reader”. A “Decoder” reads and decodes JSON objects from an input stream.
func NewDecoder(r io.Reader) *Decoder
“Decode” reads the next JSON-encoded value from its input and stores it in the value pointed to by v.
func (dec *Decoder) Decode(v interface{}) error
Finally, we extract the information from our populated “QResponse” struct variable “record”.
Here’s a sample output of the program:
Response = It’s currently 63 degrees and cloudy in Franklin, Tennessee. It will be intermittent clouds and around 62 degrees this afternoon. Expect a thunderstorms evening, with temperatures around 66 degrees.
That’s it!
One thought on “Part 1: How To Use Golang With API.ai Artificial Intelligence Service”