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
Pingback: F# Advent Calendar in English 2014 | Sergey Tihon's Blog
Great post Jamie. I still don’t understand the response to the question that Watson sends back…I think maybe I was expecting something on par with Siri/Cortana. Am I missing something?
Beats me!
From what I can tell, the result needs to be parsed and you can match the confidence level. Throw the MSFT speech Api via the Kinect at the highest confidence and we have a jeopardy contestant… 🙂
There is surely error in logic in your code. Check the Q&A at http://watson-qa-demo.mybluemix.net/ for the actual answer IBM Watson responds with. You can refer to a sample application here http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/qaapi/#nodejsApplication
Pingback: F# Weekly #50, 2014 | Sergey Tihon's Blog
IBM’s Watson is a cognitive computing system, one that behaves like our brain, learning through experiences, finding correlations, and remembering — and learning from — the outcomes.
First hitting the spotlight when pitted against two of Jeopardy’s biggest all-time winners Ken Jennings and Brad Rutter, IBM’s artificial intelligence machine names Watson threw these two off their throne in quick fashion – showing that artificial intelligence was a real thing and IBM has the technology.
If you are interested, I have posted an article about IBM Watson that you can read here:
http://worldofinnovations.net/2014/11/16/ibm-watson-the-beginning-aware-artificial/