Skip to content

JSON Lines

JSON Lines is a file with one JSON object on each line. ThinkThen judges each object on its own, and each answer starts with the object's id, so you can match the answers to your messages.

messages.jsonl
{"id":"a1","text":"Please refund my order."}
{"id":"a2","text":"Where is my parcel?"}
{"id":"a3","text":"I was charged twice for one invoice."}
Terminal window
thinkthen decide --field /text \
'Does the customer request a refund?' messages.jsonl

Output

a1	true
a2	false
a3	true

a1 and a3 ask for a refund, and a2 asks about a delivery. A file whose name ends in .jsonl is read as JSON Lines. From a pipe, add --from jsonl.

--field /text judges the text field of each object, as above. The field name starts with /, and /message/body reaches a field inside another one. THINKTHEN_FIELD sets the same thing for every command in your shell.

With no --field, ThinkThen judges the whole object, minus its id. Repeat --field to judge several fields together, such as --field /subject --field /body.

An object without an id is still judged, and its answer starts with its place in the input instead, counting from 1.

--into names a new field. Each object comes back unchanged, with its answer in that field, in the order of the file.

messages.jsonl
{"id":"a1","text":"Please refund my order."}
{"id":"a2","text":"Where is my parcel?"}
{"id":"a3","text":"I was charged twice for one invoice."}
Terminal window
thinkthen decide --field /text --into is_refund \
'Does the customer request a refund?' messages.jsonl

Output

{"id":"a1","text":"Please refund my order.","is_refund":true}
{"id":"a2","text":"Where is my parcel?","is_refund":false}
{"id":"a3","text":"I was charged twice for one invoice.","is_refund":true}

Each message keeps its id and text, and gains is_refund.

filter with --into gives back only the objects that answer yes. When some lines were not sure or failed, it then prints one line on standard error that counts each, so a not sure line never drops out unseen. --quiet hides that count, and the objects, but still prints each failure's error with its id and file.

Every line must be a JSON object that doesn't already hold the new field; otherwise the command names the line, stops with exit code 2, and asks nothing.

A not sure answer writes "unsure" in the field. A line that fails writes null, its error goes to standard error, and the command exits 6.

messages.jsonl
{"id":"a3","text":"I was charged twice for one invoice."}
{"id":"a4"}
Terminal window
thinkthen decide --field /text --into is_refund \
--low 0.2 --high 0.8 \
'Does the customer request a refund?' messages.jsonl

Output

{"id":"a3","text":"I was charged twice for one invoice.","is_refund":"unsure"}
{"id":"a4","is_refund":null}
thinkthen: record.missing: position 2 id a4 file messages.jsonl: the record holds nothing at /text

The chance that a3 asks for a refund falls between the low bar of 0.2 and the high bar of 0.8, so it is not sure. a4 has no text field, so it fails. Send both to a person; never treat either as a no. Exit codes lists what each code means.

--into can't be combined with --json, --check, --output, --in-place or --details. For every detail of each answer, leave out --into and add --json; JSON output lists its fields.

Exit codes lets a script act on the answer.