v2.5.4 — Portrait-Bilder bleiben beim Reload erhalten
- Portrait wird als [PORTRAIT]path[/PORTRAIT] in DB gespeichert - Serverseitiges Jinja2-Rendering zeigt Bild beim Reload - JS loadHistory() rendert PORTRAIT-Marker als <img> - Ollama bekommt keine PORTRAIT-Nachrichten (skip in build_prompt)
This commit is contained in:
@@ -163,6 +163,11 @@ def save_message(session_id: str, character: str, role: str, content: str):
|
|||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
def save_portrait_message(session_id: str, character: str, image_path: str):
|
||||||
|
"""Speichert ein generiertes Portrait als Bot-Nachricht mit Bild-Marker."""
|
||||||
|
content = f"[PORTRAIT]{image_path}[/PORTRAIT]"
|
||||||
|
save_message(session_id, character, "assistant", content)
|
||||||
|
|
||||||
def needs_summary(session_id: str, character: str) -> bool:
|
def needs_summary(session_id: str, character: str) -> bool:
|
||||||
conn = sqlite3.connect(str(DB_PATH))
|
conn = sqlite3.connect(str(DB_PATH))
|
||||||
cur = conn.execute(
|
cur = conn.execute(
|
||||||
@@ -268,6 +273,9 @@ REGELN:
|
|||||||
|
|
||||||
messages = [{"role": "system", "content": system}]
|
messages = [{"role": "system", "content": system}]
|
||||||
for msg in short_term:
|
for msg in short_term:
|
||||||
|
# Skip portrait messages — they're images, not text for the LLM
|
||||||
|
if msg["content"] and msg["content"].startswith("[PORTRAIT]"):
|
||||||
|
continue
|
||||||
if msg["role"] == "user":
|
if msg["role"] == "user":
|
||||||
messages.append({"role": "user", "content": msg["content"]})
|
messages.append({"role": "user", "content": msg["content"]})
|
||||||
else:
|
else:
|
||||||
@@ -572,6 +580,11 @@ async def api_generate_portrait(name: str, request: Request):
|
|||||||
image_path = generate_portrait(name, char, custom_prompt)
|
image_path = generate_portrait(name, char, custom_prompt)
|
||||||
if image_path:
|
if image_path:
|
||||||
_portrait_jobs[job_id] = {"status": "done", "image": image_path, "error": None}
|
_portrait_jobs[job_id] = {"status": "done", "image": image_path, "error": None}
|
||||||
|
# Save portrait to chat history so it survives reload
|
||||||
|
try:
|
||||||
|
save_portrait_message(session_id, name, image_path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Portrait save failed (non-fatal): {e}")
|
||||||
else:
|
else:
|
||||||
_portrait_jobs[job_id] = {"status": "error", "image": None, "error": "Generierung fehlgeschlagen"}
|
_portrait_jobs[job_id] = {"status": "error", "image": None, "error": "Generierung fehlgeschlagen"}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
+22
-2
@@ -82,7 +82,14 @@
|
|||||||
<div class="msg msg-greeting">{{ character.greeting }}</div>
|
<div class="msg msg-greeting">{{ character.greeting }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for h in history %}
|
{% for h in history %}
|
||||||
|
{% if '[PORTRAIT]' in h.content %}
|
||||||
|
<div class="msg msg-bot" style="padding: 0; overflow: hidden;">
|
||||||
|
<img src="{{ h.content | replace('[PORTRAIT]', '') | replace('[/PORTRAIT]', '') }}?t={{ range(1000, 9999) | random }}" style="width: 100%; max-width: 400px; border-radius: 16px 16px 16px 4px; display: block;">
|
||||||
|
<div style="padding: 8px 12px; font-size: 0.8rem; color: var(--muted);">🖼️ Neues Portrait generiert</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
<div class="msg {{ 'msg-user' if h.role == 'user' else 'msg-bot' }}">{{ h.content }}</div>
|
<div class="msg {{ 'msg-user' if h.role == 'user' else 'msg-bot' }}">{{ h.content }}</div>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -272,8 +279,21 @@
|
|||||||
for (let i = currentMsgs; i < data.history.length; i++) {
|
for (let i = currentMsgs; i < data.history.length; i++) {
|
||||||
const h = data.history[i];
|
const h = data.history[i];
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.className = `msg ${h.role === 'user' ? 'msg-user' : 'msg-bot'}`;
|
|
||||||
div.textContent = h.content;
|
// Check if it's a portrait message
|
||||||
|
const portraitMatch = h.content && h.content.match(/^\[PORTRAIT\](.+)\[\/PORTRAIT\]$/);
|
||||||
|
if (portraitMatch) {
|
||||||
|
div.className = 'msg msg-bot';
|
||||||
|
div.style.padding = '0';
|
||||||
|
div.style.overflow = 'hidden';
|
||||||
|
div.innerHTML = `
|
||||||
|
<img src="${portraitMatch[1]}?t=${Date.now()}" style="width: 100%; max-width: 400px; border-radius: 16px 16px 16px 4px; display: block;">
|
||||||
|
<div style="padding: 8px 12px; font-size: 0.8rem; color: var(--muted);">🖼️ Neues Portrait generiert</div>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
div.className = `msg ${h.role === 'user' ? 'msg-user' : 'msg-bot'}`;
|
||||||
|
div.textContent = h.content;
|
||||||
|
}
|
||||||
chat.appendChild(div);
|
chat.appendChild(div);
|
||||||
}
|
}
|
||||||
chat.scrollTop = chat.scrollHeight;
|
chat.scrollTop = chat.scrollHeight;
|
||||||
|
|||||||
Reference in New Issue
Block a user