# Code that knows what you mean.

Simple functions that give your software judgment. Hand one a message, ask "Does the customer ask for a refund?", and get back yes or no.

*The customer asks for money back. decide prints true and exits 0.*

```
question="Does the customer ask for a refund?"

printf '%s' "Please refund my order. It arrived broken." |
thinkthen decide "$question"
```

*Output*

```
true
```

*exit 0: yes*

*Install the command*

```
curl -fsSL https://thinkthen.dev/install.sh | sh
```

*Or with Homebrew, an option on a Mac*

```
brew install botassembly/thinkthen/thinkthen
```

```
import thinkthen as tt

question = "Does the customer ask for a refund?"
broken = "Please refund my order. It arrived broken."
is_refund = tt.decide(question, broken).value
assert is_refund is True
```

*Install it for Python*

```
pip install thinkthen
```

```
import pandas as pd
import thinkthen as tt

question = "Does the customer ask for a refund?"
messages = pd.Series([
    "Please refund my order. It arrived broken.",
])
is_refund = tt.decide(question, messages).value
assert is_refund.tolist() == [True]
```

*Install it for pandas*

```
pip install thinkthen pandas
```

```
import polars as pl
import thinkthen as tt

question = "Does the customer ask for a refund?"
messages = pl.Series([
    "Please refund my order. It arrived broken.",
])
is_refund = tt.decide(question, messages).value
assert is_refund.to_list() == [True]
```

*Install it for Polars*

```
pip install thinkthen[polars]
```

```
library(thinkthen)

question <- "Does the customer ask for a refund?"
broken <- "Please refund my order. It arrived broken."
is_refund <- tt_decide(question, broken)$value
stopifnot(identical(is_refund, TRUE))
```

*Install it for R*

```
install.packages("thinkthen", repos = c("https://botassembly.r-universe.dev", "https://cloud.r-project.org"))
```

```
import assert from "node:assert/strict";
import * as tt from "thinkthen";

const question = "Does the customer ask for a refund?";
const broken = "Please refund my order. It arrived broken.";
const isRefund = (await tt.decide(question, broken)).value;
assert.equal(isRefund, true);
```

*Install it for TypeScript*

```
npm install thinkthen
```

```
require "thinkthen"

question = "Does the customer ask for a refund?"
broken = "Please refund my order. It arrived broken."
is_refund = ThinkThen.decide(question, broken).value
raise unless is_refund == true
```

*Install it for Ruby*

```
gem install thinkthen
```

```
<?php
declare(strict_types=1);
require __DIR__ . '/thinkthen-php/autoload.php';

$library = __DIR__ . '/thinkthen-c/lib/libthinkthen.so';
$tt = new ThinkThen($library);

$question = 'Does the customer ask for a refund?';
$isRefund = $tt->decide(
    $question,
    'Please refund my order. It arrived broken.',
)['value']['outcome'];
assert($isRefund === ThinkThen::YES);
$tt->close();
```

*Install it for PHP*

```
composer require botassembly/thinkthen
```

```
import 'dart:io';

import 'package:thinkthen_dart/thinkthen_dart.dart';

void main() {
  final library = File('thinkthen-c/lib/libthinkthen.so');
  final tt = Door(library.absolute.path);
  final engine = tt.create();
  try {
    const question = 'Does the customer ask for a refund?';
    final isRefund = tt.decide(
      engine,
      question,
      'Please refund my order. It arrived broken.',
    ).value.outcome;
    assert(isRefund == Outcome.yes);
  } finally {
    tt.engineFree(engine);
  }
}
```

*Install it for Dart*

```
dart pub add thinkthen_dart
```

```
import static java.nio.charset.StandardCharsets.UTF_8;

import thinkthen.Door;
import thinkthen.Door.Outcome;

void main() {
    try (var tt = new Door()) {
        var question =
            "Does the customer ask for a refund?";
        var text =
            "Please refund my order. It arrived broken.";
        var isRefund = tt.decide(
            question, text.getBytes(UTF_8)).value();
        assert Door.outcome(isRefund) == Outcome.YES;
    }
}
```

*Install it for Java*

```
io.github.botassembly:thinkthen-jvm:VERSION
```

```
import thinkthen.Door
import thinkthen.Door.Outcome

fun main() {
    Door().use { engine ->
        val tt = KotlinFacade(engine)
        val question =
            "Does the customer ask for a refund?"
        val text =
            "Please refund my order. It arrived broken."
        val isRefund = tt.decide(question, text).value()
        check(Door.outcome(isRefund) == Outcome.YES)
    }
}
```

*Install it for Kotlin*

```
io.github.botassembly:thinkthen-jvm:VERSION:kotlin
```

```
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.Using
import thinkthen.Door
import thinkthen.Door.Outcome

@main def decide(): Unit =
  Using.resource(Door()) { engine =>
    val tt = ScalaFacade(engine)
    val question =
      "Does the customer ask for a refund?"
    val text =
      "Please refund my order. It arrived broken."
    val isRefund = tt.decide(question, text).value()
    assert(Door.outcome(isRefund) == Outcome.YES)
  }
```

