NonplayerCharacter: Just use an embedding model for repetitive chats.

An LLM drafts your bot once, from your business info and docs. After that, every visitor message is embedded, matched to the closest intent, and answered with that intent's fixed reply. No language model runs at chat time.
How it works
Generation is the only step that calls a language model. Once a bot is ready, each reply is a lookup and a template fill.
- 1
Describe your business
Give the bot your business name, what you do, pricing, FAQs, goals, tone, and links to your docs. The bot is built only from this information and the docs it can fetch.
- 2
Generate the bot once
An LLM writes 3 to 6 customer-journey stages and 25 to 40 top-level intents. Each intent has 12 to 20 example messages and a reply template. Each top-level intent is then expanded into 2 to 5 sub-intents, each with follow-ups.
- 3
Chat without a language model
Each visitor message is embedded and compared with every example by cosine similarity. The closest intent wins and its template is sent. If the best score is below the threshold (0.45 by default), the bot sends its fallback reply.
Features
What the chat engine does with each message, based on the code in this repository.
Follow-ups stay in context
Sub-intents of the topic the visitor is on get a small ranking boost. Depth-3 follow-ups only match under their parent or beside the active intent.
Collects details with validation
Intents can ask for text, email, phone, number, date, choice, or contact details. Invalid answers are rejected with a short reason. Optional fields can be skipped, and a cancel word stops collection.
Contact handoff after an offer
When a reply offers a team follow-up, a "yes" starts collecting the visitor’s details. Completed details are saved as a submission under the intent they came from.
Quick replies
Replies can include short button labels for the next likely step, so visitors can tap instead of typing. When a template has none, the bot suggests topics instead.
Template placeholders
Reply templates use {{key}} placeholders. They are filled from the bot’s facts and from details collected earlier in the same conversation.
Replies drafted from your material
The generator is instructed to use only your business info and docs, and not to invent prices, policies, links, or contact details. Review the generated bot before you go live.