Merge pull request 'Feature: Liste verfügbarer Ollama-Modelle in den Einstellungen (#103)' (#105) from fds2610-bot/Steuerkram:automate/issue-103 into main

Reviewed-on: https://codeberg.org/fds2610/Steuerkram/pulls/105
This commit is contained in:
fds2610 2026-06-11 20:09:17 +02:00
commit abee609788
4 changed files with 107 additions and 0 deletions

View file

@ -2,6 +2,11 @@
--- ---
## 2026-06-11 – Feature: Liste verfügbarer Ollama-Modelle in den Einstellungen (Issue #103)
- **`LlmService`:** Neue Methode `getAvailableModels()` fragt `/api/tags` ab und liefert die Namen aller lokal verfügbaren Ollama-Modelle; neue Getter `getMode()`, `getModel()`, `getVisionModel()`
- **Einstellungsseite:** Im KI-Abschnitt wird bei erreichbarem Ollama-Provider die Liste der verfügbaren Modelle angezeigt, das konfigurierte Standard- und Vision-Modell sind markiert
## 2026-06-11 – Feature: CSV-Importformat aus „Neue Direktverbindung"-Dialog anlegen (Issue #102) ## 2026-06-11 – Feature: CSV-Importformat aus „Neue Direktverbindung"-Dialog anlegen (Issue #102)
- **`bank/fints.php`:** Neue Auswahl „+ CSV-Importformat…" im Anbieter-Dropdown des „Neue Direktverbindung"-Dialogs; zeigt Felder für Trennzeichen, Anführungszeichen, Datumsformat, Dezimal-/Tausendertrennzeichen, Headerzeile und übersprungene Zeilen - **`bank/fints.php`:** Neue Auswahl „+ CSV-Importformat…" im Anbieter-Dropdown des „Neue Direktverbindung"-Dialogs; zeigt Felder für Trennzeichen, Anführungszeichen, Datumsformat, Dezimal-/Tausendertrennzeichen, Headerzeile und übersprungene Zeilen

View file

@ -45,6 +45,50 @@ class LlmService
}; };
} }
public function getMode(): ?string
{
return $this->mode;
}
public function getModel(): string
{
return $this->model;
}
public function getVisionModel(): string
{
return $this->visionModel;
}
/**
* Fragt beim Ollama-Server die Liste der lokal verfügbaren Modelle ab.
* Gibt ein leeres Array zurück, wenn kein Ollama-Provider konfiguriert ist
* oder der Server nicht erreichbar ist.
*
* @return string[]
*/
public function getAvailableModels(): array
{
if ($this->mode !== 'ollama') return [];
$url = $this->url . '/api/tags';
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 3,
CURLOPT_CONNECTTIMEOUT => 2,
]);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($errno !== 0 || $code < 200 || $code >= 300 || !$response) return [];
$data = json_decode($response, true);
return array_column($data['models'] ?? [], 'name');
}
public function generate(string $prompt): string public function generate(string $prompt): string
{ {
return match($this->mode) { return match($this->mode) {

View file

@ -269,6 +269,32 @@
— Kein LLM-Provider konfiguriert (Auto-Discovery localhost:11434 fehlgeschlagen) — Kein LLM-Provider konfiguriert (Auto-Discovery localhost:11434 fehlgeschlagen)
<?php endif; ?> <?php endif; ?>
</p> </p>
<?php if ($reachable && $llm->getMode() === 'ollama'):
$availableModels = $llm->getAvailableModels();
$configModel = $llm->getModel();
$visionModel = $llm->getVisionModel();
?>
<?php if (!empty($availableModels)): ?>
<div class="text-sm" style="margin:0 0 .5rem 1.75rem;color:#374151">
Verfügbare Modelle:
<ul style="margin:.25rem 0 0 1.25rem;padding:0">
<?php foreach ($availableModels as $availableModel): ?>
<li>
<?= $h($availableModel) ?>
<?php if ($availableModel === $configModel): ?>
<span class="text-muted">(Standard)</span>
<?php endif; ?>
<?php if ($availableModel === $visionModel): ?>
<span class="text-muted">(Vision)</span>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php else: ?>
<p class="text-sm text-muted" style="margin:0 0 .5rem 1.75rem">Keine Modelle gefunden.</p>
<?php endif; ?>
<?php endif; ?>
<div style="margin-left:1.75rem;display:flex;align-items:center;gap:.5rem;flex-wrap:wrap"> <div style="margin-left:1.75rem;display:flex;align-items:center;gap:.5rem;flex-wrap:wrap">
<button type="button" class="btn btn-secondary btn-sm" id="btn-llm-test">Verbindung testen</button> <button type="button" class="btn btn-secondary btn-sm" id="btn-llm-test">Verbindung testen</button>
<span id="llm-test-result" style="font-size:.8rem"></span> <span id="llm-test-result" style="font-size:.8rem"></span>

View file

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
use Steuerkram\Services\LlmService;
class LlmAvailableModelsTest extends TestCase
{
protected string $testName = 'Test 44: LLM verfügbare Modelle abfragen';
public function run(): void
{
$llm = new LlmService();
$mode = $llm->getMode();
$this->assert(
$mode === null || $mode === 'ollama' || $mode === 'openai',
'getMode() liefert null, ollama oder openai'
);
$models = $llm->getAvailableModels();
$this->assert(is_array($models), 'getAvailableModels() liefert ein Array');
if ($mode !== 'ollama') {
$this->assert(empty($models), 'Ohne Ollama-Provider ist die Modell-Liste leer');
}
if ($mode !== null) {
$this->assertNotEmpty($llm->getModel(), 'getModel() liefert konfiguriertes Modell');
}
}
}