ilusm.dev

bot

Chatbot framework - define intents with example utterances, extract entities, track dialogue state per user, generate slot-filled responses, power bots with LLMs or RAG, build multi-turn forms, and export/import bot configs.

Load with: use bot

What this module does

bot provides two paths to building a conversational bot:

  • Rule-based NLU: define intents with example utterances, use Jaccard-similarity NLU (nlpjr) to classify incoming messages, extract typed entities (numbers, dates, emails, custom lists) with regex, fill slots from context, and render template-based responses.
  • LLM-powered: wrap an LLM context with a system prompt and let btllm maintain a 10-turn per-user history for multi-turn conversations - or use btrgt for RAG (retrieval-augmented generation) that embeds documents and retrieves the top-3 most relevant before generating an answer.

Quick example

use bot

# Create a rule-based bot
b = botne("support-bot")

# Define an intent
greet = btnt0("greet", ["hello", "hi", "hey"], nil)
b = btntd(b, greet)

# Define a flow (response template for the intent)
b.flows["greet"] = {txt: "Hello! How can I help you today?", opts: nil}

# Handle a user message
rsp = bttrn(b, "user1", "hi there")
prn(rsp.txt)  # "Hello! How can I help you today?"

# LLM-powered bot
llm_b = btll0(my_llm_ctx, "You are a helpful assistant.")
rsp2 = btllm(llm_b, "user1", "What is the weather today?")

Functions

Bot definition

botne(name)

Creates a new bot with the given name. Fields: nm, ver: "1.0", int (intents map), flows, ctx (per-user context), nlu/nlg: nil, st: "idle", hist, usr, slots, act (action handlers).

Intents and entities

btnt0(name, utterances, action)

Defines an intent with example utterances and an optional action name. Default confidence threshold is 0.8. action defaults to name if nil.

btntd(b, intent)

Registers an intent in the bot's intent map by intent.nm.

btntn(name, type, vals)

Defines an entity. Supported types: "sys.number", "sys.date", "sys.email", "custom". vals is a list of allowed values for custom entities.

btntx(text, entities)

Extracts entity values from text using regex. Numbers via \b\d+\b, dates via \d{1,2}/\d{1,2}/\d{2,4}, emails via [\w.-]+@[\w.-]+\.\w+, custom by substring matching. Returns an object keyed by entity name.

NLU

btnlu(b, text)

Classifies incoming text against all registered intents by computing Jaccard similarity (nlpjr) between the text and each example utterance. Returns the best-matching {int, sc, act}.

Dialogue state

btdst(b, user, intent, entities)

Updates the dialogue state for a user. Creates a context object if it doesn't exist. Sets the current intent, merges entities into slots, and keeps a 10-turn intent history.

btfl1(b, user, slot, val)

Directly sets a slot value for a user's context.

btclr(b, user)

Clears the dialogue context for a user.

btgtc(b, user)

Returns the current dialogue context for a user.

Response generation

btrs0(text, opts)

Creates a response object. opts may include quick (quick reply buttons), cards, img, aud, and act (actions).

btrsp(b, ctx)

Generates a response for the current intent. Looks up the flow template by intent name, substitutes slot values using {slot_name} placeholders. Falls back to "I didn't understand that." if no flow is defined.

Conversation handling

bttrn(b, user, input)

Main turn handler. Classifies the input, extracts entities, updates dialogue state. If required slots are missing, prompts for the first missing one with its quick-reply values. Otherwise executes the registered action (if any) or generates a template response.

botxc(b, action, slots)

Executes a registered action function from b.act[action], passing the current slots.

btfll(b, input)

Fallback handler - checks cosine similarity against intent utterances. Suggests the closest intent if similarity > 0.5, otherwise returns "Can you rephrase?"

Dialogue flows

btfl0(name, start_state, end_state)

Creates a flow descriptor with start/end states and optional action and condition fields.

btflw(b, flow)

Registers a flow in the bot's flows map by flow.nm.

LLM-powered bots

btll0(llm_ctx, system_prompt)

Creates an LLM bot with a system prompt. Maintains per-user conversation history (up to 10 turns).

btllm(b, user, input)

Sends a message to the LLM with the full message history. Stores the response in the user's history. Returns a response object.

RAG-based bots

botrg(llm_ctx, docs)

Creates a RAG bot. Pre-embeds all documents via llmmb.

btrgt(b, user, input)

Embeds the query, computes cosine similarity against all document embeddings, retrieves the top-3 most relevant, constructs a Context:\n{docs}\n\nQuestion: {input}\nAnswer: prompt, and calls the LLM.

Multi-turn forms

btfr1(name, slots, confirm_fn)

Creates a multi-step form with a list of slot descriptors and a confirmation callback.

btfrm(form, user, input)

Advances the form - stores the input in the current slot, moves to the next, prompts for it. When all slots are filled, calls the confirm function.

Utilities

bthnd(b, user, reason)

Triggers a human handoff - sets bot state to "handoff" and returns a handoff message.

btstt(b)

Returns basic bot stats: user count, intent list with zero counts, and average turn count placeholder.

bt2js(b)

Serialises the bot's name, version, intents, and flows to a JSON string.

btfr0(json)

Deserialises a bot from a JSON string produced by bt2js.

btwbh(b, platform)

Returns a platform adapter stub for "slack", "discord", "telegram", or "web".

bttst(b, conv)

Runs a test conversation - a list of {inp, rsp} pairs. Checks each response against the expected value. Returns {inp, exp, got, pass} for each turn.

Notes

  • NLU uses Jaccard similarity via nlpjr - adequate for short utterances, not production-grade for open-domain classification.
  • LLM and RAG features require llm module functions (llmc2, llmmb, llmsm, llms3).
  • Requires trl, txt, jsn, llm, and nlp.