Using IBM’s Watson With F#
December 9, 2014 6 Comments
I think everyone is aware of IBM’s Watson from its appearance on Jeopardy. Apparently, IBM has made the Watson Api available for developers if you sign up here. Well, there goes my Sunday morning! I signed up and after one email confirm later, I was in.
IBM has tied Watson to something called “Blue Mix”, which looks to be a full-service suite of applications from deployment to hosting . When I looked at the api documentation here, I decided to use the language translation service as a good “hello world” project. Looking at the api help page, I was hoping just to make a request and get a response with a auth token in the header, like every other api in the world. However, the documentation really leads you down a path of installing the Watson Explorer on your local machine, and a create a blue mix project, etc..
Fortunately, the documentation has some pointers to other projects where people have made their own app. I used thisthis one as a model and set up Fiddler like so
The authorization token is the username and password separated by a colon encoded to base 64.
Sure enough, a 200
Setting it up in #FSharp was a snap
1 #r @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Net.Http.dll" 2 #r @"..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll" 3 4 open System 5 open System.Net.Http 6 open System.Net.Http.Headers 7 open System.Net.Http.Formatting 8 open System.Collections.Generic 9 10 11 let serviceName = "machine_translation" 12 let baseUrl = "http://wex-mt.mybluemix.net/resources/translate" 13 let userName = "youNameHere@aol.com" 14 let password = "yourPasswordHere" 15 let authKey = userName + ":" + password 16 17 let client = new HttpClient() 18 client.DefaultRequestHeaders.Authorization <- new AuthenticationHeaderValue("Basic",authKey) 19 20 let input = new Dictionary<string,string>() 21 input.Add("text","This is a test") 22 input.Add("sid","mt-enus-eses") 23 let content = new FormUrlEncodedContent(input) 24 25 let result = client.PostAsync(baseUrl,content).Result 26 let resultContent = result.Content.ReadAsStringAsync().Result
And sure enough
You can see the gist here
So with that simple call/request under my belt, I decided to look at the api that everyone is talking about, the question/answer api. I fired up Fiddler again and took a look at the docs. After some tweaking of the Uri, I got a successful request/response:
With the answers to an empty question kind interesting. if not head-scratching:
So passing in a question:
So we are cooking with gas. Back into FSI
1 #r @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Net.Http.dll" 2 #r @"..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll" 3 4 open System 5 open System.Net.Http 6 open System.Net.Http.Headers 7 open System.Net.Http.Formatting 8 open System.Collections.Generic 9 10 11 let baseUrl = "http://wex-qa.mybluemix.net/resources/question" 12 let userName = "yourName@aol.com" 13 let password = "yourCreds" 14 let authKey = userName + ":" + password 15 16 let client = new HttpClient() 17 client.DefaultRequestHeaders.Authorization <- new AuthenticationHeaderValue("Basic",authKey) 18 19 let input = new Dictionary<string,string>() 20 input.Add("question","what time is it") 21 let content = new FormUrlEncodedContent(input) 22 23 let result = client.PostAsync(baseUrl,content).Result 24 let resultContent = result.Content.ReadAsStringAsync().Result
With the result like so
And since it is Json coming back, why not use the type provider?
1 let client = new HttpClient() 2 client.DefaultRequestHeaders.Authorization <- new AuthenticationHeaderValue("Basic",authKey) 3 4 let input = new Dictionary<string,string>() 5 input.Add("question","How can I quit smoking") 6 let content = new FormUrlEncodedContent(input) 7 8 let result = client.PostAsync(baseUrl,content).Result 9 let resultContent = result.Content.ReadAsStringAsync().Result 10 11 type qaResponse = JsonProvider<".\QAResponseJson.json"> 12 let qaAnswer = qaResponse.Parse(resultContent) 13 14 qaAnswer.Question.Answers 15 |> Seq.ofArray 16 |> Seq.iter(fun a -> printfn "(%s)" a.Text)
Here is Watson’s response:
You can see the gist here