env('AI_CATEGORIZATION_MODEL', 'gemini-flash-latest'), /* |-------------------------------------------------------------------------- | Master switch |-------------------------------------------------------------------------- | | A hard kill switch independent of the per-user Pennant flag. When false, | no transaction is ever sent for AI categorization, regardless of rollout. | */ 'enabled' => (bool) env('AI_CATEGORIZATION_ENABLED', true), /* |-------------------------------------------------------------------------- | Confidence bars |-------------------------------------------------------------------------- | | Two thresholds. "label_confidence" is the minimum confidence to auto-apply | a category to a single transaction. "rule_confidence" is the higher bar a | categorization must clear before it is generalised into an automation rule | (a rule mislabels ALL future matches, so it must be more certain). Below | "label_confidence" the transaction is left uncategorized. | */ 'label_confidence' => (float) env('AI_CATEGORIZATION_LABEL_CONFIDENCE', 0.7), 'rule_confidence' => (float) env('AI_CATEGORIZATION_RULE_CONFIDENCE', 0.85), /* |-------------------------------------------------------------------------- | Backfill batching |-------------------------------------------------------------------------- | | "group_batch_size" splits aggregated merchant groups into per-request | chunks during a backfill run: a large single payload makes the model | under-enumerate, so we send reliable-size chunks and merge the results. | */ 'group_batch_size' => (int) env('AI_CATEGORIZATION_GROUP_BATCH_SIZE', 50), /* |-------------------------------------------------------------------------- | Queue |-------------------------------------------------------------------------- | | The queue the real-time categorization job runs on. Kept separate from the | default queue so a backlog of categorization jobs never delays bank syncs. | */ 'queue' => env('AI_CATEGORIZATION_QUEUE', 'ai'), /* |-------------------------------------------------------------------------- | Transient-failure retry delay |-------------------------------------------------------------------------- | | Minutes to wait before retrying a user's still-pending transactions after | the AI provider dropped a chunk with a transient failure (overload / rate | limit). The delay lets the provider recover before we try again. | */ 'retry_delay' => (int) env('AI_CATEGORIZATION_RETRY_DELAY', 10), /* |-------------------------------------------------------------------------- | Free-plan upsell nudge |-------------------------------------------------------------------------- | | Percentage (0-100) of a free user's uncategorized transactions that show | the "AI could categorize this" sparkle. Sampled deterministically by | transaction id so the same rows always decide the same way. Exposed to the | frontend as the `aiCategorizationUpsellRate` Inertia prop. | */ 'upsell_sample_rate' => (int) env('AI_CATEGORIZATION_UPSELL_SAMPLE_RATE', 40), ];