| | | 1 | | using Intentum.AI.Embeddings; |
| | | 2 | | |
| | | 3 | | namespace Intentum.AI.Similarity; |
| | | 4 | | |
| | | 5 | | /// <summary> |
| | | 6 | | /// Similarity engine that combines multiple similarity engines using weighted combination. |
| | | 7 | | /// Useful for A/B testing or combining different similarity strategies. |
| | | 8 | | /// </summary> |
| | | 9 | | public sealed class CompositeSimilarityEngine : IIntentSimilarityEngine |
| | | 10 | | { |
| | | 11 | | private readonly List<(IIntentSimilarityEngine Engine, double Weight)> _engines; |
| | | 12 | | |
| | | 13 | | /// <summary> |
| | | 14 | | /// Creates a composite similarity engine with equal weights for all engines. |
| | | 15 | | /// </summary> |
| | | 16 | | public CompositeSimilarityEngine(IEnumerable<IIntentSimilarityEngine> engines) |
| | 9 | 17 | | : this(engines.Select(e => (e, 1.0)).ToArray()) |
| | 3 | 18 | | { |
| | 3 | 19 | | } |
| | | 20 | | |
| | | 21 | | /// <summary> |
| | | 22 | | /// Creates a composite similarity engine with custom weights. |
| | | 23 | | /// </summary> |
| | 6 | 24 | | public CompositeSimilarityEngine(params (IIntentSimilarityEngine Engine, double Weight)[] engines) |
| | 6 | 25 | | { |
| | 6 | 26 | | if (engines == null || engines.Length == 0) |
| | 1 | 27 | | throw new ArgumentException("At least one engine is required", nameof(engines)); |
| | | 28 | | |
| | 5 | 29 | | _engines = engines.ToList(); |
| | 5 | 30 | | } |
| | | 31 | | |
| | | 32 | | public double CalculateIntentScore(IReadOnlyCollection<IntentEmbedding> embeddings) |
| | 5 | 33 | | { |
| | 5 | 34 | | if (embeddings.Count == 0) |
| | 1 | 35 | | return 0; |
| | | 36 | | |
| | 4 | 37 | | var totalWeightedScore = 0.0; |
| | 4 | 38 | | var totalWeight = 0.0; |
| | | 39 | | |
| | 30 | 40 | | foreach (var (engine, weight) in _engines) |
| | 9 | 41 | | { |
| | 9 | 42 | | var score = engine.CalculateIntentScore(embeddings); |
| | 9 | 43 | | totalWeightedScore += score * weight; |
| | 9 | 44 | | totalWeight += weight; |
| | 9 | 45 | | } |
| | | 46 | | |
| | 4 | 47 | | return totalWeight > 0 ? totalWeightedScore / totalWeight : 0; |
| | 5 | 48 | | } |
| | | 49 | | } |