83 lines
6.3 KiB
HTML
83 lines
6.3 KiB
HTML
{% extends "ui/templates/base/layout.html" %}
|
|
{% block content %}
|
|
<div class="space-y-6">
|
|
<div class="flex flex-wrap items-start justify-between gap-3">
|
|
<div>
|
|
<p class="text-xs font-semibold uppercase tracking-[0.16em] text-brand-600">Accounting Intelligence · Phase 13</p>
|
|
<h1 class="mt-1 text-2xl font-semibold text-slate-900">ARRR Internal Accounting Model</h1>
|
|
<p class="mt-1 max-w-4xl text-sm text-slate-500">Tenant-specific model trained only from accountant-reviewed outcomes. No external AI API is required. New models start in shadow mode and never post to Tally.</p>
|
|
</div>
|
|
<a href="/tools/accounting/ai" class="rounded-xl border border-slate-300 bg-white px-4 py-2 text-sm font-semibold">Phase 12 AI</a>
|
|
</div>
|
|
|
|
{% if message %}<div class="rounded-xl border border-emerald-200 bg-emerald-50 p-3 text-sm text-emerald-800">{{ message }}</div>{% endif %}
|
|
{% if error %}<div class="rounded-xl border border-red-200 bg-red-50 p-3 text-sm text-red-800">{{ error }}</div>{% endif %}
|
|
|
|
<section class="rounded-2xl bg-white p-5 shadow-soft">
|
|
<div class="grid gap-4 md:grid-cols-4">
|
|
<div><div class="text-xs uppercase text-slate-500">Runtime</div><div class="mt-1 font-semibold">{{ 'Internal model enabled' if summary.enabled else 'Shadow only' }}</div></div>
|
|
<div><div class="text-xs uppercase text-slate-500">Apply threshold</div><div class="mt-1 font-semibold">{{ '%.0f'|format(summary.minimum_apply_probability * 100) }}%</div></div>
|
|
<div><div class="text-xs uppercase text-slate-500">Shadow predictions</div><div class="mt-1 font-semibold">{{ summary.predictions }}</div></div>
|
|
<div><div class="text-xs uppercase text-slate-500">Reviewed live accuracy</div><div class="mt-1 font-semibold">{{ summary.live_accuracy }}%</div></div>
|
|
</div>
|
|
<p class="mt-3 text-xs text-slate-500">To allow an active model to update suggestions after shadow validation, set ACCOUNTING_INTERNAL_MODEL_ENABLED=true on the ERP server. Even then it changes only the suggested Accounting Nature; ledger mapping and human review remain unchanged.</p>
|
|
</section>
|
|
|
|
<section class="rounded-2xl bg-white p-5 shadow-soft">
|
|
<div class="flex flex-wrap gap-3">
|
|
<form method="post" action="/tools/accounting/internal-model/train">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<button class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white">Train New Model from Reviewed Data</button>
|
|
</form>
|
|
<form method="post" action="/tools/accounting/internal-model/deactivate">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<button class="rounded-xl border border-slate-300 bg-white px-4 py-2 text-sm font-semibold">Return All Models to Shadow</button>
|
|
</form>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="rounded-2xl bg-white shadow-soft">
|
|
<div class="border-b border-slate-200 px-5 py-4"><h2 class="font-semibold">Model versions</h2></div>
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full text-sm">
|
|
<thead><tr class="border-b bg-slate-50 text-left text-xs uppercase text-slate-500"><th class="px-3 py-3">Version</th><th class="px-3 py-3">Training</th><th class="px-3 py-3">Classes</th><th class="px-3 py-3">Validation</th><th class="px-3 py-3">Top-2</th><th class="px-3 py-3">Status</th><th class="px-3 py-3"></th></tr></thead>
|
|
<tbody>
|
|
{% for m in summary.models %}
|
|
<tr class="border-b border-slate-100">
|
|
<td class="px-3 py-3"><div class="font-semibold">{{ m.version_label }}</div><div class="text-xs text-slate-500">{{ m.algorithm }}</div></td>
|
|
<td class="px-3 py-3">{{ m.training_examples }} train / {{ m.validation_examples }} validation</td>
|
|
<td class="px-3 py-3">{{ m.class_count }} · {{ m.vocabulary_size }} features</td>
|
|
<td class="px-3 py-3">{{ '%.1f'|format(m.validation_accuracy * 100) }}%</td>
|
|
<td class="px-3 py-3">{{ '%.1f'|format(m.validation_top2_accuracy * 100) }}%</td>
|
|
<td class="px-3 py-3">{{ 'Active' if m.is_active else 'Shadow' }}</td>
|
|
<td class="px-3 py-3">{% if not m.is_active %}<form method="post" action="/tools/accounting/internal-model/{{ m.id }}/activate"><input type="hidden" name="csrf_token" value="{{ csrf_token }}"><button class="rounded-lg border border-indigo-300 bg-indigo-50 px-3 py-1 text-xs font-semibold text-indigo-800">Mark Active</button></form>{% endif %}</td>
|
|
</tr>
|
|
{% else %}<tr><td colspan="7" class="px-4 py-10 text-center text-slate-500">No internal model trained yet.</td></tr>{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="rounded-2xl bg-white shadow-soft">
|
|
<div class="border-b border-slate-200 px-5 py-4"><h2 class="font-semibold">Recent shadow/live predictions</h2><p class="text-sm text-slate-500">{{ summary.reviewed_predictions }} reviewed · {{ summary.correct_predictions }} correct · {{ summary.applied_predictions }} applied to suggestions</p></div>
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full text-sm">
|
|
<thead><tr class="border-b bg-slate-50 text-left text-xs uppercase text-slate-500"><th class="px-3 py-3">Source</th><th class="px-3 py-3">Model</th><th class="px-3 py-3">Nature ID</th><th class="px-3 py-3">Probability</th><th class="px-3 py-3">Mode</th><th class="px-3 py-3">Outcome</th></tr></thead>
|
|
<tbody>
|
|
{% for p in predictions %}
|
|
<tr class="border-b border-slate-100">
|
|
<td class="px-3 py-3">{{ p.source_type }} #{{ p.source_record_id }}</td>
|
|
<td class="px-3 py-3">#{{ p.model_id }}</td>
|
|
<td class="px-3 py-3">{{ p.predicted_nature_id }}</td>
|
|
<td class="px-3 py-3">{{ '%.1f'|format(p.predicted_probability * 100) }}%</td>
|
|
<td class="px-3 py-3">{{ 'Shadow' if p.shadow_mode else 'Live suggestion' }}</td>
|
|
<td class="px-3 py-3">{% if p.prediction_correct is sameas true %}<span class="text-emerald-700">Correct</span>{% elif p.prediction_correct is sameas false %}<span class="text-amber-700">Corrected by reviewer</span>{% else %}Awaiting review{% endif %}</td>
|
|
</tr>
|
|
{% else %}<tr><td colspan="6" class="px-4 py-10 text-center text-slate-500">No model predictions yet.</td></tr>{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
{% endblock %}
|