| | | 1 | | using Intentum.Core.Behavior; |
| | | 2 | | using Intentum.Core.Contracts; |
| | | 3 | | using Intentum.Core.Intents; |
| | | 4 | | |
| | | 5 | | namespace Intentum.Core.Models; |
| | | 6 | | |
| | | 7 | | /// <summary> |
| | | 8 | | /// Intent model that tries a primary model first; if confidence is below threshold, falls back to a secondary model (e. |
| | | 9 | | /// Reduces cost and latency by using cheap rule/keyword path when confidence is high. |
| | | 10 | | /// </summary> |
| | | 11 | | public sealed class ChainedIntentModel : IIntentModel |
| | | 12 | | { |
| | | 13 | | private readonly IIntentModel _primary; |
| | | 14 | | private readonly IIntentModel _fallback; |
| | | 15 | | private readonly double _confidenceThreshold; |
| | | 16 | | |
| | | 17 | | /// <summary> |
| | | 18 | | /// Creates a chained intent model. |
| | | 19 | | /// </summary> |
| | | 20 | | /// <param name="primary">Model to try first (e.g. RuleBasedIntentModel).</param> |
| | | 21 | | /// <param name="fallback">Model to use when primary confidence is below threshold (e.g. LlmIntentModel).</param> |
| | | 22 | | /// <param name="confidenceThreshold">Minimum primary confidence to accept primary result; otherwise use fallback. T |
| | 3 | 23 | | public ChainedIntentModel(IIntentModel primary, IIntentModel fallback, double confidenceThreshold = 0.7) |
| | 3 | 24 | | { |
| | 3 | 25 | | _primary = primary ?? throw new ArgumentNullException(nameof(primary)); |
| | 3 | 26 | | _fallback = fallback ?? throw new ArgumentNullException(nameof(fallback)); |
| | 3 | 27 | | _confidenceThreshold = Math.Clamp(confidenceThreshold, 0, 1); |
| | 3 | 28 | | } |
| | | 29 | | |
| | | 30 | | /// <inheritdoc /> |
| | | 31 | | public Intent Infer(BehaviorSpace behaviorSpace, BehaviorVector? precomputedVector = null) |
| | 3 | 32 | | { |
| | 3 | 33 | | var primaryIntent = _primary.Infer(behaviorSpace, precomputedVector); |
| | | 34 | | |
| | 3 | 35 | | if (primaryIntent.Confidence.Score >= _confidenceThreshold) |
| | 2 | 36 | | { |
| | 2 | 37 | | var reasoning = primaryIntent.Reasoning != null |
| | 2 | 38 | | ? $"Primary: {primaryIntent.Reasoning}" |
| | 2 | 39 | | : "Primary (confidence above threshold)"; |
| | 2 | 40 | | return primaryIntent with { Reasoning = reasoning }; |
| | | 41 | | } |
| | | 42 | | |
| | 1 | 43 | | var fallbackIntent = _fallback.Infer(behaviorSpace, precomputedVector); |
| | 1 | 44 | | var fallbackReasoning = $"Fallback: {fallbackIntent.Reasoning ?? "LLM (primary confidence below " + _confidenceT |
| | 1 | 45 | | return fallbackIntent with { Reasoning = fallbackReasoning }; |
| | 3 | 46 | | } |
| | | 47 | | } |