R SDK
The R SDK gives R the ten functions, from tt_decide() to tt_annotate(); each takes your texts and gives back a plain R vector with one answer per text, such as TRUE or FALSE from decide, or NA when it is not sure.
library(thinkthen)
is_refund <- tt_decide("Please refund my order.", question = "Does the customer request a refund?")print(is_refund)Output
[1] TRUE
TRUE means yes: the message asks for a refund.
Install it (R 4.2.0 or later):
install.packages("thinkthen", repos = c( "https://botassembly.r-universe.dev", "https://cloud.r-project.org"))The client uses the key from the Quickstart.
Handle not sure and failures
Section titled “Handle not sure and failures”Set a low bar and a high bar with threshold = c(0.2, 0.8). Between them, decide is not sure, and the answer is NA. if (NA) stops with an error, so not sure never passes for no. When ThinkThen can't judge a text, such as a blank one, the call raises a thinkthen_failed_rows error instead of answering.
library(thinkthen)
question <- "Does the customer request a refund?"is_refund <- tt_decide("I was charged twice for one invoice.", question = question, threshold = c(0.2, 0.8))print(is_refund)
failure <- tryCatch(tt_decide("", question = question), thinkthen_failed_rows = identity)print(failure$code)Output
[1] NA
[1] "record.empty"
A double charge might be a refund request, or might not, so the answer is NA: send it to a person. The blank text can't be judged, so the call raises, and the error's code is record.empty.
Test is.na() before you branch on an answer. The error is raised only after every other text is judged; its failed_rows lists the texts that failed, and rows holds every outcome already paid for. Every ThinkThen error inherits thinkthen_error and carries a code; Troubleshooting lists each one.
The ten functions
Section titled “The ten functions”Each function takes the texts first, as a character vector, a list or a data frame, and answers each text in input order. Name question = so a swapped call can't ask the wrong question. Every program reads the same support-inbox messages as the function pages.
decide
Section titled “decide”Yes or no about each text
library(thinkthen)
is_refund <- tt_decide("Please refund my order.", question = "Does the customer request a refund?")print(is_refund)Output
[1] TRUE
Yes: the message asks for a refund. tt_decide() also takes threshold, one bar or a low and a high bar, and yes_means and no_means, which say in words what each answer means. decide shows every option.
choose
Section titled “choose”The one choice that fits
library(thinkthen)
topic <- tt_choose("Please refund my order.", question = "What is the message about?", choices = c("billing", "shipping", "other"))print(topic)Output
[1] "billing"
A refund is about billing. The answer is one of your choices, or NA when not sure. descriptions says what each choice means, and threshold sets the bar. choose shows every option.
filter
Section titled “filter”Only the texts that answer yes
library(thinkthen)
messages <- c("Please refund my order.", "Where is my parcel?", "I was charged twice for one invoice.")refund_requests <- tt_filter(messages, question = "Does the customer request a refund?")print(refund_requests)Output
[1] "Please refund my order."
[2] "I was charged twice for one invoice."
The parcel question is left out. tt_filter() gives back your own texts, in the form you passed, and leaves out the ones it is not sure about. If any text fails, it raises thinkthen_failed_rows after judging the rest, and the error's kept holds the kept texts. tt_keep() gives the same answer as TRUE, FALSE or NA for each text, for dplyr::filter(). filter shows every option.
Every label that fits
library(thinkthen)
topics <- tt_tag("I was charged twice and my parcel is late again.", question = "Which topics appear?", labels = c("billing", "shipping"))[[1]]print(topics)Output
[1] "billing" "shipping"
The message is about both billing and shipping. tt_tag() gives a list with one character vector per text, so [[1]] takes the first. tag shows every option.
A number from 0 to 1 on your scale
library(thinkthen)
urgency <- tt_score("Please refund my order.", question = "How urgent is the request?", levels = c("routine", "urgent"))print(urgency)Output
[1] 0.05
The levels run lowest first, so a plain refund request scores near routine. score shows every option.
Every text, highest first
library(thinkthen)
messages <- c("Please refund my order.", "Where is my parcel?", "I was charged twice for one invoice.")urgency_rank <- tt_rank(messages, question = "How urgent is the request?", levels = c("routine", "urgent"))print(urgency_rank)Output
[1] 3 2 1
The double charge is the most urgent. Each text gets its rank, starting at 1, in input order, so messages[order(urgency_rank)] puts the most urgent first. With top = 2, ranks past the first two are NA. rank shows every option.
The line that answers the question
library(thinkthen)
action <- tt_find("Morgan works for Example Group.\nPlease refund my order.", question = "Which line states the requested action?")print(action$text)Output
[1] "Please refund my order."
The second line states the action. The answer has $text, $start and $end, counted in characters from 1 with the end included, so substr(text, action$start, action$end) gives the line. $text is NA when no line answers. find shows every option.
recognize
Section titled “recognize”Each name in the text and its kind
library(thinkthen)
mentions <- tt_recognize("Morgan works for Example Group.", kinds = c("person", "organization"))[[1]]print(data.frame(text = mentions$text, kind = mentions$kind))Output
text kind
1 Morgan person
2 Example Group organization
tt_recognize() gives a list with the names found in each text. Each name has $text, $kind, $start, $end and $probability. recognize shows every option.
relate
Section titled “relate”Names linked by the relations you allow
library(thinkthen)
employers <- tt_relate( "Morgan works for Example Group.\nPlease refund my order.", rules = tt_rule("person", "organization", "works_for"))[[1]]print(data.frame(source = employers$source$text, relation = employers$relation, target = employers$target$text))Output
source relation target
1 Morgan works_for Example Group
tt_rule() names the kind of name at each end and the relation between them; rules takes one rule or a list() of them. Relate finds its own names, so it needs no recognize call first. relate shows every option.
annotate
Section titled “annotate”Several questions for each text
library(thinkthen)
messages <- c("Please refund my order.", "Where is my parcel?", "I was charged twice for one invoice.")inbox_form <- tt_toolbox(list( "refund" = tt_decide_question("Does the customer request a refund?"), "topic" = tt_choose_question("What is the message about?", choices = c("billing", "shipping", "other")), "urgency" = tt_score_question("How urgent is the request?", levels = c("routine", "urgent"))))triage <- tt_annotate(messages, inbox_form)print(triage)Output
# A tibble: 3 × 3
refund topic urgency
<lgl> <chr> <dbl>
1 TRUE billing 0.05
2 FALSE shipping 0.14
3 TRUE billing 0.45
tt_annotate() gives a tibble with one column per question, each of its own type, and NA where a question is not sure. annotate shows every option.
The full API
Section titled “The full API”field = "/text" judges the text column of a data frame, or the text field of each list. Each function has a _rows twin, such as tt_decide_rows(), that gives every outcome with its status and probability, and tt_bind() adds those to a copy of your data frame. tt_client() makes your own client, and Esc or Ctrl-C cancels a running call. The R API reference lists every function and argument.