Add Legal Analysis tool — two-pass DBN-legal pipeline

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>
This commit is contained in:
2026-05-24 04:21:01 +02:00
parent 2013648ee0
commit 7e6463ed22
14 changed files with 1361 additions and 25 deletions
+12 -8
View File
@@ -33,6 +33,7 @@ final class CaseResults
'ask',
'redact',
'transcribe',
'legal-analysis',
];
/** True when the user is on a tier that gets saved results (Plus, Pro, or active Plus trial). */
@@ -234,10 +235,11 @@ final class CaseResults
'deep-research' => 'Dyp analyse',
'discrepancy' => 'Motstrid',
'timeline' => 'Tidslinje',
'summarize' => 'Sammendrag',
'ask' => 'Spørsmål & svar',
'redact' => 'Anonymisering',
'transcribe' => 'Transkripsjon',
'summarize' => 'Sammendrag',
'ask' => 'Spørsmål & svar',
'redact' => 'Anonymisering',
'transcribe' => 'Transkripsjon',
'legal-analysis' => 'Juridisk analyse',
][$tool] ?? ucfirst($tool);
}
@@ -251,10 +253,11 @@ final class CaseResults
'deep-research' => '🔬',
'discrepancy' => '🔍',
'timeline' => '📅',
'summarize' => '📝',
'ask' => '💬',
'redact' => '🖊️',
'transcribe' => '🎙️',
'summarize' => '📝',
'ask' => '💬',
'redact' => '🖊️',
'transcribe' => '🎙️',
'legal-analysis' => '⚖️🇳🇴',
][$tool] ?? '📄';
}
@@ -272,6 +275,7 @@ final class CaseResults
'ask' => [$input['question'] ?? null],
'redact' => [$input['text'] ?? null],
'transcribe' => [$input['filename'] ?? null],
'legal-analysis' => [$input['doc_type'] ?? null, $input['text'] ?? null],
default => [$input['title'] ?? null, $input['query'] ?? null, $input['text'] ?? null],
};
foreach ($candidates as $c) {