7e6463ed22
Restores the dbn-legal-agent-v3 fine-tune on ocelot (was silently aliased to plain qwen2.5:14b in LiteLLM since the viper retirement) and ships a new tool that uses it via a two-pass flow: Pass 1 (Azure 4o-mini) → extract up to 5 distinct legal issues Pass 2 (ocelot v3 only) → answer each issue, ≤350 tokens, with corpus Pass 3 (Azure 4o-mini) → synthesise overall assessment + next steps The 12GB-VRAM constraint motivates the split: dbn-legal-agent-v3 stays hot in VRAM through the 5 sequential per-issue calls because issue extraction and synthesis run on Azure, not on ocelot. New surface: - includes/LegalAnalysisAgent.php - api/legal-analysis.php (NDJSON streaming endpoint) - legal-analysis.php (dedicated tool page) - assets/js/legal-analysis.js (streamed UI with per-issue cards) - Save-result + case-result.php rendering for legal-analysis output - Nav registration in all four UI languages Add-on integration: a "⚖️🇳🇴 Run deep legal analysis on this text" button now appears on Summarize, Ask, and Redact result pages and streams the same pipeline inline below the existing result. Existing tools relabelled: the misleading "🇳🇴 Norwegian specialist v3 ⭐" option on advocate/deep-research/discrepancy/barnevernet is now honestly "DBN Legal Agent" — now that the real fine-tune is actually deployed, the label finally matches reality. The advocate.php v2 option was removed since the v2 GGUF is retired. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
105 lines
7.3 KiB
PHP
105 lines
7.3 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
$toolName = 'legal-analysis';
|
|
$toolTitle = 'Legal Analysis';
|
|
$toolKind = 'Deep Legal Q&A';
|
|
$toolBadge = 'Two-pass';
|
|
$extraScripts = ['assets/js/legal-analysis.js'];
|
|
require_once __DIR__ . '/includes/layout.php';
|
|
?>
|
|
<form id="laForm" class="tool-form" novalidate>
|
|
|
|
<div class="lang-switcher" id="laLangSwitcher" role="group" aria-label="UI language">
|
|
<button type="button" class="lang-btn la-lang-btn is-active" data-lang="no">🇳🇴 NO</button>
|
|
<button type="button" class="lang-btn la-lang-btn" data-lang="en">🇬🇧 EN</button>
|
|
</div>
|
|
|
|
<div class="control-row" id="laDocTypeControl">
|
|
<span class="control-label">Document type</span>
|
|
<label><input type="radio" name="laDocType" value="auto" checked> Auto-detect</label>
|
|
<label><input type="radio" name="laDocType" value="barnevernet"> Barnevernet</label>
|
|
<label><input type="radio" name="laDocType" value="adopsjon"> Adopsjon</label>
|
|
<label><input type="radio" name="laDocType" value="emergency"> Akutt-plassering</label>
|
|
<label><input type="radio" name="laDocType" value="samvær"> Samvær</label>
|
|
<label><input type="radio" name="laDocType" value="fylkesnemnd"> Fylkesnemnd</label>
|
|
<label><input type="radio" name="laDocType" value="other"> Annet</label>
|
|
</div>
|
|
|
|
<p class="upload-hint">
|
|
Engine: <strong>dbn-legal-agent-v3</strong> (Norwegian legal fine-tune on GPU). Expect ~30-60 seconds per issue, up to 5 issues per run.
|
|
</p>
|
|
|
|
<div id="docPickerSection" class="doc-picker-section">
|
|
<button type="button" id="docPickerBtn" class="doc-picker-btn" aria-haspopup="dialog">
|
|
<svg class="doc-picker-btn__icon" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><rect x="2" y="1" width="9" height="12" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M5 5h5M5 8h3" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/><rect x="7" y="9" width="6" height="5" rx="1" fill="white" stroke="currentColor" stroke-width="1.3"/><path d="M9 11h2M9 12.5h1" stroke="currentColor" stroke-width="1" stroke-linecap="round"/></svg>
|
|
<span>Select from My Docs</span>
|
|
</button>
|
|
<div id="docPickerChips" class="doc-picker-chips" aria-label="Selected documents"></div>
|
|
<input type="hidden" id="docPickerIds" name="doc_ids" value="">
|
|
</div>
|
|
|
|
<div class="upload-zone" id="laUploadZone" role="region" aria-label="File upload">
|
|
<input type="file" id="laUploadInput" multiple accept=".pdf,.docx,.txt" aria-label="Choose files to analyse">
|
|
<div id="laUploadPrompt" class="upload-prompt">
|
|
<span class="upload-icon" aria-hidden="true">⇧</span>
|
|
<p>Drop up to 5 files here, or <label for="laUploadInput" class="upload-browse">browse</label></p>
|
|
<p class="upload-hint"><strong>PDF</strong>, <strong>DOCX</strong>, <strong>TXT</strong> — text extracted in memory, never stored</p>
|
|
</div>
|
|
<div id="laUploadFileInfo" class="upload-file is-hidden">
|
|
<ul id="laUploadFileList" class="upload-file-list"></ul>
|
|
<button type="button" id="laUploadClear" class="upload-clear">× Clear files</button>
|
|
</div>
|
|
</div>
|
|
|
|
<label class="input-label" for="laInput">Pasted text <small class="control-hint">(optional if file or doc selected)</small></label>
|
|
<textarea id="laInput" name="text" rows="8" placeholder="Paste a case note, court decision, vedtak, brev, or any legal document text. You can also upload a file or select from My Docs above — at least one source is required."></textarea>
|
|
|
|
<div class="form-footer">
|
|
<p id="laStatus" class="form-status" role="status" aria-live="polite"></p>
|
|
<button id="laRunButton" type="submit">Run legal analysis</button>
|
|
</div>
|
|
</form>
|
|
|
|
<section id="laResults" class="results" aria-live="polite">
|
|
<div class="empty-state">
|
|
<h3>Ready</h3>
|
|
<p>Upload a document or paste text — the tool will extract up to 5 distinct legal issues, then ask the Norwegian-law fine-tune to answer each one with citations.</p>
|
|
<p class="upload-hint">Pass 1 uses Azure GPT-4o-mini to spot issues. Pass 2 calls the dbn-legal-agent-v3 fine-tune on ocelot for each one. Pass 3 synthesises the overall picture. A typical run takes 2-5 minutes.</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Hidden stubs so tools.js element refs don't crash on this page -->
|
|
<div class="is-hidden" id="languageControl" aria-hidden="true">
|
|
<input type="radio" name="language" value="en">
|
|
<input type="radio" name="language" value="no" checked>
|
|
</div>
|
|
<div class="is-hidden" id="redactionControl" aria-hidden="true"></div>
|
|
<div class="is-hidden" id="audioZone" aria-hidden="true">
|
|
<input type="file" id="audioInput" style="display:none">
|
|
<div id="audioPrompt"></div>
|
|
<div id="audioFileInfo"><ol id="audioQueueList"></ol><button type="button" id="audioClear"></button></div>
|
|
</div>
|
|
<div class="is-hidden" id="diarizeControl" aria-hidden="true">
|
|
<input type="checkbox" id="diarizeCheck">
|
|
<input type="number" id="numSpeakersInput">
|
|
</div>
|
|
<div class="is-hidden" id="transcribeLangControl" aria-hidden="true"><input type="radio" name="transcribeLang" value="no" checked></div>
|
|
<div class="is-hidden" id="vocabControl" aria-hidden="true">
|
|
<div id="vocabPresets"></div>
|
|
<textarea id="initPromptInput"></textarea>
|
|
</div>
|
|
<div class="is-hidden" id="aliasSection" aria-hidden="true">
|
|
<button type="button" id="addAliasRow"></button>
|
|
<div id="aliasRows"></div>
|
|
</div>
|
|
<div class="is-hidden" id="exemptSection" aria-hidden="true">
|
|
<button type="button" id="addExemptRow"></button>
|
|
<div id="exemptRows"></div>
|
|
</div>
|
|
<div class="is-hidden" id="uploadZone" aria-hidden="true">
|
|
<input type="file" id="uploadInput">
|
|
<div id="uploadPrompt"></div>
|
|
<div id="uploadFileInfo"><ul id="uploadFileList"></ul><button type="button" id="uploadClear"></button></div>
|
|
</div>
|
|
<?php require_once __DIR__ . '/includes/layout_footer.php'; ?>
|