*Install it for Scala*

```
io.github.botassembly:thinkthen-jvm:VERSION:scala
```

```
using System.Diagnostics;
using ThinkThen;

using var tt = Engine.Open();
const string question =
    "Does the customer ask for a refund?";
const string text =
    "Please refund my order. It arrived broken.";
var isRefund = tt.Decide(question, text).Value;
Trace.Assert(isRefund.OutcomeKind == Outcome.Yes);
```

*Install it for C#*

```
dotnet add package Botassembly.ThinkThen
```

```
#include <assert.h>
#include <string.h>
#include <thinkthen.h>

thinkthen_engine *tt = thinkthen_engine_new();
assert(tt);

const char *question =
    "Does the customer ask for a refund?";
const char *text =
    "Please refund my order. It arrived broken.";
thinkthen_answer is_refund;
int rc = thinkthen_decide(
    tt,
    question,
    text,
    strlen(text),
    &is_refund
);
assert(rc == THINKTHEN_OK);
assert(is_refund.outcome == THINKTHEN_YES);
thinkthen_engine_free(tt);
```

Keep the `#include` lines on top. Put the rest inside `int main(void)` and end it with `return 0;`.

*Install it for C*

```
thinkthen.h + libthinkthen
```

```
#include <cassert>
#include <thinkthen/door.hpp>

int main() {
    auto engine = tt::create();

    const char *question =
        "Does the customer ask for a refund?";
    auto is_refund = tt::decide(
        engine,
        question,
        "Please refund my order. It arrived broken.");
    assert(is_refund.value.outcome == tt::Outcome::yes);
}
```

*Install it for C++*

```
thinkthen-cpp-VERSION-TARGET.tar.gz
```

```
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "ThinkThen.h"

int main(void) {
    TTClient *client = [TTClient create];
    TTFailure failure = {0};
    TTDecision is_refund = {0};
    char *facts = NULL;

    const char *question =
        "Does the customer ask for a refund?";
    const char *broken =
        "Please refund my order. It arrived broken.";
    TTErrorKind refund_error =
        [client decide:question
                  text:broken
                length:strlen(broken)
              deadline:-1
                 token:nil
                answer:&is_refund
                 facts:&facts
               failure:&failure];
    assert(refund_error == TTErrorNone);
    assert(is_refund.outcome == TTOutcomeYes);
    free(facts);

    tt_failure_clear(&failure);
    [client dealloc];
    return 0;
}
```

*Install it for Objective-C*

```
thinkthen-objective-c-VERSION-TARGET.tar.gz
```

```
use thinkthen::{Answer, Engine, Question};

let tt = Engine::from_env()?;
let question = "Does the customer ask for a refund?";
let refund = Question::decide(question)?.cut();
let broken = "Please refund my order. It arrived broken.";
let is_refund = tt.decide(&refund, broken)?.into_value();
assert_eq!(is_refund, Answer::Yes);
```

Put this code inside `fn main() -> Result<(), Box<dyn std::error::Error>>` and end it with `Ok(())`. `main` returns a `Result`, so `?` compiles.

*Install it for Rust*

```
cargo add thinkthen
```

```
package main

import (
	"context"
	"log"

	thinkthen "github.com/botassembly/thinkthen/libraries/go"
)

func main() {
	tt, err := thinkthen.New()
	if err != nil {
		log.Fatal(err)
	}
	defer tt.Close()
	ctx := context.Background()

	question := "Does the customer ask for a refund?"
	isRefund, err := tt.Decide(
		ctx,
		question,
		"Please refund my order. It arrived broken.",
	)
	if err != nil {
		log.Fatal(err)
	}
	if isRefund.Value.Outcome != thinkthen.Yes {
		log.Fatal("expected yes")
	}
}
```

*Install it for Go*

```
go get github.com/botassembly/thinkthen/libraries/go
```

```
import ThinkThen

let tt = try Engine()
let question = "Does the customer ask for a refund?"
let isRefund = try tt.decide(
    question,
    "Please refund my order. It arrived broken."
)
precondition(isRefund.value.outcome == .yes)
tt.close()
```

*Install it for Swift*

```
thinkthen-swift-VERSION-TARGET.tar.gz
```

```
const std = @import("std");
const thinkthen = @import("thinkthen");

pub fn main() !void {
    const allocator = std.heap.page_allocator;
    var tt = switch (try thinkthen.Engine.init(allocator)) {
        .ok => |engine| engine,
        .failed => |failure| {
            thinkthen.releaseFailure(allocator, failure);
            return error.NoEngine;
        },
    };
    defer tt.deinit();

    const question = "Does the customer ask for a refund?";
    const text =
        "Please refund my order. It arrived broken.";
    const asked = try tt.decide(question, text, .{});
    const is_refund = switch (asked) {
        .ok => |answer| answer,
        .failed => |failure| {
            tt.freeFailure(failure);
            return error.Failed;
        },
    };
    defer is_refund.deinit(allocator);
    std.debug.assert(is_refund.value.outcome == .yes);
}
```

