feat(ai): IEmbeddingProvider foundation (Null + Ollama)
AI-foundation slice 1 (per docs/discovery/06). Adds the embeddings abstraction that semantic search / near-dup / find-similar will build on: IEmbeddingProvider with a NullEmbeddingProvider (AI-off: IsAvailable=false, empty vectors) and an OllamaEmbeddingProvider (/api/embeddings, nomic-embed-text). DI registers embeddings by AI mode (Ollama local, else Null). Kept separate from IAiProvider since embeddings are a distinct model/capability. AI remains fully optional — callers fall back to lexical search when unavailable. Buildable/testable without a live Ollama; unit test locks the Null fallback contract. Build + all 41 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
using FluentAssertions;
|
||||
using InboxIntel.Infrastructure.Ai;
|
||||
using Xunit;
|
||||
|
||||
namespace InboxIntel.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// The Null embedding provider is the AI-off / no-model path. Semantic features must be able
|
||||
/// to detect unavailability (IsAvailable=false) and fall back to lexical search — this locks
|
||||
/// that contract so "AI is never required" can't silently regress.
|
||||
/// </summary>
|
||||
public class EmbeddingProviderTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Null_provider_reports_unavailable_and_returns_empty_vectors()
|
||||
{
|
||||
var sut = new NullEmbeddingProvider();
|
||||
|
||||
sut.IsAvailable.Should().BeFalse();
|
||||
(await sut.EmbedAsync("anything")).Should().BeEmpty();
|
||||
(await sut.EmbedBatchAsync(new[] { "a", "b" })).Should().BeEmpty();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user