J'ai essayé de développer une application Web en utilisant Watson Developer Cloud comme support pour la présentation interne, donc ce sera un résumé et un mémorandum.
Si vous entrez un texte ou parlez et posez une question, Watson vous présentera les restaurants recommandés à partir des restaurants dans un rayon d'environ 1 km d'un certain point. Vous pouvez poser des questions telles que "Je veux manger un plat de karaage" ou "Un pub à base de poisson avec un budget allant jusqu'à 4000 yens".
Les boutiques sont affichées sous forme de liste. Le plus de ★, les restaurants les plus recommandés. Vous pouvez épingler les magasins qui vous intéressent dans la liste, alors décidez quel magasin visiter tout en vérifiant les informations sur le site Web de Guru Navi et la distance et les directions depuis votre emplacement actuel.
Si vous allez au magasin (j'y suis allé il y a longtemps, mais ce n'est pas grave), veuillez commenter vos impressions. Les résultats de la recherche seront améliorés en analysant et en apprenant le contenu des commentaires, tels que les boutiques qui peuvent être recommandées à d'autres personnes si elles sont "très délicieuses" et les boutiques qui ne peuvent pas être recommandées tant que "le commis avait une dispute".
Au début, j'ai pensé à tout construire sur Bluemix, mais je n'avais pas de niveau gratuit pour ClearDB (5 Mo), et cela signifiait également préparer un environnement de développement pour mon propre PC. ..
L'API REST préparée sur Node-RED est appelée à partir du client JS selon le cas pour afficher les résultats de la recherche et évaluer les commentaires des utilisateurs.
Imaginez les opérations suivantes.
Retrieve and Rank
curl -k -X POST -u "**username:**password**" "https://gateway.watsonplatform.net/retrieve-and-rank/api/v1/solr_clusters" -d "{\"cluster_size\":\"\",\"cluster_name\":\"WatsonRestaurantCluster\"}"
schema.xml
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<field name="shop_id" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="vote_id" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="shop_name" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="shop_name_kana" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="menu_name" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="menu_name_kana" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="latitude" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="longitude" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="shop_url" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="image_url" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="pr_text" type="string" indexed="false" stored="true" required="true" multiValued="false" />
<field name="shop_text" type="watson_text_ja" indexed="false" stored="true" required="true" multiValued="false" />
<field name="budget" type="int" indexed="true" stored="true" required="true" multiValued="false" />
schema.xml
<fieldType name="watson_text_ja" indexed="true" stored="true" class="com.ibm.watson.hector.plugins.fieldtype.WatsonTextField">
<analyzer type="index">
<tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true" tokenizerFactory="solr.JapaneseTokenizerFactory" userDictionary="lang/userdict_ja.txt"/>
<filter class="solr.JapaneseBaseFormFilterFactory"/>
<filter class="solr.CJKWidthFilterFactory"/>
<filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true" tokenizerFactory="solr.JapaneseTokenizerFactory" userDictionary="lang/userdict_ja.txt"/>
<filter class="solr.JapaneseBaseFormFilterFactory"/>
<filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt"/>
<filter class="solr.CJKWidthFilterFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt"/>
<filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
rar_documents.json
{
"id" : "5497472",
"shop_id" : "5497472",
"vote_id" : "",
"shop_name" : "Magasin Tenka Ippin Gotanda",
"shop_name_kana" : "Tenkai Pingo Tandaten",
"menu_name" : "",
"menu_name_kana" : "",
"latitude" : "35.624377",
"longitude" : "139.723394",
"shop_url" : "http://r.gnavi.co.jp/b5tzzw2g0000/",
"image_url" : "",
"pr_text" : "C'est une soupe faite en faisant bouillir du poulet et plusieurs sortes d'ingrédients au fil du temps. Il est plein de collagène bon pour la beauté et la santé.",
"shop_text" : "Magasin Tenka Ippin Gotanda. Tenkai Pingotandaten. Plats de nouilles ramen et autres. C'est une soupe riche en collagène, qui est bonne pour la beauté et la santé, et ne peut jamais être dégustée ailleurs. En outre, un menu fixe comprenant du riz à moitié frit et du soba chinois. Repas Gyoza comprenant du Gyoza, un demi-riz et du soba chinois. Nous proposons également une grande variété de menus, tels qu'un menu de service comprenant du riz semi-frit, du gyoza et du soba chinois.",
"budget" : -1
}
--Créer environ 750 éléments lors de la phase de migration initiale (aucune donnée d'apprentissage générée lorsque l'utilisateur utilise le système)
rar_training.csv
"%E3%83%AF%E3%83%83%E3%83%91%E3%83%BC","6364602.681550","2"
"%E3%82%BF%E3%82%A4%E3%82%AC%E3%83%91%E3%82%AA","7255599","1","7255599.4618610","3"
"%E5%A1%A9%E3%83%AC%E3%83%A2%E3%83%B3%E3%82%AC%E3%83%91%E3%82%AA","e584801.1192601","2","6408790.4601796","2","geyc200.4614278","4","g044108.4609358","4","6085706.1451291","1"
userdict_ja.txt
Un article au monde,Un article au monde,Un article au monde,Nomenclature personnalisée
Oiseau au goût de poulet,Oiseau au goût de poulet,Toridori Midori,Nomenclature personnalisée
Magasin de poisson Takumi Gotanda,Magasin de poisson Takumi Gotanda,Wosho Gotandaten,Nomenclature personnalisée
〆Saba,〆Saba,〆Saba,Nomenclature personnalisée
Rafute,Rafute,Rafute,Nomenclature personnalisée
synonyms.txt
biologique=>Plats médicinaux Plats bio Plats de légumes Bio
Cuisine créative créative=>Cuisine japonaise créative Nourriture créative Nourriture non nationale
italien=> italienイタリア料理 パスタ ピザ
français=> françaisフランス料理 ビストロ
Natural Language Classifier
――Il était beaucoup plus facile à utiliser que R & R. (Je ne dis pas qu'il sera jugé correctement)
nlc_training.csv
"Satisfait de l'estomac","yummy"
"Le préféré de mon fils","yummy"
"La dignité des artisans frais est également agréable","yummy"
"Gros ventre","yummy"
"Goût nostalgique","yummy"
"C'était un magasin terrible","yacky"
"La fraîcheur du sashimi était mauvaise","yacky"
"La qualité est médiocre. subtil","yacky"
"A mi-chemin et il n'y a pas de bon point","yacky"
"Pas savoureux. Ringard","yacky"
――Il a fallu plus de temps pour organiser les polices et les icônes que R & R et NLC, et pour comprendre le bootstrap et l'API Google Maps introduits avec intérêt. ――Pour affiner la recherche par budget, j'ai obtenu le montant du texte de recherche et utilisé la fonction de filtrage de Solr.
Jugement budgétaire
function getBudgets(query) {
var B_MIN = 0;
var B_MAX = 100000;
var B_RANGE = 500;
var budgets = null;
query = query.replace(/0-9/g, function(s) {
return String.fromCharCode(s.charCodeAt(0) - 0xFEE0);
});
var matches = query.match(/\d+(?=Cercle)|(De|c'est tout)|(Jusqu'à ce que|Dans|Moins que|Moins que|Pas assez)/g);
if (matches) {
var yens = matches.filter(function(y) {
if (isFinite(y)) {
return y > B_MIN && y < B_MAX
} else {
return false;
}
});
if (yens.length == 1) {
var condition;
try {
condition = matches[matches.indexOf(yens[0]) + 1];
} catch (e) {
condition = null;
}
yens = yens.map(function(y) {
return Number(y.replace(/^0+/g, ""));
});
if (condition) {
if (/De|c'est tout/g.test(condition)) {
budgets = {
budget_min: yens[0],
budget_max: B_MAX
};
} else {
budgets = {
budget_min: B_MIN,
budget_max: yens[0]
};
}
} else {
budgets = {
budget_min: yens[0] - B_RANGE,
budget_max: yens[0] + B_RANGE
};
}
} else if (yens.length >= 2) {
budgets = {
budget_min: Math.min(yens[0], yens[1]),
budget_max: Math.max(yens[0], yens[1])
};
}
}
if (budgets) {
budgets.budget_min = Math.max(B_MIN, budgets.budget_min);
budgets.budget_max = Math.min(B_MAX, budgets.budget_max);
return budgets;
} else {
return null;
}
}
--Node-RED ressemble à ce qui suit. ―― ~~ R & R ne fonctionnait pas correctement sauf s'il s'agissait d'un nœud HTTP et NLC était un nœud dédié ... ~~ J'ai écrit les informations d'identification dans le formulaire du nœud en premier lieu, mais lorsque je l'ai vérifié maintenant, si la connexion de service est définie du côté Bluemix, fonctionnera-t-elle telle quelle sur le nœud dédié?
――Java n'a pas été beaucoup touché au travail, mais c'était amusant de pouvoir faire diverses choses telles que les appels REST, JSON → DB, DB → JSON ou CSV. ――Maven of Eclipse recevait une erreur chaque fois que j'ajoutais ou supprimais une référence, et quand j'y pensais, ça guérissait soudainement et je ne suis pas sûr. ――Je pense qu'environ 3/5 du stress généré pendant le travail est causé par Maven ...
--Lors de la génération de données d'entraînement pour la création de Ranker, si vous essayez d'ajouter ou de soustraire des points pour un document qui n'est pas renvoyé pour le résultat de la recherche d'une certaine instruction de recherche, une erreur se produira dans train.py, recherchez donc Solr à partir de Java et renvoyez-le. Nous sélectionnons les documents à utiliser.
―― Il faut environ 4 à 5 jours-homme pour terminer les vacances de fin d'année et du nouvel an. ――Si vous ne considérez pas le quota gratuit, les frais de maintenance sont-ils d'environ 5000 yens / mois? (Instance Ranker1 1000 yens + instance NLC1 2000 yens + Node-RED ~ 1500 yens + API d'apprentissage) --Il y a un cadre gratuit et si c'est la seule application que vous créez, les frais de maintenance peuvent être de 0 yen (devrait?)
Je l'ai publié sur Github.
Recommended Posts