watsonのTradeoff Analyticsをcurlでためしてみる
概要 Tradeoff Analytics APIを使うことで、複数の条件からなる選択肢のうち、ベターなものが何かを調べることができます 条件と候補をまとめたJSONをPOSTするだけで、結果を返してくれます 無料枠もあ […]
目次
概要
- Tradeoff Analytics APIを使うことで、複数の条件からなる選択肢のうち、ベターなものが何かを調べることができます
- 条件と候補をまとめたJSONをPOSTするだけで、結果を返してくれます
- 無料枠もあるので、比較的気軽に試せます。
Tradeoff Analytics | IBM Watson Developer Cloud
APIの呼び出し方
もっともシンプルなのはcurlでPOSTリクエストを投げるだけです。
$ curl -X POST --user YOUR_USERNAME:YOUR_PASSWORD --header "Content-Type: application/json" --data @problem.json "https://gateway.watsonplatform.net/tradeoff-analytics/api/v1/dilemmas?generate_visualization=false" | jq .
YOUR_USERNAMEとYOUR_PASSWORDは、「サービス資格情報」にあるものを使用します。

problem.jsonというファイルをPOSTしていますので、ここからはJSONファイルの中身をざっと紹介します。
Request body(JSON)
problem.jsonの中には以下のキーが含まれます。
- subject
- タイトル
- columns
- 選択の条件ための
- options
- 選択候補
これらの3つを含めたJSONファイルを生成して、POSTします。
例
from:チュートリアル
7種類のスマートフォンから、自分の条件に合うものを探すというクエリです。
{
"subject": "phones",
"columns": [
{
"key": "price",
"type": "numeric",
"goal": "min",
"is_objective": true,
"full_name": "Price",
"range": {
"low": 0,
"high": 400
},
"format": "number:2"
},
{
"key": "weight",
"type": "numeric",
"goal": "min",
"is_objective": true,
"full_name": "Weight",
"format": "number:0"
},
{
"key": "brand",
"type": "categorical",
"goal": "min",
"is_objective": true,
"full_name": "Brand",
"range": [
"Apple",
"HTC",
"Samsung",
"Sony"
],
"preference": [
"Samsung",
"Apple",
"HTC"
]
},
{
"key": "rDate",
"type": "datetime",
"goal": "max",
"full_name": "Release Date",
"format": "date: 'MMM dd, yyyy'"
}
],
"options": [
{
"key": "1",
"name": "Samsung Galaxy S4",
"values": {
"price": 249,
"weight": 130,
"brand": "Samsung",
"rDate": "2013-04-29T00:00:00Z"
}
},
{
"key": "2",
"name": "Apple iPhone 5",
"values": {
"price": 349,
"weight": 112,
"brand": "Apple",
"rDate": "2012-09-21T00:00:00Z"
}
},
{
"key": "3",
"name": "HTC One",
"values": {
"price": 299,
"weight": 112,
"brand": "HTC",
"rDate": "2013-03-01T00:00:00Z"
}
},
{
"key": "4",
"name": "Samsung Galaxy S5",
"values": {
"price": 349,
"weight": 135,
"brand": "Samsung",
"rDate": "2014-04-29T00:00:00Z"
}
},
{
"key": "5",
"name": "Apple iPhone 6",
"values": {
"price": 399,
"weight": 118,
"brand": "Apple",
"rDate": "2013-09-21T00:00:00Z"
}
},
{
"key": "6",
"name": "Apple iPhone 7",
"values": {
"price": 499,
"weight": 118,
"brand": "Apple",
"rDate": "2014-09-21T00:00:00Z"
}
},
{
"key": "7",
"name": "Sony Xperia",
"values": {
"price": 199,
"weight": 120,
"brand": "Sony",
"rDate": "2014-08-21T00:00:00Z"
}
}
]
}
columnsの中身をざっくりとまとめるとこんな感じです。
| 項目 | 条件 |
|---|---|
| 価格 | 0 ~ 400の間 |
| 重さ | できるだけ軽いもの |
| ブランド | サムスン・アップル・HTCのどれか |
| リリース日 | できるだけ新しいもの |
戻り値
リクエストが成功した場合、以下のようなJSONが返ってきます。
{
"problem": {
"columns": [
{
"type": "numeric",
"key": "price",
"full_name": "Price",
"range": {
"low": 0,
"high": 400
},
"format": "number:2",
"goal": "min",
"is_objective": true
},
{
"type": "numeric",
"key": "weight",
"full_name": "Weight",
"format": "number:0",
"goal": "min",
"is_objective": true
},
{
"type": "categorical",
"key": "brand",
"full_name": "Brand",
"range": [
"Apple",
"HTC",
"Samsung",
"Sony"
],
"goal": "min",
"preference": [
"Samsung",
"Apple",
"HTC"
],
"is_objective": true
},
{
"type": "datetime",
"key": "rDate",
"full_name": "Release Date",
"format": "date: 'MMM dd, yyyy'",
"goal": "max",
"is_objective": false
}
],
"subject": "phones",
"options": [
{
"key": "1",
"name": "Samsung Galaxy S4",
"values": {
"price": 249,
"weight": 130,
"brand": "Samsung",
"rDate": "2013-04-29T00:00:00Z"
}
},
{
"key": "2",
"name": "Apple iPhone 5",
"values": {
"price": 349,
"weight": 112,
"brand": "Apple",
"rDate": "2012-09-21T00:00:00Z"
}
},
{
"key": "3",
"name": "HTC One",
"values": {
"price": 299,
"weight": 112,
"brand": "HTC",
"rDate": "2013-03-01T00:00:00Z"
}
},
{
"key": "4",
"name": "Samsung Galaxy S5",
"values": {
"price": 349,
"weight": 135,
"brand": "Samsung",
"rDate": "2014-04-29T00:00:00Z"
}
},
{
"key": "5",
"name": "Apple iPhone 6",
"values": {
"price": 399,
"weight": 118,
"brand": "Apple",
"rDate": "2013-09-21T00:00:00Z"
}
},
{
"key": "6",
"name": "Apple iPhone 7",
"values": {
"price": 499,
"weight": 118,
"brand": "Apple",
"rDate": "2014-09-21T00:00:00Z"
}
},
{
"key": "7",
"name": "Sony Xperia",
"values": {
"price": 199,
"weight": 120,
"brand": "Sony",
"rDate": "2014-08-21T00:00:00Z"
}
}
]
},
"resolution": {
"solutions": [
{
"solution_ref": "1",
"status": "FRONT"
},
{
"solution_ref": "2",
"status": "FRONT"
},
{
"solution_ref": "3",
"status": "FRONT"
},
{
"solution_ref": "4",
"status": "EXCLUDED"
},
{
"solution_ref": "5",
"status": "EXCLUDED"
},
{
"solution_ref": "6",
"status": "INCOMPLETE",
"status_cause": {
"message": "A column of a option is out of range. Option \"6\" has a value in column \"price\" which is:\"499\" while the column range\" is: [0.0,400.0]",
"error_code": "RANGE_MISMATCH",
"tokens": [
"price",
"499",
"[0.0,400.0]"
]
}
},
{
"solution_ref": "7",
"status": "DOES_NOT_MEET_PREFERENCE",
"status_cause": {
"message": "Option \"7\" has a value that does not meet preference for column \"brand\"",
"error_code": "DOES_NOT_MEET_PREFERENCE",
"tokens": [
"brand"
]
}
}
]
}
}
どこを見ればいいか?
code>resolutionという値がJSONの中に含まれています。
この値の中に、それぞれのoptionsが条件に一致するものか否かが格納されています。
resolutionのみjqでピックアップした例
$ curl -X POST --user YOUR_USERNAME:YOUR_PASSWORD --header "Content-Type: application/json" --data @problem.json "https://gateway.watsonplatform.net/tradeoff-analytics/api/v1/dilemmas?generate_visualization=false | jq ".resolution"
{
"solutions": [
{
"solution_ref": "1",
"status": "FRONT"
},
{
"solution_ref": "2",
"status": "FRONT"
},
{
"solution_ref": "3",
"status": "FRONT"
},
{
"solution_ref": "4",
"status": "EXCLUDED"
},
{
"solution_ref": "5",
"status": "EXCLUDED"
},
{
"solution_ref": "6",
"status": "INCOMPLETE",
"status_cause": {
"message": "A column of a option is out of range. Option \"6\" has a value in column \"price\" which is:\"499\" while the column range\" is: [0.0,400.0]",
"error_code": "RANGE_MISMATCH",
"tokens": [
"price",
"499",
"[0.0,400.0]"
]
}
},
{
"solution_ref": "7",
"status": "DOES_NOT_MEET_PREFERENCE",
"status_cause": {
"message": "Option \"7\" has a value that does not meet preference for column \"brand\"",
"error_code": "DOES_NOT_MEET_PREFERENCE",
"tokens": [
"brand"
]
}
}
]
}
各項目のstatusというパラメータを確認することで、検索条件に一致するものか否かを確認できます。
- Front
- 条件に一致する選択肢
- Excluded
- 条件に一致しない選択肢
- Incomplete / DOES_NOT_MEET_PREFERENCE
- optionsのパラメータに問題があり、判定できなかった選択肢
上記の例の場合、以下の3台が検索候補に一致すると判断されています。
- ID:1 – Samsung Galaxy S4
- ID:2 – Apple iPhone 5
- ID:3 – HTC One
日本語は使えるのか?
「すごいのはわかったけど、日本語認識しないなら用はないかな」という人もいるんじゃないでしょうか。安心してください。日本語もちゃんと動きます。
SamsungとAppleを日本語表記にしたサンプル
念のため、存在しない値をわざと追加しておきます。
{
"subject": "phones",
"columns": [
{
"key": "price",
"type": "numeric",
"goal": "min",
"is_objective": true,
"full_name": "Price",
"range": {
"low": 0,
"high": 400
},
"format": "number:2"
},
{
"key": "weight",
"type": "numeric",
"goal": "min",
"is_objective": true,
"full_name": "Weight",
"format": "number:0"
},
{
"key": "brand",
"type": "categorical",
"goal": "min",
"is_objective": true,
"full_name": "Brand",
"range": [
"アップル",
"HTC",
"サムスン",
"Sony"
],
"preference": [
"サムスン",
"アップル",
"HTC"
]
},
{
"key": "rDate",
"type": "datetime",
"goal": "max",
"full_name": "Release Date",
"format": "date: 'MMM dd, yyyy'"
}
],
"options": [
{
"key": "1",
"name": "サムスン Galaxy S4",
"values": {
"price": 249,
"weight": 130,
"brand": "サムスン",
"rDate": "2013-04-29T00:00:00Z"
}
},
{
"key": "2",
"name": "アップル iPhone 5",
"values": {
"price": 349,
"weight": 112,
"brand": "アップル",
"rDate": "2012-09-21T00:00:00Z"
}
},
{
"key": "3",
"name": "HTC One",
"values": {
"price": 299,
"weight": 112,
"brand": "HTC",
"rDate": "2013-03-01T00:00:00Z"
}
},
{
"key": "4",
"name": "サムスン Galaxy S5",
"values": {
"price": 349,
"weight": 135,
"brand": "サムスン",
"rDate": "2014-04-29T00:00:00Z"
}
},
{
"key": "5",
"name": "アップル iPhone 6",
"values": {
"price": 399,
"weight": 118,
"brand": "アップル",
"rDate": "2013-09-21T00:00:00Z"
}
},
{
"key": "6",
"name": "アップル iPhone 7",
"values": {
"price": 499,
"weight": 118,
"brand": "アップル",
"rDate": "2014-09-21T00:00:00Z"
}
},
{
"key": "7",
"name": "Sony Xperia",
"values": {
"price": 199,
"weight": 120,
"brand": "Sony",
"rDate": "2014-08-21T00:00:00Z"
}
},
{
"key": "8",
"name": "失敗するサンプル",
"values": {
"price": 199,
"weight": 120,
"brand": "エラー",
"rDate": "2014-08-21T00:00:00Z"
}
}
]
}
日本語が混ざった場合の結果
ちゃんと日本語を認識して、columnsで定義されていないbrandを指定した8番目のアイテムにはエラーを返しています。
$ curl -X POST --user YOUR_USERNAME:YOUR_PASSWORD --header "Content-Type: application/json" --data @problem.json "https://gateway.watsonplatform.net/tradeoff-analytics/api/v1/dilemmas?generate_visualization=false | jq ".resolution"
{
"solutions": [
{
"solution_ref": "1",
"status": "FRONT"
},
{
"solution_ref": "2",
"status": "FRONT"
},
{
"solution_ref": "3",
"status": "FRONT"
},
{
"solution_ref": "4",
"status": "EXCLUDED"
},
{
"solution_ref": "5",
"status": "EXCLUDED"
},
{
"solution_ref": "6",
"status": "INCOMPLETE",
"status_cause": {
"message": "A column of a option is out of range. Option \"6\" has a value in column \"price\" which is:\"499\" while the column range\" is: [0.0,400.0]",
"error_code": "RANGE_MISMATCH",
"tokens": [
"price",
"499",
"[0.0,400.0]"
]
}
},
{
"solution_ref": "7",
"status": "DOES_NOT_MEET_PREFERENCE",
"status_cause": {
"message": "Option \"7\" has a value that does not meet preference for column \"brand\"",
"error_code": "DOES_NOT_MEET_PREFERENCE",
"tokens": [
"brand"
]
}
},
{
"solution_ref": "8",
"status": "INCOMPLETE",
"status_cause": {
"message": "A column of a option is out of range. Option \"8\" has a value in column \"brand\" which is:\"エラー\" while the column range\" is: [\"アップル\",\"HTC\",\"サムスン\",\"Sony\"]",
"error_code": "RANGE_MISMATCH",
"tokens": [
"brand",
"エラー",
"[\"アップル\",\"HTC\",\"サムスン\",\"Sony\"]"
]
}
}
]
}