/** * `LLMClassifier` — thin wrapper around `AIRouter` for the classify pattern * every downstream reinvents: * * 1. Build a system prompt + user message ("classify X into one of Y"). * 2. Route via `AIRouter` (multi-provider failover + circuit breaker). * 3. Parse the LLM response (JSON preferred, loose regex fallback). * 4. Fail-closed to a safe default on ANY error. * * Two projects (bibliafala `ai/intent_classifier.js`, aysu `ai/classifier.ts`) * hand-rolled this same shape. Codifying here so consumers write ~10 lines * instead of ~80. * * const classifier = new LLMClassifier<'pastoral' | 'duvida' | 'conversa' | 'other'>({ * router, * chainName: 'classifier', * systemPrompt: 'Classify the message into one of: pastoral, duvida, conversa, other. Return {"categoria":"X"}.', * categories: ['pastoral', 'duvida', 'conversa', 'other'], * fallback: 'duvida', * }); * * const { category, confident, provider } = await classifier.classify(text); */ import type { AIRouter } from './router.js'; /** Result of one classification attempt. */ export interface ClassificationResult { /** Winning category — always populated (falls back to `fallback` on any failure). */ category: C; /** `true` only when the LLM answered AND parsing succeeded AND the parsed value was in `categories`. */ confident: boolean; /** Provider that answered, when confident. */ provider?: string; /** Raw LLM response — populated on both success and parse failure for debug logging. */ raw?: string; /** Populated when `AIRouter` itself failed (all providers exhausted / circuit-broken). */ routerError?: string; /** Populated when the LLM answered but the parser couldn't find a valid category. */ parseError?: boolean; } export interface LLMClassifierOptions { router: AIRouter; /** Chain key registered in `AIRouter` (e.g. `'classifier'`). */ chainName: string; /** System prompt handed to the LLM. Should tell the model exactly which categories to emit and in what shape. */ systemPrompt: string; /** The categories the model is allowed to return. Anything outside → parse failure → fallback. */ categories: readonly C[]; /** Category returned on ANY failure (router error, parse fail, unknown category). Must be one of `categories`. */ fallback: C; /** * Optional override for the user-message template. Default: * (text) => `${text}` * matches bibliafala's fenced-input pattern that survived a 100-message eval. */ userTemplate?: (text: string) => string; /** Optional parser override. Default extracts `"categoria":"X"` (JSON or loose). */ parse?: (raw: string) => string | null; /** Forwarded to `AIRouter.route()`. */ maxTokens?: number; /** Forwarded to `AIRouter.route()`. */ temperature?: number; } export declare class LLMClassifier { private readonly router; private readonly chainName; private readonly systemPrompt; private readonly categories; private readonly fallback; private readonly userTemplate; private readonly parse; private readonly maxTokens; private readonly temperature; constructor(opts: LLMClassifierOptions); classify(text: string, opts?: { whatsapp?: string; tenantId?: string; }): Promise>; } //# sourceMappingURL=llm_classifier.d.ts.map