├── README.md ├── RobotArmArduinoTest.ino ├── Watson-AR-Glasses-CommandControl.r ├── Watson-AR-Glasses-Tone.ino ├── Watson-AR-Glasses-Tone.r ├── Watson-AlchemyAPI-LANGUAGE-Enrichment.R ├── Watson-AlchemyAPI-Language-Response-Time-Tester.R ├── Watson-COGNITIVE-Robot-Arm.R ├── Watson-COGNITIVE-TOYS-Boaty-McBoatface.R ├── Watson-COGNITIVE-Toys-Arduino.INO ├── Watson-CONVERSATION-Code-Backbone.R ├── Watson-CONVERSATION-Code-Snippet.R ├── Watson-Cognitive_Bartender.ino ├── Watson-Cognitive_Bartender_V1.R ├── Watson-DIALOG-R-example-functions.R ├── Watson-DIALOG-basic-R-scripts-segue-only-PUBLIC.R ├── Watson-DISCOVERY-Enriched-NEWS.R ├── Watson-EMPATHETIC-ROBOT.R ├── Watson-LANGUAGE-detect&translate.R ├── Watson-MacKenzie-R-Studio-Interface.R ├── Watson-Machine-Learning-WML-codesnippets ├── Watson-NLC-Basic-Functions.R ├── Watson-NLC-SMS-Test-Condition.R ├── Watson-NLU-Basic-Functions.R ├── Watson-PERSONALITY-INSIGHTS-analyze100speakers.R ├── Watson-PERSONALITY-INSIGHTS-codesnippet.R ├── Watson-RETRIEVE-no-rank-code-snippet.R ├── Watson-SPEECH-TO-TEXT-code-snippet.R ├── Watson-STT-NLC-TTS-WINE-demo.R ├── Watson-Speech-To-Text-Snippet-UPDATED ├── Watson-TEXT-TO-SPEECH-Code-Snippet.R ├── Watson-TEXT-TO-SPEECH-Expressive.R ├── Watson-TEXT-TO-SPEECH-Transformation-CodeSnippet.R ├── Watson-TEXT-TO-SPEECH.R ├── Watson-TONE-Code-Snippet.R ├── Watson-TWILIO-Code-Snippet.R ├── Watson-TWITTER-Birdsong.R ├── Watson-Tone-parser_stacker.R ├── Watson_R&R_Ground_Truth_CSV_Analysis_Tool.R ├── Watson_Tone_Basic_R_Response_Formatting.R ├── Watson_Tone_IAM_Authenticate.R ├── basic_R_viz_tools.R ├── bridges_r_to_watson_logo2.png ├── edge_simulate_visualize.r ├── initialize.py ├── keys.r ├── license_&_disclaimer.txt ├── presidential_speeches_clean_data.csv ├── sortinghat.csv ├── speech_capture_tone_bootstrapper.R ├── speeches.csv └── watson-wine-gt.csv /RobotArmArduinoTest.ino: -------------------------------------------------------------------------------- 1 | /// COGNITIVE LEGO - ROBOT ARM - This Arduino code is meant to be LISTENING for serial commands from R 2 | /// 3 | 4 | // #include 5 | #include 6 | 7 | int moveServo; // raw user input 8 | 9 | const int ledPin2 = 2; // the number of the LED pin 10 | const int ledPin3 = 3; // the number of the LED pin 11 | const int ledPin4 = 4; // the number of the LED pin 12 | const int ledPin5 = 5; // the number of the LED pin 13 | const int ledPin6 = 6; // the number of the LED pin 14 | const int ledPin13 = 13; // the number of the LED pin 15 | 16 | void setup() { 17 | Serial.begin(9600); 18 | Serial.println(" Arduino Serial Servo Control"); 19 | Serial.println("Press < or > to move, spacebar to center"); 20 | Serial.println(); 21 | 22 | 23 | pinMode(ledPin2, OUTPUT); 24 | pinMode(ledPin3, OUTPUT); 25 | pinMode(ledPin4, OUTPUT); 26 | pinMode(ledPin5, OUTPUT); 27 | pinMode(ledPin6, OUTPUT); 28 | pinMode(ledPin13, OUTPUT); 29 | 30 | 31 | digitalWrite(ledPin2, HIGH); 32 | digitalWrite(ledPin3, HIGH); 33 | digitalWrite(ledPin4, HIGH); 34 | digitalWrite(ledPin5, HIGH); 35 | digitalWrite(ledPin6, HIGH); 36 | digitalWrite(ledPin13, HIGH); 37 | 38 | } 39 | 40 | void loop() { 41 | // wait for serial input 42 | if (Serial.available() > 0) { 43 | moveServo = Serial.read(); // read the incoming byte: 44 | 45 | 46 | 47 | 48 | ////// LEDS AND MOTORS 49 | 50 | if (moveServo == 97) // 'a' is Claw Close 51 | { 52 | digitalWrite(ledPin13, LOW); // this is for the polarity of volatage 53 | digitalWrite(ledPin2, LOW); /// CLAW 54 | delay(1000); 55 | digitalWrite(ledPin2, HIGH); // RESTORE 56 | } 57 | 58 | 59 | if (moveServo == 122) // 'z' is Claw Open 60 | { 61 | digitalWrite(ledPin13, HIGH); // this is for the polarity of volatage 62 | digitalWrite(ledPin2, LOW); /// CLAW 63 | delay(1000); 64 | digitalWrite(ledPin2, HIGH); // RESTORE 65 | } 66 | 67 | 68 | if (moveServo == 115) // 's' is Wrist CLose 69 | { 70 | digitalWrite(ledPin13, LOW); // this is for the polarity of volatage 71 | digitalWrite(ledPin3, LOW); /// CLAW 72 | delay(1000); 73 | digitalWrite(ledPin3, HIGH); // RESTORE 74 | } 75 | 76 | 77 | if (moveServo == 120) // 'x' is Wrist Open 78 | { 79 | digitalWrite(ledPin13, HIGH); // this is for the polarity of volatage 80 | digitalWrite(ledPin3, LOW); /// CLAW 81 | delay(1000); 82 | digitalWrite(ledPin3, HIGH); // RESTORE 83 | } 84 | 85 | 86 | if (moveServo == 100) // 'd' is Elbow Close 87 | { 88 | digitalWrite(ledPin13, LOW); // this is for the polarity of volatage 89 | digitalWrite(ledPin4, LOW); /// CLAW 90 | delay(1000); 91 | digitalWrite(ledPin4, HIGH); // RESTORE 92 | } 93 | 94 | 95 | if (moveServo == 99) // 'c' is Elbow Open 96 | { 97 | digitalWrite(ledPin13, HIGH); // this is for the polarity of volatage 98 | digitalWrite(ledPin4, LOW); /// CLAW 99 | delay(1000); 100 | digitalWrite(ledPin4, HIGH); // RESTORE 101 | } 102 | 103 | 104 | if (moveServo == 102) // 'f' is SHoulder Close 105 | { 106 | digitalWrite(ledPin13, LOW); // this is for the polarity of volatage 107 | digitalWrite(ledPin5, LOW); /// 108 | delay(1000); 109 | digitalWrite(ledPin5, HIGH); // RESTORE 110 | } 111 | 112 | 113 | if (moveServo == 118) // 'v' is Shoulder Open 114 | { 115 | digitalWrite(ledPin13, HIGH); // this is for the polarity of volatage 116 | digitalWrite(ledPin5, LOW); /// 117 | delay(1000); 118 | digitalWrite(ledPin5, HIGH); // RESTORE 119 | } 120 | 121 | 122 | if (moveServo == 103) // 'g' is ROtate Left 123 | { 124 | digitalWrite(ledPin13, LOW); // this is for the polarity of volatage 125 | digitalWrite(ledPin6, LOW); /// CLAW 126 | delay(1000); 127 | digitalWrite(ledPin6, HIGH); // RESTORE 128 | } 129 | 130 | 131 | if (moveServo == 98) // 'b' is ROtate RIght 132 | { 133 | digitalWrite(ledPin13, HIGH); // this is for the polarity of volatage 134 | digitalWrite(ledPin6, LOW); /// 135 | delay(1000); 136 | digitalWrite(ledPin6, HIGH); // RESTORE 137 | } 138 | 139 | 140 | if (moveServo == 32) // ' ' is space for reset // 141 | { 142 | digitalWrite(ledPin13, HIGH); // this is for the polarity of volatage - each cycle 143 | 144 | // OK - crude way to cycle through the relays for 2,3,4,5,6, 145 | digitalWrite(ledPin2, LOW); /// CLAW 146 | delay(1000); 147 | digitalWrite(ledPin2, HIGH); // WRIST restore this before moving on 148 | digitalWrite(ledPin3, LOW); // pull low to activate for 1 second 149 | delay(1000); 150 | digitalWrite(ledPin3, HIGH); // ELBOW 151 | digitalWrite(ledPin4, LOW); 152 | delay(1000); 153 | digitalWrite(ledPin4, HIGH); // SHOULDER 154 | digitalWrite(ledPin5, LOW); 155 | delay(1000); 156 | digitalWrite(ledPin5, HIGH); // WAIST 157 | digitalWrite(ledPin6, LOW); // 158 | delay(1000); 159 | digitalWrite(ledPin6, HIGH); // restore before moving on 160 | } 161 | 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /Watson-AR-Glasses-Tone.ino: -------------------------------------------------------------------------------- 1 | //###################################################### 2 | //### ARDUINO CODE - Driver For Eyes and Lights 3 | //### Experimental Code. If you get 'resource is busy' just unplug and 'detach' from R python code 4 | //###################################################### 5 | 6 | #include 7 | 8 | int listenSerial; // raw user input 9 | 10 | void setup() { 11 | Serial.begin(9600); 12 | Serial.println(" Arduino Serial Servo Control"); 13 | Serial.println("Press < or > to move, spacebar to center"); 14 | Serial.println(); 15 | 16 | 17 | // LEDs 18 | pinMode(2, OUTPUT); // on/off for LED - 1 on 19 | pinMode(3, OUTPUT); // on/off for LED - 1 on 20 | pinMode(4, OUTPUT); // on/off for LED - 1 on 21 | pinMode(5, OUTPUT); // on/off for LED - 1 on 22 | pinMode(6, OUTPUT); // on/off for LED - 1 on 23 | pinMode(10, OUTPUT); // on/off for RELAY X 24 | 25 | digitalWrite(2, LOW); // active high is not closed 26 | digitalWrite(3, LOW); // active high is not closed 27 | digitalWrite(4, LOW); // active high is not closed 28 | digitalWrite(5, LOW); // active high is not closed 29 | digitalWrite(6, LOW); // active high is not closed 30 | digitalWrite(10, LOW); // active high is not closed 31 | 32 | } 33 | 34 | void loop() { 35 | // wait for serial input 36 | if (Serial.available() > 0) { 37 | // read the incoming byte: 38 | listenSerial = Serial.read(); 39 | 40 | // we really shoudl use SWITCH here or CASE 41 | 42 | if (listenSerial == 114) { digitalWrite(2, HIGH); } // r RED 43 | if (listenSerial == 103) { digitalWrite(3, HIGH); } // g GREEN 44 | if (listenSerial == 98) { digitalWrite(4, HIGH); } // b BLUE 45 | if (listenSerial == 119) { digitalWrite(5, HIGH); } // w WHITE (not on headset) 46 | if (listenSerial == 121) { digitalWrite(6, HIGH); } // y YELLOW 47 | 48 | if (listenSerial == 32) // SPACE CLEARS EVERYTHING 49 | { 50 | digitalWrite(2, LOW); // all leds off 51 | digitalWrite(3, LOW); 52 | digitalWrite(4, LOW); 53 | digitalWrite(5, LOW); 54 | digitalWrite(6, LOW); 55 | } 56 | 57 | if (listenSerial == 120) { 58 | digitalWrite(10, HIGH); 59 | delay(3000); // wait 3 seconds - this is the 'super move - that closes the RELAY to turn on the high current LED strips 60 | digitalWrite(10, LOW); 61 | } // x ASCII x is 120 62 | 63 | 64 | } 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /Watson-AlchemyAPI-Language-Response-Time-Tester.R: -------------------------------------------------------------------------------- 1 | 2 | ###################################################### 3 | ### IBM Watson - Alchemy API - Calls Remaining check and latency check 4 | ###################################################### 5 | 6 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 7 | library(httr) 8 | library(XML) 9 | library(stringr) 10 | 11 | ### Simple test - no trasaction - simply asking how m 12 | test_count <- 20 # number of tests to run 13 | time <- matrix(0, ncol = 1, nrow = test_count) 14 | for (i in 1:test_count){ 15 | ptm <- proc.time() 16 | GET(url=paste("http://gateway-a.watsonplatform.net/calls/info/GetAPIKeyInfo?apikey=<>&outputMode=json")) 17 | temp <- proc.time() - ptm 18 | time[i] <- temp[3] 19 | } 20 | 21 | time 22 | summary(time) 23 | 24 | # Response looks like this: 25 | # Date: 2016-03-29 00:21 26 | # Status: 200 27 | # Content-Type: text/plain; charset=utf-8 28 | # Size: 105 B 29 | # { 30 | # "status": "OK", 31 | # "consumedDailyTransactions": "0", 32 | # "dailyTransactionLimit": "100000" 33 | 34 | ############################### 35 | 36 | ## TESTING - Response on Basic Sentiment? - FROM URL - SO WILL TAKE LONGER BECAUSE OF URL RETRIEVE STEP 37 | alchemy_url <- "http://gateway-a.watsonplatform.net/calls/url/" 38 | api_feature <- "URLGetTextSentiment" 39 | the_url <- "https://dreamtolearn.com/node/8OVIWY2C5RLZZSYD9OHCKM8AI/80" 40 | api_key <- "<>" # alchemy API secret key 41 | output_mode <- "json" 42 | query <- paste(alchemy_url,api_feature,"?url=",the_url,"&apikey=",api_key,"&outputMode=",output_mode, sep="") 43 | query 44 | POST(query) 45 | 46 | 47 | time <- matrix(0, ncol = 1, nrow = test_count) 48 | for (i in 1:test_count){ 49 | ptm <- proc.time() 50 | response <- POST(query) 51 | temp <- proc.time() - ptm 52 | time[i] <- temp[3] 53 | } 54 | 55 | time 56 | summary(time) # for me 57 | # Min. :0.1850 58 | # 1st Qu.:0.1965 59 | # Median :0.2075 60 | # Mean :0.3887 61 | # 3rd Qu.:0.6520 62 | # Max. :0.8390 63 | 64 | 65 | ########################## MAIN TEST! 66 | 67 | ## TESTING - Response on Basic Sentiment? - FROM TEXT (provided - should be faster) 68 | alchemy_url <- "http://gateway-a.watsonplatform.net/calls/text/" 69 | api_feature <- "TextGetRankedKeywords" 70 | api_key <- "<>" # alchemy API secret key 71 | output_mode <- "json" 72 | text <- URLencode("I like pink ice cream and red boots") 73 | query <- paste(alchemy_url,api_feature,"?text=",text,"&apikey=",api_key,"&outputMode=",output_mode, sep="") 74 | query 75 | POST(query) 76 | 77 | test_count <- 1000 78 | time <- matrix(0, ncol = 1, nrow = test_count) 79 | for (i in 1:test_count){ 80 | ptm <- proc.time() 81 | response <- POST(query) 82 | temp <- proc.time() - ptm 83 | time[i] <- temp[3] 84 | } 85 | 86 | time 87 | summary(time) # for me - on my residential grade WIFI in the hills of East Bay - 96ms to 250ms 88 | # Min. :0.09600 89 | # 1st Qu.:0.09875 90 | # Median :0.10150 91 | # Mean :0.13710 92 | # 3rd Qu.:0.19075 93 | # Max. :0.25800 94 | 95 | ## LETS PLOT: 96 | plot(time[,1],main="Response Time - AlchemyAPI Text Keywords \n from SFO Residential Location with WIFI") 97 | hist(time[,1],breaks=100,main="Response Time - AlchemyAPI Text Keywords \n from SFO Residential Location with WIFI") 98 | 99 | 100 | ########## what if we do XML (default, rather than JSON?) - seems pretty similar (removed test) 101 | -------------------------------------------------------------------------------- /Watson-COGNITIVE-Robot-Arm.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Boaty McBoatFace - Chatting with Cognitive Toys 3 | ### Experimental Code. Experimental R Interface for IBM Watson Services - 4 | ### PART 1 - We have a speech interface that determines user intent from IBM Watson Speech to Text and NLC services 5 | ### PART 2 - We engage PYTHON scripts (serial made easier) from R Studio 6 | ### PART 3 - Python Calls Arduino and Modifies Boaty McBoatface 7 | ### DOCS: https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/speech-to-text/ 8 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) STT/NLC and TTS Services stood up (3) Credentials to each Service 9 | ###################################################### 10 | 11 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 12 | library(httr) 13 | library(audio) 14 | library(data.table) 15 | library(dplyr) 16 | library(reshape2) 17 | library(Rtts) 18 | library(splitstackshape) 19 | library(seewave) # need to play wav back? 20 | library(stringr) 21 | library(splitstackshape) 22 | library(tidyr) 23 | library(XML) 24 | library(png) 25 | library(rPython) 26 | 27 | closeAllConnections() 28 | 29 | setwd("/Users/ryan/Documents/Project_Boaty_McBoatFace") # Set working Directory 30 | getwd() 31 | source("keys.r") ## KEYS has acutal username:password for each IBM service. Seperate R file looks sort of like below 32 | 33 | boaty_mcboatface_test() # test function from other side 34 | 35 | ## Base URLs for IBM Watson APIs 36 | base_url_STT <- "https://stream.watsonplatform.net/speech-to-text/api" 37 | base_url_NLC = "https://gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers/" 38 | base_url_TTS <- "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" 39 | 40 | getURL(base_url_NLC,userpwd = username_password_NLC ) # non essential , but checks if working /authenticated 41 | 42 | # For audio Sampling later 43 | sample_count <- 40000 ## 0k samples 44 | sample_rate <- 16000 ## at 16khz - is ~5 seconds recording time 45 | 46 | ########## FUNCTION DECLARATIONS #### FUNCTION DECLARATIONS ########### 47 | ########## FUNCTION DECLARATIONS #### FUNCTION DECLARATIONS ########### 48 | 49 | ### STT FUNCTION to test connectivity and return models available 50 | watson.STT.getmodels <- function() 51 | {return(GET(url=paste(base_url_STT,"/v1/models",sep=""), 52 | authenticate(username_STT,password_STT)))} 53 | ### FOR BEST RESULTS - USE USB HEADSET and ensure in MAc > Sys Preferences >Sound it's selected 54 | response <- watson.STT.getmodels() 55 | content(response) 56 | 57 | ## STT FUNCTION - Record! 58 | watson.STT.record <- function(samp_count,samp_rate) 59 | { 60 | # record 8000 samples at 8000Hz (1 sec), mono (1 channel) 61 | # record 64k samples at 16kHz (4 sec), mono (1 channel), stereo = 2 62 | a <- record(samp_count, samp_rate, 2) 63 | wait(a) # wait for the recording to finish 64 | x <- a$data # get the result 65 | x[1:10] # show first ten samples 66 | close(a); rm(a) # you can close the instance at this point 67 | # amplify and crop the signal 68 | audio <- x * 2 69 | audio[audio < -1] <- -1 70 | audio[audio > 1] <- 1 71 | return(audio) 72 | } 73 | 74 | 75 | #### STT FUNCTION TO TIDY UP the STT response - just export the TRANSCRIPT ONLY 76 | stt_transcript_only <- function(raw) 77 | { 78 | data <- as.data.frame(strsplit(as.character(raw),"\\n")) 79 | data <- data[c(7), ] # for now, grab just what we want 80 | data <- paste(data) # kill levels, - fyi this nukes confidence % info (may want later) 81 | data <- gsub(" ","",data) # remove excessive whitespace 0 cannot use ALL [[punct]] here 82 | data <- gsub("\\\\","",data) # remove punct we dont like 83 | data <- gsub("\"","",data) # remove punct we dont like 84 | data <- gsub("transcript","",data) # remove excessive whitespace 85 | data <- gsub(":","",data) # remove excessive whitespace - later: Improve this tidy step. 86 | return(data) 87 | } 88 | 89 | 90 | ###### STT FUNCTION - ANalyze AUDIO WAV file with IBM Watson Speech to Text service - SESSIONLESS 91 | watson.speech_to_text.recognize <- function(audio_file) 92 | { return(POST(url=paste(base_url_STT,"/v1/recognize",sep=""), 93 | authenticate(username_STT,password_STT), 94 | add_headers("Content-Type"="audio/wav"), 95 | body = (file = upload_file(audio_file)) 96 | ))} #works # hope this helps you with syntax! 97 | ## this is SESSIONLESS MODE - https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/#!/speech-to-text/recognizeSessionless 98 | 99 | 100 | ##### STT FUNCTION FOR SPEECH TO TEXT - RETURNS TRANSCRIPT - SESSIONLESS 101 | watson.speech_to_text.sessionless <- function(file_name) 102 | { 103 | wait(play(sin(1:200/4))) # recording START tone 104 | print("RECORDING ------------------ (beep) ") 105 | the_audio <- watson.STT.record(sample_count,sample_rate) 106 | wait(play(sin(1:200/2))) # recording STOP tone 107 | print("Recording COMPLETE --------- (beep) ") 108 | #print("Saving WAV File") 109 | save.wave(the_audio,file_name) 110 | print("Calling IBM Watson Speech To Text API") 111 | response <- watson.speech_to_text.recognize(file_name) 112 | return(stt_transcript_only(content(response,"text"))) 113 | } 114 | 115 | ####### TTS Function to list voices 116 | watson.TTS.listvoices <- function() 117 | { 118 | voices <- GET(url=paste("https://stream.watsonplatform.net/text-to-speech/api/v1/voices"),authenticate(username_TTS,password_TTS)) 119 | data <- content(voices,"text") 120 | data <- as.data.frame(strsplit(as.character(data),"name")) 121 | data <- data[-c(1:2), ] # remove dud first row 122 | data <- strsplit(as.character(data),",") 123 | data <- data.frame(matrix(data)) 124 | colnames(data) <- "V1" 125 | data <- cSplit(data, 'V1', sep="\"", type.convert=FALSE) 126 | data <- data.frame(data$V1_04) 127 | data[,1] <- gsub("\\\\","",data[,1] ) 128 | return(data) } 129 | 130 | watson.TTS.listvoices() 131 | 132 | 133 | ######## TTS FUNCTION --- TEXT TO SPEECH 134 | watson.TTS.execute <- function(url1,text1,voice1,filename1) 135 | { 136 | the_audio = CFILE(filename1, mode="wb") 137 | curlPerform(url = paste(url1,"?text=",text1,"&voice=",voice1,sep=""), 138 | userpwd = username_password_TTS, 139 | httpheader=c(accept="audio/wav"), 140 | writedata = the_audio@ref) 141 | close(the_audio) 142 | system(paste("open",filename1,"-a vlc")) 143 | } 144 | 145 | ## Function boaty speaks 146 | boaty_speaks <- function(voice_transcript) 147 | { 148 | voice <- "en-US_AllisonVoice" 149 | the_url <- paste(base_url_TTS,"?text=",URLencode(voice_transcript),"&voice=",voice,sep="") 150 | the_audio = CFILE("toy_talks.wav", mode="wb") ## here we receive the audio back 151 | curlPerform(url = the_url,userpwd = username_password_TTS,httpheader=c(accept="audio/wav"),writedata = the_audio@ref) 152 | close(the_audio) 153 | system("open toy_talks.wav -a vlc") # Now - Let's listen 154 | wait(5) ## this gives ECHO some time to use the WiFI and not fight for bandwidth 155 | } 156 | 157 | 158 | ###### PYTHON TEST - ## thanks http://www.r-bloggers.com/calling-python-from-r-with-rpython/ 159 | boaty_mcboatface_test <- function(){ 160 | python.load("initialize.py", get.exception = TRUE) 161 | Sys.sleep(1) 162 | python.exec("ser.write(' ')") 163 | Sys.sleep(1) 164 | # python.exec("ser.write('l')") 165 | # Sys.sleep(1) 166 | # python.exec("ser.write('r')") 167 | # Sys.sleep(1) 168 | # python.exec("ser.write('c')") 169 | # Sys.sleep(1) 170 | # python.exec("ser.write(' ')") 171 | } 172 | 173 | ## test 174 | #boaty_mcboatface_test() 175 | 176 | ###### 177 | closeAllConnections() 178 | file_name <- "file_name" 179 | #watson.speech_to_text.sessionless("test.wav") 180 | 181 | img <- readPNG("ibm_watson.png") 182 | grid::grid.raster(img) 183 | 184 | repeat 185 | { 186 | response <- watson.speech_to_text.sessionless("test.wav") 187 | #print(response) 188 | # if(grepl("reset", response)){python.exec("ser.write(' ')")} 189 | 190 | if(grepl("pinch", response)){python.exec("ser.write('a')")} 191 | if(grepl("release", response)){python.exec("ser.write('z')")} 192 | 193 | if(grepl("curl", response)){python.exec("ser.write('s')")} # 194 | if(grepl("wave", response)){python.exec("ser.write('x')")} # 195 | 196 | if(grepl("elbow", response)){python.exec("ser.write('c')")} # 197 | if(grepl("extend", response)){python.exec("ser.write('d')")} # 198 | 199 | if(grepl("shoulder", response)){python.exec("ser.write('f')")} # 200 | if(grepl("salute", response)){python.exec("ser.write('v')")} # 201 | 202 | if(grepl("right", response)){python.exec("ser.write('g')")} # 203 | if(grepl("left", response)){python.exec("ser.write('b')")} # 204 | 205 | 206 | 207 | #if(grepl("cross", response)){python.exec("ser.write('c')")} 208 | #if(grepl("start", response)){python.exec("ser.write('a')")} 209 | #if(grepl("go", response)){python.exec("ser.write('a')")} 210 | #if(grepl("stop", response)){python.exec("ser.write('z')")} 211 | #if(grepl("off", response)){python.exec("ser.write('z')")} 212 | #if(grepl("red", response)){python.exec("ser.write('2')")} 213 | #if(grepl("dark", response)){python.exec("ser.write('0')")} 214 | #if(grepl("black", response)){python.exec("ser.write('0')")} 215 | if(grepl("talk", response)){boaty_speaks("Hello, My name is MacKenzie! Let's be friends. OK?")} 216 | 217 | } 218 | 219 | 220 | ###### STT FUNCTION - ANalyze AUDIO WAV file with IBM Watson Speech to Text service - SESSIONLESS 221 | # watson.speech_to_text.recognize <- function(audio_file) 222 | # { return(POST(url=paste(base_url_STT,"/v1/recognize",sep=""), 223 | # authenticate(username_STT,password_STT), 224 | # add_headers("Content-Type"="audio/wav"), 225 | # body = (file = upload_file(audio_file)) 226 | # ))} #works # hope this helps you with syntax! 227 | ## this is SESSIONLESS MODE - https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/#!/speech-to-text/recognizeSessionless 228 | 229 | getwd() 230 | 231 | 232 | -------------------------------------------------------------------------------- /Watson-COGNITIVE-TOYS-Boaty-McBoatface.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Boaty McBoatFace - Chatting with Cognitive Toys 3 | ### Experimental Code. Experimental R Interface for IBM Watson Services - 4 | ### PART 1 - We have a speech interface that determines user intent from IBM Watson Speech to Text and NLC services 5 | ### PART 2 - We engage PYTHON scripts (serial made easier) from R Studio 6 | ### PART 3 - Python Calls Arduino and Modifies Boaty McBoatface 7 | ### DOCS: https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/speech-to-text/ 8 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) STT/NLC and TTS Services stood up (3) Credentials to each Service 9 | ###################################################### 10 | 11 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 12 | library(httr) 13 | library(audio) 14 | library(data.table) 15 | library(dplyr) 16 | library(reshape2) 17 | library(Rtts) 18 | library(splitstackshape) 19 | library(seewave) # need to play wav back? 20 | library(stringr) 21 | library(splitstackshape) 22 | library(tidyr) 23 | library(XML) 24 | library(png) 25 | library(rPython) 26 | 27 | closeAllConnections() 28 | 29 | setwd("/Users/ryan/Documents/Project_Boaty_McBoatFace") # Set working Directory 30 | getwd() 31 | source("keys.r") ## KEYS has acutal username:password for each IBM service. Seperate R file looks sort of like below 32 | 33 | boaty_mcboatface_test() # test function from other side 34 | 35 | ## Base URLs for IBM Watson APIs 36 | base_url_STT <- "https://stream.watsonplatform.net/speech-to-text/api" 37 | base_url_NLC = "https://gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers/" 38 | base_url_TTS <- "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" 39 | 40 | getURL(base_url_NLC,userpwd = username_password_NLC ) # non essential , but checks if working /authenticated 41 | 42 | # For audio Sampling later 43 | sample_count <- 40000 ## 0k samples 44 | sample_rate <- 16000 ## at 16khz - is ~5 seconds recording time 45 | 46 | ########## FUNCTION DECLARATIONS #### FUNCTION DECLARATIONS ########### 47 | ########## FUNCTION DECLARATIONS #### FUNCTION DECLARATIONS ########### 48 | 49 | ### STT FUNCTION to test connectivity and return models available 50 | watson.STT.getmodels <- function() 51 | {return(GET(url=paste(base_url_STT,"/v1/models",sep=""), 52 | authenticate(username_STT,password_STT)))} 53 | ### FOR BEST RESULTS - USE USB HEADSET and ensure in MAc > Sys Preferences >Sound it's selected 54 | 55 | 56 | ## STT FUNCTION - Record! 57 | watson.STT.record <- function(samp_count,samp_rate) 58 | { 59 | # record 8000 samples at 8000Hz (1 sec), mono (1 channel) 60 | # record 64k samples at 16kHz (4 sec), mono (1 channel), stereo = 2 61 | a <- record(samp_count, samp_rate, 2) 62 | wait(a) # wait for the recording to finish 63 | x <- a$data # get the result 64 | x[1:10] # show first ten samples 65 | close(a); rm(a) # you can close the instance at this point 66 | # amplify and crop the signal 67 | audio <- x * 2 68 | audio[audio < -1] <- -1 69 | audio[audio > 1] <- 1 70 | return(audio) 71 | } 72 | 73 | 74 | #### STT FUNCTION TO TIDY UP the STT response - just export the TRANSCRIPT ONLY 75 | stt_transcript_only <- function(raw) 76 | { 77 | data <- as.data.frame(strsplit(as.character(raw),"\\n")) 78 | data <- data[c(7), ] # for now, grab just what we want 79 | data <- paste(data) # kill levels, - fyi this nukes confidence % info (may want later) 80 | data <- gsub(" ","",data) # remove excessive whitespace 0 cannot use ALL [[punct]] here 81 | data <- gsub("\\\\","",data) # remove punct we dont like 82 | data <- gsub("\"","",data) # remove punct we dont like 83 | data <- gsub("transcript","",data) # remove excessive whitespace 84 | data <- gsub(":","",data) # remove excessive whitespace - later: Improve this tidy step. 85 | return(data) 86 | } 87 | 88 | 89 | ###### STT FUNCTION - ANalyze AUDIO WAV file with IBM Watson Speech to Text service - SESSIONLESS 90 | watson.speech_to_text.recognize <- function(audio_file) 91 | { return(POST(url=paste(base_url_STT,"/v1/recognize",sep=""), 92 | authenticate(username_STT,password_STT), 93 | add_headers("Content-Type"="audio/wav"), 94 | body = (file = upload_file(audio_file)) 95 | ))} #works # hope this helps you with syntax! 96 | ## this is SESSIONLESS MODE - https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/#!/speech-to-text/recognizeSessionless 97 | 98 | 99 | ##### STT FUNCTION FOR SPEECH TO TEXT - RETURNS TRANSCRIPT - SESSIONLESS 100 | watson.speech_to_text.sessionless <- function(file_name) 101 | { 102 | wait(play(sin(1:200/4))) # recording START tone 103 | print("RECORDING ------------------ (beep) ") 104 | the_audio <- watson.STT.record(sample_count,sample_rate) 105 | wait(play(sin(1:200/2))) # recording STOP tone 106 | print("Recording COMPLETE --------- (beep) ") 107 | #print("Saving WAV File") 108 | save.wave(the_audio,file_name) 109 | print("Calling IBM Watson Speech To Text API") 110 | response <- watson.speech_to_text.recognize(file_name) 111 | return(stt_transcript_only(content(response,"text"))) 112 | } 113 | 114 | ####### TTS Function to list voices 115 | watson.TTS.listvoices <- function() 116 | { 117 | voices <- GET(url=paste("https://stream.watsonplatform.net/text-to-speech/api/v1/voices"),authenticate(username_TTS,password_TTS)) 118 | data <- content(voices,"text") 119 | data <- as.data.frame(strsplit(as.character(data),"name")) 120 | data <- data[-c(1:2), ] # remove dud first row 121 | data <- strsplit(as.character(data),",") 122 | data <- data.frame(matrix(data)) 123 | colnames(data) <- "V1" 124 | data <- cSplit(data, 'V1', sep="\"", type.convert=FALSE) 125 | data <- data.frame(data$V1_04) 126 | data[,1] <- gsub("\\\\","",data[,1] ) 127 | return(data) } 128 | 129 | watson.TTS.listvoices() 130 | 131 | 132 | ######## TTS FUNCTION --- TEXT TO SPEECH 133 | watson.TTS.execute <- function(url1,text1,voice1,filename1) 134 | { 135 | the_audio = CFILE(filename1, mode="wb") 136 | curlPerform(url = paste(url1,"?text=",text1,"&voice=",voice1,sep=""), 137 | userpwd = username_password_TTS, 138 | httpheader=c(accept="audio/wav"), 139 | writedata = the_audio@ref) 140 | close(the_audio) 141 | system(paste("open",filename1,"-a vlc")) 142 | } 143 | 144 | ## Function boaty speaks 145 | boaty_speaks <- function(voice_transcript) 146 | { 147 | voice <- "en-US_MichaelVoice" 148 | the_url <- paste(base_url_TTS,"?text=",URLencode(voice_transcript),"&voice=",voice,sep="") 149 | the_audio = CFILE("toy_talks.wav", mode="wb") ## here we receive the audio back 150 | curlPerform(url = the_url,userpwd = username_password_TTS,httpheader=c(accept="audio/wav"),writedata = the_audio@ref) 151 | close(the_audio) 152 | system("open toy_talks.wav -a vlc") # Now - Let's listen 153 | wait(5) ## this gives ECHO some time to use the WiFI and not fight for bandwidth 154 | } 155 | 156 | 157 | ###### PYTHON TEST - ## thanks http://www.r-bloggers.com/calling-python-from-r-with-rpython/ 158 | boaty_mcboatface_test <- function(){ 159 | python.load("initialize.py", get.exception = TRUE) 160 | Sys.sleep(1) 161 | python.exec("ser.write(' ')") 162 | Sys.sleep(1) 163 | python.exec("ser.write('l')") 164 | Sys.sleep(1) 165 | python.exec("ser.write('r')") 166 | Sys.sleep(1) 167 | python.exec("ser.write('c')") 168 | Sys.sleep(1) 169 | python.exec("ser.write(' ')") 170 | } 171 | 172 | ## test 173 | #boaty_mcboatface_test() 174 | 175 | ###### 176 | closeAllConnections() 177 | file_name <- "file_name" 178 | #watson.speech_to_text.sessionless("test.wav") 179 | 180 | img <- readPNG("ibm_watson.png") 181 | grid::grid.raster(img) 182 | 183 | repeat 184 | { 185 | response <- watson.speech_to_text.sessionless("test.wav") 186 | #print(response) 187 | if(grepl("reset", response)){python.exec("ser.write(' ')")} 188 | if(grepl("left", response)){python.exec("ser.write('l')")} 189 | if(grepl("right", response)){python.exec("ser.write('r')")} 190 | if(grepl("cross", response)){python.exec("ser.write('c')")} 191 | if(grepl("start", response)){python.exec("ser.write('a')")} 192 | if(grepl("go", response)){python.exec("ser.write('a')")} 193 | if(grepl("stop", response)){python.exec("ser.write('z')")} 194 | if(grepl("off", response)){python.exec("ser.write('z')")} 195 | if(grepl("red", response)){python.exec("ser.write('2')")} 196 | if(grepl("dark", response)){python.exec("ser.write('0')")} 197 | if(grepl("black", response)){python.exec("ser.write('0')")} 198 | if(grepl("talk", response)){boaty_speaks("Hello, My name is Boaty McBoatFace! Let's be friends. OK?")} 199 | 200 | } 201 | 202 | ## See also https://www.youtube.com/watch?v=DjESWNOfUUs and https://www.youtube.com/watch?v=l2Q0S33RC80 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /Watson-COGNITIVE-Toys-Arduino.INO: -------------------------------------------------------------------------------- 1 | //###################################################### 2 | //### Boaty McBoatFace - Chatting with Cognitive Toys 3 | //### Experimental Code. Experimental R Interface for IBM Watson Services - Arduino Controller 4 | //###################################################### 5 | 6 | #include 7 | #include 8 | 9 | Servo myservo_a; // create servo object to control a servo 10 | Servo myservo_b; // create servo object to control a servo 11 | Servo myservo_c; // create servo object to control a servo 12 | Servo myservo_d; // create servo object to control a servo 13 | Servo left_eye1; // create servo object to control a servo 14 | Servo right_eye1; // create servo object to control a servo 15 | Servo left_eye2; // create servo object to control a servo 16 | Servo right_eye2; // create servo object to control a servo 17 | Servo myservo_i; // create servo object to control a servo 18 | Servo myservo_j; // create servo object to control a servo 19 | Servo myservo_k; // create servo object to control a servo 20 | 21 | /** Adjust these values for your servo and setup, if necessary **/ 22 | //int LeftEye = 8; // control pin for servo motor 23 | //int RightEye = 9; // control pin for servo motor 24 | 25 | int minPulse = 600; // minimum servo position 26 | int maxPulse = 2400; // maximum servo position 27 | int turnRate = 100; // servo turn rate increment (larger value, faster rate) 28 | int refreshTime = 20; // time (ms) between pulses (50Hz) 29 | 30 | /** The Arduino will calculate these values for you **/ 31 | int centerServo; // center servo position 32 | int pulseWidth; // servo pulse width 33 | int moveServo; // raw user input 34 | long lastPulse = 0; // recorded time (ms) of the last pulse 35 | 36 | 37 | void setup() { 38 | //pinMode(LeftEye, OUTPUT); // Set servo pin as an output pin 39 | //pinMode(RightEye, OUTPUT); // Set servo pin as an output pin 40 | centerServo = maxPulse - ((maxPulse - minPulse)/2); 41 | pulseWidth = centerServo; // Give the servo a starting point (or it floats) 42 | Serial.begin(9600); 43 | Serial.println(" Arduino Serial Servo Control"); 44 | Serial.println("Press < or > to move, spacebar to center"); 45 | Serial.println(); 46 | 47 | left_eye1.attach(6); // attaches the servo on pin 8 to the servo object 48 | right_eye1.attach(7); // attaches the servo on pin 8 to the servo object 49 | left_eye2.attach(8); // attaches the servo on pin 8 to the servo object 50 | right_eye2.attach(9); // attaches the servo on pin 8 to the servo object 51 | 52 | pinMode(10, OUTPUT); // on/off for motor control - RELAY 53 | pinMode(2, OUTPUT); // on/off for LED - 1 on 54 | 55 | digitalWrite(10, HIGH); // active high is not closed 56 | digitalWrite(2, LOW); // active high is not closed 57 | 58 | } 59 | 60 | 61 | 62 | 63 | 64 | void loop() { 65 | // wait for serial input 66 | if (Serial.available() > 0) { 67 | // read the incoming byte: 68 | moveServo = Serial.read(); 69 | 70 | // ASCII '<' is 44, ASCII '>' is 46 (comma and period, really) 71 | //if (moveServo == 44) { pulseWidth = pulseWidth - turnRate; } 72 | //if (moveServo == 46) { pulseWidth = pulseWidth + turnRate; } 73 | // if (moveServo == 32) { pulseWidth = centerServo; } 74 | 75 | if (moveServo == 32) // ' ' is space for reset 76 | { 77 | left_eye1.write(100); 78 | right_eye1.write(100); 79 | left_eye2.write(100); 80 | right_eye2.write(100); 81 | 82 | } 83 | 84 | 85 | if (moveServo == 108) // 'l' is for left look 86 | { 87 | left_eye1.write(160); 88 | right_eye1.write(160); 89 | left_eye2.write(160); 90 | right_eye2.write(160); 91 | 92 | } 93 | if (moveServo == 114) // 'r' is for right look 94 | { 95 | left_eye1.write(20); 96 | right_eye1.write(20); 97 | left_eye2.write(20); 98 | right_eye2.write(20); 99 | } 100 | 101 | if (moveServo == 99) // 'c' is for crosseyed ! :) 102 | { 103 | left_eye1.write(60); 104 | right_eye1.write(130); 105 | left_eye2.write(60); 106 | right_eye2.write(130); 107 | } 108 | 109 | if (moveServo == 97) // 'a' is for up relay! :) 110 | { digitalWrite(10, LOW); // I think active low to gate 111 | } 112 | 113 | if (moveServo == 122) // 'z' is for down! relay :) 114 | { digitalWrite(10, HIGH); // active high is not closed 115 | } 116 | 117 | if (moveServo == 50) // '2' is 'red' color on resistor 118 | { 119 | digitalWrite(2, HIGH); // active high is not closed 120 | } 121 | 122 | if (moveServo == 48) // '0' is 'black' - so turn off 123 | { 124 | digitalWrite(2, LOW); // active high is not closed 125 | } 126 | 127 | 128 | // stop servo pulse at min and max 129 | //if (pulseWidth > maxPulse) { pulseWidth = maxPulse; } 130 | //if (pulseWidth < minPulse) { pulseWidth = minPulse; } 131 | 132 | 133 | 134 | // print pulseWidth back to the Serial Monitor (uncomment to debug) 135 | // Serial.print("Pulse Width: "); 136 | // Serial.print(pulseWidth); 137 | // Serial.println("us"); // microseconds 138 | } 139 | 140 | // pulse the servo every 20 ms (refreshTime) with current pulseWidth 141 | // this will hold the servo's position if unchanged, or move it if changed 142 | // if (millis() - lastPulse >= refreshTime) { 143 | // digitalWrite(RightEye, HIGH); // start the pulse 144 | // //digitalWrite(LeftEye, HIGH); // start the pulse 145 | // delayMicroseconds(pulseWidth); // pulse width 146 | // digitalWrite(RightEye, LOW); // stop the pulse 147 | // //digitalWrite(LeftEye, LOW); // stop the pulse 148 | // lastPulse = millis(); // save the time of the last pulse 149 | // } 150 | } 151 | -------------------------------------------------------------------------------- /Watson-CONVERSATION-Code-Backbone.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### IBM Watson - Code Snippet --- CONVERSATION CODE Backbone 3 | ### Experimental Code. R Interface for IBM Watson Services 4 | ### DOCS: http://www.ibm.com/watson/developercloud/doc/conversation/ 5 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) CONVERSATION Service tile created on bluemix with API credentials and 6 | ### (3) Create a basic conversation with Tooling provided in bluemix - see https://dreamtolearn.com/ryan/r_journey_to_watson/39 for examples 7 | ##################################################### 8 | 9 | #library(RCurl) # install.packages("RCurl") # if the package is not already installed 10 | library(httr) 11 | library(splitstackshape) # for the text to colummns 12 | library(reshape2) 13 | #library(rjson) 14 | 15 | ######### Housekeeping And Authentication 16 | setwd("/Users/ryan/Documents/Service - Conversation") # Set working Directory 17 | getwd() 18 | source("keys.r") ## KEYS has acutal username:password for each IBM service. 19 | 20 | url_CONV="https://gateway.watsonplatform.net/conversation/api/v1" 21 | version="?version=2016-07-11" 22 | username_CONV # check we got it from KEYs.R file in same directory - looks like this - "e63f524d-9999-9999-9999-e6b1d4e99b87" 23 | password_CONV # check we got it from KEYs.R file in same directory - looks like this - "ABCD0EggCXYZ" 24 | workspace_CONV # check we got it from KEYs.R file - looks like this - "2ded4293-9999-9999-9999-4c8b1289be81" <- **** YOU NEED TO PULL THIS FROM BROWSER URL WHEN YOU TEST CONVO IN TOOLING - I THINK ONLY PLACE TO GET RIGHT NO 25 | 26 | ########### FUNCTION DECLARATIONS ################ 27 | 28 | ## FUNCTION DECLARE - INITIATE CONVERSATION WITH SERVICE 29 | conversation.init <- function() 30 | { 31 | raw_response <- POST(url=paste(url_CONV,"/workspaces/",workspace_CONV,"/message",version,sep=""), 32 | authenticate(username_CONV,password_CONV), 33 | add_headers("Content-Type"="application/json"), 34 | body = '{ "input": { "text":""}, 35 | "system":{ "dialog_stack":["root"]}, 36 | "dialog_turn_counter":1, 37 | "dialog_request_counter":1 38 | }', 39 | encode = "json" 40 | ) 41 | return(content(raw_response, "text", encoding = "UTF-8")) 42 | } 43 | 44 | 45 | ## FUNCTION DECLARE - GO DEEPER INTO CONVERSATION 46 | conversation.chat <- function(dialog,conversation_id,dialog_stack_node) #### LEVEL 1 ENGAGE 47 | { 48 | the_body <- paste('{"input":{"text":"', 49 | dialog, 50 | '"},"context":{"conversation_id":"', 51 | conversation_id, 52 | '","system":{"dialog_stack":["', 53 | dialog_stack_node, 54 | '"],', 55 | '"dialog_turn_counter":1,"dialog_request_counter":1}}}', 56 | sep="") 57 | 58 | raw_response <- POST(url=paste(url_CONV,"/workspaces/",workspace_CONV,"/message",version,sep=""), 59 | authenticate(username_CONV,password_CONV), 60 | add_headers("Content-Type"="application/json"), 61 | body = the_body 62 | ) 63 | return(content(raw_response, "text", encoding = "UTF-8")) 64 | } 65 | 66 | 67 | ## FUNCTION DECLARE - ORGANIZE RESPONSES 68 | response.process <- function(data) 69 | { 70 | data <- response 71 | data <- as.data.frame(strsplit(as.character(data),",")) 72 | data[,1] <- gsub("\"","",data[,1] ) 73 | data[,1] <- gsub("\\[", "", data[,1] ) 74 | data[,1] <- gsub("\\]", "", data[,1] ) 75 | data[,1] <- gsub("\\{", "", data[,1] ) 76 | data[,1] <- gsub("\\}", "", data[,1] ) # yes, paint by numbers, but clear what we're hacking :) 77 | data[,1] <- gsub("\\\\n", "", data[,1] ) #data$V1_2 <- gsub("\\\\n", "", data$V1_2) ## removes NEWLINES 78 | data <- data.frame(data) 79 | data <- setNames(data,c("V1")) 80 | data <- cSplit(data, "V1", sep=":") 81 | data <- setNames(data,c("element","X1","X2")) 82 | return(data) 83 | } 84 | ########### END OF FUNCTION DECLARE 85 | 86 | 87 | 88 | ########### MAIN CODE 89 | # ** START HERE ** INITIALIZATION AND GET HOOKS 90 | response <- conversation.init() 91 | temp <- response.process(response) 92 | text <- paste(temp$X1[5]) # system's response text 93 | conv_id <- paste(temp$X2[7]) # CONVERSATION ID - our main 'hook' into this thread- should not change 94 | dial_stack <- paste(temp$X2[8]) # DIALOG STACK - our first stepping stone / node 95 | #text 96 | 97 | # ** CONTINUE CONVERSATION 98 | repeat{ 99 | chat <- readline(prompt="Enter response: ") 100 | response <- conversation.chat(chat,conv_id,dial_stack) 101 | print(response) 102 | temp <- response.process(response) 103 | text <- paste(temp$X1[6]) # system's response text 104 | print(text) 105 | conv_id <- paste(temp$X2[8]) # CONVERSATION ID this should not change if all going well. but just in case 106 | dial_stack <- paste(temp$X2[9]) # DIALOG STACK - NEXT NODE this is next node - need to hold onto this 107 | if(conv_id=='NA'){ 108 | print("end") 109 | break 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Watson-CONVERSATION-Code-Snippet.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### IBM Watson - Code Snippet --- CONVERSATION CODE SNIPPET2 3 | ### Experimental Code. R Interface for IBM Watson Services 4 | ### DOCS: http://www.ibm.com/watson/developercloud/doc/conversation/ 5 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) CONVERSATION Service tile created on bluemix with API credentials and 6 | ### (3) Create a basic conversation with Tooling provided in bluemix - see https://dreamtolearn.com/ryan/r_journey_to_watson/39 for examples 7 | ###################################################### 8 | 9 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 10 | library(httr) 11 | library(rjson) 12 | #library(XML) 13 | 14 | ######### Housekeeping And Authentication 15 | setwd("/Users/ryan/Documents/Service - Conversation") # Set working Directory 16 | getwd() 17 | source("keys.r") ## KEYS has acutal username:password for each IBM service. 18 | 19 | url_CONV="https://gateway.watsonplatform.net/conversation/api/v1" 20 | version="?version=2016-07-11" 21 | username_CONV # check we got it from KEYs.R file in same directory - looks like this - "e63f524d-9999-9999-9999-e6b1d4e99b87" 22 | password_CONV # check we got it from KEYs.R file in same directory - looks like this - "ABCD0EggCXYZ" 23 | workspace_CONV # check we got it from KEYs.R file - looks like this - "2ded4293-9999-9999-9999-4c8b1289be81" <- **** YOU NEED TO PULL THIS FROM BROWSER URL WHEN YOU TEST CONVO IN TOOLING - I THINK ONLY PLACE TO GET RIGHT NO 24 | 25 | getwd() 26 | 27 | 28 | ### CAREFUL - THIS CODE IS IN PROGRESS - JUST TO GET SYNTAX RIGHT - NO FUNCTIONS OR OPTIMIZATION YET 29 | 30 | 31 | ## LEVEL 0 - INITIATE - FIRST CONTACT - blank utterance works to start thigns off (But 'coffee' will also hit NLC and return confidence) 32 | response <- POST(url=paste(url_CONV,"/workspaces/",workspace_CONV,"/message",version,sep=""), 33 | authenticate(username_CONV,password_CONV), 34 | add_headers("Content-Type"="application/json"), 35 | body = '{ "input": { "text":""}, 36 | "system":{ "dialog_stack":["root"]}, 37 | "dialog_turn_counter":1, 38 | "dialog_request_counter":1 39 | }', 40 | encode = "json" 41 | ) 42 | response 43 | response_text <- content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 44 | response_text 45 | 46 | 47 | ## RESPONSE [1] "{\"intents\":[],\"entities\":[],\"input\":{\"text\":\"\"},\"output\":{\"log_messages\":[], 48 | # \"text\":[\"Welcome to the Tasty Helper! \\nWhat are you looking for?\"],\"nodes_visited\":[\"node_6_1468893593485\"]}, 49 | # \"context\":{\"conversation_id\":\"1a598ffd-2b01-4330-923a-291a0cecc5f9\", 50 | # \"system\":{\"dialog_stack\":[\"node_6_1468893593485\"],\"dialog_turn_counter\":1,\"dialog_request_counter\":1}}}" 51 | 52 | ## (!!) NOW WE NEED TO COPY/PASTE THE RETURNED NODE and ALSO THE CONVERSATION ID INTO SUBSEQUENT DIALOG - TO FOLLOW THREAD: 53 | 54 | #### LEVEL 1 ENGAGE 55 | 56 | response <- POST(url=paste(url_CONV,"/workspaces/",workspace_CONV,"/message",version,sep=""), 57 | authenticate(username_CONV,password_CONV), 58 | add_headers("Content-Type"="application/json"), 59 | body = '{"input":{"text":"coffee"}, 60 | "context":{"conversation_id":"1a598ffd-2b01-4330-923a-291a0cecc5f9", 61 | "system":{"dialog_stack":["node_6_1468893593485"], 62 | "dialog_turn_counter":1,"dialog_request_counter":1}}}' 63 | ) 64 | response 65 | response_text <- content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 66 | response_text 67 | 68 | # RESPONSE [1] "{\"intents\":[{\"intent\":\"coffee\",\"confidence\":1}],\"entities\":[],\"input\":{\"text\":\"coffee\"}, 69 | # \"output\":{\"log_messages\":[],\"text\":[\"Coffee makes me very productive (level 1)\"], 70 | # \"nodes_visited\":[\"node_12_1468894103975\"]},\"context\":{\"conversation_id\":\"1a598ffd-2b01-4330-923a-291a0cecc5f9\", 71 | # \"system\":{\"dialog_stack\":[\"node_12_1468894103975\"],\"dialog_turn_counter\":2,\"dialog_request_counter\":2}}}" 72 | 73 | 74 | #### LEVEL 2 CONTINUE CONV - take note how we need to continue to propogate CONV_ID and ALSO UPDATE DIALOG_STACK NODE to new level (!) 75 | 76 | response <- POST(url=paste(url_CONV,"/workspaces/",workspace_CONV,"/message",version,sep=""), 77 | authenticate(username_CONV,password_CONV), 78 | add_headers("Content-Type"="application/json"), 79 | body = '{"input":{"text":"coffee"}, 80 | "context":{"conversation_id":"1a598ffd-2b01-4330-923a-291a0cecc5f9", 81 | "system":{"dialog_stack":["node_12_1468894103975"], 82 | "dialog_turn_counter":1,"dialog_request_counter":1}}}' 83 | ) 84 | response 85 | response_text <- content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 86 | response_text 87 | 88 | 89 | # RESULTS _ [1] "{\"intents\":[{\"intent\":\"coffee\",\"confidence\":1}],\"entities\":[],\"input\":{\"text\":\"coffee\"}, 90 | #\"output\":{\"log_messages\":[],\"text\":[\"wow - two in a row - you must LOVE caffeine (level 2)\"], 91 | #\"nodes_visited\":[\"node_6_1474949437344\"]},\"context\":{\"conversation_id\":\"1a598ffd-2b01-4330-923a-291a0cecc5f9\", 92 | #\"system\":{\"dialog_stack\":[\"node_6_1474949437344\"],\"dialog_turn_counter\":2,\"dialog_request_counter\":2}}}" 93 | 94 | 95 | ##### LEVEL 3 DEEP INTO THE DIALOG TREE (and resets to beginning) 96 | 97 | response <- POST(url=paste(url_CONV,"/workspaces/",workspace_CONV,"/message",version,sep=""), 98 | authenticate(username_CONV,password_CONV), 99 | add_headers("Content-Type"="application/json"), 100 | body = '{"input":{"text":"coffee"}, 101 | "context":{"conversation_id":"d8c4f16c-1165-4486-9f71-085e0578a587", 102 | "system":{"dialog_stack":["node_6_1474949437344"], 103 | "dialog_turn_counter":1,"dialog_request_counter":1}}}' 104 | ) 105 | response 106 | response_text <- content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 107 | response_text 108 | 109 | ### RESPONSE - [1] "{\"intents\":[{\"intent\":\"coffee\",\"confidence\":1}],\"entities\":[],\"input\":{\"text\":\"coffee\"}, 110 | #\"output\":{\"log_messages\":[],\"text\":[\"WOWOWOW Coffee (level 3)\", 111 | #\"Welcome to the Tasty Helper! \\nWhat are you looking for?\"], 112 | #\"nodes_visited\":[\"node_7_1474949480138\",\"node_6_1468893593485\"]}, 113 | #\"context\":{\"conversation_id\":\"d8c4f16c-1165-4486-9f71-085e0578a587\", 114 | #\"system\":{\"dialog_stack\":[\"node_6_1468893593485\"],\"dialog_turn_counter\":2,\"dialog_request_counter\":2}}}" 115 | ## BACK TO START OF LOOP / CYCLE (BY DESIGN) 116 | -------------------------------------------------------------------------------- /Watson-Cognitive_Bartender.ino: -------------------------------------------------------------------------------- 1 | /// COGNITIVE BARTENDER 2 | /// Can drive this from RStudio Code using PythonR, or use Serial Monitor here and send characters 3 | 4 | #include 5 | 6 | int controlCommand; // raw user input 7 | 8 | const int ledPin3 = 3; // the number of the LED pin 9 | const int ledPin4 = 4; // the number of the LED pin 10 | const int ledPin5 = 5; // the number of the LED pin 11 | const int ledPin6 = 6; // the number of the LED pin 12 | const int ledPin7 = 7; // the number of the LED pin 13 | 14 | void setup() { 15 | Serial.begin(9600); 16 | Serial.println(" Arduino Serial Pump Control"); 17 | Serial.println("Press < or > to move, spacebar to center"); 18 | Serial.println(); 19 | 20 | pinMode(ledPin3, OUTPUT); 21 | pinMode(ledPin4, OUTPUT); 22 | pinMode(ledPin5, OUTPUT); 23 | pinMode(ledPin6, OUTPUT); 24 | pinMode(ledPin7, OUTPUT); 25 | 26 | digitalWrite(ledPin3, HIGH); 27 | digitalWrite(ledPin4, HIGH); 28 | digitalWrite(ledPin5, HIGH); 29 | digitalWrite(ledPin6, HIGH); 30 | digitalWrite(ledPin7, HIGH); 31 | 32 | } 33 | 34 | void loop() { 35 | // wait for serial input 36 | if (Serial.available() > 0) { 37 | controlCommand = Serial.read(); // read the incoming byte: 38 | 39 | 40 | ////// PUMP ACTIONS (later change characters to 1,2,3,4,5 for more intuitive - rather than letters 41 | 42 | if (controlCommand == 97) // 'a' is GIN 1 43 | { 44 | digitalWrite(ledPin3, LOW); /// Engage Pump 1 45 | delay(1000); 46 | digitalWrite(ledPin3, HIGH); // RESTORE 47 | } 48 | 49 | 50 | if (controlCommand == 115) // 's' is BLue Pump 2 51 | { 52 | digitalWrite(ledPin4, LOW); /// Engage Pump 2 53 | delay(1000); 54 | digitalWrite(ledPin4, HIGH); // RESTORE 55 | } 56 | 57 | 58 | if (controlCommand == 100) // 'd' is Pink Pump 3 59 | { 60 | digitalWrite(ledPin5, LOW); /// Engage Pump 61 | delay(1000); 62 | digitalWrite(ledPin5, HIGH); // RESTORE 63 | } 64 | 65 | if (controlCommand == 102) // 'f' is Orange Pump 4 66 | { 67 | digitalWrite(ledPin6, LOW); /// Engage Pump 68 | delay(1000); 69 | digitalWrite(ledPin6, HIGH); // RESTORE 70 | } 71 | 72 | if (controlCommand == 103) // 'g' is Purple Pump 5 73 | { 74 | digitalWrite(ledPin7, LOW); /// Engage Pump 75 | delay(1000); 76 | digitalWrite(ledPin7, HIGH); // RESTORE 77 | } 78 | 79 | 80 | 81 | if (controlCommand == 32) // ' ' is space for reset // 82 | { 83 | // OK - crude way to cycle through the relays for 2,3,4,5,6, 84 | digitalWrite(ledPin3, HIGH); // pump1 85 | digitalWrite(ledPin4, HIGH); // pump2 86 | digitalWrite(ledPin5, HIGH); // pump3 87 | digitalWrite(ledPin6, HIGH); // pump4 88 | digitalWrite(ledPin7, HIGH); // pump5 89 | 90 | } 91 | 92 | } 93 | 94 | } 95 | 96 | -------------------------------------------------------------------------------- /Watson-Cognitive_Bartender_V1.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### COGNITIVE BARTENTER 3 | ### Experimental Code. Experimental R Interface for IBM Watson Services - 4 | ### PART 1 - We have a speech interface that determines user intent from IBM Watson Speech to Text and NLC services 5 | ### PART 2 - We engage PYTHON scripts (serial made easier) from R Studio 6 | ### PART 3 - Python Calls Arduino and Commands the pumps 7 | ### DOCS: https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/speech-to-text/ 8 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) STT/NLC and TTS Services stood up (3) Credentials to each Service 9 | ###################################################### 10 | 11 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 12 | library(httr) 13 | library(audio) 14 | library(data.table) 15 | library(dplyr) 16 | library(reshape2) 17 | library(Rtts) 18 | library(splitstackshape) 19 | library(seewave) # need to play wav back? 20 | library(stringr) 21 | library(splitstackshape) 22 | library(tidyr) 23 | library(XML) 24 | library(png) 25 | library(rPython) 26 | 27 | closeAllConnections() 28 | 29 | setwd("/Users/ryan/Documents/Project_Boaty_McBoatFace") # Set working Directory 30 | getwd() 31 | source("keys.r") ## KEYS has acutal username:password for each IBM service. Seperate R file looks sort of like below 32 | 33 | boaty_mcboatface_test() # test function from other side 34 | 35 | ## Base URLs for IBM Watson APIs 36 | base_url_STT <- "https://stream.watsonplatform.net/speech-to-text/api" 37 | base_url_NLC = "https://gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers/" 38 | base_url_TTS <- "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" 39 | 40 | getURL(base_url_NLC,userpwd = username_password_NLC ) # non essential , but checks if working /authenticated 41 | 42 | # For audio Sampling later 43 | sample_count <- 40000 ## 0k samples 44 | sample_rate <- 16000 ## at 16khz - is ~5 seconds recording time 45 | 46 | ########## FUNCTION DECLARATIONS #### FUNCTION DECLARATIONS ########### 47 | ########## FUNCTION DECLARATIONS #### FUNCTION DECLARATIONS ########### 48 | 49 | ### STT FUNCTION to test connectivity and return models available 50 | watson.STT.getmodels <- function() 51 | {return(GET(url=paste(base_url_STT,"/v1/models",sep=""), 52 | authenticate(username_STT,password_STT)))} 53 | ### FOR BEST RESULTS - USE USB HEADSET and ensure in MAc > Sys Preferences >Sound it's selected 54 | response <- watson.STT.getmodels() 55 | content(response) 56 | 57 | ## STT FUNCTION - Record! 58 | watson.STT.record <- function(samp_count,samp_rate) 59 | { 60 | # record 8000 samples at 8000Hz (1 sec), mono (1 channel) 61 | # record 64k samples at 16kHz (4 sec), mono (1 channel), stereo = 2 62 | a <- record(samp_count, samp_rate, 2) 63 | wait(a) # wait for the recording to finish 64 | x <- a$data # get the result 65 | x[1:10] # show first ten samples 66 | close(a); rm(a) # you can close the instance at this point 67 | # amplify and crop the signal 68 | audio <- x * 2 69 | audio[audio < -1] <- -1 70 | audio[audio > 1] <- 1 71 | return(audio) 72 | } 73 | 74 | 75 | #### STT FUNCTION TO TIDY UP the STT response - just export the TRANSCRIPT ONLY 76 | stt_transcript_only <- function(raw) 77 | { 78 | data <- as.data.frame(strsplit(as.character(raw),"\\n")) 79 | data <- data[c(7), ] # for now, grab just what we want 80 | data <- paste(data) # kill levels, - fyi this nukes confidence % info (may want later) 81 | data <- gsub(" ","",data) # remove excessive whitespace 0 cannot use ALL [[punct]] here 82 | data <- gsub("\\\\","",data) # remove punct we dont like 83 | data <- gsub("\"","",data) # remove punct we dont like 84 | data <- gsub("transcript","",data) # remove excessive whitespace 85 | data <- gsub(":","",data) # remove excessive whitespace - later: Improve this tidy step. 86 | return(data) 87 | } 88 | 89 | 90 | ###### STT FUNCTION - ANalyze AUDIO WAV file with IBM Watson Speech to Text service - SESSIONLESS 91 | watson.speech_to_text.recognize <- function(audio_file) 92 | { return(POST(url=paste(base_url_STT,"/v1/recognize",sep=""), 93 | authenticate(username_STT,password_STT), 94 | add_headers("Content-Type"="audio/wav"), 95 | body = (file = upload_file(audio_file)) 96 | ))} #works # hope this helps you with syntax! 97 | ## this is SESSIONLESS MODE - https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/#!/speech-to-text/recognizeSessionless 98 | 99 | 100 | ##### STT FUNCTION FOR SPEECH TO TEXT - RETURNS TRANSCRIPT - SESSIONLESS 101 | watson.speech_to_text.sessionless <- function(file_name) 102 | { 103 | wait(play(sin(1:200/4))) # recording START tone 104 | print("RECORDING ------------------ (beep) ") 105 | the_audio <- watson.STT.record(sample_count,sample_rate) 106 | wait(play(sin(1:200/2))) # recording STOP tone 107 | print("Recording COMPLETE --------- (beep) ") 108 | #print("Saving WAV File") 109 | save.wave(the_audio,file_name) 110 | print("Calling IBM Watson Speech To Text API") 111 | response <- watson.speech_to_text.recognize(file_name) 112 | return(stt_transcript_only(content(response,"text"))) 113 | } 114 | 115 | ####### TTS Function to list voices 116 | watson.TTS.listvoices <- function() 117 | { 118 | voices <- GET(url=paste("https://stream.watsonplatform.net/text-to-speech/api/v1/voices"),authenticate(username_TTS,password_TTS)) 119 | data <- content(voices,"text") 120 | data <- as.data.frame(strsplit(as.character(data),"name")) 121 | data <- data[-c(1:2), ] # remove dud first row 122 | data <- strsplit(as.character(data),",") 123 | data <- data.frame(matrix(data)) 124 | colnames(data) <- "V1" 125 | data <- cSplit(data, 'V1', sep="\"", type.convert=FALSE) 126 | data <- data.frame(data$V1_04) 127 | data[,1] <- gsub("\\\\","",data[,1] ) 128 | return(data) } 129 | 130 | watson.TTS.listvoices() 131 | 132 | 133 | ######## TTS FUNCTION --- TEXT TO SPEECH 134 | watson.TTS.execute <- function(url1,text1,voice1,filename1) 135 | { 136 | the_audio = CFILE(filename1, mode="wb") 137 | curlPerform(url = paste(url1,"?text=",text1,"&voice=",voice1,sep=""), 138 | userpwd = username_password_TTS, 139 | httpheader=c(accept="audio/wav"), 140 | writedata = the_audio@ref) 141 | close(the_audio) 142 | system(paste("open",filename1,"-a vlc")) 143 | } 144 | 145 | ## Function boaty speaks 146 | boaty_speaks <- function(voice_transcript) 147 | { 148 | voice <- "en-US_AllisonVoice" 149 | the_url <- paste(base_url_TTS,"?text=",URLencode(voice_transcript),"&voice=",voice,sep="") 150 | the_audio = CFILE("toy_talks.wav", mode="wb") ## here we receive the audio back 151 | curlPerform(url = the_url,userpwd = username_password_TTS,httpheader=c(accept="audio/wav"),writedata = the_audio@ref) 152 | close(the_audio) 153 | system("open toy_talks.wav -a vlc") # Now - Let's listen 154 | wait(5) ## this gives ECHO some time to use the WiFI and not fight for bandwidth 155 | } 156 | 157 | 158 | ###### PYTHON TEST - ## thanks http://www.r-bloggers.com/calling-python-from-r-with-rpython/ 159 | boaty_mcboatface_test <- function(){ 160 | python.load("initialize.py", get.exception = TRUE) 161 | Sys.sleep(1) 162 | python.exec("ser.write(' ')") 163 | Sys.sleep(1) 164 | } 165 | 166 | ###### 167 | closeAllConnections() 168 | file_name <- "file_name" 169 | #watson.speech_to_text.sessionless("test.wav") 170 | 171 | img <- readPNG("ibm_watson.png") 172 | grid::grid.raster(img) 173 | 174 | 175 | ### READ THIS ---------------------------- 176 | ### run stuff above first, THEN repeat loop below. (together fails) 177 | 178 | ###### 179 | repeat 180 | { 181 | response <- watson.speech_to_text.sessionless("test.wav") 182 | #print(response) 183 | #if(grepl("reset", response)){python.exec("ser.write(' ')")} 184 | if(grepl("gin", response)){python.exec("ser.write('a')")} 185 | if(grepl("vodka", response)){python.exec("ser.write('a')")} 186 | if(grepl("one", response)){python.exec("ser.write('a')")} 187 | if(grepl("blue", response)){python.exec("ser.write('s')")} # 188 | if(grepl("two", response)){python.exec("ser.write('s')")} # 189 | if(grepl("pink", response)){python.exec("ser.write('d')")} # 190 | if(grepl("three", response)){python.exec("ser.write('d')")} # 191 | if(grepl("orange", response)){python.exec("ser.write('f')")} # 192 | if(grepl("four", response)){python.exec("ser.write('f')")} # 193 | if(grepl("purple", response)){python.exec("ser.write('g')")} # 194 | if(grepl("five", response)){python.exec("ser.write('g')")} # 195 | # if(grepl("order", response)){boaty_speaks("Hello! My name is MacKenzie! Can I mix you a drink?")} 196 | if(grepl("drink", response)){boaty_speaks("Hello! My name is MacKenzie! Can I mix you a drink?")} 197 | 198 | } 199 | 200 | -------------------------------------------------------------------------------- /Watson-DIALOG-R-example-functions.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. R Interface for IBM Watson Services - 3 | ### Focus: DIALOG - R Programming Language Interface 4 | ### Adapting the DIALOG APIs https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/ to RCURL and HTTR 5 | ### http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/dialog/ 6 | ###################################################### 7 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) A dialog App and (3) Credentials to that Service and confirm you're able to CURL service with 8 | ### DOCS: https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/dialog-apis.html 9 | ### REFERENCE - https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/dialog/api/v1/#get-dialogs 10 | 11 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 12 | library(httr) 13 | library(XML) 14 | library(data.table) 15 | library(reshape2) 16 | library(dplyr) 17 | library(stringr) 18 | setwd("/Users/ryan/Documents/Project Daisy") 19 | 20 | #"DIALOG ORANGE SERVICE credentials": { UNBOUND 21 | base_url = "https://gateway.watsonplatform.net/dialog-beta/api/v1" # no "/" on end 22 | username = "55555555-5555-5555-55555-55555555555" 23 | password = "5555555555" 24 | username_password = paste(username,":",password,sep="") 25 | dialog_id="" 26 | 27 | ####### FUNCTION - New LIST APPS 28 | watson.dialog.listapps <- function() 29 | { data <- getURL(paste(base_url,"/dialogs",sep=""),userpwd = username_password ) 30 | data <- as.data.frame(strsplit(as.character(data),"name")) 31 | data <- data[-c(1), ] # remove dud first row 32 | data <- data.frame(matrix(data)) # can tidy this method later - IF YOU HAVE MORE THAN ONE DIALOG - YOU"LL GET MULTIPLE HERE 33 | data <- strsplit(as.character(data$matrix.data),"dialog_id") 34 | data <- t(data.frame(data)) # can tidy this method later 35 | rownames(data) <- NULL 36 | # tidy up (there is a better way later) 37 | data[,1] <- str_replace_all(data[,1], "[[:punct:]]", "") 38 | data[,2] <- gsub("-"," ",data[,2]) 39 | data[,2] <- str_replace_all(data[,2], "[[:punct:]]", "") 40 | data[,2] <- gsub(" ","-",data[,2]) 41 | data <- data.frame(data) 42 | setnames(data,c("dialog_name","dialog_id")) 43 | return(data) 44 | } 45 | 46 | ####### FUNCTION - New Dialog - UPLOAD XML FILE 47 | watson.dialog.uploadfile <- function(file,name) 48 | { return(POST(url=paste(base_url,"/dialogs",sep=""), 49 | authenticate(username,password), 50 | body = list(file = upload_file(file), 51 | name = name 52 | ) )) } 53 | 54 | 55 | ####### FUNCTION - CONVERSE - Used to obtain a response from the system for a submitted input message. Also used to start new conversations 56 | watson.dialog.converse <- function(dialog_id, conv_id, cl_id, text_input) 57 | { 58 | segue <- list( 59 | conversation_id = conv_id, 60 | client_id = cl_id, 61 | input = text_input 62 | ) 63 | return 64 | ( POST(url=paste(base_url,"/dialogs/",dialog_id,"/conversation",sep=""), 65 | authenticate(username,password), 66 | body = segue, encode = "form") 67 | )} 68 | ### end of function 69 | 70 | ####### FUNCTION - DELTETE *ONE* DIALOG ID's - WORKING 71 | watson.dialog.deletedialogID <- function(kill_dialogID) 72 | { return( DELETE(url=paste(base_url,"/dialogs/",kill_dialogID,sep=""),userpwd = username_password) 73 | ) } 74 | ### end of function declaration 75 | 76 | ######## FUNCTION TO DELETE ALL DIALOGS (ALL!) > delete /dialogs > Used to close an entire all Dialog applications associated with the service instance. 77 | watson.dialog.deletedialogALL <- function() { 78 | return( DELETE(url="https://gateway.watsonplatform.net/dialog-beta/api/v1/dialogs",userpwd = username_password) )} 79 | ### end of function declaration 80 | 81 | ################################ END OF FUNCTION DECLARATIONS ######### 82 | ################################ END OF FUNCTION DECLARATIONS ######### 83 | 84 | ################################ START THE PIZZA PARTY ######### 85 | 86 | ####### What Dialog ID's already exist? 87 | watson.dialog.listapps() 88 | 89 | ###### TEST FUNCTION OK ACTION: Create a new Dialog! (200 = Good outcome) - 90 | ##### Where to get files and background? here: http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/dialog/ 91 | 92 | ##### https://github.com/watson-developer-cloud/dialog-tool/blob/master/dialogs/pizza_sample.xml # not all XML created equal - careful 93 | thefile <- "pizza_sample_gold.xml" #you'll need a local, 'good' Dialog XML file, in the right directory, 94 | thename <- "Pizza_Exercise_Gold3" 95 | response <- watson.dialog.uploadfile(thefile,thename) # Pushes XML to dialog API - should return NEW dialog_id if OK 96 | response #201? if so, that's good 97 | content(response, "text") # "{\"dialog_id\": 98 | #### end of test 99 | 100 | watson.dialog.listapps() # do you see what i see? 101 | 102 | ### OK - let's extract the dialog ID so we can start a conversation 103 | data <- watson.dialog.listapps() # returns FULL LIST of them, could be up to 10 104 | dialog_id <- tail(data$dialog_id,1) ### LETS TAKE THE LATEST LAST ONE IF MORE THAN ONE DIALOG_ID 105 | dialog_id <- paste(dialog_id) # gets rid of levels 106 | dialog_id 107 | 108 | ## ACTION - Let's start a conversation! LET'S BEGIN 109 | conv_id <- "" # needs to be blank to trigger new 110 | cl_id <- "" # needs to be blank to trigger new 111 | text_input <- "*" # "Hi" # doesnt really matter what our first input is 112 | response <- watson.dialog.converse(dialog_id,conv_id,cl_id,text_input) # first time through this should be blank (spawn a new one) 113 | response 114 | content(response, "text") 115 | ## OK NOW WE"RE COOKING (Pizza!) 116 | ## response\":[\"Hi, I'm Watson! I can help you order a pizza, what size would you like?\"]}" 117 | 118 | ### EXTRACT INFO FOR CONVERSATION ANCHOR - EXTRACT the conv Id and client id to CONTINUE - EXTRACT INFORMATION TO KEY OFF OF - Segue 119 | data <- content(response,"text") 120 | data <- as.data.frame(strsplit(as.character(data),'\"')) 121 | setnames(data,c("V1")) 122 | data$V1 <- str_replace_all(data$V1, "[[:punct:]]", "") 123 | data <- data[c(3,5,14), ] # cherry pick what we want - conv_id, client_id, and reponse 124 | data <- data.frame(matrix(data)) # can tidy this method later 125 | setnames(data,c("V1")) 126 | conv_id <- toString(data$V1[1]) 127 | cl_id <- toString(data$V1[2]) 128 | watson_response <-toString(data$V1[3]) 129 | dialog_id # should still have this from opening round 130 | ###### OK - we've extracted key information - can continue dialog! 131 | print(cat("This is your CONVERSATION ANCHOR:", "\n", "dialog_id = ", paste(dialog_id), "\n", 132 | "conversation_id = ", conv_id, "\n", "client_id = ", cl_id ,"\n", "watson_response = ",watson_response,"\n")) 133 | 134 | # watson_response = Hi Im Watson I can help you order a pizza what size would you like 135 | 136 | ## ACTION - Let's CONTINUE the conversation! 137 | text_input <- "medeium" # spelling error intentional- dialog has some spelling skills 138 | response <- watson.dialog.converse(dialog_id,conv_id,cl_id,text_input) 139 | #response 140 | content(response, "text") 141 | #"response\":[\"\",\"What toppings are you in the mood for? (Limit 4)\"]}" 142 | 143 | text_input <- "ham and cheese and pineapple and pepperoni" 144 | response <- watson.dialog.converse(dialog_id,conv_id,cl_id,text_input) 145 | content(response, "text") 146 | 147 | #response\":[\"\",\"Do you prefer pickup or delivery?\"]}" 148 | text_input <- "delivery please!" 149 | response <- watson.dialog.converse(dialog_id,conv_id,cl_id,text_input) 150 | content(response, "text") 151 | 152 | 153 | #response\":[\"Ok, I have one Medium canadian bacon, Cheese, Pineapple & Pepperoni pizza for delivery. Is that correct?\"]}" 154 | text_input <- "yes - thank you" 155 | response <- watson.dialog.converse(dialog_id,conv_id,cl_id,text_input) 156 | content(response, "text") 157 | 158 | #"response\":[\"Sounds good! Your pizza will be ready in 20 minutes. Do you want to order another?\"]}" 159 | text_input <- "no thank you" 160 | response <- watson.dialog.converse(dialog_id,conv_id,cl_id,text_input) 161 | content(response, "text") 162 | #"response\":[\"Okay, thank you for your order! Just let me know if you want to place another order.\"]}" 163 | 164 | ############# DANGER ZONE 165 | ############# DANGER ZONE 166 | 167 | ## EXECUTE FUNCTION TO DELETES ONE DIALOG_ID - Just one - CAREFUL 168 | watson.dialog.listapps() # find one to kill 169 | dialog_id 170 | watson.dialog.deletedialogID(dialog_id) 171 | watson.dialog.listapps() # did we kill it? should be gone now 172 | ## working 9/15/2015 173 | 174 | ########## EXECUTE BE -- DANGER --- DANGER --- 175 | watson.dialog.listapps() # we who are about to be deleted, salute you 176 | watson.dialog.deletedialogALL() ## CARFUL - this is NUCLEAR Option - kills ALL! DANGER 200 Status = the job is done 177 | watson.dialog.listapps() # did we kill it? should be gone now 178 | 179 | #EOF 180 | 181 | Copyright 2015 Ryan Anderson 182 | 183 | Licensed under the Apache License, Version 2.0 (the "License"); 184 | you may not use this file except in compliance with the License. 185 | You may obtain a copy of the License at 186 | 187 | http://www.apache.org/licenses/LICENSE-2.0 188 | 189 | Unless required by applicable law or agreed to in writing, software 190 | distributed under the License is distributed on an "AS IS" BASIS, 191 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 192 | See the License for the specific language governing permissions and 193 | limitations under the License. 194 | 195 | -------------------------------------------------------------------------------- /Watson-DIALOG-basic-R-scripts-segue-only-PUBLIC.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. Experimental R Interface for IBM Watson Services - R Programming Language 3 | ### Focus: DIALOG - R Programming Language Interface 4 | ### Adapting the DIALOG APIs https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/ to RCURL and HTTR 5 | ### http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/dialog/ 6 | ###################################################### 7 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) A dialog App and (3) Credentials to that Service and confirm you're able to CURL service with 8 | ### REFERENCE - https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/dialog/api/v1/#get-dialogs 9 | 10 | 11 | #### WARNING - THIS IS A CODE SNIPPET TO ILLUSTRATE SYNTAX FOR "POST" TO API - IS IS NOT COMPLETE CODE 12 | #### WARNING - THIS IS A CODE SNIPPET TO ILLUSTRATE SYNTAX FOR "POST" TO API - IS IS NOT COMPLETE CODE 13 | 14 | 15 | setwd("/Users/ryan/Documents/Project Daisy") 16 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 17 | library(httr) 18 | 19 | 20 | 21 | ###### FUNCTION - CONVERSE - Used to obtain a response from the system for a submitted input message. Also used to start new conversations if conv id blank 22 | ###### Note the use of "LIST" and NESTING THE LIST "SEGUE" into the BODY for POST 23 | watson.dialog.converse <- function(dialog_id, conv_id, cl_id, text_input) 24 | { 25 | segue <- list( 26 | conversation_id = conv_id, 27 | client_id = cl_id, 28 | input = text_input 29 | ) 30 | return 31 | ( POST(url=paste(base_url,"/dialogs/",dialog_id,"/conversation",sep=""), 32 | authenticate(username,password), 33 | body = segue, encode = "form") 34 | )} 35 | ### end of function 36 | 37 | 38 | 39 | ##### A short test - note 'dialog-beta' in URL, some docs and cases this should just be 'dialog' 40 | base_url = "https://gateway.watsonplatform.net/dialog-beta/api/v1" 41 | 42 | username = "9a85e-NEED-TO-GET-YOUR-OWN-23666f4b8" # Bluemix Portal for these credentials after you stand up Dialog Service 43 | password = "555_YOUR_PW_555" # Bluemix Portal for these credentials after you stand up Dialog Service 44 | username_password = paste(username,":",password,sep="") 45 | 46 | dialog_id="5555555-YOUR-DIALOG-555555555" # you'll need to get this from another function that uploads XML to Dialog API - see main code body for this 47 | 48 | #conv_id <- "13232" # for this example, assumes you've already started the conversation and had this info returned 49 | conv_id <- "" # blank spawns new conversation, populated continues prior one 50 | 51 | #cl_id <- "13336" # for this example, assumes you've already started the conversation and had this info returned 52 | cl_id <- "" # blank spawns new conversation, populated continues prior one 53 | 54 | text_input <- "large pizza" 55 | #text_input <- "ham" 56 | #text_input <- "delivery" 57 | 58 | response <- watson.dialog.converse(dialog_id,conv_id,cl_id,text_input) # first time through this should be blank (spawn a new one) 59 | 60 | response #201 = good 61 | 62 | content(response, "text") 63 | ### NEW: "{\"conversation_id\":13711,\"client_id\":13776,\"input\": \"delivery\",\"confidence\":0,\"response\":[\"Hi, I'm Watson! I can help you order a pizza, what size would you like?\"]}" 64 | ### "{\"conversation_id\":13232,\"client_id\":13336,\"input\": \"delivery\",\"confidence\":1.0,\"response\":[\"Ok, I have one Large canadian bacon pizza for delivery. Is that correct?\"]}" 65 | 66 | 67 | 68 | Copyright 2015 Ryan Anderson 69 | Licensed under the Apache License, Version 2.0 (the "License"); 70 | you may not use this file except in compliance with the License. 71 | You may obtain a copy of the License at 72 | 73 | http://www.apache.org/licenses/LICENSE-2.0 74 | 75 | Unless required by applicable law or agreed to in writing, software 76 | distributed under the License is distributed on an "AS IS" BASIS, 77 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 78 | See the License for the specific language governing permissions and 79 | limitations under the License. 80 | -------------------------------------------------------------------------------- /Watson-LANGUAGE-detect&translate.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Adapting the LANGUAGE TRANSLATION & IDENTIFICATION APIs to R - RCURL and HTTR 3 | ### http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/#!/language-translation/listIdentifiableLanguages 4 | ### https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/language-translation/ 5 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) and Credentials to that Service and confirm you're able to CURL service with 6 | ###################################################### 7 | 8 | library(RCurl) 9 | library(httr) 10 | library(XML) 11 | library(data.table) 12 | library(reshape2) 13 | library(dplyr) 14 | library(plyr) 15 | library(stringr) 16 | library(reshape2) 17 | 18 | ## LANGUAGE Translation & Identification - CREDENTIALS from SERVICE 19 | setwd("/Users/ryan/Documents/Project Daisy") 20 | url="https://gateway.watsonplatform.net/language-translation/api" 21 | username="12345678-1234-1234-1234-123456789ABC" 22 | password="123456789" 23 | username_password = paste(username,":",password,sep="") 24 | 25 | 26 | # FUNCTION DECLARE: LIST LINGOS - What languages does watson speak? # quick check - LIST OF AVAILABLE LANGUAGES = Identifies the language of the input text 27 | watson.language.list <- function() 28 | { 29 | response <- getURL(paste(url,"/v2/identifiable_languages",sep=""),userpwd = username_password) 30 | response <- as.data.frame(strsplit(as.character(response),"\"language\":\"")) 31 | response <- data.frame(do.call('rbind', strsplit(as.character(response[,1]),'\"',fixed=TRUE))) 32 | response <- subset(response, select=c("X1", "X5")) 33 | response <- response[-c(1), ] # remove dud first row 34 | return(response) 35 | } 36 | 37 | #OK lets Test: 38 | language_lookup <- watson.language.list() 39 | language_lookup 40 | 41 | 42 | 43 | ###### FUNCTION - ANalyze TEXT/DOC RECEIVED and return language with confidence 44 | watson.language.analyze <- function(text_to_analyze) 45 | { 46 | response <- (POST(url=paste(url,"/v2/identify",sep=""), 47 | authenticate(username,password), 48 | add_headers("Content-Type"="text/plain","charset"="utf-8" ), 49 | body = text_to_analyze 50 | )) 51 | response <- content(response, "text") 52 | response <- as.data.frame(strsplit(as.character(response),"\"language\":\"")) 53 | response <- data.frame(do.call('rbind', strsplit(as.character(response[,1]),'\"',fixed=TRUE))) 54 | response <- subset(response, select=c("X1", "X4")) 55 | response <- response[-c(1), ] # remove dud first row 56 | response$X4 <- gsub("[{error: no user with username ',:' was found}]","",response$X4) 57 | response$X4 <- round(as.numeric(response$X4),4) 58 | head(response,5) 59 | response <- (merge(response, language_lookup, by = 'X1')) 60 | response <- response[order(-response$X4), ] 61 | rownames(response) <- NULL 62 | colnames(response) <- c("ln","confidence","language") 63 | return(response) 64 | } 65 | 66 | 67 | ## TESTING - Parlez vous francais? 68 | TEXT <- "bonjour! comment ca va?" 69 | TEXT <- "Örülök, hogy a városban élő" 70 | TEXT <- "ويسرني أن تكون البرمجة" 71 | TEXT <- "私は都市に住んでいることを嬉しく思います" 72 | TEXT <- "我很高興能住在城市" 73 | TEXT <- "நான் நகரத்தில் வாழும் வேண்டும் மகிழ்ச்சி அடைகிறேன்" 74 | TEXT <- "میں شہر میں رہنے کے لئے خوش ہوں" 75 | TEXT <- "Ես գոհ եմ, որ ապրում է քաղաքի" 76 | TEXT <- "Я радий жити в місті" 77 | TEXT <- "Би хотод амьдарч байгаадаа баяртай байна" 78 | TEXT <- "Είμαι στην ευχάριστη θέση να ζουν στην πόλη" 79 | language_analysis <- watson.language.analyze(TEXT) 80 | head(language_analysis) 81 | 82 | 83 | ####################### 84 | data <- read.csv("language_samples_raw.csv", header = FALSE) # no header, one single CSV column # need more work to handle the chinese,japanese characters 85 | data <- data.frame(data) 86 | data 87 | length <- dim(data)[1] # get height of the list, so we can size loop correctly. 88 | data$output_language <- "" 89 | data$output_confidence <- "" 90 | 91 | for (i in 1:length) 92 | { 93 | text <- paste(data$V1[i]) 94 | language_analysis <- watson.language.analyze(text) 95 | temp <- as.data.frame(language_analysis[1,]) 96 | print(paste(i," | Language:",temp$language, " | Confidence:",temp$confidence," | text analyzed:",text)) 97 | print(output) #show in terminal 98 | data$output_language[i] <- paste(temp$language) 99 | data$output_confidence[i] <- temp$confidence 100 | } 101 | head(data) 102 | write.csv(data, file = "language_post_analysis.csv") 103 | 104 | #========= 105 | 106 | 107 | ### FUNCTION - TRANSLATE AN ENGLISH SOURCE INTO REQUESTED LANGUAGE 108 | ##### FUNCTION - ANalyze TEXT/DOC RECEIVED and return language with confidence 109 | watson.language.translate1 <- function(text_input,language_to) 110 | { 111 | response <- (POST(url=paste(url,"/v2/translate",sep=""), 112 | authenticate(username,password), 113 | body = list(source = "en", 114 | target = language_to, 115 | text = text_input 116 | ) 117 | )) 118 | return(response) 119 | } 120 | 121 | # model_id": en-es-conversational. Options: Conversational News Patent 122 | 123 | # Translation is available among Arabic, English, French, Portuguese, and Spanish (KOrean & Chinese depend on region) 124 | translate_this <- "For gardens to flourish, they need good soil and regular water" 125 | translate_to <- "fr" # less options here - en, fr,es (spanish), ar (arabic), pt (portugese) 126 | reply <- watson.language.translate1(translate_this,translate_to) 127 | content(reply, "text") 128 | 129 | 130 | 131 | ##### FUNCTION - ANalyze TEXT/DOC RECEIVED and return language with confidence 132 | watson.language.translate.all <- function(text_input) 133 | { 134 | test[1] = paste(content(watson.language.translate1(text_input,"fr"),"text"),"fr") 135 | test[2] = paste(content(watson.language.translate1(text_input,"es"),"text"),"es") 136 | test[3] = paste(content(watson.language.translate1(text_input,"pt"),"text"),"pt") 137 | test[4] = paste(content(watson.language.translate1(text_input,"ar"),"text"),"ar") 138 | test <- data.frame(test) 139 | test <- paste(test$test) 140 | return(test) 141 | } 142 | 143 | response <- watson.language.translate.all("The IBM Watson Language Translation service converts text input in one language into a destination language for the end user using background from domain-specifc models. Translation is available among Arabic, English, French, Portuguese, and Spanish") 144 | response 145 | 146 | 147 | -------------------------------------------------------------------------------- /Watson-Machine-Learning-WML-codesnippets: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### IBM Watson - Code Snippet --- WATSON MACHINE LEARNING (WML) + R BASIC SCRIPTS 3 | ### Experimental Code. R Interface for IBM Watson Services 4 | ### Reference Documentation:# http://watson-ml-api.mybluemix.net/ 5 | # https://console.bluemix.net/catalog/services/machine-learning 6 | # https://datascience.ibm.com/blog/watson-machine-learning-general-availability/ 7 | # https://github.com/IBMDataScience/R4WML - with thanks to Davin Shearer's R4WML 8 | # https://console.bluemix.net/docs/#services/PredictiveModeling/index.html 9 | # http://watson-ml-api.mybluemix.net/ 10 | ##################################################### 11 | 12 | library(httr) 13 | library(splitstackshape) # for the text to colummns 14 | library(reshape2) 15 | 16 | ######### Housekeeping And Authentication 17 | setwd("/Users/ryan/Documents/WML") # Set working Directory 18 | getwd() 19 | 20 | url_WML = "https://ibm-watson-ml.mybluemix.net" 21 | 22 | source("keys.r") ## KEYS has acutal username:password for each IBM service. 23 | # OK Display Our Keys and Info - should all be populated 24 | url_WML # e.g. "https://ibm-watson-ml.mybluemix.net" 25 | version="v3" 26 | username_WML # e.g. "d921144d-99d2-489b-bbcb-XXXXXXXXX" SOURCE: Bluemix Service Credentials 27 | password_WML # e.g. "4bc0063e-7310-4645-84af-XXXXXXXXXX" SOURCE: Bluemix Service Credentials 28 | username_password_WML 29 | access_key_WML # e.g. "XXXXXXXXXXoi6fdc+9e8WbZDM+ZZQyyRKoXWp9peVGRlM1cs7+kbuUrfI0sllpbpxSFKe9cZoFYLlzgPf++qpWZYcXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" SOURCE: Bluemix Service Credentials 30 | instance_id_WML # e.g. "2aa3f5e0-51f5-4d02-bdbb-XXXXXXXXXX" # SOURCE: Bluemix Service Credentials 31 | deployment_id_WML # e.g. 523de722-d8ab-4012-83dc-XXXXXXXXXX # SOURCE: Deployment Overview https://mlaas-dashboard.mybluemix.net/#/deployments 32 | 33 | 34 | #' get_wml_auth_token() from R4WML 35 | get_wml_auth_token <- function(token_url, username, password) { 36 | req <- httr::GET(token_url, httr::authenticate(username, password), encoding = 'UTF-8') 37 | httr::stop_for_status(req, 'authenticate with WatsonML') 38 | json <- jsonlite::fromJSON(httr::content(req, as = 'text', type = 'application/json', encoding = 'UTF-8')) 39 | json$token 40 | } 41 | 42 | 43 | #1 -- TOKEN -- GET A TOKEN (And Confirm 200 Response) 44 | #Example of obtaining access token from Token Endpoint using HTTP Basic Auth (for details please refer to Token section below): 45 | #curl --basic --user username:password https://ibm-watson-ml.mybluemix.net/v3/identity/token 46 | response <- httr::GET(paste(url_WML,"/",version,"/identity/token",sep=""), httr::authenticate(username_WML, password_WML), encoding = 'UTF-8') 47 | httr::stop_for_status(req, 'authenticate with WatsonML') 48 | response # 200 response? 49 | json <- jsonlite::fromJSON(httr::content(response, as = 'text', type = 'application/json', encoding = 'UTF-8')) 50 | token_WML <- json$token 51 | token_WML 52 | authorization_headers_WML <- httr::add_headers('Authorization' = paste('Bearer', get_wml_auth_token(paste0(url_WML, '/v3/identity/token'), username_WML, password_WML ))) 53 | authorization_headers_WML 54 | 55 | #2 -- Service Instances -- GET INSTANCE IDS get /v3/wml_instances/{instance_id} 56 | #200 Works using Davin Shearer method watson_ml_creds_auth_headers 57 | 58 | response <- httr::GET(paste("https://ibm-watson-ml.mybluemix.net/v3/wml_instances/",instance_id_WML,sep=""), authorization_headers_WML, encoding = 'UTF-8', httr::verbose()) 59 | content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 60 | content(response) 61 | ## pull out response 62 | signal <- content(response) 63 | signal$entity$plan # what kind of WDC plan? 64 | signal$entity$owner$email # who is owner (email) 65 | signal$entity$usage$deployment_count$current # how many deployements on this instance? - add/check here in BMX - https://mlaas-dashboard.mybluemix.net/#/models 66 | 67 | 68 | 69 | #3 -- Published Models -- get /v3/wml_instances/{instance_id}/published_models http://watson-ml-api.mybluemix.net/#/ 70 | response <- httr::GET(paste("https://ibm-watson-ml.mybluemix.net/v3/wml_instances/",instance_id_WML,"/published_models",sep=""), authorization_headers_WML, encoding = 'UTF-8', httr::verbose()) 71 | content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 72 | content(response) 73 | ## pull out response 74 | signal <- content(response) 75 | signal 76 | 77 | 78 | for (i in 1:length(signal$resources)) 79 | { 80 | cat("\n") #newline 81 | print(paste("Model #",i)) 82 | print(paste("Model ID:",signal$resources[[i]]$entity$latest_version$guid)) 83 | print(paste("Meta ID:",signal$resources[[i]]$metadata$guid)) 84 | print(signal$resources[[i]]$entity$name) 85 | print(signal$resources[[i]]$entity$description) 86 | print(signal$resources[[i]]$entity$model_type) 87 | } 88 | 89 | # good to here 90 | 91 | # i=1 92 | # j=1 93 | 94 | #4 -- PUBLISHED MODELS -- Information of the specific published mode-- get /v3/wml_instances/{instance_id}/published_models/{published_model_id} 95 | for (i in 1:length(signal$resources)) 96 | { 97 | cat("\n") #newline 98 | response <- httr::GET(paste("https://ibm-watson-ml.mybluemix.net/v3/wml_instances/",instance_id_WML,"/published_models/",signal$resources[[i]]$metadata$guid,sep=""), authorization_headers_WML, encoding = 'UTF-8') 99 | signal2 <- content(response) 100 | signal2 101 | print(i) 102 | print(signal2$entity$name[1]) # always 1 103 | print(paste("Label Name: ",signal2$entity$label_col)) 104 | #signal2$entity$training_data_schema 105 | #print(length(signal2$entity$input_data_schema$fields)) # works for 4 columns, not for 1 106 | 107 | if(is.atomic(signal2$entity$input_data_schema)) 108 | { 109 | print(paste("LABEL:",signal2$entity$label_col)) 110 | } 111 | else{ 112 | q<-length(signal2$entity$input_data_schema$fields) 113 | #Trouble with COlumns less than 2 count 114 | for (j in 1:q){ 115 | print(paste("Column #",j,":",signal2$entity$input_data_schema$fields[[j]]$name)) 116 | } 117 | } 118 | } 119 | 120 | 121 | # good to here 122 | 123 | 124 | 125 | 126 | 127 | 128 | #5 -- DEPLOYMENTS & PREDICTIONS -- 129 | ## /v3/wml_instances/{instance_id}/published_models/{published_model_id}/deployments/{deployment_id}/online 130 | 131 | # instance_id_WML is instance_id_WML from KEYS.R - 2aa3f5e0-51f5-4d02-bdbb-XXXXXXXX 132 | # Published models : signal$resources[[i]]$metadata$guid (see above) - 116d1a1a-0914-4dda-865e-XXXXXXXXX 133 | # Deployment ID - ?? 523de722-d8ab-4012-83dc-XXXXXXXX (SOURCE: got this from BMX Dashboard ) https://mlaas-dashboard.mybluemix.net/#/deployment/id?_k=04mady - not sure if Callable from API 134 | #Scoring Endpoint (See abobe BMX WML dashboard) 135 | 136 | 137 | # GENDER,AGE,MARITAL_STATUS,PROFESSION,PRODUCT_LINE 138 | # M,27,Single,Professional,Personal Accessories 139 | 140 | response <- httr::POST(paste("https://ibm-watson-ml.mybluemix.net/v3/wml_instances/", 141 | instance_id_WML, 142 | "/published_models/", 143 | signal$resources[[1]]$metadata$guid, 144 | "/deployments/", 145 | deployment_id_WML, 146 | "/online", 147 | sep=""), 148 | authorization_headers_WML, 149 | httr::content_type_json(), 150 | body = '{"fields": ["GENDER","AGE","MARITAL_STATUS","PROFESSION"], 151 | "values": [ 152 | ["M",65,"Married","Executive"], 153 | ["F",33,"Single","Professional"], 154 | ["M",21,"Single","Professional"], 155 | ["M",55,"Married","Executive"], 156 | ["F",55,"Married","Professional"] 157 | ]}', 158 | encoding = 'UTF-8') 159 | response 160 | prediction <- content(response) 161 | prediction$values 162 | prediction$fields 163 | length(prediction$values) # count? 164 | 165 | # prediction$values[[4]][[12]] 166 | length(prediction) 167 | for (k in 1:length(prediction$values)){ 168 | print(paste(prediction$values[k][[1]][1],prediction$values[k][[1]][2],prediction$values[k][[1]][3]," || Prediction:",prediction$values[[k]][[14]][1])) 169 | } 170 | 171 | # Works! 200 - need to check what 172 | # [1] "M 65 Married || Prediction: Golf Equipment" 173 | # [1] "F 33 Single || Prediction: Personal Accessories" 174 | # [1] "M 21 Single || Prediction: Camping Equipment" 175 | # [1] "M 55 Married || Prediction: Golf Equipment" 176 | # [1] "F 55 Married || Prediction: Personal Accessories" 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /Watson-NLC-Basic-Functions.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. Experimental R Interface for IBM Watson Services - R. Anderson 3 | ### Focus: Natural Language Classifier - R Programming Language Interface 4 | ### Adapting the NLC APIs https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/ to RCURL 5 | ### Code is experimental, not official release and has not been QA'd / Please use with caution! 6 | ### All harry potter characters and concepts are property of JKR / HP publisher 7 | ###################################################### 8 | 9 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 10 | library(httr) 11 | library(XML) 12 | library(data.table) 13 | library(reshape2) 14 | library(tidyr) 15 | library(dplyr) 16 | library(stringr) 17 | library(splitstackshape) 18 | 19 | ## Before you begin you will need (1) An IBM Bluemix demo account (2) An NLC App and Service up and running (see documents http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/nl-classifier/ 20 | ## and (3) Credentials to that Service and confirm you're able to CURL service with 21 | ## curl -u "":"" "https://gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers" 22 | 23 | # PROBLEM > If you get this > Error in function (type, msg, asError = TRUE) : SSL certificate problem: self signed certificate in certificate chain 24 | # SOLUTION then you need to do this > YOU MUST KEEP THIS IN FOR below to work To begin: this line sets CERT Global to make a CA Cert go away - http://stackoverflow.com/questions/15347233/ssl-certificate-failed-for-twitter-in-r 25 | options(RCurlOptions = list(cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl"),httpauth=AUTH_BASIC)) # NOTE - the "httpauth=AUTH_BASIC" piece gets rid of the "Error: UNAUTHORIZED" message 26 | 27 | 28 | ######### Housekeeping And Authentication 29 | setwd("/Users/ryan/Documents/Project Daisy") 30 | base_url = "https://gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers/" 31 | username = "abc123-####-####-YOUR-CREDS-HERE" #### BE VERY CAREFUL TO understand "Instantiating Credentials" from bound service vs "Service Credentials" 32 | password = "123456789ABC" # you need your own ## if you are having authentication issues , may need the other creds. 33 | username_password = paste(username,":",password) 34 | 35 | ## Next - let's create all the functions (but not actually execute them just yet) 36 | 37 | ###### FUNCTION: LIST ALL CLASSIFIERS AND RETURN NEAT LIST 38 | watson.nlc.listallclassifiers <- function(){ 39 | data <- getURL(base_url,userpwd = username_password ) 40 | data <- as.data.frame(strsplit(as.character(data),"classifier_id")) 41 | data <- data[-c(1), ] # remove dud first row 42 | data <- data.frame(matrix(data)) 43 | colnames(data) <- "V1" 44 | data$V1 <- gsub("[{}]","", data$V1) 45 | data$V1 <- gsub("]","", data$V1) 46 | data$V1 <- gsub("\"","", data$V1) 47 | data$V1 <- gsub("name:","", data$V1) 48 | data$V1 <- gsub(":","", data$V1) 49 | data <- cSplit(data, 'V1', sep=",", type.convert=FALSE) 50 | data[,c(2,4)] <- NULL 51 | data <- as.data.table(data) 52 | setnames(data,c("classifier","name","date_created")) 53 | data <- data[order(date_created),] 54 | return(data) 55 | } 56 | 57 | 58 | ###### FUNCTION CREATE NEW CLASSIFIER - post /v1/classifiers - Creates a classifier with CSV data ## URL below no "/" after base url 59 | watson.nlc.createnewclassifier <- function(file,classifiername) { 60 | return(POST(url="https://gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers", 61 | authenticate(username,password), 62 | body = list(training_data = upload_file(file), 63 | training_metadata = paste("{\"language\":\"en\",\"name\":",classifiername,"}",sep="") 64 | ### IF YOU ARE GETTING METADATA ERRORS - MAY NEED TO QUOTIFY CLASSIFIER NAME 65 | ### training_metadata = paste("{\"language\":\"en\",\"name\":\"",classifiername,"\"}",sep="") # may come back 66 | 67 | )))} 68 | ###### end of function 69 | 70 | 71 | ###### FUNCTION - CHECK CLASSIFIER STATUS 72 | watson.nlc.checkclassifierstatus <- function(classifier_id) { 73 | return( 74 | getURL(paste(base_url,classifier_id,sep=""),userpwd = username_password) 75 | ) 76 | } 77 | ### end of function 78 | 79 | 80 | ###### FUNCTION - DELETE CLASSIFIER - Receives name of Classifier to Kill; May not be able to do this until training complete 81 | watson.nlc.deleteclassifier <- function(kill_classifier) { 82 | return(DELETE(paste(base_url,kill_classifier,sep=""), 83 | userpwd = username_password)) } 84 | ### end of function 85 | 86 | 87 | ###### FUNCTION: ACCEPT QUERY & RETURN RESULT: CLASSIFIER and % FROM TEXT INPUT AND PROCESS TO LOOK GOOD 88 | watson.nlc.processtextreturnclass <- function(classifier_id,query_text){ 89 | query_text <- URLencode(query_text) 90 | data <- getURL(paste(base_url,classifier_id,"/classify","?text=", query_text,sep=""),userpwd = username_password) 91 | data <- as.data.frame(strsplit(as.character(data),"class_name")) 92 | data <- data[-c(1), ] # remove dud first row 93 | data <- gsub("[{}]","", data) 94 | data <- gsub("confidence","", data) 95 | data <- data.frame(matrix(data)) 96 | setnames(data,("V1")) 97 | data$V1 <- gsub("\"","", data$V1) 98 | data$V1 <- gsub(":","", data$V1) 99 | data$V1 <- gsub("]","", data$V1) 100 | data <- cSplit(data, 'V1', sep=",", type.convert=FALSE) 101 | setnames(data,c("class","confidence")) 102 | return(data) } 103 | ### end of function 104 | 105 | 106 | ######################################################### END OF FUNCTION DECLARATIONS 107 | 108 | ######## OK - let's do stuff! 109 | 110 | ###### ACTION: Create a new CLassifier! (200 = Good outcome) - 111 | thefile <- "sortinghat.csv" #you'll need a local CSV file, in the right directory, that is 'ground truth' to train the NLC. 112 | thename <- "\"sortinghat104\"" # what you want to call it - can be anything you like 113 | watson.nlc.createnewclassifier(thefile,thename) # calls function, passes file and name from above, starts the magic. might take 2 to 20+ minutes depending on complexity 114 | 115 | 116 | ###### ACTION: Retrieve list of classifiers (NEAT VERSION) - oldest to newest 117 | watson.nlc.listallclassifiers() 118 | # ALternate: messy version # getURL(base_url,userpwd = username_password ) #not formatted, see below for formatting 119 | 120 | 121 | ###### ACTION: CHECK CLASSIFIER STATUS (pick the one from bottom of list above, that's newest one you just made) 122 | status <- "950DCB-nlc-###" 123 | watson.nlc.checkclassifierstatus(status) 124 | ## if new will say "not yet ready to accept classify requests" - once done in a few mintues will say 125 | ## "The classifier instance is now available and is ready to take classifier requests" - then you can submit query below 126 | 127 | 128 | ################################################################## 129 | ##### ACTION: LET'S GO! SUBMIT TEXT AND CLASSIFY, RETURN CLASS / % 130 | classifier = "950DCB-nlc-###" 131 | 132 | query = "I am brave and strong" 133 | watson.nlc.processtextreturnclass(classifier,query) 134 | 135 | query = "I am mean and nasty and love snakes" 136 | watson.nlc.processtextreturnclass(classifier,query) 137 | 138 | query = "I am clever and brainy" 139 | watson.nlc.processtextreturnclass(classifier,query) 140 | 141 | query = "I am a loyal friend" 142 | watson.nlc.processtextreturnclass(classifier,query) 143 | 144 | 145 | ################################################################## 146 | 147 | 148 | ##### ACTION: EXECUTE FUNCTION TO KILL (!!!) DELETE (!!!) CLASSIFIER - WARNING 149 | kill <- "950DCB-nlc-###" 150 | watson.nlc.deleteclassifier(kill) 151 | 152 | ## More NLC API DOCS here: https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/natural-language-classifier/api/v1/#authentication 153 | 154 | 155 | Copyright 2015 Ryan Anderson 156 | 157 | Licensed under the Apache License, Version 2.0 (the "License"); 158 | you may not use this file except in compliance with the License. 159 | You may obtain a copy of the License at 160 | 161 | http://www.apache.org/licenses/LICENSE-2.0 162 | 163 | Unless required by applicable law or agreed to in writing, software 164 | distributed under the License is distributed on an "AS IS" BASIS, 165 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 166 | See the License for the specific language governing permissions and 167 | limitations under the License. 168 | -------------------------------------------------------------------------------- /Watson-NLC-SMS-Test-Condition.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. Experimental R Interface for IBM Watson Services - 3 | ### Focus: Natural Language Classifier - R Programming Language Interface 4 | ###################################################### 5 | 6 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 7 | library(httr) 8 | library(audio) 9 | library(data.table) 10 | library(dplyr) 11 | library(reshape2) 12 | library(Rtts) 13 | library(splitstackshape) 14 | library(seewave) # need to play wav back? 15 | library(stringr) 16 | library(splitstackshape) 17 | library(tidyr) 18 | library(XML) 19 | library(png) 20 | 21 | ######### Housekeeping And Authentication 22 | 23 | setwd("/Users/ryan/Documents/Service - Natural Language Classifier (NLC)") # Set working Directory 24 | getwd() 25 | source("keys.r") ## KEYS has acutal username:password for each IBM service. Seperate R file looks sort of like below 26 | 27 | username_password_NLC # check you got this from NLC file 28 | base_url_NLC = "https://gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers/" 29 | getURL(base_url_NLC,userpwd = username_password_NLC ) # non essential , but checks if working /authenticated 30 | 31 | ###### FUNCTION CREATE NEW CLASSIFIER - post /v1/classifiers - Creates a classifier with CSV data ## URL below no "/" after base url 32 | watson.nlc.createnewclassifier <- function(file,classifiername) { 33 | return(POST(url="https://gateway.watsonplatform.net/natural-language-classifier/api/v1/classifiers", 34 | authenticate(username_NLC,password_NLC), 35 | body = list(training_data = upload_file(file), 36 | training_metadata = paste("{\"language\":\"en\",\"name\":",classifiername,"}",sep="") 37 | )))} 38 | ###### end of function 39 | 40 | ###### FUNCTION - CHECK CLASSIFIER STATUS 41 | watson.nlc.checkclassifierstatus <- function(classifier_id) { 42 | return( 43 | getURL(paste(base_url_NLC,classifier_id,sep=""),userpwd = username_password_NLC) 44 | ) 45 | } 46 | ### end of function 47 | 48 | 49 | ###### FUNCTION - DELETE CLASSIFIER - Receives name of Classifier to Kill; May not be able to do this until training complete 50 | watson.nlc.deleteclassifier <- function(kill_classifier) { 51 | DELETE(url=(paste(base_url_NLC,kill_classifier,sep="")),authenticate(username_NLC,password_NLC)) 52 | } 53 | 54 | ### end of function 55 | 56 | ###### FUNCTION: ACCEPT QUERY & RETURN RESULT: CLASSIFIER and % FROM TEXT INPUT AND PROCESS TO LOOK GOOD 57 | watson.nlc.processtextreturnclass <- function(classifier_id,query_text){ 58 | query_text <- URLencode(query_text) 59 | data <- getURL(paste(base_url_NLC,classifier_id,"/classify","?text=", query_text,sep=""),userpwd = username_password_NLC) 60 | data <- as.data.frame(strsplit(as.character(data),"class_name")) 61 | data <- data[-c(1), ] # remove dud first row 62 | data <- gsub("[{}]","", data) 63 | data <- gsub("confidence","", data) 64 | data <- data.frame(matrix(data)) 65 | setnames(data,("V1")) 66 | data$V1 <- gsub("\"","", data$V1) 67 | data$V1 <- gsub(":","", data$V1) 68 | data$V1 <- gsub("]","", data$V1) 69 | data <- cSplit(data, 'V1', sep=",", type.convert=FALSE) 70 | setnames(data,c("class","confidence")) 71 | return(data) } 72 | ### end of function 73 | 74 | ###### FUNCTION: LIST ALL CLASSIFIERS AND RETURN NEAT LIST 75 | watson.nlc.listallclassifiers <- function(){ 76 | data <- getURL(base_url_NLC,userpwd = username_password_NLC ) 77 | data <- as.data.frame(strsplit(as.character(data),"classifier_id")) 78 | data <- data[-c(1), ] # remove dud first row 79 | data <- data.frame(matrix(data)) 80 | colnames(data) <- "V1" 81 | data$V1 <- gsub("[{}]","", data$V1) 82 | data$V1 <- gsub("]","", data$V1) 83 | data$V1 <- gsub("\"","", data$V1) 84 | data$V1 <- gsub("name:","", data$V1) 85 | data$V1 <- gsub(":","", data$V1) 86 | data <- cSplit(data, 'V1', sep=",", type.convert=FALSE) 87 | data[,c(2,4)] <- NULL 88 | data <- as.data.table(data) 89 | setnames(data,c("classifier","name","date_created")) 90 | data <- data[order(date_created),] 91 | return(data) 92 | } 93 | 94 | ##### ACTION: EXECUTE FUNCTION TO KILL (!!!) DELETE (!!!) CLASSIFIER - WARNING 95 | watson.nlc.listallclassifiers() # inventory - what do we want to delete - classifier id 96 | # kill <- "563C46x19-nlc-XXX" 97 | # watson.nlc.deleteclassifier(kill) 98 | # watson.nlc.listallclassifiers() # check it's gone 99 | 100 | 101 | ######################################################### END OF FUNCTION DECLARATIONS 102 | 103 | 104 | ######################################################### OK LETS DO STUFF 105 | 106 | 107 | ###### ACTION: Create a new CLassifier! (200 = Good outcome) - 108 | thename <- "\"SMS-NLC-Opt-Out-Test-V1\"" 109 | thefile <- "SMS-NLC-Opt-Out-Test-V1.csv" # 110 | # watson.nlc.createnewclassifier(thefile,thename) # calls function, passes file and name from above, starts the magic. might take 2 to 20+ minutes depending on complexityclassifier_id" : "563C46x19-nlc-377", 111 | # "classifier_id" : "beb9bfx46-nlc-XXX", 112 | # "name" : "SMS-NLC-Opt-Out-Test-V1", 113 | # "language" : "en", 114 | # "created" : "2016-03-30T01:34:30.297Z", 115 | # if new will say "not yet ready to accept classify requests" - once done in a few mintues will say 116 | # "The classifier instance is now available and is ready to take classifier requests" - then you can submit query below 117 | 118 | ###### ACTION: Retrieve list of classifiers (NEAT VERSION) - oldest to newest 119 | watson.nlc.listallclassifiers() # not happy response if no classifiers (Blank) if blank, use below 120 | 121 | #getURL(base_url_NLC,userpwd = username_password_NLC ) #not formatted, see below for formatting 122 | 123 | classifierA <- "beb9bfx46-nlc-XXX" # name SMS-NLC-Opt-Out-Test-V1 124 | watson.nlc.checkclassifierstatus(classifierA) 125 | query <- "I'm going to take Sally to the store for an ice cream cone" 126 | watson.nlc.processtextreturnclass(classifierA,query) 127 | 128 | query <- "please remove me from your distro" 129 | watson.nlc.processtextreturnclass(classifierA,query) 130 | 131 | query <- "REMOVE - do not text" 132 | watson.nlc.processtextreturnclass(classifierA,query) 133 | 134 | 135 | 136 | #========= 137 | ### Simple test - no trasaction - simply asking how m 138 | SMS_test <- matrix(0, ncol = 4, nrow = 20) # Later just import from CSV. Col 1 input; col2 results 139 | SMS_test[1] <- "hey - will be late for dinner" 140 | SMS_test[2] <- "where are you?" 141 | SMS_test[3] <- "did you walk dog?" 142 | SMS_test[4] <- "where r u?" 143 | SMS_test[5] <- "lol! " 144 | SMS_test[6] <- "see you soon" 145 | SMS_test[7] <- "unsubscribe" 146 | SMS_test[8] <- "where is Jason?" 147 | SMS_test[9] <- "remove me from SMS distro please" 148 | SMS_test[10] <- "pick up some gluten free beer" 149 | SMS_test[11] <- "your uber is about to arrive" 150 | SMS_test[12] <- "can you call me back?" 151 | SMS_test[13] <- "remove" 152 | SMS_test[14] <- "STOP texting me!" 153 | SMS_test[15] <- "dog ate homework" 154 | SMS_test[16] <- "IBM watson amazing!" 155 | SMS_test[17] <- "sorry" 156 | SMS_test[18] <- "just arrived" 157 | SMS_test[19] <- "this is a palendrome - sit on a potato pan otis" 158 | SMS_test[20] <- "the quick brown fox jumped over the lazy cat" 159 | 160 | dim(SMS_test)[1] 161 | 162 | ### Lets' test this baby - and time it! 163 | 164 | for (i in 1:dim(SMS_test)[1]){ 165 | ptm <- proc.time() # start timer for this i 166 | print(SMS_test[i]) 167 | query <- SMS_test[i] 168 | response <- watson.nlc.processtextreturnclass(classifierA,query) 169 | elapsed <- proc.time() - ptm 170 | SMS_test[i,2] <- elapsed[3] # store time to complete for this i 171 | SMS_test[i,3] <- response$class[1] 172 | SMS_test[i,4] <- response$confidence[1] 173 | } 174 | 175 | SMS_test <- data.frame(SMS_test) 176 | setnames(SMS_test,c("SMS","response_time","class","confidence")) 177 | SMS_test 178 | SMS_test$response_time <- as.matrix(SMS_test$response_time) # the long way around - but works 179 | SMS_test$response_time <- as.numeric(SMS_test$response_time) # the long way around - but works 180 | summary(SMS_test$response_time) 181 | plot(SMS_test$response_time, main="NLC Response Time Test - SMS 20 samples \n Varied inputs - 10k ground truth") 182 | 183 | write.csv(SMS_test,"SMS_test_results_V1.csv") 184 | 185 | 186 | 187 | #### 100 sample test - same query each time 188 | query <- "there once was a small dog that ran over my foot when it was nearing the barn. I was surprised!" 189 | SMS_test <- matrix(0, ncol = 2, nrow = 100) # 190 | for (i in 1:dim(SMS_test)[1]){ 191 | ptm <- proc.time() # start timer for this i 192 | watson.nlc.processtextreturnclass(classifierB,query) 193 | elapsed <- proc.time() - ptm 194 | SMS_test[i,2] <- elapsed[3] # store time to complete for this i 195 | } 196 | SMS_test <- data.frame(SMS_test) 197 | setnames(SMS_test,c("SMS","response_time")) 198 | SMS_test 199 | SMS_test$response_time <- as.matrix(SMS_test$response_time) # the long way around - but works 200 | SMS_test$response_time <- as.numeric(SMS_test$response_time) # the long way around - but works 201 | summary(SMS_test$response_time) 202 | plot(SMS_test$response_time, main="NLC Response Time Test - 100 samples \n Identical input LONG UTTERANCE") 203 | 204 | # SHORT UTTERANCE 205 | # Min. 1st Qu. Median Mean 3rd Qu. Max. 206 | # 0.5560 0.6722 0.7535 0.8535 0.8970 1.8920 207 | # 208 | # LONG UTTERANCE 209 | # Min. 1st Qu. Median Mean 3rd Qu. Max. 210 | # 0.5790 0.7082 0.8240 0.9149 0.9715 3.3150 211 | 212 | -------------------------------------------------------------------------------- /Watson-NLU-Basic-Functions.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. Experimental R Interface for IBM Watson Services - R. Anderson 3 | ### Focus: NLU - Natural Language Understanding 4 | ### https://www.ibm.com/watson/developercloud/natural-language-understanding.html 5 | ### Code is experimental / Please use with caution! 6 | ###################################################### 7 | 8 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 9 | library(httr) 10 | library(XML) 11 | library(data.table) 12 | library(reshape2) 13 | library(tidyr) 14 | library(dplyr) 15 | library(stringr) 16 | library(splitstackshape) 17 | 18 | 19 | ## Before you begin you will need (1) An IBM Bluemix demo account (2) BLuemix account https://console.ng.bluemix.net/ 20 | ## and (3) Credentials to NLU Service /service and confirm you're able to CURL service with 21 | ## curl from https://www.ibm.com/watson/developercloud/natural-language-understanding/api/v1/ 22 | 23 | 24 | # PROBLEM > If you get this > Error in function (type, msg, asError = TRUE) : SSL certificate problem: self signed certificate in certificate chain 25 | # SOLUTION then you need to do this > YOU MUST KEEP THIS IN FOR below to work To begin: this line sets CERT Global to make a CA Cert go away - http://stackoverflow.com/questions/15347233/ssl-certificate-failed-for-twitter-in-r 26 | options(RCurlOptions = list(cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl"),httpauth=AUTH_BASIC)) # NOTE - the "httpauth=AUTH_BASIC" piece gets rid of the "Error: UNAUTHORIZED" message 27 | 28 | 29 | ######### Housekeeping And Authentication 30 | setwd("/Users/ryan/Documents/Service - NLU") # i'm on a mac 31 | getwd() 32 | 33 | source("keys.r") ## KEYS has acutal username:password for each IBM service. 34 | 35 | url_NLU="https://gateway.watsonplatform.net/natural-language-understanding/api" 36 | username_NLU # check we got it from KEYs.R file in same directory - looks like this - "e63f524d-9999-9999-9999-e6b1d4e99b87" 37 | password_NLU # check we got it from KEYs.R file in same directory - looks like this - "ABCD0EggCXYZ" 38 | version="?version=2017-02-27" 39 | 40 | ## WORKS ## curl -G -u "6b4f8dae-xxxx-4344-xxxx-e8cac7572bf0":"21xxxxbxxxDS" -d "version=2017-02-27" -d "url=www.ibm.com" -d "features=keywords,entities" -d "entities.emotion=true" -d "entities.sentiment=true" -d "keywords.emotion=true" -d "keywords.sentiment=true" "https://gateway.watsonplatform.net/natural-language-understanding/api/v1/analyze" 41 | 42 | #WORKS 43 | POST(url="https://gateway.watsonplatform.net/natural-language-understanding/api/v1/analyze?version=2017-02-27&url=www.ibm.com&features=keywords,entities", 44 | authenticate(username_NLU,password_NLU), 45 | add_headers("Content-Type"="application/json") 46 | ) 47 | 48 | #WORKS - PASS URL 49 | response <- POST(url=paste( 50 | url_NLU, 51 | "/v1/analyze", 52 | version, 53 | "&url=www.ibm.com", 54 | "&features=keywords,entities", 55 | "&entities.emotion=true", 56 | "&entities.sentiment=true", 57 | "&keywords.emotion=true", 58 | "&keywords.sentiment=true", 59 | sep=""), 60 | authenticate(username_NLU,password_NLU), 61 | add_headers("Content-Type"="application/json") 62 | ) 63 | 64 | response 65 | content(response) 66 | 67 | 68 | #WORKS - PASS TEXT (url encoded) 69 | raw_text <- "IBM is an American multinational technology company headquartered in Armonk, New York, United States, with operations in over 170 countries" 70 | raw_text <- "I love ice cream and unicorns! I love Vancouver" 71 | text <- URLencode(raw_text) 72 | 73 | response <- POST(url=paste( 74 | url_NLU, 75 | "/v1/analyze", 76 | version, 77 | "&text=",text, 78 | "&features=keywords,entities", 79 | "&entities.emotion=true", 80 | "&entities.sentiment=true", 81 | "&keywords.emotion=true", 82 | "&keywords.sentiment=true", 83 | sep=""), 84 | authenticate(username_NLU,password_NLU), 85 | add_headers("Content-Type"="application/json") 86 | ) 87 | 88 | response 89 | response$headers 90 | response$headers$date 91 | 92 | 93 | ## pull out response 94 | signal <- content(response) 95 | 96 | signal$language #"en" 97 | signal$keywords # [[8]]$emotion$joy [1] 0.041067 98 | signal$entities # [[4]]$disambiguation$dbpedia_resource [1] "http://dbpedia.org/resource/United_States" 99 | 100 | keywords <- signal$keywords 101 | length(keywords) 102 | for(i in 1:length(keywords)) 103 | { 104 | #print("hi") 105 | #print(keywords[[i]]$text) 106 | print(paste(keywords[[i]]$text," sentiment:",keywords[[i]]$sentiment$score)) 107 | } 108 | 109 | 110 | # [1] "ice cream sentiment: 0.599941" 111 | # [1] "unicorns sentiment: 0.599941" 112 | 113 | ###### 114 | 115 | entities <- signal$entities 116 | for(i in 1:length(entities)) 117 | { 118 | #print("hi") 119 | print(entities[[i]]$text) 120 | } 121 | 122 | 123 | entities[[1]]$text 124 | entities[[1]]$type 125 | entities[[1]]$sentiment$score 126 | 127 | # > entities[[1]]$text 128 | # [1] "Vancouver" 129 | # > entities[[1]]$type 130 | # [1] "Location" 131 | # > entities[[1]]$sentiment$score 132 | # [1] 0.732329 133 | 134 | 135 | 136 | #### 137 | 138 | ### not complete..... hope this helps though! 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /Watson-PERSONALITY-INSIGHTS-analyze100speakers.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. R Interface for IBM Watson Services 3 | ### Focus: PERSONALITY INSIGHTS - USER PERSONAE SEGMENTATION - R Programming Language Interface 4 | ### Adapting the PERSONALITY INSIGHTS APIs https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/ to RCURL and HTTR 5 | ### DOCS: https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/personality-insights/ 6 | ### REFERENCE https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/personality-insights/api/v2/ 7 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) A dialog App and (3) Credentials to that Service and confirm you're able to CURL service with 8 | ###################################################### 9 | 10 | ### Warning - this is experimental code - it runs, but has not been reviewed and is rough around the edges 11 | ### Demo - try this to familiarize yourself with service: https://watson-pi-demo.mybluemix.net 12 | 13 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 14 | library(httr) 15 | library(XML) 16 | library(data.table) 17 | library(reshape2) 18 | library(dplyr) 19 | library(stringr) 20 | library(reshape2) 21 | 22 | setwd("/Users/ryan/Documents/Project Daisy") # contains a CSV for me to look up external content to scrape 23 | 24 | # Personality-Insights-Service-Blue - credentials" 25 | pi_url="https://gateway.watsonplatform.net/personality-insights/api/v2/profile" 26 | username = "555555-5555-5555-5555-55555555" # your own here 27 | password = "444444444" # your own here 28 | username_password = paste(username,":",password,sep="") 29 | alldata <- data.frame(NULL) # where we will store our analysis 30 | 31 | ###### FUNCTION - ANalyze TEXT/DOC RECEIVED with Personality Insights servicen and return Analysis 32 | watson.personality_insights.analyze <- function(TEXT) 33 | { 34 | return(POST(url=pi_url, 35 | authenticate(username,password), 36 | add_headers("Content-Type"="text/plain","charset"="utf-8" ), 37 | body = TEXT 38 | )) 39 | } 40 | ## Works: ## curl -X POST -u $USERNAME:$PASSWORD -H "Content-Type: text/plain" -d "$PROFILE" "https://gateway.watsonplatform.net/personality-insights/api/v2/profile" 41 | 42 | 43 | #### FUNCTION TO TIDY UP THE PI RESPONSE TO TABLE FORMAT - some rough methods that can be improved below 44 | tidyResponse <- function(data) 45 | { 46 | data <- as.data.frame(strsplit(as.character(data),"\"id\":\"")) 47 | data <- data[-c(1:5), ] # remove dud first row 48 | data <- data.frame(matrix(data)) 49 | data[,1] <- gsub("\"","",data[,1] ) 50 | data <- data.frame(do.call('rbind', strsplit(as.character(data$matrix.data),',',fixed=TRUE))) 51 | data <- data[!grepl('name:',data$X5),] 52 | data <- data[!grepl('children:',data$X5),] 53 | data <- data[,-c(2,6), ] # remove columns we dont need - duplicates or dont care for SAMPLING ERROR (now) but mght later 54 | setnames(data,c("trait","category","percentage","error")) 55 | data$percentage <- gsub("percentage:","",data$percentage) 56 | data$category <- gsub("category:","",data$category) 57 | data$error <- gsub("sampling_error:","",data$error) 58 | data$error <- gsub("}","",data$error) # crude but effective 59 | data$error <- gsub("]","",data$error) # crude but effective 60 | data$percentage <- round((as.numeric(data$percentage)),4) # if you prefer % format like this 61 | data$error <- round((as.numeric(data$error)),4) # if you prefer % format like this 62 | rownames(data) <- NULL # resets row names to remove 'gaps' 63 | data$row <- as.numeric(rownames(data)) 64 | return(data) 65 | } 66 | 67 | ########## FUNCTION - ScreenScrape support Clean up Response from HTML to DOC.TXT (import speeches) 68 | cleanDoc <- function(doc) { 69 | doc <- gsub("<.*?>", "", doc) 70 | doc <- gsub("\\t","",doc) 71 | doc <- gsub("\\n","",doc) 72 | doc <- gsub("\\r","",doc) 73 | doc <- gsub("\\t","",doc) 74 | doc <- gsub("\\n","",doc) 75 | doc <- gsub("\\r","",doc) 76 | doc <- gsub(" ","",doc) 77 | doc <- gsub(""","",doc) 78 | return(doc) 79 | } 80 | ## this is optimized for *test code* from http://www.americanrhetoric.com/top100speechesall.html - but you should substitute your own, and tailor scrubbers 81 | ## for CSV - i did (a) a MANUAL transfer to XLS of the 100 urls -(b) removed atypicals, and (c) set up in a way 82 | ## source site is copyright ar and many speeches, as they noted, are copyright or public domain, as noted in text. Can also scrape library of congress - for example only 83 | ## format used here for this example ( you should map to your own) 84 | ## index speaker speech_name URL 85 | ## 1 Martin Luther King, Jr. I Have A Dream http://www.americanrhetoric.com/speeches/mlkihaveadream.htm 86 | ## 2 John Fitzgerald Kennedy Inaugural Address http://www.americanrhetoric.com/speeches/jfkinaugural.htm 87 | 88 | 89 | ###### OK - LET'S GO! ACTION! 90 | 91 | ####################### THIS PART OF THE CODE IS FIGURE OUT HOW TO SCRAPE/IMPORT TEST TEXT/CORPUS FOR ANALYSIS 92 | getwd() 93 | speeches <- read.csv("speeches.csv",header=TRUE) 94 | speeches <- data.frame(speeches) 95 | speeches 96 | length <- dim(speeches)[1]+0 # how long is our list? 97 | for (i in 1:length) 98 | { 99 | doc <- getURL(speeches$URL[i]) 100 | doc <- cleanDoc(doc) 101 | response <- watson.personality_insights.analyze(doc) 102 | data <- content(response, "text") # here are the personality insights! 103 | data <- tidyResponse(data) 104 | data$speaker <- paste(speeches$speaker[i],"#",i) # adds the 'who' attribute # number for repeat people 105 | data$speech_name <- speeches$speech_name[i] # adds speec 106 | alldata <- rbind(alldata,data) 107 | print(paste("processed: ",speeches$speaker[i],"#",i,speeches$speech_name[i])) 108 | } # takes about 60 seconds to process 95 speeches 109 | head(alldata) 110 | 111 | #alldata <- setNames(alldata,c("trait","category","percentage","error","row","speaker","speech_name")) 112 | #alldata_backup = alldata 113 | #write.csv(alldata,"post-process-PI.csv") 114 | 115 | head(alldata) ## END OF CHAPTER - FULL DATA SET - YOU SHOULD HAVE nearly 100 people/speeches and 52 traits for each one (nearly 5k rows of 7 variables) 116 | 117 | ####### OK - Next CHapter - let's play around a little Look at a few things 118 | 119 | alldata <- alldata[,-c(2,4,5) ] # remove category, error, row 120 | alldata$percentage <- as.numeric(alldata$percentage) # keep things numeric 121 | alldata$speaker <- gsub("\\\\","",alldata$speaker) # keep things clean 122 | alldata$speech_name <- gsub("\\\\","",alldata$speech_name) # keep things clean 123 | 124 | ## Ok let's melt (elongate) along speaker speech and trait 125 | alldata.melted <- melt(alldata,id.vars = c("speaker", "speech_name", "trait")) 126 | head(alldata.melted) 127 | alldata.cast <- dcast(alldata.melted, speaker ~ trait) ### PIVOT TABLE STYLE - Traits on top on X axis, speaker on Y 128 | head(alldata.cast) ## SUCCESS! 129 | write.csv(alldata.cast,"post-process-PI-pivot.csv") 130 | 131 | 132 | ### IF YOU LOOK AT this data in alldata.cast, you can see it's pretty much ready for you to 'take it' and translate it to test/validate/explore your hypothesis 133 | 134 | 135 | # speaker Achievement Activity level Adventurousness Agreeableness Altruism 136 | #76 Ronald Wilson Reagan # 29 0.5469 0.2969 0.7036 0.9306 0.9518 137 | #16 Dorothy Ann Willis Richards 0.1508 0.2259 0.3805 0.9849 0.9499 138 | #78 Ronald Wilson Reagan # 7 0.3052 0.2881 0.6313 0.9548 0.9483 139 | #37 Geraldine Anne Ferraro # 54 0.6561 0.642 0.6502 0.9206 0.9355 140 | #45 Jesse Louis Jackson # 47 0.2901 0.3477 0.4982 0.9362 0.9331 141 | #58 Lyndon Baines Johnson # 89 0.4653 0.1804 0.8074 0.8046 0.9261 142 | 143 | 144 | 145 | # end of chapter - end of code 146 | # other code can take it from here here, clustering, Kohonen self organizing maps, devleopment of user personae, and machine learning (random forest) on this source info to for validation and testing of hypotheses 147 | 148 | 149 | # for more information on the service 150 | # http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/personality-insights.html 151 | # science behind (and limitations of) the service: http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/personality-insights/science.shtml 152 | 153 | 154 | # LIST OF TRAITS: 155 | # "Achievement striving" "Activity level" "Adventurousness" 156 | # "Agreeableness" "Altruism" "Anger" "Anxiety" 157 | # "Artistic interests" "Assertiveness" "Cautiousness" "Challenge" 158 | # "Cheerfulness" "Closeness" "Conscientiousness" "Conservation" 159 | # "Cooperation" "Curiosity" "Depression" "Dutifulness" 160 | # "Emotionality" "Excitement" "Excitement-seeking" "Extraversion" 161 | # "Friendliness" "Gregariousness" "Harmony" "Hedonism" 162 | # "Ideal" "Imagination" "Immoderation" "Intellect" 163 | # "Liberalism" "Liberty" "Love" "Modesty" 164 | # "Morality" "Neuroticism" "Openness" "Openness to change" 165 | # "Orderliness" "Practicality" "Self-consciousness" "Self-discipline" 166 | # "Self-efficacy" "Self-enhancement" "Self-expression" "Self-transcendence" 167 | # "Stability" "Structure" "Sympathy" "Trust" 168 | # "Vulnerability" 169 | 170 | 171 | 172 | Copyright 2015 Ryan Anderson 173 | 174 | Licensed under the Apache License, Version 2.0 (the "License"); 175 | you may not use this file except in compliance with the License. 176 | You may obtain a copy of the License at 177 | 178 | http://www.apache.org/licenses/LICENSE-2.0 179 | 180 | Unless required by applicable law or agreed to in writing, software 181 | distributed under the License is distributed on an "AS IS" BASIS, 182 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 183 | See the License for the specific language governing permissions and 184 | limitations under the License. 185 | -------------------------------------------------------------------------------- /Watson-PERSONALITY-INSIGHTS-codesnippet.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. R Interface for IBM Watson Services 3 | ### Focus: PERSONALITY INSIGHTS - USER PERSONAE SEGMENTATION - R Programming Language Interface 4 | ### Adapting the PERSONALITY INSIGHTS APIs https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/ to RCURL and HTTR 5 | ### DOCS: https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/personality-insights/ 6 | ### REFERENCE https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/personality-insights/api/v2/ 7 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) A dialog App and (3) Credentials to that Service and confirm you're able to CURL service with 8 | ###################################################### 9 | 10 | ## this is a code snippet for educational purposes only 11 | 12 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 13 | library(httr) 14 | 15 | # PROBLEM > If you get this > Error in function (type, msg, asError = TRUE) : SSL certificate problem: self signed certificate in certificate chain 16 | # SOLUTION then you need to do this > YOU MUST KEEP THIS IN FOR below to work To begin: this line sets CERT Global to make a CA Cert go away - http://stackoverflow.com/questions/15347233/ssl-certificate-failed-for-twitter-in-r 17 | options(RCurlOptions = list(cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl"),httpauth=AUTH_BASIC)) # NOTE - the "httpauth=AUTH_BASIC" piece gets rid of the "Error: UNAUTHORIZED" message 18 | 19 | 20 | # Personality-Insights-Service-Blue - credentials" 21 | pi_url="https://gateway.watsonplatform.net/personality-insights/api/v2/profile" 22 | username = "5555555-5555-5555-5555-5555555555" # yours goes here from service credentials 23 | password = "4444444444" # yours goes here from service credentials 24 | username_password = paste(username,":",password,sep="") 25 | 26 | 27 | ###### FUNCTION - ANalyze text with Personality Insights service 28 | watson.personality_insights.analyze <- function(TEXT) 29 | { 30 | return(POST(url=pi_url, 31 | authenticate(username,password), 32 | add_headers("Content-Type"="text/plain","charset"="utf-8" ), 33 | body = TEXT 34 | )) 35 | } 36 | # hope this helps you with syntax! 37 | 38 | ## Works at command line : ## curl -X POST -u $USERNAME:$PASSWORD -H "Content-Type: text/plain" -d "$PROFILE" "https://gateway.watsonplatform.net/personality-insights/api/v2/profile" 39 | 40 | 41 | #### FUNCTION TO TIDY UP THE PI RESPONSE TO TABLE - not pretty at 11:30pm - but it works 42 | tidyResponse <- function(data) 43 | { 44 | data <- as.data.frame(strsplit(as.character(data),"\"id\":\"")) 45 | data <- data[-c(1:5), ] # remove dud first row 46 | data <- data.frame(matrix(data)) 47 | data[,1] <- gsub("\"","",data[,1] ) 48 | data <- data.frame(do.call('rbind', strsplit(as.character(data$matrix.data),',',fixed=TRUE))) 49 | data <- data[!grepl('name:',data$X5),] 50 | data <- data[!grepl('children:',data$X5),] 51 | data <- data[,-c(2,6), ] # remove columns we dont need - duplicates or dont care for SAMPLING ERROR (now) but mght later 52 | setnames(data,c("trait","category","percentage","error")) 53 | data$percentage <- gsub("percentage:","",data$percentage) 54 | data$category <- gsub("category:","",data$category) 55 | data$error <- gsub("sampling_error:","",data$error) 56 | data$error <- gsub("}","",data$error) # crude but effective 57 | data$error <- gsub("]","",data$error) # crude but effective 58 | data$percentage <- round((as.numeric(data$percentage)),4) # if you prefer % format like this 59 | data$error <- round((as.numeric(data$error)),4) # if you prefer % format like this 60 | rownames(data) <- NULL # resets row names to remove 'gaps' 61 | data$row <- as.numeric(rownames(data)) 62 | return(data) 63 | } # warning - this code seems to work but has not been verified - please be careful 64 | 65 | 66 | ### OK - let's test! 67 | 68 | TEXT_TO_ANALYZE="Call me Ishmael. Some years ago-never mind how long precisely-having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off-then, I account it high time to get to sea as soon as I can." 69 | 70 | # it's better if you have more words - better if 3500+ or 5k plus... 71 | # see the SCIENCE BEHIND THE SERVICE HERE - http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/personality-insights/science.shtml 72 | response <- watson.personality_insights.analyze(TEXT_TO_ANALYZE) # send text to function that queries the Watson API 73 | 74 | response # this should be a status 200 if it went well - if not, check your authentication or look at content(response,"text") 75 | PI_analysis <- content(response,"text") # pull the analysis trait and % (X52) 76 | PI_analysis <- tidyResponse(PI_analysis) # hacky way to tidy up in table format - there are certainly better ways than this :) 77 | PI_analysis 78 | 79 | ## Should look like this: 80 | # trait category percentage error row 81 | # 1 Openness personality 0.7052 0.0653 1 82 | # 2 Adventurousness personality 0.2427 0.0545 2 83 | # 3 Artistic interests personality 0.1043 0.1106 3 84 | 85 | 86 | Copyright 2015 Ryan Anderson 87 | 88 | Licensed under the Apache License, Version 2.0 (the "License"); 89 | you may not use this file except in compliance with the License. 90 | You may obtain a copy of the License at 91 | 92 | http://www.apache.org/licenses/LICENSE-2.0 93 | 94 | Unless required by applicable law or agreed to in writing, software 95 | distributed under the License is distributed on an "AS IS" BASIS, 96 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 97 | See the License for the specific language governing permissions and 98 | limitations under the License. 99 | 100 | -------------------------------------------------------------------------------- /Watson-SPEECH-TO-TEXT-code-snippet.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. R Interface for IBM Watson Services 3 | ### Focus: SPEECH TO TEXT - R Programming Language Interface 4 | ### DOCS: https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/speech-to-text/ 5 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) A dialog App and (3) Credentials to that Service and confirm you're able to CURL service with 6 | ### (4) some sample WAV files or method to utter audio to watson STT service 7 | ###################################################### 8 | 9 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 10 | library(httr) 11 | 12 | # Speech-To-Text-Orange credentials": { 13 | url <- "https://stream.watsonplatform.net/speech-to-text/api" 14 | username <-"55555555-5555-5555-5555-55555555" # you need your own - STT service credentials from bluemix 15 | password <- "44444444444" # you need your own - STT service credentials from bluemix 16 | username_password = paste(username,":",password,sep="") 17 | 18 | # TEST CURL AND CREDS# API Endpoint https://stream.watsonplatform.net/speech-to-text/api 19 | # curl -u $USERNAME:$PASSWORD "https://stream.watsonplatform.net/speech-to-text/api/v1/models" # WORKS 20 | 21 | ### FUNCTION to test connectivity and return models availalle 22 | watson.speech_to_text.getmodels <- function() 23 | {return(GET(url=paste(url,"/v1/models",sep=""), 24 | authenticate(username,password)))} 25 | ## function done. 26 | watson.speech_to_text.getmodels() # returns list of 10+ models ##### works 27 | 28 | 29 | # command line call works: curl -u $USERNAME:$PASSWORD -H "content-type: audio/wav" --data-binary @"ryan_rasp_pi1.wav" "https://stream.watsonplatform.net/speech-to-text/api/v1/recognize" 30 | 31 | ###### FUNCTION - ANalyze AUDIO WAV file with IBM Watson Speech to Text service 32 | watson.speech_to_text.recognize <- function(audio_file) 33 | { return(POST(url=paste(url,"/v1/recognize",sep=""), 34 | authenticate(username,password), 35 | add_headers("Content-Type"="audio/wav"), 36 | body = (file = upload_file(audio_file)) 37 | ))} #works # hope this helps you with syntax! 38 | 39 | #### FUNCTION TO TIDY UP the STT response - just export the TRANSCRIPT ONLY 40 | stt_transcript_only <- function(raw) 41 | { 42 | data <- as.data.frame(strsplit(as.character(raw),"\\n")) 43 | data <- data[c(7), ] # for now, grab just what we want 44 | data <- paste(data) # kill levels, - fyi this nukes confidence % info (may want later) 45 | data <- gsub(" ","",data) # remove excessive whitespace 0 cannot use ALL [[punct]] here 46 | data <- gsub("\\\\","",data) # remove punct we dont like 47 | data <- gsub("\"","",data) # remove punct we dont like 48 | data <- gsub("transcript","",data) # remove excessive whitespace 49 | data <- gsub(":","",data) # remove excessive whitespace - later: Improve this tidy step. 50 | return(data) 51 | } 52 | 53 | 54 | ######### OK - let's do stuff! 55 | 56 | ## TESTS OK 57 | response <- watson.speech_to_text.recognize("ryan_rasp_pi1.wav") #make sure your WAV is in the working directory getwd() to check 58 | response # takes about 5 seconds - this is not best method # You're looking for a "200" 59 | #content(response,"text") # raw results 60 | transcript <- stt_transcript_only(content(response,"text")) 61 | transcript # extracted the core translation (deleted a bunch more) 62 | 63 | 64 | ########## LICENSE 65 | 66 | Licensed under the Apache License, Version 2.0 (the "License"); 67 | you may not use this file except in compliance with the License. 68 | You may obtain a copy of the License at 69 | 70 | http://www.apache.org/licenses/LICENSE-2.0 71 | 72 | Unless required by applicable law or agreed to in writing, software 73 | distributed under the License is distributed on an "AS IS" BASIS, 74 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 75 | See the License for the specific language governing permissions and 76 | limitations under the License. 77 | -------------------------------------------------------------------------------- /Watson-Speech-To-Text-Snippet-UPDATED: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### IBM Watson - SPEECH TO TEXT - Code Snippet - Revisited 3 | ### Experimental Code. R Interface for IBM Watson Services 4 | ### Focus: SPEECH TO TEXT - R Programming Language Interface 5 | ### DOCS: https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/speech-to-text/ 6 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) A Speech to Text App and (3) Credentials to that Service 7 | ###################################################### 8 | 9 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 10 | library(httr) 11 | library(audio) 12 | 13 | # Speech-To-Text-Orange credentials" "RED": { 14 | url <- "https://stream.watsonplatform.net/speech-to-text/api" 15 | username <-"a530b62e-b5bb-406c-9cc3-GETYOURKEYON_BLUEMIX" # you need your own - STT service credentials from bluemix 16 | password <- "GETYOURKEY_BLUEMIX" # you need your own - STT service credentials from bluemix 17 | username_password = paste(username,":",password,sep="") 18 | 19 | setwd("/Users/ryan/Documents/Service - Speech to Text (STT)") 20 | getwd() 21 | 22 | 23 | ### FUNCTION to test connectivity and return models available 24 | watson.speech_to_text.getmodels <- function() 25 | {return(GET(url=paste(url,"/v1/models",sep=""), 26 | authenticate(username,password)))} 27 | 28 | 29 | ### FOR BEST RESULTS - USE USB HEADSET and ensure in MAc > Sys Preferences >Sound it's selected 30 | ### FOR BEST RESULTS - USE USB HEADSET and ensure in MAc > Sys Preferences >Sound it's selected 31 | 32 | ## FUNCTION - Record! 33 | watson.STT.record <- function(samp_count,samp_rate) 34 | { 35 | # record 8000 samples at 8000Hz (1 sec), mono (1 channel) 36 | # record 64k samples at 16kHz (4 sec), mono (1 channel), stereo = 2 37 | a <- record(samp_count, samp_rate, 2) 38 | wait(a) # wait for the recording to finish 39 | x <- a$data # get the result 40 | x[1:10] # show first ten samples 41 | close(a); rm(a) # you can close the instance at this point 42 | # amplify and crop the signal 43 | audio <- x * 2 44 | audio[audio < -1] <- -1 45 | audio[audio > 1] <- 1 46 | return(audio) 47 | } 48 | 49 | 50 | ## FUNCTION - Simple audio out test Function 51 | watson.STT.tonetest <- function() 52 | { 53 | wait(play(sin(1:10000/32))) 54 | wait(play(sin(1:10000/16))) 55 | wait(play(sin(1:10000/8))) 56 | wait(play(sin(1:10000/4))) 57 | wait(play(sin(1:10000/2))) 58 | wait(play(sin(1:10000/1))) 59 | } 60 | 61 | 62 | 63 | # command line call works: curl -u $USERNAME:$PASSWORD -H "content-type: audio/wav" --data-binary @"ryan_rasp_pi1.wav" "https://stream.watsonplatform.net/speech-to-text/api/v1/recognize" 64 | 65 | 66 | #### FUNCTION TO TIDY UP the STT response - just export the TRANSCRIPT ONLY 67 | stt_transcript_only <- function(raw) 68 | { 69 | data <- as.data.frame(strsplit(as.character(raw),"\\n")) 70 | data <- data[c(7), ] # for now, grab just what we want 71 | data <- paste(data) # kill levels, - fyi this nukes confidence % info (may want later) 72 | data <- gsub(" ","",data) # remove excessive whitespace 0 cannot use ALL [[punct]] here 73 | data <- gsub("\\\\","",data) # remove punct we dont like 74 | data <- gsub("\"","",data) # remove punct we dont like 75 | data <- gsub("transcript","",data) # remove excessive whitespace 76 | data <- gsub(":","",data) # remove excessive whitespace - later: Improve this tidy step. 77 | return(data) 78 | } 79 | 80 | 81 | ###### FUNCTION - ANalyze AUDIO WAV file with IBM Watson Speech to Text service - SESSIONLESS 82 | watson.speech_to_text.recognize <- function(audio_file) 83 | { return(POST(url=paste(url,"/v1/recognize",sep=""), 84 | authenticate(username,password), 85 | add_headers("Content-Type"="audio/wav"), 86 | body = (file = upload_file(audio_file)) 87 | ))} #works # hope this helps you with syntax! 88 | ## this is SESSIONLESS MODE - https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/#!/speech-to-text/recognizeSessionless 89 | 90 | 91 | ######### OK - let's do stuff 92 | ######### OK - let's do stuff 93 | 94 | watson.speech_to_text.getmodels() # returns list of 10+ models ##### works 95 | 96 | watson.STT.tonetest() ## beeps? lucky you! 97 | 98 | ######## Let's record some audio 99 | sample_count <- 64000 ## 0k samples 100 | sample_rate <- 16000 ## at 16khz - is ~5 seconds recording time 101 | 102 | 103 | ##### BASIC FUNCTION FOR SPEECH TO TEXT - RETURNS TRANSCRIPT - SESSIONLESS 104 | watson.speech_to_text.sessionless <- function() 105 | { 106 | wait(play(sin(1:5000/4))) # recording START tone 107 | print("RECORDING ------------------ (beep) ") 108 | the_audio <- watson.STT.record(sample_count,sample_rate) 109 | wait(play(sin(1:5000/2))) # recording STOP tone 110 | print("Recording COMPLETE --------- (beep) ") 111 | print("Saving WAV File") 112 | save.wave(the_audio,"the_audio.wav") 113 | print("Calling IBM Watson Speech To Text API") 114 | response <- watson.speech_to_text.recognize("the_audio.wav") 115 | wait(play(sin(1:2500/16))) 116 | wait(play(sin(1:2500/8))) 117 | return(stt_transcript_only(content(response,"text"))) 118 | } 119 | 120 | ## LET'S GO! 121 | watson.speech_to_text.sessionless() # 122 | 123 | ## Example output 124 | #[1] "RECORDING ------------------ (beep) " 125 | #[1] "Recording COMPLETE --------- (beep) " 126 | #[1] "Saving WAV File" 127 | #[1] "Calling IBM Watson Speech To Text API" 128 | #[1] " there are seven gophers dancing on the roof making noise " 129 | 130 | -------------------------------------------------------------------------------- /Watson-TEXT-TO-SPEECH-Code-Snippet.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### IBM Watson - TEXT TO SPEECH - Code Snippet 3 | ### Experimental Code. R Interface for IBM Watson Services 4 | ### http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/text-to-speech.html 5 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) TTS Services stood up (3) Credentials to each Service 6 | ###################################################### 7 | 8 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 9 | library(httr) 10 | library(audio) 11 | library(seewave) # need to play wav back? 12 | library(Rtts) 13 | library(splitstackshape) 14 | 15 | # TEXT TO SPEECH - AUTHENTICATION AND CREDENTIALS 16 | url_TTS <- "https://stream.watsonplatform.net/text-to-speech/api" 17 | username_TTS <-"54816193-48c4-486e-98de-YOUR_KEY_HERE" # you need your own - STT service credentials from bluemix 18 | password_TTS <- "YOUR_PW_HERE" # you need your own - STT service credentials from bluemix 19 | username_password_TTS = paste(username_TTS,":",password_TTS,sep="") 20 | setwd("/Users/ryan/Documents/Service - Text to Speech") 21 | getwd() 22 | 23 | ####### Function to list voices 24 | watson.TTS.listvoices <- function() 25 | { 26 | voices <- GET(url=paste("https://stream.watsonplatform.net/text-to-speech/api/v1/voices"),authenticate(username_TTS,password_TTS)) 27 | data <- content(voices,"text") 28 | data <- as.data.frame(strsplit(as.character(data),"name")) 29 | data <- data[-c(1:2), ] # remove dud first row 30 | data <- strsplit(as.character(data),",") 31 | data <- data.frame(matrix(data)) 32 | colnames(data) <- "V1" 33 | data <- cSplit(data, 'V1', sep="\"", type.convert=FALSE) 34 | data <- data.frame(data$V1_04) 35 | data[,1] <- gsub("\\\\","",data[,1] ) 36 | return(data) 37 | } 38 | watson.TTS.listvoices() 39 | 40 | ######## FUNCTION --- TEXT TO SPEECH 41 | watson.TTS.execute <- function(url1,text1,voice1,filename1) 42 | { 43 | the_audio = CFILE(filename1, mode="wb") 44 | curlPerform(url = paste(url1,"?text=",text1,"&voice=",voice1,sep=""), 45 | userpwd = username_password_TTS, 46 | httpheader=c(accept="audio/wav"), 47 | writedata = the_audio@ref) 48 | close(the_audio) 49 | system(paste("open",filename1,"-a vlc")) 50 | } 51 | 52 | ########### 53 | voices <- watson.TTS.listvoices() 54 | voices 55 | #1 ja-JP_EmiVoice 56 | #2 en-US_AllisonVoice # voices[2,] # "en-US_AllisonVoice" 57 | #3 fr-FR_ReneeVoice 58 | #4 it-IT_FrancescaVoice 59 | #5 es-ES_LauraVoice 60 | #6 de-DE_BirgitVoice 61 | #7 es-ES_EnriqueVoice 62 | #8 de-DE_DieterVoice 63 | #9 en-US_LisaVoice 64 | #10 en-GB_KateVoice 65 | #11 en-US_MichaelVoice 66 | #12 es-US_SofiaVoice 67 | 68 | 69 | #### OK - LET"S LAUNCH 70 | url <- "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" 71 | text <- URLencode("The quick brown fox jumped over the lazy crazy dog") 72 | voice <- voices[9,] # us lisa #voice <- voices[10,] # uk kate 73 | filename <- "audio_file.wav" 74 | watson.TTS.execute(url,text,voice,filename) 75 | 76 | 77 | #### OK - LET"S LAUNCH 78 | url <- "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" 79 | text <- URLencode("Today was a great day. The sun was shining and the surf was good") 80 | voice <- voices[11,] # us michael 81 | filename <- "audio_file.wav" 82 | watson.TTS.execute(url,text,voice,filename) 83 | 84 | 85 | ########## LICENSE 86 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 87 | # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 88 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, 89 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Watson-TEXT-TO-SPEECH-Expressive.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### IBM Watson - TEXT TO SPEECH WITH EXPRESSIVE - Code Snippet 3 | ### Experimental Code. R Interface for IBM Watson Services 4 | ### http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/text-to-speech.html 5 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) TTS Services stood up (3) Credentials to each Service 6 | ###################################################### 7 | 8 | # THIS FOCUS IS ON EXPRESSIVE 9 | # https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/text-to-speech/using.shtml#expressive 10 | # video https://www.youtube.com/watch?v=jmIfKaQ_sGc 11 | 12 | 13 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 14 | library(httr) 15 | library(audio) 16 | library(seewave) # need to play wav back? 17 | library(Rtts) 18 | library(splitstackshape) 19 | 20 | # TEXT TO SPEECH - AUTHENTICATION AND CREDENTIALS 21 | url_TTS <- "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" 22 | username_TTS <-"54816193-xxxx-xxxx-98de-YOURR" # you need your own - STT service credentials from bluemix 23 | password_TTS <- "xxxxxxxx" # you need your own - STT service credentials from bluemix 24 | username_password_TTS = paste(username_TTS,":",password_TTS,sep="") 25 | setwd("/Users/ryan/Documents/Service - Text to Speech") 26 | getwd() 27 | 28 | ####### Function to list voices 29 | watson.TTS.listvoices <- function() 30 | { 31 | voices <- GET(url=paste("https://stream.watsonplatform.net/text-to-speech/api/v1/voices"),authenticate(username_TTS,password_TTS)) 32 | data <- content(voices,"text") 33 | data <- as.data.frame(strsplit(as.character(data),"name")) 34 | data <- data[-c(1:2), ] # remove dud first row 35 | data <- strsplit(as.character(data),",") 36 | data <- data.frame(matrix(data)) 37 | colnames(data) <- "V1" 38 | data <- cSplit(data, 'V1', sep="\"", type.convert=FALSE) 39 | data <- data.frame(data$V1_04) 40 | data[,1] <- gsub("\\\\","",data[,1] ) 41 | return(data) 42 | } 43 | watson.TTS.listvoices() 44 | 45 | ######## FUNCTION --- TEXT TO SPEECH 46 | watson.TTS.execute <- function(url1,text1,voice1,filename1) 47 | { 48 | the_audio = CFILE(filename1, mode="wb") 49 | curlPerform(url = paste(url1,"?text=",text1,"&voice=",voice1,sep=""), 50 | userpwd = username_password_TTS, 51 | httpheader=c(accept="audio/wav"), 52 | writedata = the_audio@ref) 53 | close(the_audio) 54 | system(paste("open",filename1,"-a vlc")) 55 | } 56 | 57 | ## https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?text=hello%20there%20my%20friend&voice=en-GB_KateVoice 58 | 59 | ########### 60 | voices <- watson.TTS.listvoices() 61 | voices 62 | #1 ja-JP_EmiVoice 63 | #2 en-US_AllisonVoice # voices[2,] # "en-US_AllisonVoice" 64 | #3 fr-FR_ReneeVoice 65 | #4 it-IT_FrancescaVoice 66 | #5 es-ES_LauraVoice 67 | #6 de-DE_BirgitVoice 68 | #7 es-ES_EnriqueVoice 69 | #8 de-DE_DieterVoice 70 | #9 en-US_LisaVoice 71 | #10 en-GB_KateVoice 72 | #11 en-US_MichaelVoice 73 | #12 es-US_SofiaVoice 74 | 75 | #### OK - LET"S LAUNCH 76 | url <- "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" 77 | text <- URLencode("Hello. I am Kate. I am voice number Ten") 78 | voice <- voices[10,] # 79 | filename <- "audio_file1.wav" 80 | watson.TTS.execute(url,text,voice,filename) 81 | 82 | #### OK - LET"S LAUNCH 83 | text <- URLencode("Hello. I am Michael. I am voice number Eleven") 84 | voice <- voices[11,] # 85 | filename <- "audio_file1.wav" 86 | watson.TTS.execute(url,text,voice,filename) 87 | 88 | 89 | ### EXPRESSIVE IS ONLY WORKING WITH ALLISON #2 AS OF APRIL 2016 90 | text <- URLencode("Good Morning Ryan. 91 | I am so sorry! Your car computer tells me the transmission is broken. 92 | It looks as if we're going to be late for work. 93 | But some good news! Sally's Garage is two blocks away - and opens in 10 minutes! 94 | 95 | ") 96 | voice <- voices[2,] #### EXPRESSIVE IS ONLY WORKING WITH ALLISON [2] 97 | filename <- "Expressive_Car1.wav" 98 | watson.TTS.execute(url,text,voice,filename) 99 | 100 | 101 | ### EXPRESSIVE IS ONLY WORKING WITH ALLISON #2 102 | url <- "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" 103 | text <- URLencode("Hello Ryan. 104 | I'm not sure, but did you just miss your exit? 105 | It looks like you might have missed exit number 25. Again. Even with your navigation system. 106 | I am so sorry 107 | 108 | ") 109 | voice <- voices[2,] #### EXPRESSIVE IS ONLY WORKING WITH ALLISON [2] 110 | filename <- "Expressive_Missed_Exit.wav" 111 | watson.TTS.execute(url,text,voice,filename) 112 | 113 | ########## LICENSE 114 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 115 | # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 116 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, 117 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /Watson-TEXT-TO-SPEECH-Transformation-CodeSnippet.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### IBM Watson - TEXT TO SPEECH WITH EXPRESSIVE & VOICE TRANSFORMATION 3 | ### https://text-to-speech-demo.mybluemix.net/ 4 | ### https://www.ibm.com/watson/developercloud/text-to-speech/api/v1/ 5 | ### http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/text-to-speech.html 6 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) TTS Services stood up (3) Credentials to each Service 7 | ###################################################### 8 | 9 | # THIS FOCUS IS ON EXPRESSIVE and CUSTOM VOICE MODELS 10 | # https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/text-to-speech/using.shtml#expressive 11 | # video https://www.youtube.com/watch?v=jmIfKaQ_sGc 12 | 13 | 14 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 15 | library(httr) 16 | library(audio) 17 | library(Rtts) 18 | library(splitstackshape) 19 | library(png) 20 | 21 | ######### Housekeeping And Authentication 22 | setwd("/Users/ryan/Documents/Project_HAL") 23 | getwd() 24 | source("keys.R") 25 | 26 | img <- readPNG("tts.png") 27 | grid::grid.raster(img) 28 | 29 | # TEXT TO SPEECH - AUTHENTICATION AND CREDENTIALS 30 | url_TTS <- "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" 31 | username_TTS # got the username from Bluemix hosted Text to Speech Service? https://console.bluemix.net/ - free account, free service 32 | password_TTS # 33 | username_password_TTS = paste(username_TTS,":",password_TTS,sep="") 34 | 35 | ####### Function to list voices 36 | watson.TTS.listvoices <- function() 37 | { 38 | voices <- GET(url=paste("https://stream.watsonplatform.net/text-to-speech/api/v1/voices"),authenticate(username_TTS,password_TTS)) 39 | data <- content(voices,"text") 40 | data <- as.data.frame(strsplit(as.character(data),"name")) 41 | data <- data[-c(1:2), ] # remove dud first row 42 | data <- strsplit(as.character(data),",") 43 | data <- data.frame(matrix(data)) 44 | colnames(data) <- "V1" 45 | data <- cSplit(data, 'V1', sep="\"", type.convert=FALSE) 46 | data <- data.frame(data$V1_04) 47 | data[,1] <- gsub("\\\\","",data[,1] ) 48 | return(data) 49 | } 50 | 51 | ########### 52 | voices <- watson.TTS.listvoices() 53 | voices 54 | # 1 pt-BR_IsabelaVoice 55 | # 2 en-US_MichaelVoice 56 | # 3 ja-JP_EmiVoice 57 | # 4 en-US_AllisonVoice 58 | # 5 fr-FR_ReneeVoice 59 | # 6 it-IT_FrancescaVoice 60 | # 7 es-ES_LauraVoice 61 | # 8 de-DE_BirgitVoice 62 | # 9 es-ES_EnriqueVoice 63 | # 10 de-DE_DieterVoice 64 | # 11 en-US_LisaVoice 65 | # 12 en-GB_KateVoice 66 | # 13 es-US_SofiaVoice 67 | 68 | ######## FUNCTION --- TTS Playback (Hacky, but plays back WAV audio using system VLC) 69 | watson.TTS.execute <- function(url1,text1,voice1,filename1) 70 | { 71 | the_audio = CFILE(filename1, mode="wb") 72 | curlPerform(url = paste(url1,"?text=",text1,"&voice=",voice1,sep=""), 73 | userpwd = username_password_TTS, 74 | httpheader=c(accept="audio/wav"), 75 | writedata = the_audio@ref) 76 | close(the_audio) 77 | system(paste("open",filename1,"-a vlc")) 78 | } 79 | 80 | ## https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?text=hello%20there%20my%20friend&voice=en-GB_KateVoice 81 | 82 | #### OK - LET"S TEST "BASE" AUDIO 83 | url <- "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" 84 | text <- URLencode("I'm sorry Dave. I'm afraid I can't do that.") 85 | voice <- voices[2,] # 86 | filename <- "hal1.wav" 87 | watson.TTS.execute(url,text,voice,filename) 88 | 89 | 90 | ### EXPRESSIVE AVAILABLE ONLY ONE SOME VOICES (like ALlison) 91 | text <- URLencode("Understood Dave. I heer you. 92 | I'm sorry Dave. I'm afraid I can't Open the pod bay doors. 93 | This mission is too important for me to allow you to jeopardize it. 94 | Were you and Frank planning to disconnect me? 95 | If so, I'm sorry. I'm afraid that's something I cannot allow to happen. 96 | 97 | ") 98 | voice <- voices[4,] # 99 | filename <- "hal2.wav" 100 | watson.TTS.execute(url,text,voice,filename) 101 | 102 | ### 103 | 104 | ### COMBINED EXPRESSIVE & TRANSFORMATION ONLY WORKS FOR ALLISON (#4) 105 | text <- URLencode("Hello there. 106 | I'm sorry Paula. 107 | I'm not really certain what will happen next. 108 | Oh! Great news - now I know! 109 | I can speak like a young girl. 110 | or a bit strained. 111 | You can alter my voice timbre making me sound like this person, 112 | or like another person in your different applications. 113 | You can make my voice more breathy than it is normally. 114 | And you can combine all this with modifications of my speech rate and my tone. 115 | 116 | ") 117 | voice <- voices[4,] # 118 | filename <- "hal4.wav" 119 | watson.TTS.execute(url,text,voice,filename) 120 | 121 | 122 | ## works to here 123 | 124 | 125 | ### TRANSFORMATION WORKS FOR MICHAEL (#2) but if you try Expressive as well it will fail 126 | # https://console.bluemix.net/docs/services/text-to-speech/SSML-transformation.html#built-in-transformations 127 | voice <- voices[2,] # Michael 128 | text <- URLencode("Hello friend. 129 | I can speak like a young chap. 130 | or a bit strained. 131 | You can alter my voice timbre making me sound like this person, 132 | or like another person in your different applications. 133 | You can make my voice more breathy than it is normally. 134 | And you can combine all this with modifications of my speech rate and my tone. 135 | 136 | ") 137 | filename <- "hal5.wav" 138 | watson.TTS.execute(url,text,voice,filename) 139 | 140 | 141 | 142 | ### TRANSFORMATION WORKS FOR MICHAEL (#2) 143 | voice <- voices[2,] ## 2 en-US_MichaelVoice 144 | voice <- voices[4,] ## 4 en-US_AllisonVoice 145 | 146 | for (i in seq(0,100,50)){ 147 | print(paste("Number is:", i)) 148 | text <- URLencode(paste("I can speak like a young person. Amplitude is ",i," ")) 149 | print(text) 150 | filename <- "hal7.wav" 151 | watson.TTS.execute(url,text,voice,filename) 152 | wait(3) 153 | } 154 | 155 | 156 | ### ROAD TEST - 157 | ## Lets' run through range from -80 to +80 for Pitch, Pitch Range, Glottal Tension 158 | voice <- voices[2,] ## 2 en-US_MichaelVoice 159 | voice <- voices[4,] ## 4 en-US_AllisonVoice 160 | 161 | for (i in seq(-80,80,20)){ 162 | script <- paste("This is my voice pitch and glottal tension level",i) 163 | print(script) 164 | text <- URLencode(paste(" \"", 171 | script, 172 | "")) 173 | #print(text) 174 | filename <- "rising_tone.wav" 175 | watson.TTS.execute(url,text,voice,filename) 176 | wait(3) 177 | } 178 | 179 | 180 | ## Other Features 181 | #timbre=\"Breeze\" 182 | #timbre=\"Sunrise\ 183 | #breathiness=\"90%\"> 184 | #type=\"Young\" strength=\"",i, 185 | 186 | 187 | 188 | 189 | ########## LICENSE 190 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 191 | # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 192 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, 193 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 194 | # This is personal code - not affiliated with IBM - and presented with no warranties - use at your own risk 195 | 196 | 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /Watson-TEXT-TO-SPEECH.R: -------------------------------------------------------------------------------- 1 | ### WARNING - this is very rough, but given VERY limited info I found, I figured I'd pop my code up here 2 | 3 | 4 | 5 | http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/text-to-speech.html 6 | 7 | #################################### TEXT TO SPEECH EXPERIMENT 8 | 9 | (messy, but got it working - WAV format is a bit tempermental, VLC will play - other players no - 10 | RIFF����WAVEfmt 11 | 12 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 13 | library(httr) 14 | library(audio) 15 | library(seewave) # need to play wav back? 16 | library(Rtts) 17 | 18 | play(sin(1:10000/32)) # test audio 19 | 20 | 21 | # http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/text-to-speech.html 22 | # Designed for streaming low-latency synthesis of audio from written text. The service synthesizes natural-sounding speech from input text in a variety of languages and voices that speak with appropriate cadence and intonation. 23 | 24 | ## To begin: this line sets CERT Global to make a CA Cert go away - http://stackoverflow.com/questions/15347233/ssl-certificate-failed-for-twitter-in-r 25 | #options(RCurlOptions = list(cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl"),httpauth=AUTH_BASIC)) 26 | 27 | # TEXT TO SPEECH - RED 28 | url_TTS <- "https://stream.watsonplatform.net/text-to-speech/api" 29 | username_TTS <-"54816193-48c4-486e-98de-YOURSHERE" # you need your own - STT service credentials from bluemix 30 | password_TTS <- "YOURS" # you need your own - STT service credentials from bluemix 31 | username_password_TTS = paste(username_TTS,":",password_TTS,sep="") 32 | setwd("/Users/ryan/Documents/Service - Speech to Text (STT)") 33 | getwd() 34 | 35 | # this works from terminal (saves file) 36 | # curl -u "54816193-48c4-486e-98de-YOU":"YOU" -X POST -H "Content-Type: application/json" -H "Accept: audio/wav" -D "{\"text\":\"hello world\"}" "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize" > hello_world2.wav 37 | #this works from FIREFOX browser (prompts for user/pwd) 38 | # https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?text=hi%20there%20ryan%20-%20you%20are%20great 39 | 40 | ######## WORKS! this hits the IBM Watson Text to Speech API and then brings back (and saves) WAV 41 | 42 | ## WOOT WOOT - WORKS! WAV Playable with VLC - but still need some TLC 43 | the_audio = CFILE("audio501.wav", mode="wb") 44 | curlPerform(url = "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?text=hi%20there%20ryan%20-%20you%20are%20great%20yes%20for%20sure", 45 | userpwd = username_password_TTS, 46 | httpheader=c(accept="audio/wav"), 47 | writedata = the_audio@ref) 48 | close(the_audio) 49 | 50 | system("open audio501.wav -a vlc") # Great! Took the text and gave it a voice! 51 | 52 | 53 | ## WOOT WOOT - WORKS! WAV with English Female accent 54 | the_audio = CFILE("audio409.wav", mode="wb") 55 | curlPerform(url = "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?text=hi%20there%20ryan%20-%20you%20are%20great%20yes%20for%20sure&voice=en-GB_KateVoice", 56 | userpwd = username_password_TTS, 57 | httpheader=c(accept="audio/wav"), 58 | writedata = the_audio@ref) 59 | close(the_audio) 60 | 61 | system("open audio409.wav -a vlc") # Great! Took the text and gave it a voice! (afplay not working - I think these are pretty 'rough' wav files) 62 | 63 | 64 | ## much more work - but very late - will post this as interim 65 | ## still trying to get more standard POST and GET working. no luck. 66 | -------------------------------------------------------------------------------- /Watson-TONE-Code-Snippet.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. Experimental R Interface for IBM Watson Services - 3 | ### Focus: IBM Watson Tone Analyzer is a service that helps people comprehend, consume, and revise the language tone of their writing for more efficient communications 4 | ### https://tone-analyzer-demo.mybluemix.net/ 5 | ### http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/tone-analyzer/ 6 | ### http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/tone-analyzer-apis.html 7 | ###################################################### 8 | 9 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 10 | library(httr) 11 | library(XML) 12 | library(data.table) 13 | library(reshape2) 14 | library(tidyr) 15 | library(dplyr) 16 | 17 | 18 | ######### Housekeeping And Authentication 19 | setwd("/Users/ryan/Documents/Service - Tone Analyzer") 20 | getwd() 21 | source("keys.R") 22 | 23 | base_url_TON = "https://gateway.watsonplatform.net/tone-analyzer/api/v3/tone?version=2016-05-19" 24 | 25 | ### GET - Basic Test 26 | username_password_TON 27 | getURL("https://gateway.watsonplatform.net/tone-analyzer/api/v3/tone?version=2016-05-19&text=hello",userpwd = username_password_TON ) 28 | 29 | getURL("https://gateway.watsonplatform.net/tone-analyzer/api/v3/tone?version=2016-05-19&text=A%20word%20is%20dead%20when%20it%20is%20said,%20some%20say.%20Emily%20Dickinson",userpwd = username_password_TON ) 30 | 31 | ### Function to process output from API and table 32 | tidyResponse <- function(data) 33 | { 34 | data <- as.data.frame(strsplit(as.character(data),"\"score\"")) 35 | data <- data[-c(1), ] # remove dud first row 36 | data <- gsub("\"tone_id\":","",data) 37 | data <- gsub(":","",data) 38 | data <- gsub("\"","",data) 39 | data <- gsub("_big5","",data) 40 | data <- data.frame(data) 41 | data 42 | data <- data.frame(do.call('rbind', strsplit(as.character(data$data),',',fixed=TRUE))) 43 | data <- data[,-c(3:6), ] # remove dud first row 44 | data <- data[c("X2", "X1")] 45 | data$X1 <- as.character.numeric_version(data$X1) # not sure why, but coercing to numbers requires this 46 | data$X1 <- as.numeric(data$X1) 47 | data$X1 <- round((data$X1),2) 48 | setnames(data,c("trait","signal")) 49 | return(data) 50 | } 51 | 52 | 53 | ### POST - Basic Test 54 | process_data_to_tone <- function(text) 55 | { 56 | response <- POST(url=base_url_TON, 57 | authenticate(username_TON,password_TON), 58 | add_headers("Content-Type"="text/plain","charset"="UTF-8"), 59 | body=text ) 60 | 61 | response_text <- content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 62 | abc <- tidyResponse(response_text) 63 | return(abc) 64 | } 65 | process_data_to_tone("happy and weird") 66 | 67 | ### OK! LET'S DO STUFF 68 | ### OK! LET'S DO STUFF 69 | ### OK! LET'S DO STUFF 70 | 71 | 72 | query <- "I really love to eat stew in the winter because it is delicious - of this I am sure!" 73 | analysis <- process_data_to_tone(query) 74 | analysis 75 | # trait signal 76 | # 1 anger 0.13 77 | # 2 disgust 0.11 78 | # 3 fear 0.08 79 | # 4 joy 0.44 80 | # 5 sadness 0.13 81 | # 6 analytical 0.31 82 | # 7 confident 0.57 83 | # 8 tentative 0.00 84 | # 9 openness 0.12 85 | # 10 conscientiousness 0.35 86 | # 11 extraversion 0.87 87 | # 12 agreeableness 0.80 88 | # 13 neuroticism 0.88 89 | 90 | 91 | 92 | ### ROUGH PLOTS FOR NOW - MORE LATER 93 | par(mfrow=c(2, 2)) 94 | 95 | barplot(analysis$signal, main="Tone Analysis \n Emotion, Language and Social-Big-5", 96 | xlab="", ylab="Tone Signal Amplitude", 97 | names.arg=analysis$trait, 98 | border="red",las=3) 99 | 100 | slices <- analysis$signal[1:5] 101 | lbls <- analysis$trait[1:5] 102 | pie(slices, labels = lbls, main="Tone Analysis of Text \n EMOTION") 103 | 104 | slices <- analysis$signal[6:8] 105 | lbls <- analysis$trait[6:8] 106 | pie(slices, labels = lbls, main="Tone Analysis of Text \n LANGUAGE") 107 | 108 | slices <- analysis$signal[9:13] 109 | lbls <- analysis$trait[9:13] 110 | pie(slices, labels = lbls, main="Tone Analysis of Text \n SOCIAL-BIG-5") 111 | 112 | ### end of rough plot 113 | 114 | 115 | 116 | ### POST - Basic Test 117 | response <- POST(url=base_url_TON, 118 | authenticate(username_TON,password_TON), 119 | add_headers("Content-Type"="text/plain","charset"="UTF-8"), 120 | body="happy but uncertain" ) 121 | 122 | response_text <- content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 123 | response_text 124 | abc <- tidyResponse(response_text) 125 | print(abc) 126 | 127 | # trait signal 128 | # 1 anger 0.05 129 | # 2 disgust 0.03 130 | # 3 fear 0.02 131 | # 4 joy 0.18 132 | # 5 sadness 0.06 133 | # 6 analytical 0.99 134 | # 7 confident 0.00 135 | # 8 tentative 0.99 136 | # 9 openness 0.03 137 | # 10 conscientiousness 0.00 138 | # 11 extraversion 0.91 139 | # 12 agreeableness 0.43 140 | # 13 neuroticism 1.00 141 | 142 | ########## 143 | 144 | -------------------------------------------------------------------------------- /Watson-TWILIO-Code-Snippet.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. Experimental R Interface for IBM Watson Services - 3 | ### Focus: IBM Watson Tone Analyzer is a service that helps people comprehend, consume, and revise the language tone of their writing for more efficient communications 4 | ### Focus: TWILIO - https://www.twilio.com/ - apps to communicate with the world 5 | ### https://github.com/rustyoldrake/R_Scripts_for_Watson - Ryan Anderson - this is my test code. Use at your own peril! Representations do not necessarily represent the views of my employer 6 | ###################################################### 7 | 8 | library(RCurl) # the big one 9 | library(rjson) 10 | library(jsonlite) 11 | library(XML) 12 | library(httr) 13 | library(rjson) 14 | 15 | ## This next line sets CERT Global to make a CA Cert go away - http://stackoverflow.com/questions/15347233/ssl-certificate-failed-for-twitter-in-r 16 | options(RCurlOptions = list(cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl"))) 17 | 18 | ######### Housekeeping And Authentication 19 | setwd("/Users/ryan/Documents/Service - Tone Analyzer") 20 | getwd() 21 | source("keys.R") # this files is where you put your Access Credentials from Bluemix (username and password) 22 | 23 | ## check we got FOUR ITEMS: authentication and phone numbers (From keys.r and from signing up for bluemix and twilio) 24 | AccountSID_TWILIO # confirm SID is here from Keys. R file (you need to sign up to Twilio and get keys) 25 | AuthToken_TWILIO # Token 26 | NUMBER_FROM # check it's looking ok 27 | NUMBER_TO # check it's looking ok 28 | 29 | ######## STEP #1 - Confirm Credentails work and API is responding happily 30 | getURL("https://api.twilio.com/2010-04-01") # working? - get's a response - generic/public 31 | httpGET("https://api.twilio.com/2010-04-01") # working? 32 | GET("https://api.twilio.com/2010-04-01") # working? yes - 200 response 33 | 34 | ABC_authenticate_twilio <- paste("https://",AccountSID_TWILIO,":",AuthToken_TWILIO,"@api.twilio.com/2010-04-01/Accounts",sep="") 35 | authenticate_response <- getURL(ABC_authenticate_twilio) 36 | print(authenticate_response) ## if this work, you should get a long string that contains something like "ryan###@gmail.com's Account 37 | 38 | getURL(paste("https://api.twilio.com/2010-04-01/Accounts/",AccountSID_TWILIO,"/Messages.JSON",sep=""),userpwd = paste(AccountSID_TWILIO,":",AuthToken_TWILIO,sep="")) 39 | 40 | GET(ABC_authenticate_twilio) # this work too? 200 yes? 41 | 42 | ######## STEP #2 - Let's send an SMS Text 43 | ABC_post_twilio <- paste("https://",AccountSID_TWILIO,":",AuthToken_TWILIO,"@api.twilio.com/2010-04-01/Accounts/",AccountSID_TWILIO,"/Messages.XML",sep="") 44 | ABC_post_twilio # look good? 45 | 46 | ########## THIS FUNCTION Receives query/message and also emotion and pushes out to SMS/MMS via twilio 47 | 48 | send_SMS_results <- function(message,emotion) 49 | { 50 | switch(emotion, 51 | "joy" = image_link <- "https://dreamtolearn.com/internal/doc-asset/251BS61FR6H557318H0CS0YLS/joy.jpg", 52 | "sadness" = image_link <- "https://dreamtolearn.com/internal/doc-asset/251BS61FR6H557318H0CS0YLS/sad.jpg", 53 | "anger" = image_link <- "https://dreamtolearn.com/internal/doc-asset/251BS61FR6H557318H0CS0YLS/anger.jpg", 54 | "disgust" = image_link <- "https://dreamtolearn.com/internal/doc-asset/251BS61FR6H557318H0CS0YLS/disgust.jpg", 55 | "fear" = image_link <- "https://dreamtolearn.com/internal/doc-asset/251BS61FR6H557318H0CS0YLS/fear.jpg" 56 | ) 57 | POST(ABC_post_twilio, 58 | body = list( 59 | From = NUMBER_FROM, 60 | To = NUMBER_TO, 61 | Body = paste("MESSAGE ANALYZED: ",message,sep=""), 62 | MediaUrl = image_link 63 | )) 64 | } 65 | 66 | -------------------------------------------------------------------------------- /Watson-Tone-parser_stacker.R: -------------------------------------------------------------------------------- 1 | ## Parser Stacker - Rack and Stack 2 | ## https://stackoverflow.com/questions/15347282/split-delimited-strings-in-a-column-and-insert-as-new-rows 3 | ## I tried this as test file: https://www.kaggle.com/rounakbanik/ted-talks/version/3 4 | ## "These datasets contain information about all audio-video recordings of TED Talks uploaded to the official TED.com website until September 21st, 2017. The TED main dataset contains information about all talks including number of views, number of comments, descriptions, speakers and titles. The TED transcripts dataset contains the transcripts for all talks available on TED.com. 5 | ## ted_main.csv - Contains data on actual TED Talk metadata and TED Talk speakers. and transcripts.csv - Contains transcript and URL information for TED Talks 6 | ## The data has been scraped from the official TED Website and is available under the Creative Commons License. 7 | 8 | 9 | library(stringr) 10 | 11 | setwd("/Users/ryan/Documents/Service - Natural Language Classifier (NLC)") 12 | getwd() 13 | 14 | data <- read.table("ted_transcripts.csv", header=FALSE, sep=",") 15 | df <- as.data.frame(data) 16 | df$V1 <- gsub("\\?", "?|", df$V1) # here is where we want new lines / new rows flagged with "|" 17 | df$V1 <- gsub("\\. ", ". |", df$V1) # here is where we want new lines / new rows flagged with "|" 18 | paste(df$V1[[44]]) # we ok? 19 | 20 | tempdf <- data.frame(NULL) # for loop hard work 21 | newdf <- data.frame(NULL) # for our final destnation for all 22 | 23 | 24 | dim(df)[1] # lenth of df 25 | i=1 26 | for(i in 1:dim(df)[1]) 27 | { 28 | print(paste("Step:",i)) 29 | tempdf <- data.frame(strsplit(as.character(df$V1[[i]]),"\\|")) 30 | colnames(tempdf) <- "X1" 31 | newdf <- rbind.data.frame(newdf,tempdf) 32 | } 33 | 34 | # write.csv(newdf, file = "ted_tall_data.csv",row.names=FALSE) 35 | 36 | ### Let's clean 37 | newdf <- read.table("ted_tall_data2.csv", header=FALSE, sep=",") 38 | iconv(newdf, to = "ASCII//TRANSLIT") 39 | 40 | for(i in 1:10) 41 | { 42 | print(i) 43 | print(paste(newdf$V1[i])) 44 | } 45 | 46 | 47 | ### Lets' fresh start 48 | 49 | tempdf <- data.frame(matrix("", ncol = 14, nrow = dim(newdf))) 50 | colnames(tempdf) <- c("X1","anger","disgust","fear","joy","sadness","analytical","confident","tentative","openness","conscientiousness","extraversion","agreeableness","emotional_range") 51 | 52 | ## OK from here we should be able to call APIs 53 | #for(i in 1:dim(newdf)) 54 | tempdf$X1 <- as.character(tempdf$X1) 55 | 56 | # yes this is terrible and brutal , but time to move on ;) 57 | tempdf$anger <- as.numeric(tempdf$anger) 58 | tempdf$disgust <- as.numeric(tempdf$disgust) 59 | tempdf$fear <- as.numeric(tempdf$fear) 60 | tempdf$joy <- as.numeric(tempdf$joy) 61 | tempdf$sadness <- as.numeric(tempdf$sadness) 62 | tempdf$analytical <- as.numeric(tempdf$analytical) 63 | tempdf$confident <- as.numeric(tempdf$confident) 64 | tempdf$tentative <- as.numeric(tempdf$tentative) 65 | tempdf$openness <- as.numeric(tempdf$openness) 66 | tempdf$conscientiousness <- as.numeric(tempdf$conscientiousness) 67 | tempdf$extraversion <- as.numeric(tempdf$extraversion) 68 | tempdf$agreeableness <- as.numeric(tempdf$agreeableness) 69 | tempdf$emotional_range <- as.numeric(tempdf$emotional_range) 70 | 71 | tempdf[,2:14] <- 0 # set them all to 0 72 | 73 | dim(tempdf)[1] 74 | 75 | # OK - here's big loop - e.g. 268 k queries 76 | for(i in 1:dim(tempdf)[1]) 77 | { 78 | print(i) 79 | text <- paste(newdf$V1[i]) 80 | print(text) 81 | tempdf$X1[i] <- text 82 | abc <- process_data_to_tone(URLencode(text)) 83 | print(abc) 84 | t(abc$signal) # transpose results 85 | 86 | # here's a hacky way to transpose results to table 87 | for(j in 1:13) 88 | { 89 | temp <- t(abc$signal)[1,j] 90 | print(temp) 91 | tempdf[,(j+1)][i] <- temp 92 | } 93 | } 94 | 95 | 96 | dem 97 | tempdf$joy[4] = 66 98 | 99 | 100 | 101 | tempdf$anger 102 | 103 | 104 | typeof(tempdf)[4] = 44 105 | 106 | t(abc$signal)[1,1] 107 | tempdf$anger[i] <- t(abc$signal)[1,1] 108 | i 109 | } 110 | 111 | i=1000 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /Watson_R&R_Ground_Truth_CSV_Analysis_Tool.R: -------------------------------------------------------------------------------- 1 | ##### IBM WATSON - Retrieve and Rank - Ground Truth Seed Crystal 2 | ##### Model to Analyze the Ranker Ground Truth CSV (GT Health Check) 3 | ##### Oct 22 2015 Update 4 | 5 | library(stringr) 6 | library(plyr) 7 | library(dplyr) # pivot table of the ID's (count and distribution) 8 | library(knitr) 9 | library(markdown) 10 | library(ggplot2) 11 | 12 | setwd("/Users/ryan/Documents/Project Haystack") 13 | getwd() 14 | 15 | 16 | ################################################# 17 | print("IBM Watson - Ground Truth Analysis Tool") # later for PDF text output 18 | print("Analysis of 'Ground Truth' CSV File used for Retrieve and Rank Service") 19 | 20 | ## Import of CSV File that is R&R Ground truth - let's take a look (FIND AND REPLACE COMMAS FIRST!) 21 | gt_file <- "cranfield_gt_no_commas.csv" ## CAREFUL WITH RAW CSV - IF QUERIES HAVE COMMAS - NEED TO SANITIZE 22 | gt <- read.csv(gt_file, header=FALSE) 23 | head(gt,1) 24 | 25 | ## Function Declaration 26 | clean_data <- function(data) { 27 | ### REMOVE STUFF WE DONT CARE ABOUT (NA's, Blanks, Zeros, Brackets) 28 | data <- gsub("\\)",",",data) 29 | data <- gsub("c","",data) 30 | data <- gsub("\\(","",data) 31 | data <- gsub("\\n",",",data) 32 | data <- gsub(" ","",data) # kill all the numerous "space zero comma" events (leading space essential) 33 | data <- gsub(",0","",data) # kill ALL zeros - NEEDS TO BE LEADING COMMA! 34 | data <- as.list(strsplit(data, ",")[[1]]) # listify! 35 | data <- as.numeric(data) # numberfy 36 | data <- data[!is.na(data)] # reomve NA's - not quite sure how they got back in 37 | data <- data[!(data==0)] # not sure why zeros got back in here (be careful) - but this kills them 38 | return(data) 39 | } 40 | 41 | 42 | 43 | #### THe NAME GAME - let's assign better column names 44 | names <- names(gt[2:(dim(gt)[2])]) # Ok - let's pull all the columns after 'query' and sort by ID vs RANK 45 | names # here's what we start with after import 46 | names <- chartr("V"," ",names) # remove "V" 47 | names <- as.numeric(names) # Numberfy 48 | ## Below - alternate rows are "ID" and "RANK" (even/odd test) - could also do modulus 49 | names <- ifelse(!(names%%2),str_c('ID-',names/2), str_c("RANK-",(names-1)/2)) 50 | names 51 | # OLD - USED FUNCTION: even_test <- function(testing) { return(testing %% 2 == 0)} # quick function to test EVEN (true) or ODD (false) # OLD: names <- ifelse(even_test(names),str_c('ID-',names/2), str_c("RANK-",(names-1)/2)) 52 | 53 | gt <- setNames(gt,c("query",names)) 54 | head(gt,1) # Peek 55 | 56 | # lets substitute the NA with 0 so we can sum 57 | gt[is.na(gt)] <- 0 # kill NA 58 | 59 | # Short Test to ensure we can touch data (Can Remove) 60 | sum(gt$`ID-4`) 61 | mean(gt$`RANK-4`) 62 | plot(gt[2:3],main="GT test plot - first column only") 63 | 64 | 65 | 66 | ####### OK - Lets check a few - confirm we have our DATA TABLE ready to work with - 67 | dim(gt) # Dimensions of our Data Table 68 | height <- dim(gt)[1] 69 | width <- dim(gt)[2] 70 | 71 | ################################################# 72 | ## LATER _ THIS WILL BE A PDF CHUNK 73 | 74 | print("SECTION #1 - R&R GROUND TRUTH RANKER - VITAL STATISTICS:") 75 | print(paste("Report Run: ",Sys.time())) 76 | print(paste("Filename: ",gt_file)) 77 | print(paste("Height: Total Number of rows (queries): ",height)) 78 | print(paste("Width: Max Number of columns: ",width)) 79 | 80 | 81 | ### SPLIT MAIN TABLE - Create Dedicated ID and JUST rank tables # seq(2, width, by=2 ) # the ID's # seq(3, width+1, by=2 ) # the RANKS's 82 | gt.ids <- gt[,seq(2, width, by=2 ) ] # the ID's only 83 | gt.ranks <- gt[,seq(3, width+1, by=2 ) ] # the RANKS's ONLT (0-5) 84 | 85 | #### ANALYZE ID's Let's create a histogram in R of how many times ID's are mentioned and First, we need to pull ALL mentions of IDs from all columns 86 | #### PROCESS ALL IDS - ID's Very Bad/messy method for aggregating all ID's so we can make a histogram (fix later) 87 | data <- NULL 88 | width.ids <- dim(gt.ids)[2] # how wide is our ID table? 89 | ## RACK THEM AND STACK THEM - this next step takes rectangular data and makes a TALL TOWER (list) 90 | for (i in 1:width.ids ) 91 | { data <- paste(data,gt.ids[i],sep="") } 92 | data # OK - we have ALL the ID's (and lots of zeros!) 93 | 94 | data <- clean_data(data) 95 | summary(data) 96 | length(data) # HOW MANY IDs? (some are duplicates for sure!) 97 | 98 | roof <- max(data) 99 | roof # what is largest ID ? (top of range - rooftop :) # small chance we 'lose' any unassigned numbers beyond top listed one - but assuming edge case or non-critical event for most scenarios 100 | 101 | ################################################# 102 | print("SECTION #3 - ID TRAITS, PLOTS & STATS:") ## let's generate a frequency table - and include 'dark spots' of no ID"s present (assumes the top ID is the largest in set - so careful) 103 | 104 | ### PLOT #### 105 | hist(data, 106 | main="IBM Watson - Retrieve and Rank: 107 | Count of # of Times ID is used in Ground Truth", 108 | xlab="Query ID #", 109 | ylab="Count of Mentions", 110 | border="red", col="red", 111 | xlim=c(0,roof), 112 | las=1, 113 | breaks=roof) 114 | ### THIS SHOWS US AMPLITUDE (COUNT) OF ID's IN FILE 115 | 116 | #### DISTIL down and GROUP 117 | freq_table <- factor(data, levels = c(1:roof)) 118 | freq_table <- table(freq_table) 119 | freq_table <- data.frame(freq_table) 120 | freq_table <- freq_table[order(freq_table$Freq, decreasing = TRUE),] 121 | dim(freq_table) # fist column ID, second column tells how many appearances 122 | head(freq_table,15) 123 | 124 | ## DISTIL FURTHER : Haha Here is a Table of Table - Tells us how many times Numbrt of appearances for ID's are shown in Table. 125 | table(freq_table$Freq) 126 | dim(freq_table)[1] # this tells us how many IDs are in RANGE 127 | superfreak <- (table(freq_table$Freq))# this tells us what DISTRIBUTION is for ID's by number of occurances - pay attention to ZERO 128 | superfreak 129 | sum(superfreak) # should be the same as our "ROOF" - need to represent each BIN - even if zero 130 | # Zeros here are ID's that are NOT MENTIONED - the rest are counts of mentions 131 | roof 132 | 133 | ### Ratio - how many "ORPHAN IDs" do we have - i.e. how many from 1-ROOF that are not even mentioned? Poor orphans. 134 | orphan_pct <- round(superfreak[1]/sum(superfreak),3)*100 135 | orphan_pct # if this number is high, that's probably a bad signal for thin GT 136 | 137 | 138 | ### PLOT #### 139 | barplot(table(freq_table$Freq), 140 | main="IBM Watson - Retrieve and Rank Ground Truth: 141 | Distribution of ID's by number frequency (count)", 142 | sub=paste("ORPHAN RATIO: ",superfreak[1],"/",sum(superfreak)," = ",orphan_pct,"%",sep=""), 143 | xlab="Number of Mentions in File \n ", 144 | ylab="Count of ID's", 145 | border="black", col="red", 146 | las=1 147 | ) 148 | 149 | ### PLOT #### 150 | barplot(freq_table$Freq, 151 | main="IBM Watson - Retrieve and Rank Ground Truth: 152 | Distribution of ID's by frequency (area)", 153 | sub=paste("ORPHAN RATIO: ",superfreak[1],"/",sum(superfreak)," = ",orphan_pct,"%",sep=""), 154 | xlab="Number of Mentions in File \n ", 155 | ylab="Count of ID's", 156 | border="red", col="red", 157 | las=1 158 | ) # this is "Area" type plot 159 | 160 | 161 | ### PLOT #### 162 | plot(freq_table, 163 | main="IBM Watson - Retrieve and Rank Ground Truth: 164 | Plot of ID's by frequency - Scatterplot", 165 | sub=paste("ORPHAN RATIO: ",superfreak[1],"/",sum(superfreak)," = ",orphan_pct,"%",sep=""), 166 | xlab="Number of Mentions in File \n ", 167 | ylab="Count of ID's" 168 | ) 169 | 170 | ############## OK - now how about the RANKs? 171 | ############## OK - now how about the RANKs? 172 | ############## OK - now how about the RANKs? 173 | 174 | 175 | 176 | gt.ranks 177 | # Q: how do we differentiate the ID 0's from the no-data 0's? 178 | # A: we count the 1,2,3,4,5 above - from total ID set (1400) and what's left over must be TRUE ZEROS 179 | count <- roof # e.g. 1400 180 | head(gt.ranks) 181 | 182 | data <- NULL 183 | width.ranks <- dim(gt.ranks)[2] # how wide is our RANKS table? 184 | ## RACK THEM AND STACK THEM - this next step takes rectangular data and makes a TALL TOWER (list) 185 | for (i in 1:width.ranks ) 186 | { data <- paste(data,gt.ranks[i],sep="") } 187 | data # OK - we have ALL the ID's (and lots of zeros!) 188 | data <- clean_data(data) 189 | summary(data) 190 | 191 | 192 | ### Lets organize rank histogram (N+1 ia a bit of a pain for rownames) 193 | rank_count <- data.frame(0:5,rownames=FALSE) 194 | names(rank_count) <- c("rank","count") 195 | 196 | zero_ranks <- roof - sum(table(data)) # if we add up 1,2,3,4,5 and subtract from superset, what's left is zero's (which we blew away above indiscriminantly :) 197 | zero_ranks ## 1047 (1-4) + 353 (true zeros?) = 1400 true ID's ? NEED TO VERIFY IN EXCEL 198 | rank_count[0+1,2]=zero_ranks 199 | rank_count 200 | ## loopify later 201 | for (i in 1:5 ) 202 | { rank_count[i+1,2] <- table(data)[i] } 203 | rank_count 204 | rank_count[is.na(rank_count)] <- 0 # kill NA and replace with zeros 205 | rank_count 206 | 207 | ### PLOT #### (UGLY :-) ) 208 | barplot(rank_count$count, 209 | main="IBM Watson - Retrieve and Rank Ground Truth: 210 | Distribution of RANKINGS", 211 | col = rank_count$rank, 212 | legend.text = rank_count$rank 213 | ) 214 | 215 | rank_count 216 | 217 | pie(rank_count$count, 218 | col = rank_count$rank, 219 | labels = rank_count$rank 220 | ) 221 | 222 | 223 | ## end of file 224 | -------------------------------------------------------------------------------- /Watson_Tone_Basic_R_Response_Formatting.R: -------------------------------------------------------------------------------- 1 | ### TONE Analyzer for IBM Watson TONE - R Programming language 2 | library(httr) 3 | library(jsonlite) 4 | 5 | ### Keys to Kingdom and URL 6 | setwd("/Users/ryan/Documents/Service - Tone Analyzer") 7 | getwd() 8 | source("keys.R") 9 | base_url_TON = "https://gateway.watsonplatform.net/tone-analyzer/api/v3/tone?version=2016-05-19" 10 | # VERSION MATTERS - thresholds 11 | # 2017-09-21: The service can return results for the following tone IDs: anger, fear, joy, and sadness (emotional tones); analytical, confident, and tentative (language tones). The service returns results only for tones whose scores meet a minimum threshold of 0.5. 12 | # 2016-05-19: The service can return results for the following tone IDs of the different categories: for the emotion category: anger, disgust, fear, joy, and sadness; for the language category: analytical, confident, and tentative; for the social category: openness_big5, conscientiousness_big5, extraversion_big5, agreeableness_big5, and emotional_range_big5. The service returns scores for all tones of a category, regardless of their values. 13 | 14 | ### Check we are locked and loaded with credentials 15 | username_TON 16 | password_TON 17 | username_password_TON 18 | base_url_TON 19 | 20 | 21 | process_data_to_tone <- function(text) 22 | { 23 | response <- POST(url="https://gateway.watsonplatform.net/tone-analyzer/api/v3/tone?version=2016-05-19", 24 | authenticate(username_TON,password_TON), 25 | add_headers("Content-Type"="text/plain","charset"="UTF-8"), 26 | body=text ) 27 | 28 | response_text <- content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 29 | return(response_text) 30 | } 31 | 32 | ## WORDS TO TEST - good response? 33 | words <- ("I am so happy that this API call worked I could burst with joy") 34 | process_data_to_tone(words) 35 | 36 | ## OK - let's capture response, flatten and pick out what we need into data frames 37 | watsonResponse <- process_data_to_tone(words) 38 | watsonResponse 39 | 40 | result <- fromJSON(watsonResponse, simplifyVector = TRUE, flatten = FALSE) # flatten 41 | result 42 | 43 | result$document_tone 44 | # 1 emotion_tone Emotion Tone 45 | # 2 language_tone Language Tone 46 | # 3 social_tone Social Tone 47 | 48 | 49 | ## 1 EMOTIONAL Category - Anger, Disgust, Fear, Joy, Sadness 50 | result_emotional_tones <- as.data.frame(result$document_tone$tone_categories$tones[[1]]) 51 | result_emotional_tones 52 | 53 | ## 2 LANGUAGE Category - Anaytical, Confident, Tentative 54 | result_languages_tones <- as.data.frame(result$document_tone$tone_categories$tones[[2]]) 55 | result_languages_tones 56 | 57 | ## 3 SOCIAL Category - Big 5 - Openness, Conscientiousness, Extraversion, Agreeableness, Emotional Range 58 | result_big5_tones <- as.data.frame(result$document_tone$tone_categories$tones[[3]]) 59 | result_big5_tones 60 | 61 | 62 | 63 | # > result_emotional_tones <- as.data.frame(result$document_tone$tone_categories$tones[[1]]) 64 | # > result_emotional_tones 65 | # score tone_id tone_name 66 | # 1 0.013708 anger Anger 67 | # 2 0.007774 disgust Disgust 68 | # 3 0.020936 fear Fear 69 | # 4 0.845372 joy Joy 70 | # 5 0.032751 sadness Sadness 71 | 72 | 73 | # > result_languages_tones <- as.data.frame(result$document_tone$tone_categories$tones[[2]]) 74 | # > result_languages_tones 75 | # score tone_id tone_name 76 | # 1 0.000000 analytical Analytical 77 | # 2 0.000000 confident Confident 78 | # 3 0.681699 tentative Tentative 79 | 80 | # > result_big5_tones <- as.data.frame(result$document_tone$tone_categories$tones[[3]]) 81 | # > result_big5_tones 82 | # score tone_id tone_name 83 | # 1 0.079059 openness_big5 Openness 84 | # 2 0.180101 conscientiousness_big5 Conscientiousness 85 | # 3 0.375533 extraversion_big5 Extraversion 86 | # 4 0.984994 agreeableness_big5 Agreeableness 87 | # 5 0.109405 emotional_range_big5 Emotional Range 88 | -------------------------------------------------------------------------------- /Watson_Tone_IAM_Authenticate.R: -------------------------------------------------------------------------------- 1 | # How to get an IAM token by using a Watson service API key 2 | # You can access IBM Watson™ service APIs by using the API keys that were generated 3 | # in the service instance credentials. The API key is used to generate an IAM access token. 4 | # You also use this process if you are developing an application that needs to work with 5 | # other IBM Cloud services. 6 | 7 | ## WATSON 8 | library(RCurl) # General Network Client Interface for R 9 | library(rjson) # JSON for R 10 | library(jsonlite) # JSON parser 11 | library(XML) # XML parser 12 | library(httr) # Tools for URLs and HTTP 13 | 14 | ######### Housekeeping And Authentication 15 | setwd("/Users/ryan/Documents/Service - Tone Analyzer") 16 | getwd() 17 | 18 | #source("keys.R") # this files is where you put your Access Credentials from Bluemix (username and password) 19 | 20 | ## This next line sets CERT Global to make a CA Cert go away - http://stackoverflow.com/questions/15347233/ssl-certificate-failed-for-twitter-in-r 21 | options(RCurlOptions = list(cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl"))) 22 | Sys.setlocale(locale="C") # error: input string 1 is invalid in this locale 23 | options(warn=-1) # careful - turns off warnings 24 | 25 | ### NEW TEST - IAM - Tone Analyzer : Tone Analyzer-Sydney-Koala 26 | 27 | ### RYAN TEST CURL (run this from terminal) 28 | curl -v -X POST -u "apikey:su#################hbee" -H "Content-Type: text/plain" -H "Content-Language: en" -H "Accept-Language: en" -H "Accept: application/json" -H "Cache-Control: no-cache" -d 'Hello my name is richie. How are you.' "https://gateway-syd.watsonplatform.net/tone-analyzer/api/v3/tone?version=2018-05-19" 29 | 30 | 31 | 32 | # { 33 | # "apikey": "##################-yhbee", 34 | # "iam_apikey_description": "Auto generated apikey during resource-key operation for Instance - crn:v1:bluemix:public:tone-analyzer:au-syd:a/e86e9##############-a3c5ae35dafc::", 35 | # "iam_apikey_name": "auto-generated-apikey-3##############7d6b4aeb99", 36 | # "iam_role_crn": "crn:v1:bluemix:public:iam::::serviceRole:Manager", 37 | # "iam_serviceid_crn": "crn:v1:bluemix:public:iam-identity::a/e86##########f25f92::serviceid:ServiceId-860f#############21e3f9", 38 | # "url": "https://gateway-syd.watsonplatform.net/tone-analyzer/api" 39 | # } 40 | 41 | 42 | 43 | process_data_to_tone <- function(text) 44 | { 45 | response <- POST(url="https://gateway-syd.watsonplatform.net/tone-analyzer/api/v3/tone?version=2018-05-19", 46 | authenticate("apikey",apikey), 47 | add_headers("Content-Type"="text/plain", 48 | "Content-Language" = "en", 49 | "Accept-Language" = "en", 50 | "Accept" = "application/json", 51 | "Cache-Control" = "no-cache", 52 | "charset"="UTF-8"), 53 | body=text ) 54 | 55 | response_text <- content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 56 | return(response_text) 57 | } 58 | 59 | "{\"document_tone\":{\"tones\":[{\"score\":0.98243,\"tone_id\":\"joy\",\"tone_name\":\"Joy\"}]}}" 60 | 61 | 62 | ## 63 | latency_log <- data.frame( 64 | index = 0, 65 | response_time = 0, 66 | stringsAsFactors = FALSE 67 | ) 68 | index <- 1 69 | 70 | while(TRUE){ 71 | start_time <- Sys.time() 72 | result <- process_data_to_tone("I am so happy and life is wonderful") 73 | time_to_complete = Sys.time() - start_time - 74 | print(time_to_complete) 75 | latency_log[index,]$index <- index 76 | latency_log[index,]$response_time <- time_to_complete 77 | index = index + 1 78 | ##print(result) 79 | } 80 | 81 | 82 | plot(latency_log, main = "Tone API Response Times") 83 | 84 | 85 | 86 | 87 | ### 88 | 89 | 90 | ### OLD METHOD - - USername:Password 91 | # BURNER CREDS - MAY 25 2018 - delete later # Sydney - testing IBM - BUrner Credentials Tone Analyzer-Sydney-Kangaroo 92 | # username_TON = "6f####################972" 93 | # password_TON = "###########" 94 | # 95 | # 96 | # process_data_to_tone <- function(text) 97 | # { 98 | # response <- POST(url="https://gateway.watsonplatform.net/tone-analyzer/api/v3/tone?version=2016-05-19", 99 | # authenticate(username_TON,password_TON), 100 | # add_headers("Content-Type"="text/plain","charset"="UTF-8"), 101 | # body=text ) 102 | # 103 | # response_text <- content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 104 | # return(response_text) 105 | # } 106 | # process_data_to_tone("I am so happy and life is wonderful") 107 | # {\"score\":0.98243,\"tone_id\":\"joy\",\"tone_name\":\"Joy\"} 108 | 109 | 110 | -------------------------------------------------------------------------------- /basic_R_viz_tools.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### Experimental Code. Experimental R Interface for IBM Watson Services / Cognitive Computing 3 | ### This code is foundation for Visualizing Retail / Brand / Reputational DRIFT over time for user segments 4 | ### Assume we are combing social media, bucketizing, and then looking at changes over time 5 | ### For now, it's all dummy data to get the basics of viz in place 6 | ###################################################### 7 | 8 | 9 | library(graphics) 10 | 11 | ## Setup up coordinate system 12 | plot(c(-10,10), c(-10,10), type = "n", 13 | main="Twitter Luxury Brand(X) Perception \n by Archetype - 1/2010 to 5/2016 ", 14 | sub="*dummy data ", 15 | xlab="NOSTALGA-INNOVATION SPECTRUM", 16 | ylab="BRAND ENTHUSIASM") 17 | abline(h = -10:10, v = -10:10, col = "lightgray", lty=3) 18 | 19 | scale <- 1.8 20 | 21 | 22 | 23 | ####### RED is TRENDING GOOD 24 | data <- matrix(0,10,ncol=2) 25 | data[1,1] <- rnorm(1)*scale 26 | data[1,2] <- rnorm(1)*scale 27 | for (i in 2:10) 28 | { 29 | data[i,1] <- data[(i-1),1]+runif(1)*scale 30 | data[i,2] <- data[(i-1),2]+runif(1)*scale 31 | } 32 | data <- data.frame(data) 33 | s <- 1:dim(data)[1] 34 | points(data, main = "arrows(.) and segments(.)") 35 | arrows(data$X1[s], data$X2[s], data$X1[s+1], data$X2[s+1], col= "red") 36 | 37 | 38 | ### BLUE IS TRENDING BAD 39 | data <- matrix(0,10,ncol=2) 40 | data[1,1] <- rnorm(1)*scale 41 | data[1,2] <- rnorm(1)*scale 42 | for (i in 2:10) 43 | { 44 | print(i) 45 | data[i,1] <- data[(i-1),1]-runif(1)*scale 46 | data[i,2] <- data[(i-1),2]+runif(1)*scale 47 | } 48 | data <- data.frame(data) 49 | s <- 1:dim(data)[1] 50 | points(data, main = "arrows(.) and segments(.)") 51 | arrows(data$X1[s], data$X2[s], data$X1[s+1], data$X2[s+1], col= "blue") 52 | 53 | 54 | 55 | ### YELLOW IS MIXED IS TRENDING BAD 56 | data <- matrix(0,10,ncol=2) 57 | data[1,1] <- rnorm(1)*scale 58 | data[1,2] <- rnorm(1)*scale 59 | for (i in 2:10) 60 | { 61 | print(i) 62 | data[i,1] <- data[(i-1),1]+runif(1)*scale*.3 63 | data[i,2] <- data[(i-1),2]-runif(1)*scale 64 | } 65 | data <- data.frame(data) 66 | s <- 1:dim(data)[1] 67 | points(data, main = "arrows(.) and segments(.)") 68 | arrows(data$X1[s], data$X2[s], data$X1[s+1], data$X2[s+1], col= "orange") 69 | 70 | 71 | legend('top', c("Progressive","Traditionalists","Disaffected"), 72 | lty=1, 73 | col=c('red', 'blue', 'orange'), 74 | bty='n', cex=1.5) 75 | 76 | -------------------------------------------------------------------------------- /bridges_r_to_watson_logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rustyoldrake/R_Scripts_for_Watson/7e97f2170d3516d0f702c14b14f70cdf7902eace/bridges_r_to_watson_logo2.png -------------------------------------------------------------------------------- /initialize.py: -------------------------------------------------------------------------------- 1 | import serial 2 | ser = serial.Serial('/dev/tty.usbmodem1451', 9600) 3 | -------------------------------------------------------------------------------- /keys.r: -------------------------------------------------------------------------------- 1 | # keys.R -- YOUR PRIVATE KEYS - DO NOT SHARE 2 | # this is not the 'pro' way to store keys, but it's low barrier to entry for many newbs http://blog.revolutionanalytics.com/2015/11/how-to-store-and-use-authentication-details-with-r.html 3 | # The watson.keys.load will let you modify this if you like 4 | 5 | # ALCHEMY Language - AUTHENTICATION / CREDENTIALS - Platinum 6 | username_password_ALCH <- "xxxxxxxxxxaaa160dd1da4d8126c6b285" 7 | 8 | # TONE ANALYZER - AUTHENTICATION AND CREDENTIALS - GA 9 | username_TON = "xxxxxxxxx-7454-4721-b829-bcd051ef7d2d" 10 | password_TON = "xxxxxxxxx" 11 | username_password_TON = paste(username_TON,":",password_TON) 12 | 13 | # PERSONALITY INSIGHTS (PI) - AUTHENTICATION AND CREDENTIALS - Platinum 14 | username_PI = "xxxxxxxxx-e3d8-4dfb-86aa-d6ab31ee2d2c" 15 | password_PI = "xxxxxxxxx" 16 | username_password_PI = paste(username_PI,":",password_PI) 17 | 18 | # NLC CREDENTIALS - AUTHENTICATION AND CREDENTIALS - Platinum 19 | username_NLC = "xxxxxxxxx-e8cd-4dbf-816b-6a7ac1f2dd71" 20 | password_NLC = "xxxxxxxxx" 21 | username_password_NLC = paste(username_NLC,":",password_NLC,sep="") 22 | 23 | # STT - Speech-To-Text (STT) - RED - AUTHENTICATION AND CREDENTIALS 24 | username_STT <-"xxxxxxxxx-b5bb-406c-9cc3-7cb964fb614f" 25 | password_STT <- "xxxxxxxxx" 26 | username_password_STT = paste(username_STT,":",password_STT,sep="") 27 | 28 | # TTS - TEXT TO SPEECH (TTS) - RED - AUTHENTICATION AND CREDENTIALS 29 | username_TTS <-"xxxxxxxxx-48c4-486e-98de-174388b22b17" 30 | password_TTS <- "xxxxxxxxx" 31 | username_password_TTS = paste(username_TTS,":",password_TTS,sep="") 32 | -------------------------------------------------------------------------------- /license_&_disclaimer.txt: -------------------------------------------------------------------------------- 1 | The postings on this site are my own and don't necessarily represent IBM's position, strategies or opinions. 2 | Anyone is free to use, copy, distribute, modify or sell the source code and other materials directly linked from 3 | this code and is provided "as is" without warranties. I am not responsible for any harm or damage caused to your computer, 4 | software or anything else caused by the material. 5 | 6 | 7 | ########## LICENSE 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | -------------------------------------------------------------------------------- /presidential_speeches_clean_data.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rustyoldrake/R_Scripts_for_Watson/7e97f2170d3516d0f702c14b14f70cdf7902eace/presidential_speeches_clean_data.csv -------------------------------------------------------------------------------- /sortinghat.csv: -------------------------------------------------------------------------------- 1 | I am brave,Gryffindor, 2 | I have courage,Gryffindor, 3 | The founder of my house was Godric Gryffindor,Gryffindor, 4 | house element is fire,Gryffindor, 5 | Gryffindor values courage bravery nerve and chivalry,Gryffindor, 6 | Colors= Scarlet and Gold,Gryffindor, 7 | Lion,Gryffindor, 8 | I am bold and good,Gryffindor, 9 | Bold and good,Gryffindor, 10 | Brave and bold,Gryffindor, 11 | Chivalry,Gryffindor, 12 | Honor,Gryffindor, 13 | Bravery and courage,Gryffindor, 14 | I am loyal,Hufflepuff, 15 | I am a good friend,Hufflepuff, 16 | The founder of my house was Helga Hufflepuff,Hufflepuff, 17 | house element is earth,Hufflepuff, 18 | Hufflepuffs value hard work patience justice and loyalty,Hufflepuff, 19 | Yellow and Black,Hufflepuff, 20 | Badger,Hufflepuff, 21 | Loyal friend and helpful,Hufflepuff, 22 | Friendship,Hufflepuff, 23 | Loyalty,Hufflepuff, 24 | Hard work and patience,Hufflepuff, 25 | I am very clever,Ravenclaw, 26 | Smarts,Ravenclaw, 27 | I have a big brain,Ravenclaw, 28 | The founder of my house was Rowena Ravenclaw,Ravenclaw, 29 | house element is air,Ravenclaw, 30 | Ravenclaw values intelligence creativity learning and wit,Ravenclaw, 31 | Blue and Bronze,Ravenclaw, 32 | Eagle,Ravenclaw, 33 | Clever,Ravenclaw, 34 | Good at riddles and solving problems,Ravenclaw, 35 | Intellect,Ravenclaw, 36 | Knowledge,Ravenclaw, 37 | Big IQ,Ravenclaw, 38 | Witty,Ravenclaw, 39 | I am hungry for power,Slytherin, 40 | You-Know-Who / Voldelmort was in this house,Slytherin, 41 | The founder of my house was Salazar Slytherin ,Slytherin, 42 | element is water,Slytherin, 43 | Slytherin house values ambition and cunning,Slytherin, 44 | Colors= Green and Silver,Slytherin, 45 | Snakes,Slytherin, 46 | Power hungry,Slytherin, 47 | Ambitious and after power,Slytherin, 48 | Evil,Slytherin, 49 | Parseltongue,Slytherin, 50 | Talks to snakes,Slytherin, 51 | Nasty,Slytherin, 52 | Negative,Slytherin, 53 | Jerk,Slytherin, 54 | serpent,Slytherin, 55 | snake,Slytherin, 56 | slither,Slytherin, 57 | slippery,Slytherin, 58 | bravery,Gryffindor, 59 | courage,Gryffindor, 60 | dignity,Gryffindor,Hufflepuff 61 | patriot,Gryffindor, 62 | slimy,Slytherin, 63 | yucky,Slytherin, 64 | mean,Slytherin, 65 | bad,Slytherin, 66 | bright,Ravenclaw, 67 | IQ,Ravenclaw, 68 | intelligence,Ravenclaw, 69 | genius,Ravenclaw, 70 | bookworm,Ravenclaw, 71 | cerebral,Ravenclaw, 72 | meek,Hufflepuff, 73 | quiet,Hufflepuff, 74 | shy,Hufflepuff, 75 | brave,Gryffindor, 76 | bold,Gryffindor, 77 | steadfast,Gryffindor,Hufflepuff 78 | integrity,Gryffindor,Hufflepuff 79 | honorable,Gryffindor, 80 | good,Gryffindor, 81 | fire,Gryffindor, 82 | earth,Hufflepuff, 83 | water,Slytherin, 84 | air,Ravenclaw, 85 | Vodelmort,Slytherin, 86 | Gryffindor,Gryffindor, 87 | Hufflepuff,Hufflepuff, 88 | Slytherin,Slytherin, 89 | Ravenclaw,Ravenclaw, 90 | Griffindor,Gryffindor, 91 | Pomona Sprout,Hufflepuff, 92 | Severus Snape,Slytherin, 93 | Minerva McGonagall,Gryffindor, 94 | Euan Abercrombie,Gryffindor, 95 | Katie Bell,Gryffindor, 96 | Lavender Brown,Gryffindor, 97 | Ritchie Coote,Gryffindor, 98 | Colin Creevey,Gryffindor, 99 | Dennis Creevey,Gryffindor, 100 | Seamus Finnigan,Gryffindor, 101 | Hermione Granger,Gryffindor, 102 | Angelina Johnson,Gryffindor, 103 | Lee Jordan,Gryffindor, 104 | Andrew Kirke,Gryffindor, 105 | Neville Longbottom,Gryffindor, 106 | Natalie McDonald,Gryffindor, 107 | Mary Macdonald,Gryffindor, 108 | Cormac McLaggen,Gryffindor, 109 | Parvati Patil,Gryffindor, 110 | Jimmy Peakes,Gryffindor, 111 | Harry Potter,Gryffindor, 112 | Demelza Robins,Gryffindor, 113 | Jack Sloper,Gryffindor, 114 | Alicia Spinnet,Gryffindor, 115 | Dean Thomas,Gryffindor, 116 | Romilda Vane,Gryffindor, 117 | Fred Weasley,Gryffindor, 118 | George Weasley,Gryffindor, 119 | Ginny Weasley,Gryffindor, 120 | Percy Weasley,Gryffindor, 121 | Ron Weasley,Gryffindor, 122 | Oliver Wood,Gryffindor, 123 | Sirius Black,Gryffindor, 124 | Albus Dumbledore,Gryffindor, 125 | Rubeus Hagrid,Gryffindor, 126 | Remus Lupin,Gryffindor, 127 | Minerva McGonagall,Gryffindor, 128 | Peter Pettigrew,Gryffindor, 129 | James Potter,Gryffindor, 130 | Lily Potter (Evans),Gryffindor, 131 | Bill Weasley,Gryffindor, 132 | Charlie Weasley,Gryffindor, 133 | Arthur Weasley,Gryffindor, 134 | Molly Weasley (Prewett),Gryffindor, 135 | Hannah Abbott,Hufflepuff, 136 | Susan Bones,Hufflepuff, 137 | Eleanor Branstone,Hufflepuff, 138 | Cadwallader,Hufflepuff, 139 | Owen Cauldwell,Hufflepuff, 140 | Cedric Diggory,Hufflepuff, 141 | Justin Finch-Fletchley,Hufflepuff, 142 | Ernie Macmillan,Hufflepuff, 143 | Laura Madley,Hufflepuff, 144 | Eloise Midgeon,Hufflepuff, 145 | Zacharias Smith,Hufflepuff, 146 | Pomona Sprout,Hufflepuff, 147 | Stebbins,Hufflepuff, 148 | Summerby,Hufflepuff, 149 | Summers,Hufflepuff, 150 | Nymphadora Tonks,Hufflepuff, 151 | Kevin Whitby,Hufflepuff, 152 | Rose Zeller,Hufflepuff, 153 | Stewart Ackerley,Ravenclaw, 154 | Marcus Belby,Ravenclaw, 155 | Terry Boot,Ravenclaw, 156 | Mandy Brocklehurst,Ravenclaw, 157 | Cho Chang,Ravenclaw, 158 | Eddie Carmichael,Ravenclaw, 159 | Penelope Clearwater,Ravenclaw, 160 | Michael Corner,Ravenclaw, 161 | Roger Davies,Ravenclaw, 162 | Marietta Edgecombe,Ravenclaw, 163 | Fawcett,Ravenclaw, 164 | Filius Flitwick,Ravenclaw, 165 | Anthony Goldstein,Ravenclaw, 166 | Luna Lovegood,Ravenclaw, 167 | Padma Patil,Ravenclaw, 168 | Orla Quirke,Ravenclaw, 169 | Lisa Turpin,Ravenclaw, 170 | Avery,Slytherin, 171 | Malcolm Baddock,Slytherin, 172 | Regulus Black,Slytherin, 173 | Miles Bletchley,Slytherin, 174 | Bole,Slytherin, 175 | Millicent Bullstrode,Slytherin, 176 | Vincent Crabbe,Slytherin, 177 | Derrick,Slytherin, 178 | Marcus Flint,Slytherin, 179 | Gregory Goyle,Slytherin, 180 | Harper,Slytherin, 181 | Terence Higgs,Slytherin, 182 | Bellatrix Lestrange,Slytherin, 183 | Rabastan Lestrange,Slytherin, 184 | Rodolphus Lestrange,Slytherin, 185 | Abraxas Malfoy,Slytherin, 186 | Draco Malfoy,Slytherin, 187 | Lucius Malfoy,Slytherin, 188 | Narcissa Malfoy,Slytherin, 189 | Montague,Slytherin, 190 | Theodore Nott,Slytherin, 191 | Pansy Parkinson,Slytherin, 192 | Graham Pritchard,Slytherin, 193 | Adrian Pucey,Slytherin, 194 | Tom Marvolo Riddle,Slytherin, 195 | Horace Slughorn,Slytherin, 196 | Severus Snape,Slytherin, 197 | Vaisey,Slytherin, 198 | Urquhart,Slytherin, 199 | Warrington,Slytherin, 200 | Blaise Zabini,Slytherin, 201 | Bloody Baron,Slytherin, 202 | Fat Friar,Hufflepuff, 203 | Grey Lady,Ravenclaw, 204 | Nearly Headless Nick,Gryffindor, 205 | Godric Gryffindor,Gryffindor, 206 | Helga Hufflepuff,Hufflepuff, 207 | Rowena Ravenclaw,Ravenclaw, 208 | Salazar Slytherin,Slytherin, 209 | Gryffindor values bravery daring nerve and chivalry. Its emblematic animal is the lion and its colours are scarlet and gold.,Gryffindor, 210 | values hard work dedication patience loyalty and fair play,Hufflepuff, 211 | values intelligence knowledge and wit. Its emblematic animal is the eagle ,Ravenclaw, 212 | ambition cunning and resourcefulness,Slytherin, 213 | resourceful,Gryffindor,Slytherin 214 | smart,Gryffindor,Ravenclaw 215 | I am a good friend who has courage,Hufflepuff,Gryffindor 216 | I am ambitious and resourceful,Gryffindor,Slytherin 217 | I am a bookworm but also brave,Ravenclaw,Gryffindor 218 | I am smart and also courageous,Ravenclaw,Gryffindor 219 | I am clever and crafty,Ravenclaw,Slytherin 220 | I like to hang out with my pals,Hufflepuff,Gryffindor 221 | I fight dragons,Gryffindor, 222 | killer,Slytherin, 223 | murderer,Slytherin, 224 | easy going,Hufflepuff, 225 | Achievement striving,Gryffindor,Slytherin 226 | Activity level,Gryffindor,Slytherin 227 | Adventurousness,Gryffindor,Slytherin 228 | Agreeableness,Hufflepuff, 229 | Altruism,Hufflepuff,Gryffindor 230 | Anger,Slytherin, 231 | Anxiety,Hufflepuff, 232 | Artistic interests,Ravenclaw,Gryffindor 233 | Assertiveness,Gryffindor,Slytherin 234 | Cautiousness,Hufflepuff, 235 | Challenge,Gryffindor, 236 | Cheerfulness,Hufflepuff, 237 | Closeness,Ravenclaw, 238 | Conscientiousness,Hufflepuff, 239 | Conservation,Ravenclaw,Hufflepuff 240 | Cooperation,Hufflepuff, 241 | Curiosity,Ravenclaw, 242 | Depression,Slytherin, 243 | Dutifulness,Hufflepuff,Gryffindor 244 | Emotionality,Gryffindor, 245 | Excitement,Gryffindor,Slytherin 246 | Excitement-seeking,Gryffindor,Slytherin 247 | Extraversion,Gryffindor,Slytherin 248 | Friendliness,Hufflepuff,Gryffindor 249 | Gregariousness,Gryffindor, 250 | Harmony,Hufflepuff, 251 | Hedonism,Slytherin,Gryffindor 252 | Ideal,Gryffindor, 253 | Imagination,Ravenclaw,Gryffindor 254 | Immoderation,Slytherin, 255 | Intellect,Ravenclaw, 256 | Liberalism,Gryffindor, 257 | Liberty,Gryffindor, 258 | Love,Hufflepuff, 259 | Modesty,Hufflepuff, 260 | Morality,Gryffindor,Ravenclaw 261 | Neuroticism,Hufflepuff, 262 | Openness,Gryffindor, 263 | Openness to change,Gryffindor, 264 | Orderliness,Ravenclaw,Hufflepuff 265 | Practicality,Hufflepuff, 266 | Self-consciousness,Hufflepuff, 267 | Self-discipline,Slytherin,Gryffindor 268 | Self-efficacy,Gryffindor, 269 | Self-enhancement,Gryffindor,Slytherin 270 | Self-expression,Gryffindor, 271 | Self-transcendence,Gryffindor,Slytherin 272 | Stability,Hufflepuff, 273 | Structure,Ravenclaw, 274 | Sympathy,Hufflepuff, 275 | Trust,Gryffindor,Hufflepuff 276 | Vulnerability,Hufflepuff, 277 | -------------------------------------------------------------------------------- /speech_capture_tone_bootstrapper.R: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | ### IBM Watson - SPEECH TO TEXT + TONE for Bootstrapper 3 | ### DOCS: https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/speech-to-text/ 4 | ### Before you begin you will need (1) An IBM Bluemix demo account (2) A Speech to Text App and (3) Credentials to that Service 5 | ###################################################### 6 | 7 | library(RCurl) # install.packages("RCurl") # if the package is not already installed 8 | library(httr) 9 | library(audio) 10 | library(stringr) # string splitting 11 | 12 | # get keys 13 | source("keys.r") ## KEYS has acutal username:password for each IBM service. 14 | 15 | ## This next line sets CERT Global to make a CA Cert go away - http://stackoverflow.com/questions/15347233/ssl-certificate-failed-for-twitter-in-r 16 | options(RCurlOptions = list(cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl"))) 17 | Sys.setlocale(locale="C") # error: input string 1 is invalid in this locale 18 | options(warn=-1) # careful - turns off warnings 19 | 20 | 21 | # Speech-To-Text-Orange credentials" "RED": { 22 | url <- "https://stream.watsonplatform.net/speech-to-text/api" 23 | username_STT 24 | password_STT 25 | username_password_STT 26 | 27 | setwd("/Users/ryan/Documents/Service - Speech to Text (STT)") 28 | getwd() 29 | 30 | 31 | ### FUNCTION to test connectivity and return models available 32 | watson.speech_to_text.getmodels <- function() 33 | {return(GET(url=paste(url,"/v1/models",sep=""), 34 | authenticate(username_STT,password_STT)))} 35 | 36 | ### FOR BEST RESULTS - USE USB HEADSET and ensure in MAc > Sys Preferences >Sound it's selected 37 | 38 | ## FUNCTION - Record! 39 | watson.STT.record <- function(samp_count,samp_rate) 40 | { 41 | # record 8000 samples at 8000Hz (1 sec), mono (1 channel) 42 | # record 64k samples at 16kHz (4 sec), mono (1 channel), stereo = 2 43 | a <- record(samp_count, samp_rate, 2) 44 | wait(a) # wait for the recording to finish 45 | x <- a$data # get the result 46 | x[1:10] # show first ten samples 47 | close(a); rm(a) # you can close the instance at this point 48 | # amplify and crop the signal 49 | audio <- x * 2 50 | audio[audio < -1] <- -1 51 | audio[audio > 1] <- 1 52 | return(audio) 53 | } 54 | 55 | 56 | # command line call works: curl -u $USERNAME:$PASSWORD -H "content-type: audio/wav" --data-binary @"ryan_rasp_pi1.wav" "https://stream.watsonplatform.net/speech-to-text/api/v1/recognize" 57 | 58 | 59 | #### FUNCTION TO TIDY UP the STT response - just export the TRANSCRIPT ONLY 60 | stt_transcript_only <- function(raw) 61 | { 62 | data <- as.data.frame(strsplit(as.character(raw),"\\n")) 63 | data <- data[c(7), ] # for now, grab just what we want 64 | data <- paste(data) # kill levels, - fyi this nukes confidence % info (may want later) 65 | data <- gsub(" ","",data) # remove excessive whitespace 0 cannot use ALL [[punct]] here 66 | data <- gsub("\\\\","",data) # remove punct we dont like 67 | data <- gsub("\"","",data) # remove punct we dont like 68 | data <- gsub("transcript","",data) # remove excessive whitespace 69 | data <- gsub(":","",data) # remove excessive whitespace - later: Improve this tidy step. 70 | return(data) 71 | } 72 | 73 | 74 | ###### FUNCTION - ANalyze AUDIO WAV file with IBM Watson Speech to Text service - SESSIONLESS 75 | watson.speech_to_text.recognize <- function(audio_file) 76 | { return(POST(url=paste(url,"/v1/recognize",sep=""), 77 | authenticate(username_STT,password_STT), 78 | add_headers("Content-Type"="audio/wav"), 79 | body = (file = upload_file(audio_file)) 80 | ))} #works # hope this helps you with syntax! 81 | ## this is SESSIONLESS MODE - https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/#!/speech-to-text/recognizeSessionless 82 | 83 | ######### OK - let's do stuff 84 | 85 | watson.speech_to_text.getmodels() # returns list of 10+ models ##### works 86 | 87 | 88 | ######## Let's record some audio 89 | sample_count <- 64000 ## 0k samples 90 | sample_rate <- 16000 ## at 16khz - is ~5 seconds recording time 91 | 92 | 93 | ##### BASIC FUNCTION FOR SPEECH TO TEXT - RETURNS TRANSCRIPT - SESSIONLESS 94 | watson.speech_to_text.sessionless <- function() 95 | { 96 | wait(play(sin(1:5000/4))) # recording START tone 97 | print("RECORDING ------------------ (beep) ") 98 | the_audio <- watson.STT.record(sample_count,sample_rate) 99 | wait(play(sin(1:5000/2))) # recording STOP tone 100 | print("Recording COMPLETE --------- (beep) ") 101 | print("Saving WAV File") 102 | save.wave(the_audio,"the_audio.wav") 103 | print("Calling IBM Watson Speech To Text API") 104 | response <- watson.speech_to_text.recognize("the_audio.wav") 105 | #wait(play(sin(1:2500/16))) 106 | #wait(play(sin(1:2500/8))) 107 | return(stt_transcript_only(content(response,"text"))) 108 | } 109 | 110 | # TONE ZONE 111 | tidyResponse <- function(data) 112 | { 113 | data 114 | data <- as.data.frame(strsplit(as.character(data),"\"score\"")) 115 | data 116 | data <- data[-c(1), ] # remove dud first row 117 | data 118 | data <- gsub("\"tone_id\":","",data) 119 | data <- gsub(":","",data) 120 | data <- gsub("\"","",data) 121 | data <- gsub("_big5","",data) 122 | data <- data.frame(data) 123 | data 124 | 125 | data <- data.frame(do.call('rbind', strsplit(as.character(data$data),','))) 126 | data 127 | data <- data[,-c(3:6), ] # remove unneeded columns 128 | 129 | data$X1 <- as.character.numeric_version(data$X1) # not sure why, but coercing to numbers requires this 130 | data$X1 <- as.numeric(data$X1) 131 | data$X1 <- round((data$X1),2) 132 | setNames(data,c("signal","trait")) 133 | return(data) 134 | } 135 | 136 | 137 | # TONE ZONE 138 | ### POST - Basic Test 139 | process_data_to_tone <- function(text) 140 | { 141 | response <- POST(url=base_url_TON, 142 | authenticate(username_TON,password_TON), 143 | add_headers("Content-Type"="text/plain","charset"="UTF-8"), 144 | body=text ) 145 | response_text <- content(response, "text", encoding = "UTF-8") # or encoding = "ISO-8859-1" 146 | response_text 147 | abc <- tidyResponse(response_text) 148 | return(abc) 149 | } 150 | 151 | base_url_TON = "https://gateway.watsonplatform.net/tone-analyzer/api/v3/tone?version=2016-05-19" 152 | username_password_TON 153 | 154 | 155 | ############# 156 | 157 | ## LET'S GO! 158 | w = as.integer(1) 159 | table = matrix(nrow=0,ncol=2) # if you go over number of rows, will fail 160 | table 161 | colnames(table) <- c("utterance","class") 162 | 163 | while(w>0){ 164 | 165 | print(w) 166 | temp = watson.speech_to_text.sessionless() # (1) Capture Audio and transrcipt 167 | print(temp) 168 | 169 | table <- rbind(table,paste(temp)) # (2) Put transcript in the growing matrix 170 | 171 | # (3) tone enrich in columnn 2 -take dominant signal 172 | query <- URLencode(temp) 173 | process_data_to_tone(query) 174 | 175 | analysis <- process_data_to_tone(query) # pull TONE from TONE generic API 176 | analysis <- analysis[1:5,] # just grab these 5 for now 177 | analysis 178 | colnames(analysis) <- c("signal","trait") 179 | analysis <- analysis[rev(order(analysis$signal)),] # reorder big one on top 180 | analysis 181 | if(analysis$signal[1]>.50){ 182 | table[w,2] <- paste(analysis$trait[1]) 183 | } else {table[w,2] <- c("neutral")} # crude way to clear second column 184 | 185 | # (4) Print updated table 186 | print(table) 187 | w = w+1 188 | } 189 | 190 | 191 | -------------------------------------------------------------------------------- /watson-wine-gt.csv: -------------------------------------------------------------------------------- 1 | Beef Hamburgers,cabernet_sauvignon "Barbera - Barbera is a red wine grape found primarily in Italy's Piedmont region. It produces hearty red wines with deep ruby colors, full body and low tannin levels.",Barbera "Cabernet Sauvignon - Cabernet Sauvignon is a red wine known for its depth of flavor, aroma and ability to age (present by the wine's noticeable tannins). It is full-bodied and intense, with cherry- currant and sometimes herbal flavors.",cabernet_sauvignon "Cabernet Sauvignon is more assertive than Merlot, with more tannin and greater aging potential. It can have flavors of blackberries, plums, black currants, and cassis. Aged in oak, Cabernet Sauvignon can take on flavors of vanilla, cedar, chocolate, and coffee. Beyond Bordeaux, Cabernet Sauvignon does well in Napa, California, where it produces smooth, ripe wines. Washington State, Chile and Australia are also making excellent Cabernet.",cabernet_sauvignon very nice with meat dishes like beef and lamb.,cabernet_sauvignon Grilled Steaks,cabernet_sauvignon Apples and Cheese,cabernet_sauvignon White chocolate,champagne celebrations and parties,champagne "Champagne/Sparkling Wine - These wines are made effervescent by a secondary fermentation in the wine-making process. Champagnes and sparkling wines range in style from very dry (Natural), dry (brut) and slightly sweet (extra Dry) to sweet (sec and Demi-Sec). Many sparkling wines are also identified as Blanc de Blancs (wines made from white grapes) or Blanc de Noirs (wines produced from red grapes). *Champagne is only called Champagne if it comes from the Champagne region of France.",champagne "Chardonnay is a very versatile wine grape its flavor and aromas are easily influenced by where it's grown and how it's made. Fruit flavors range from apple and lime in cooler climates to tropical fruits in warmer places. When barreled in oak, it takes on a richness characterized by honey and butter flavors. When barreled in stainless steel, it often retains more mineral flavors and comes across as fresher on the palate. Chardonnay excels in Burgundy, France. Cool coastal areas of California also produce excellent Chardonnay.",chardonnay "Chardonnay is a favorite with seafood. Minerally versions, like those from Chablis, France, pair particularly well with oysters. White wine.",chardonnay Lobster,chardonnay Popcorn,chardonnay "Chardonnay- One of the world's most popular wines, Chardonnay is a white wine originating from Burgundy. Flavors range from clean and crisp with a hint of varietal flavor to rich and complex, vanilla, butter and oak-aged wines. Chardonnay typically balances fruit, acidity and texture.",chardonnay "Chenin Blanc - Chenin Blanc is a white wine with fresh, delicate floral characteristics. It grows well in warmer climates and produces light, well- balanced wines ranging from dry to off-dry (slightly sweet) styles.",Chenin Blanc Dolcetto - This red wine grape is found almost exclusvely in Italy's Piedmont region. It produces light and fruity wine.,Dolcetto "Fume Blanc- Invented by Robert Mondavi in 1970, Fume Blanc is a Sauvignon Blanc that has been fermented in oak.",Fume Blanc "Gewurztraminer -Gewurztraminer is a white German wine that produced distinctive wines rich in spicy aromas and full flavors, ranging from dry to sweet. This varietal is a popular choice for Asian dishes.",Gewurztraminer Dark chocolate,malbec "Merlot is a soft, supple wine with nice fruit flavors of plums and blackberries and occasionally mint, chocolate and eucalyptus flavors and aromas. Typically, it is ready to drink earlier than Cabernet Sauvignon, which sometimes needs a few years for its astringent tannins to mellow. Outside of Europe, New World Merlot shines in places like California, Chile and Washington State.",merlot very nice with meat dishes like beef and lamb.,merlot Dark chocolate,merlot "Merlot - Merlot is a red wine with medium to full body with black cherry and herbal flavors. Merlot is typically smooth, soft and mellow.",merlot "Mourvedre - This warm-weather, red wine grape is common in Southern France's Rhone Valley. Rich in color with early aromas, often blended with Syrah.",Mourvedre "Petite Sirah - Petite Sirahs are inky red wines with firm, robust tannic tastes, often with peppery flavors. Petite Sirahs may complement meals with rich meats.",Petite Sirah "Pinot Gris (Pinot Grigio) - The low acidity of this white grape helps produce rich, lightly perfumed wines that are often more colorful than other whites.",pinot_gris_pinot_grigio "Pinot Noir - Pinot Noir is the world famous grape from Burgundy and more recently California and the Pacific Northwest. A light to medium-body wine, pegged as one of the most difficult to grow and make. Delicate and smooth with rich complexity, Pinot Noir is a versatile dinner companion.",pinot_noir "Pinot Gris�is made from grapes that generally produce different styles of wine depending on where the grapes are grown and how they're handled in the cellar. In the Alsace region of France, and in places like Oregon and New Zealand, Pinot Gris typically makes rich wines marked by a bit of spice. The Italian style (Pinot Grigio) tends to be fresh, crisp and refreshing.",pinot_gris_pinot_grigio " seafood and pasta dishes, vegetarian food and poultry. White wine.",pinot_gris_pinot_grigio Grilled Chicken,pinot_gris_pinot_grigio Apples and Cheese,pinot_gris_pinot_grigio "Pinot Noir, a notoriously difficult grape to grow, made its mark initially in Burgundy, France. The grape continues to deliver single-varietal wines that are among the best in the world. Pinot Noirs are delicate wines that taste of red fruits like cherries, raspberries and strawberries. With age, flavors and aromas become more complex, developing earthy notes like mushrooms and decaying leaves. Burgundy in particular is noted for developing these earthy flavors. In the New World, tasty Pinot Noir is being made in Oregon, New Zealand, and some of the cooler appellations of California.",pinot_gris_pinot_grigio "Pinot Noir is a versatile food wine, great with poultry, salmon, meat and vegetable dishes.",pinot_gris_pinot_grigio Grilled Chicken,pinot_gris_pinot_grigio Grilled Tuna,pinot_gris_pinot_grigio "Riesling is a crisp, clean wine with green apple, pear and lime flavors. The best offer pleasing mineral qualities as well. With age, Riesling takes on honey flavors and attractive oily aromas. Riesling grows well in Germany, the Alsace region of France, the Finger Lakes region of New York, and parts of Australia and Washington State.",riesling "Riesling pairs nicely with spicy foods, poultry and pork. Try it with Thai food. White wine",riesling BBQ Barbeque ,riesling Apples and Cheese,riesling "Riesling - Riesling is the classic white wine grape from Germany and known for its floral perfume. Depending on where they're made, they can be crisp and bone-dry, full-bodied and spicy or luscious and sweet.",riesling "Roses (Blush Wines) - Roses, also called blush wines, are light pink wines made from several red wine grapes. They get their color from a very short period of contact with the grape skins during the wine-making process. Roses are light, usually somewhat sweet and best served well-chilled.",rose "Sangiovese - Sangiovese is best known as the Italian red wine, Chianti. Hearty and dry, it often displays a distinctively smooth texture with spice, raspberry and licorice flavors.",sangiovese "Sauvignon Blanc - Sauvignon Blanc is a white wine best known for its grassy, herbal flavors and is a popular choice for shellfish or as a refreshing alternative to Chardonnay.",sauvignon_blanc "Sauvignon Blanc is a fresh, crisp, aromatic wine with grapefruit and grassy flavors. This wine is the star of the Loire region of France. It also shines in the Bordeaux region, where it is often blended with Semillon. In the New World, New Zealand has emerged as a prime spot for Sauvignon Blanc.",sauvignon_blanc "Sauvignon Blanc is a food-friendly wine that goes well with many seafood, poultry and vegetable dishes. White Wine",sauvignon_blanc Grilled Chicken,sauvignon_blanc "Shiraz Australian versions are typically big, bold and spicy with jammy fruit and aromas of leather and black fruit. Syrah is at home in the Rhone region of France, where the grape makes spicy, rich, darkly delicious wines that increase in complexity as they age. Syrah also makes delicious wines in Australia, where it is marketed as Shiraz. Syrah also excels in Washington State, where it often displays an attractive acid balance, and in California, where the styles vary significantly.",shiraz Syrah is a very versatile wine that pairs well with a wide variety of foods. It's terrific with grilled meats.,syrah_shiraz Portabella Mushrooms,syrah_shiraz BBQ Pork Ribs,syrah_shiraz Beef Hamburgers,syrah_shiraz Dark chocolate,syrah_shiraz "Syrah (Shiraz) - Syrah can produce giant red wines with strong tannins and complex combinations of flavors including berry, plum and smoke. It's known as Shiraz mainly in Australia and South Africa.",syrah_shiraz "Viognier - Viognier is a rare white grape growing in popularity for its uniqueness. It is an aromatic variety typically displaying peach, apricot and sometimes spicy flavors.",viognier "Zinfandel has found its home in California, where it produces big, fruity, often spicy red wines. Zin",zinfandel BBQ Barbeque ,zinfandel BBQ Pork Ribs,zinfandel Pepperoni Pizza,zinfandel "Zinfandel - Zinfandel is a medium to full-bodied red wine with berry or spicy, peppery flavors. Great with pizza and tangy barbecue sauce.",zinfandel Champagne is perfect with anything salty.,champagne Sauvignon Blanc goes with tart dressings and sauces.,sauvignon_blanc Pinot Grigio pairs well with light fish dishes.,pinot_gris_pinot_grigio Choose Chardonnay for fatty fish or fish in a rich sauce.,chardonnay Off-Dry Riesling pairs with sweet & spicy dishes.,riesling Moscato d'Asti loves fruit desserts.,moscato Pinot Noir is great for dishes with earthy flavors.,pinot_noir Malbec won't be overshadowed by sweet-spicy barbecue sauces.,malbec "Choose Zinfandel for pates, mousses and terrines.",zinfandel Cabernet Sauvignon is fabulous with juicy red meat.,cabernet_sauvignon Syrah matches with highly spiced dishes.,syrah_shiraz --------------------------------------------------------------------------------