65 lines
4.5 KiB
HTML
65 lines
4.5 KiB
HTML
<article class="card {{ 'aiw-message-user' if m.role == 'user' else 'aiw-message-assistant' }}" id="message-{{ m.id }}">
|
||
<div class="card-body stack stack-sm">
|
||
{% set u = m.usage or {} %}
|
||
<p class="aiw-meta">
|
||
<span class="aiw-meta-who">{{ 'Frage' if m.role == 'user' else 'Antwort' }}</span>
|
||
<span>{{ m.created.strftime('%H:%M') }}</span>
|
||
{% if m.role == 'assistant' and m.model %}<span class="aiw-pill">{{ m.model }}</span>{% endif %}
|
||
{% if m.role == 'assistant' and u.get('context_tokens') and u.get('context_window') %}{% set pct = (100 * u.context_tokens / u.context_window)|round|int %}<span class="aiw-pill{{ ' aiw-pill-danger' if pct >= 80 }}" title="Geschätzte Größe der Anfrage im Verhältnis zum Kontextfenster des Modells">Kontext {{ pct }} %</span>{% endif %}
|
||
{% if m.role == 'assistant' and u.get('rules') %}<span class="aiw-pill" title="Projektregeln aus dem Repository, die die KI befolgt hat">Regeln: {{ u.rules|join(', ') }}</span>{% endif %}
|
||
{% if m.role == 'assistant' and u.get('hugin') %}<span class="aiw-pill" title="Pakete aus Hugin, die für diese Antwort galten">Hugin: {% for k, v in u.hugin.items() %}{{ k }} {{ v }}{{ ', ' if not loop.last }}{% endfor %}</span>{% endif %}
|
||
{% if m.role == 'user' and u.get('command') %}<span class="aiw-pill" title="Slash-Befehl aus Hugin; an die KI ging der ausgeschriebene Text">Befehl {{ u.command.id }} {{ u.command.version }}</span>{% endif %}
|
||
</p>
|
||
{% set calls = m.items|selectattr('type', 'equalto', 'function_call')|list if m.items else [] %}
|
||
{% if calls %}
|
||
<details class="text-sm">
|
||
<summary class="text-muted">{{ calls|length }} Tool-Aufruf{{ 'e' if calls|length != 1 }}</summary>
|
||
<ol class="aiw-tools">{% for c in calls %}<li><code>{{ c.name }}</code> <span class="text-muted aiw-break">{{ c.arguments }}</span></li>{% endfor %}</ol>
|
||
</details>
|
||
{% endif %}
|
||
{% if m.role == 'assistant' %}
|
||
<div class="aiw-markdown" data-copy-source>{{ m.content|markdown }}</div>
|
||
{% for call in (results|default({})).get(m.run_id, []) %}
|
||
{% set r = call.result %}
|
||
{% set figure = chart(r.columns, r.rows) %}
|
||
<details class="aiw-result">
|
||
<summary>Abfrageergebnis: {{ r.rows|length }} Zeile{{ 'n' if r.rows|length != 1 }}{% if r.truncated %} (gekürzt){% endif %}, {{ r.columns|length }} Spalte{{ 'n' if r.columns|length != 1 }}{% if figure %} · mit Diagramm{% endif %}</summary>
|
||
<div class="stack stack-sm">
|
||
{% if call.arguments.get('sql') %}<pre class="text-xs aiw-message">{{ call.arguments.sql }}</pre>{% endif %}
|
||
{% if figure %}{{ figure }}{% endif %}
|
||
<div class="table-wrap aiw-result-table"><table>
|
||
<thead><tr>{% for c in r.columns %}<th>{{ c }}</th>{% endfor %}</tr></thead>
|
||
<tbody>{% for row in r.rows %}<tr>{% for v in row %}<td>{{ '–' if v is none else v }}</td>{% endfor %}</tr>{% endfor %}</tbody>
|
||
</table></div>
|
||
<p class="cluster text-xs"><a class="btn btn-ghost btn-xs" href="/tool-calls/{{ call.id }}.csv" download>Als CSV herunterladen</a>
|
||
{% if r.truncated %}<span class="text-muted">Nur die ersten {{ r.rows|length }} Zeilen; für vollständige Auswertungen die KI aggregieren lassen.</span>{% endif %}</p>
|
||
</div>
|
||
</details>
|
||
{% endfor %}
|
||
{% if (m.usage or {}).get('round_limit') %}
|
||
<div class="alert alert-info" role="status"><div class="alert-content">
|
||
<p class="text-sm">Das Limit an Tool-Schritten für eine Antwort ist erreicht; die KI hat den Stand zusammengefasst.</p>
|
||
{% if latest %}
|
||
<form hx-post="/chats/{{ m.chat_session_id }}/messages" hx-target="#messages" hx-swap="beforeend">
|
||
<input type="hidden" name="_csrf" value="{{ p.csrf }}">
|
||
<input type="hidden" name="content" value="Bitte mach dort weiter, wo du aufgehört hast.">
|
||
<button class="btn btn-primary btn-sm" type="submit">Weiterarbeiten</button>
|
||
</form>
|
||
{% endif %}
|
||
</div></div>
|
||
{% endif %}
|
||
<div class="aiw-message-actions">
|
||
<button class="btn btn-ghost btn-xs" type="button" data-copy>Kopieren</button>
|
||
{% with message_id = m.id, fb = (feedback|default({})).get(m.id), thanks = false %}{% include "_feedback.html" %}{% endwith %}
|
||
</div>
|
||
{% else %}
|
||
<div class="aiw-message">{{ m.content }}</div>
|
||
{% if (m.usage or {}).get('command') and m.items %}
|
||
<details class="text-sm">
|
||
<summary class="text-muted">An die KI gesendet</summary>
|
||
<div class="aiw-message text-sm">{{ m.items[0].content }}</div>
|
||
</details>
|
||
{% endif %}
|
||
{% endif %}
|
||
</div>
|
||
</article>
|