*Install it for Zig*

```
thinkthen-zig-VERSION-TARGET.tar.gz
```

```
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Thinkthen; use Thinkthen;

procedure Sample is
   Client    : Engine;
   Is_Refund : Decision;
   Facts     : Unbounded_String;
   Error     : Failure;

   Question : constant String :=
     "Does the customer ask for a refund?";
begin
   Decide
     (Client,
      Question,
      "Please refund my order. It arrived broken.",
      Is_Refund,
      Facts,
      Error);
   pragma Assert (Error.Kind = None);
   pragma Assert (Is_Refund.Value = Yes);
end Sample;
```

*Install it for Ada*

```
thinkthen-ada-VERSION-TARGET.tar.gz
```

```
identification division.
program-id. sample.
environment division.
configuration section.
repository. function all intrinsic.
data division.
working-storage section.
copy "thinkthen.cpy".
01 engine usage pointer.
01 free-engine pic x(24) value "thinkthen_engine_free".
01 question pic x(200)
    value "Does the customer ask for a refund?".
01 question-length usage binary-double unsigned.
01 evidence pic x(200)
    value "Please refund my order. It arrived broken.".
01 evidence-length usage binary-double unsigned.
01 is-refund.
   02 refund-outcome usage binary-long signed.
      88 is-refund-yes value 1.
   02 filler usage binary-long unsigned.
   02 filler usage float-long.
procedure division.
    call "thinkthen_engine_new" returning engine

    move length(trim(question trailing))
        to question-length
    move length(trim(evidence trailing))
        to evidence-length
    call "TT-DECIDE" using engine
        question question-length
        evidence evidence-length
        tt-deadline-ms is-refund tt-facts tt-failure
    if not is-refund-yes
        stop run returning 1
    end-if

    call free-engine using by value engine
    stop run returning 0.
```

*Install it for COBOL*

```
thinkthen-cobol-VERSION-TARGET.tar.gz
```

```
LOAD './thinkthen.duckdb_extension';

SELECT thinkthen_decide(
    'Does the customer ask for a refund?',
    'Please refund my order. It arrived broken.'
) AS is_refund;
```

*What DuckDB printed*

```
is_refund
true
```

*Install it for DuckDB*

```
thinkthen-duckdb-VERSION-TARGET.tar.gz
```

```
.load ./thinkthen

SELECT thinkthen_decide(
    'Does the customer ask for a refund?',
    'Please refund my order. It arrived broken.'
) AS is_refund;
```

*What SQLite printed*

```
1
```

*Install it for SQLite*

```
thinkthen-sqlite-VERSION-TARGET.tar.gz
```

```
SELECT thinkthen_decide(
    'Does the customer ask for a refund?',
    'Please refund my order. It arrived broken.'
) AS is_refund;
```

*What PostgreSQL printed*

```
 is_refund 
-----------
 t
(1 row)
```

*Install it for PostgreSQL*

```
thinkthen-postgresql16-VERSION-TARGET.tar.gz
```

[Every binding and backend](/install/)

`decide` is an if that understands. `filter` is a grep that understands. `rank` is a sort that understands. Every answer rests on the model's probabilities. On `decide`, a band sends anything between its two sides back as not sure. A person reads those.

## The ten functions

10 functions, [1 CLI](/install/shell/), [24 bindings](/install/).

- [decide](/functions/decide/): Answer one yes or no question about the evidence.

- [choose](/functions/choose/): Pick one option from your list.

- [tag](/functions/tag/): Name every label that fits.

- [score](/functions/score/): Place the evidence on a scale you name.

- [filter](/functions/filter/): Keep the records where the answer is yes.

- [rank](/functions/rank/): Sort records by how likely the answer is yes.

- [find](/functions/find/): Pick the one line that best answers a question.

- [annotate](/functions/annotate/): Fill out a form for every record.

- [recognize](/functions/recognize/): Find every name in the evidence and say what kind it is.

- [relate](/functions/relate/): Find relationships among named entities.

[Save a question as a file](/functions/question-file/)

## Learn it on the Beatles

[Beatles Bench](/learn/beatles-bench/) asks questions about Beatles songs. A script set the right answer to each scored question ahead of time, from Wikipedia and Wikidata. New to ThinkThen? Start with the [tutorial](/learn/tutorial/).

## Jobs your software can take on

- [Triage a support inbox](/how-tos/triage-a-support-inbox/): for support teams

- [Join two tables by meaning](/how-tos/join-two-tables-by-meaning/): for data analysts

- [Sort survey answers by mood and problem](/how-tos/code-open-ended-survey-answers/): for survey and market researchers

- [Screen studies for a review](/how-tos/screen-studies-for-a-review/): for researchers

- [Group alerts into incidents](/how-tos/group-alerts-into-incidents/): for on-call engineers

- [Rank the inbound leads](/how-tos/rank-the-inbound-leads/): for sales teams

[See every how-to](/how-tos/)

On GitHub: [github.com/botassembly/thinkthen](https://github.com/botassembly/thinkthen)
