improve interacting with ollama api and models

This commit is contained in:
2026-05-10 17:40:24 +03:30
parent b89ae98524
commit 4c910cb8e8
11 changed files with 265 additions and 225 deletions

View File

@@ -8,16 +8,8 @@ use Laravel\Ai\Embeddings;
use Laravel\Ai\Prompts\EmbeddingsPrompt;
use Livewire\Livewire;
beforeEach(function () {
config([
'ai.default_for_embeddings' => 'ollama',
'ai.providers.ollama.url' => 'http://ollama.test',
'ai.providers.ollama.models.embeddings.default' => 'test-embed',
'ai.providers.ollama.models.embeddings.available' => ['test-embed'],
'ai.providers.ollama.models.embeddings.dimensions' => 3,
]);
Http::preventStrayRequests();
function fakeEmbeddingToolOllamaModels(): void
{
Http::fake([
'http://ollama.test/api/tags' => Http::response([
'models' => [
@@ -26,6 +18,23 @@ beforeEach(function () {
],
]),
]);
}
function fakeUnavailableEmbeddingToolOllama(): void
{
Http::fake([
'http://ollama.test/api/tags' => Http::response(['error' => 'offline'], 500),
]);
}
beforeEach(function () {
config([
'ai.default_for_embeddings' => 'ollama',
'ai.providers.ollama.url' => 'http://ollama.test',
'ai.providers.ollama.models.embeddings.dimensions' => 3,
]);
Http::preventStrayRequests();
});
test('guests are redirected from embedding pages', function (string $route) {
@@ -44,6 +53,8 @@ test('embeddings index redirects to embed page', function () {
});
test('authenticated users can open embedding pages', function (string $route, string $text) {
fakeEmbeddingToolOllamaModels();
$this->actingAs(User::factory()->create());
$this->get(route($route))
@@ -56,6 +67,8 @@ test('authenticated users can open embedding pages', function (string $route, st
]);
test('comparison page renders separate phrase inputs', function () {
fakeEmbeddingToolOllamaModels();
$this->actingAs(User::factory()->create());
$this->get(route('embeddings.compare'))
@@ -67,6 +80,8 @@ test('comparison page renders separate phrase inputs', function () {
});
test('comparison phrase inputs can be added and removed', function () {
fakeEmbeddingToolOllamaModels();
$this->actingAs(User::factory()->create());
Livewire::test('pages::embeddings.compare')
@@ -90,6 +105,8 @@ test('app header has a menu item for each embedding tool', function () {
});
test('embedding pages do not duplicate tool navigation below the header', function () {
fakeEmbeddingToolOllamaModels();
$this->actingAs(User::factory()->create());
$response = $this->get(route('embeddings.embed'))->assertOk();
@@ -100,6 +117,8 @@ test('embedding pages do not duplicate tool navigation below the header', functi
});
test('embedding model options are fetched from ollama', function () {
fakeEmbeddingToolOllamaModels();
$this->actingAs(User::factory()->create());
$component = Livewire::test('pages::embeddings.embed');
@@ -110,16 +129,48 @@ test('embedding model options are fetched from ollama', function () {
Http::assertSent(fn ($request): bool => $request->url() === 'http://ollama.test/api/tags');
});
test('first ollama model is selected when configured default is unavailable', function () {
config(['ai.providers.ollama.models.embeddings.default' => 'missing-default']);
test('first ollama model is selected from the api model list', function () {
fakeEmbeddingToolOllamaModels();
$this->actingAs(User::factory()->create());
Livewire::test('pages::embeddings.embed')
->assertSet('ollamaAvailable', true)
->assertSet('embeddingModel', 'test-embed');
});
test('embedding pages show when ollama is unavailable', function () {
fakeUnavailableEmbeddingToolOllama();
$this->actingAs(User::factory()->create());
Livewire::test('pages::embeddings.embed')
->assertSet('ollamaAvailable', false)
->assertSet('embeddingModel', '')
->assertSee(__('Ollama is unavailable'))
->assertSee(__('Ollama offline'));
});
test('embedding actions stop when ollama model list is unavailable', function () {
fakeUnavailableEmbeddingToolOllama();
Embeddings::fake();
$this->actingAs(User::factory()->create());
Livewire::test('pages::embeddings.embed')
->set('embeddingInput', 'apple')
->call('generateEmbeddings')
->assertHasErrors('embeddingModel');
expect(EmbeddingEntry::query()->count())->toBe(0);
Embeddings::assertNothingGenerated();
});
test('phrases can be embedded and stored', function () {
fakeEmbeddingToolOllamaModels();
Embeddings::fake([
[
[1, 0, 0],
@@ -155,6 +206,8 @@ test('phrases can be embedded and stored', function () {
});
test('similarity search ranks stored embeddings', function () {
fakeEmbeddingToolOllamaModels();
Embeddings::fake([
[
[1, 0, 0],
@@ -196,6 +249,8 @@ test('similarity search ranks stored embeddings', function () {
});
test('comparison builds a pairwise similarity matrix', function () {
fakeEmbeddingToolOllamaModels();
Embeddings::fake([
[
[1, 0, 0],