Files
Wiki/test/Wiki.Contracts/EmbeddingModelContract.cs
T

50 lines
1.6 KiB
C#

using Wiki.Core.Ports;
namespace Wiki.Contracts;
/// <summary>Every <see cref="IEmbeddingModel"/> adapter derives from this. The adapter under test may talk to a fake server.</summary>
public abstract class EmbeddingModelContract
{
protected abstract Task<IEmbeddingModel> CreateModelAsync();
[Fact]
public async Task VectorsHaveTheDeclaredDimensionAndUnitLength()
{
var model = await CreateModelAsync();
var vectors = await model.EmbedAsync(["alpha", "beta"], CancellationToken.None);
Assert.Equal(2, vectors.Count);
foreach (var v in vectors)
{
Assert.Equal(model.Dimension, v.Length);
var norm = MathF.Sqrt(v.Sum(x => x * x));
Assert.InRange(norm, 0.99f, 1.01f);
}
}
[Fact]
public async Task SameTextSameVectorAndOrderPreserved()
{
var model = await CreateModelAsync();
var once = await model.EmbedAsync(["one", "two", "three"], CancellationToken.None);
var again = await model.EmbedAsync(["three", "one"], CancellationToken.None);
Assert.Equal(once[2], again[0]);
Assert.Equal(once[0], again[1]);
}
[Fact]
public async Task EmptyBatchIsEmpty()
{
var model = await CreateModelAsync();
Assert.Empty(await model.EmbedAsync([], CancellationToken.None));
}
[Fact]
public async Task ModelIdIsSet()
{
var model = await CreateModelAsync();
Assert.False(string.IsNullOrWhiteSpace(model.ModelId));
var health = await model.CheckAsync(CancellationToken.None);
Assert.True(health.Ok, health.Detail);
}
}