using TarninaHub.Application.Matchmaking; namespace TarninaHub.Tests.Matchmaking; public class EmbeddingAndRankingTests { private static double Magnitude(float[] vector) => Math.Sqrt(vector.Sum(value => (double)value * value)); [Fact] public void HashingEmbeddingProvider_ProducesNormalizedVectorOfConfiguredDimension() { var provider = new HashingEmbeddingProvider(); var vector = provider.Embed("klub sąsiedzki dla seniorów"); Assert.Equal(EmbeddingConstants.Dimension, vector.Length); Assert.Equal(1.0, Magnitude(vector), precision: 5); } [Fact] public void HashingEmbeddingProvider_IsDeterministic() { var provider = new HashingEmbeddingProvider(); var first = provider.Embed("praca wspierana niepełnosprawność"); var second = provider.Embed("praca wspierana niepełnosprawność"); Assert.Equal(first, second); } [Fact] public void CosineSimilarity_IsHigherForSharedVocabulary() { var provider = new HashingEmbeddingProvider(); var query = provider.Embed("seniorzy spotkania samotność"); var related = provider.Embed("klub sąsiedzki seniorzy spotkania samotność"); var unrelated = provider.Embed("hostel młodzież bezdomność"); var relatedScore = VectorMath.CosineSimilarity(query, related); var unrelatedScore = VectorMath.CosineSimilarity(query, unrelated); Assert.True(relatedScore > unrelatedScore); } [Fact] public void SemanticRanker_OrdersByScoreAndRespectsTopK() { var provider = new HashingEmbeddingProvider(); var query = provider.Embed("cyfryzacja seniorzy internet"); var candidates = new (string Id, IReadOnlyList Vector)[] { ("cyfryzacja", provider.Embed("cyfryzacja seniorzy internet szkolenie")), ("praca", provider.Embed("praca wspierana doradca")), ("hostel", provider.Embed("hostel młodzież bezdomność")), }; var ranked = SemanticRanker.Rank(query, candidates, topK: 2); Assert.Equal(2, ranked.Count); Assert.Equal("cyfryzacja", ranked[0].Item); } [Fact] public void CosineSimilarity_ReturnsZeroForMismatchedDimensions() { Assert.Equal(0, VectorMath.CosineSimilarity([1f, 0f], [1f])); } }