This commit is contained in:
ValueOn AG 2026-02-06 10:42:44 +01:00
parent edf1101cfc
commit 4fea024339

View file

@ -656,11 +656,11 @@
<div class="upload-zone" id="upload-zone"> <div class="upload-zone" id="upload-zone">
<div class="upload-placeholder" id="upload-placeholder"> <div class="upload-placeholder" id="upload-placeholder">
<div class="upload-icon">📤</div> <div class="upload-icon">📤</div>
<p class="upload-text">Bild oder PDF</p> <p class="upload-text">Bild hochladen</p>
<p class="upload-hint">Drag & Drop</p> <p class="upload-hint">Drag & Drop</p>
</div> </div>
<img id="preview-image" class="preview-image" style="display: none;"> <img id="preview-image" class="preview-image" style="display: none;">
<input type="file" id="file-input" accept="image/*,.pdf,application/pdf"> <input type="file" id="file-input" accept="image/*">
</div> </div>
<div class="image-actions" id="image-actions" style="display: none;"> <div class="image-actions" id="image-actions" style="display: none;">
<button class="btn btn-secondary btn-small" id="remove-image"></button> <button class="btn btn-secondary btn-small" id="remove-image"></button>
@ -835,51 +835,55 @@ Falls ein Feld nicht erkennbar ist, setze den Wert auf null.</textarea>
async function _checkOllamaStatus() { async function _checkOllamaStatus() {
ollamaStatusDiv.style.display = 'block'; ollamaStatusDiv.style.display = 'block';
ollamaStatusDiv.className = 'ollama-status loading'; ollamaStatusDiv.className = 'ollama-status loading';
ollamaStatusDiv.textContent = 'Verbinde mit Ollama...'; ollamaStatusDiv.textContent = 'Prüfe Ollama-Verbindung...';
try { try {
const response = await fetch(`/api/ollama/status?url=${encodeURIComponent(ollamaUrl.value)}`); // Direkt Ollama API abfragen (ohne Auth)
const result = await response.json(); const response = await fetch(`${ollamaUrl.value}/api/tags`, {
method: 'GET',
if (result.connected) { headers: { 'Accept': 'application/json' }
ollamaStatusDiv.className = 'ollama-status success'; });
// PowerOn Modelle in Dropdown laden (nur wenn Backend-Modell verfügbar) if (!response.ok) {
modelName.innerHTML = ''; throw new Error(`Ollama antwortet mit Status ${response.status}`);
const availableModels = result.models || [];
const availablePowerOnModels = POWERON_MODELS.filter(pm =>
availableModels.some(m => m.startsWith(pm.ollamaModel.split(':')[0]))
);
if (availablePowerOnModels.length > 0) {
const optGroup = document.createElement('optgroup');
optGroup.label = 'PowerOn Modelle';
availablePowerOnModels.forEach(model => {
const opt = document.createElement('option');
opt.value = model.name;
opt.textContent = `${model.displayName}`;
opt.title = model.description;
optGroup.appendChild(opt);
});
modelName.appendChild(optGroup);
// Erstes Modell auswählen
modelName.value = availablePowerOnModels[0].name;
}
ollamaStatusDiv.innerHTML = `✓ Verbunden - ${availablePowerOnModels.length} PowerOn Modelle verfügbar`;
// Button-Status nach Modell-Laden aktualisieren
_updateAnalyzeButtonState();
} else {
ollamaStatusDiv.className = 'ollama-status error';
ollamaStatusDiv.textContent = `✗ ${result.error}`;
modelName.innerHTML = '<option value="">-- Ollama nicht verbunden --</option>';
} }
const result = await response.json();
const availableModels = (result.models || []).map(m => m.name);
ollamaStatusDiv.className = 'ollama-status success';
// PowerOn Modelle in Dropdown laden (nur wenn Backend-Modell verfügbar)
modelName.innerHTML = '';
const availablePowerOnModels = POWERON_MODELS.filter(pm =>
availableModels.some(m => m.startsWith(pm.ollamaModel.split(':')[0]))
);
if (availablePowerOnModels.length > 0) {
const optGroup = document.createElement('optgroup');
optGroup.label = 'PowerOn Modelle';
availablePowerOnModels.forEach(model => {
const opt = document.createElement('option');
opt.value = model.name;
opt.textContent = `${model.displayName}`;
opt.title = model.description;
optGroup.appendChild(opt);
});
modelName.appendChild(optGroup);
// Erstes Modell auswählen
modelName.value = availablePowerOnModels[0].name;
}
ollamaStatusDiv.innerHTML = `✓ Verbunden - ${availablePowerOnModels.length} PowerOn Modelle verfügbar`;
// Button-Status nach Modell-Laden aktualisieren
_updateAnalyzeButtonState();
} catch (error) { } catch (error) {
ollamaStatusDiv.className = 'ollama-status error'; ollamaStatusDiv.className = 'ollama-status error';
ollamaStatusDiv.textContent = `✗ Fehler: ${error.message}`; ollamaStatusDiv.textContent = `✗ Keine Verbindung zu Ollama: ${error.message}`;
modelName.innerHTML = '<option value="">-- Ollama nicht verbunden --</option>';
} }
} }
@ -1100,9 +1104,15 @@ Falls ein Feld nicht erkennbar ist, setze den Wert auf null.</textarea>
promptInput.value = DEFAULT_PROMPT; promptInput.value = DEFAULT_PROMPT;
}); });
// Analysis - using Python backend with CORS // Analysis - direct Ollama API call
analyzeBtn.addEventListener('click', _analyzeDocument); analyzeBtn.addEventListener('click', _analyzeDocument);
// Map PowerOn model names to Ollama model names
function _getOllamaModelName(powerOnName) {
const model = POWERON_MODELS.find(m => m.name === powerOnName);
return model ? model.ollamaModel : powerOnName;
}
async function _analyzeDocument() { async function _analyzeDocument() {
const isVision = _isVisionModel(modelName.value); const isVision = _isVisionModel(modelName.value);
@ -1129,37 +1139,65 @@ Falls ein Feld nicht erkennbar ist, setze den Wert auf null.</textarea>
_hideError(); _hideError();
try { try {
// Request-Body erstellen // Get Ollama model name from PowerOn name
const ollamaModelName = _getOllamaModelName(modelName.value);
// Model-specific context lengths
const modelContextLengths = {
'deepseek-ocr': 8192,
'qwen2.5vl:7b': 32768,
'granite3.2-vision': 16000
};
const numCtx = modelContextLengths[ollamaModelName] || 8192;
// Request-Body für Ollama erstellen
const requestBody = { const requestBody = {
model: ollamaModelName,
prompt: promptInput.value, prompt: promptInput.value,
ollamaUrl: ollamaUrl.value, stream: false,
modelName: modelName.value options: {
num_ctx: numCtx
}
}; };
// Bild nur hinzufügen wenn vorhanden // Bild nur hinzufügen wenn vorhanden
if (currentImageBase64) { if (currentImageBase64) {
requestBody.imageBase64 = currentImageBase64; requestBody.images = [currentImageBase64];
} }
// Call Python backend API (has CORS enabled) // Call Ollama API directly
const response = await fetch('/api/analyze', { const response = await fetch(`${ollamaUrl.value}/api/generate`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody) body: JSON.stringify(requestBody)
}); });
const result = await response.json();
if (!response.ok) { if (!response.ok) {
throw new Error(result.error || `HTTP ${response.status}`); const errorText = await response.text();
throw new Error(`Ollama Fehler: ${response.status} - ${errorText.substring(0, 200)}`);
} }
if (!result.success) { const result = await response.json();
throw new Error(result.error || 'Unbekannter Fehler'); const responseText = result.response || '';
// Try to extract JSON from response
let extractedData = null;
const jsonMatch = responseText.match(/\{[\s\S]*\}/);
if (jsonMatch) {
try {
extractedData = JSON.parse(jsonMatch[0]);
} catch (e) {
extractedData = null;
}
}
// Wrap plain text response in JSON object
if (extractedData === null) {
extractedData = { response: responseText.trim() };
} }
extractedData = result.data; _displayResults(extractedData, responseText);
_displayResults(extractedData, result.rawResponse);
_setStatus('success', 'Erfolgreich extrahiert'); _setStatus('success', 'Erfolgreich extrahiert');
} catch (error) { } catch (error) {