query-intent-router
v0.2.0
Published
Zero-dependency query intent classification for handbook, policy and wiki corpora. Regex and priority rules, no LLM call.
Maintainers
Readme
IntentRouter
Query intent classification for handbook, policy and wiki corpora. Regex and priority rules — no model, no network call, no dependencies.
Why
In a document Q&A system, what you should do with a query depends on what kind of question it is. "Who owns expense exceptions?" wants an owner and an escalation path. "How many offers went out last month?" wants a number you must not invent. "Draft a rejection email" wants a template.
Routing that decision through an LLM costs a round trip and a token bill to answer a question a regex can settle. IntentRouter does the classification locally in microseconds, so the model call — if you make one at all — starts with the intent already known.
Install
npm install query-intent-routerIt has no runtime dependencies. You can also copy src/index.ts straight into your project — it is a single file under the MIT licence.
Usage
import { classifyIntent, intentLabel, intentDescription } from "query-intent-router";
const intent = classifyIntent("Who owns expense policy exceptions?");
// → "contact"
intentLabel(intent); // "Contact"
intentDescription(intent); // "Owners, escalation paths, POCs"Intents
| Intent | Matches queries like | Description |
|---|---|---|
| contact | "who owns", "point of contact", "escalate" | Owners, escalation paths, POCs |
| policy | "policy", "allowed", "compliance", "GDPR" | Rules, compliance, constraints |
| template | "draft", "template", "write an email" | Copy-ready drafts with placeholders |
| metric | "how many", "count", "KPI", "report" | Counts and reports (do not invent numbers) |
| procedure | "how do I", "process", "approval", "where is" | How-to steps and workflows |
Rules are evaluated highest priority first, and the first match wins. procedure is the fallback for anything unmatched, on the assumption that an unclassified question is usually someone asking how to do something.
API
classifyIntent(query, rules?, fallback?)
Returns a DocumentIntent. Empty or whitespace-only input returns the fallback.
classifyIntent(query); // default rules, "procedure" fallback
classifyIntent(query, myRules); // custom rules
classifyIntent(query, myRules, "policy"); // custom fallbackintentLabel(intent) / intentDescription(intent)
A display label and a one-line description, handy for showing users why a query was routed the way it was.
Custom rules
Pass your own rules to extend or replace the defaults. Give a rule a higher priority than the built-ins to make it win.
import { classifyIntent, DEFAULT_RULES, type IntentRule } from "query-intent-router";
const rules: IntentRule[] = [
{ intent: "policy", priority: 100, pattern: /\b(security|incident|breach)\b/i },
...DEFAULT_RULES,
];
classifyIntent("security incident process", rules); // → "policy"Rules are matched against a stateless copy of your pattern, so a /g or /y flag will not make the same query classify differently on repeated calls. DEFAULT_RULES is frozen; spread it as above rather than pushing into it.
Exports
classifyIntent, intentLabel, intentDescription, DEFAULT_RULES, DOCUMENT_INTENTS, and the types DocumentIntent and IntentRule.
Limitations
English only, and it matches on surface wording rather than meaning. A query that avoids the vocabulary entirely — "I need Priya's manager" instead of "who owns" — falls through to the fallback. For a fixed corpus with predictable phrasing that trade is usually worth it; if your queries are open-ended natural language, use this as a cheap pre-filter rather than the whole decision.
Test
npm testBuilds, type-checks the tests, and runs them on Node's built-in test runner.
License
MIT — Amit Singh
