Integrate dbn-legal-agent-v2: upgrade all v1 refs + add Korrespond legal-check
- Replace dbn-legal-agent with dbn-legal-agent-v2 in bootstrap.php (dbnToolsRunLegalCheck), DeepResearchAgent.php (interpretSeed, expandQueries, synthesis fallback, deploy label), BvjAnalyzerAgent.php (check_model label) — 8 locations total - Add dbn-legal-agent-v2 legal threshold check to KorrespondAgent: called after selfCheck() in both generate() and refine(); result surfaced as legal_check[] in the API response - Render legal_check card in korrespond.js using existing bvj-red-flag styles; shows only when non-empty - Add .korr-legal-check CSS block in tools.css Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,14 @@ require_once __DIR__ . '/includes/layout.php';
|
|||||||
<button type="button" class="lang-btn" data-lang="pl">🇵🇱 PL</button>
|
<button type="button" class="lang-btn" data-lang="pl">🇵🇱 PL</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="korr-doc-links">
|
||||||
|
<a href="/advocate-about.php" target="_blank">About this tool</a>
|
||||||
|
<span aria-hidden="true">·</span>
|
||||||
|
<a href="/advocate-guide.php" target="_blank">User guide</a>
|
||||||
|
<span aria-hidden="true">·</span>
|
||||||
|
<a href="/advocate-tech.php" target="_blank">How it works</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Role selector — the defining field for advocate mode -->
|
<!-- Role selector — the defining field for advocate mode -->
|
||||||
<div class="adv-role-row">
|
<div class="adv-role-row">
|
||||||
<label class="control-label" for="advRoleSelect">Who are you representing?</label>
|
<label class="control-label" for="advRoleSelect">Who are you representing?</label>
|
||||||
|
|||||||
@@ -7960,3 +7960,22 @@ body.lt-landing {
|
|||||||
border-bottom-color: var(--dbn-blue);
|
border-bottom-color: var(--dbn-blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Korrespond legal-check card (dbn-legal-agent-v2) ────────────────────── */
|
||||||
|
.korr-legal-check {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 14px 16px;
|
||||||
|
background: rgba(186, 12, 47, 0.04);
|
||||||
|
border: 1px solid rgba(186, 12, 47, 0.15);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
.korr-legal-check__title {
|
||||||
|
margin: 0 0 10px;
|
||||||
|
font-size: 0.92rem;
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
|
.korr-legal-check__title small {
|
||||||
|
font-weight: 400;
|
||||||
|
color: var(--muted, #6b7280);
|
||||||
|
font-size: 0.78em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -574,6 +574,22 @@
|
|||||||
|
|
||||||
${data.disclaimer ? `<p class="upload-hint" style="margin-top:16px;font-style:italic">${esc(data.disclaimer)}</p>` : ''}
|
${data.disclaimer ? `<p class="upload-hint" style="margin-top:16px;font-style:italic">${esc(data.disclaimer)}</p>` : ''}
|
||||||
|
|
||||||
|
${(data.legal_check && data.legal_check.length) ? `
|
||||||
|
<div class="korr-legal-check">
|
||||||
|
<h4 class="korr-legal-check__title">⚖ Legal threshold check <small>(dbn-legal-agent-v2)</small></h4>
|
||||||
|
${data.legal_check.map((f) => `
|
||||||
|
<div class="bvj-red-flag">
|
||||||
|
<div class="bvj-red-flag__head">
|
||||||
|
<div class="bvj-red-flag__desc">${esc(f.description || '')}</div>
|
||||||
|
<span class="bvj-severity bvj-severity-${esc(f.severity || 'low')}">${esc(f.severity || 'low')}</span>
|
||||||
|
</div>
|
||||||
|
${f.legal_basis ? `<span class="bvj-red-flag__legal">${esc(f.legal_basis)}</span>` : ''}
|
||||||
|
${f.what_to_check ? `<details class="bvj-red-flag__details"><summary>What to verify</summary><p class="bvj-red-flag__check">${esc(f.what_to_check)}</p></details>` : ''}
|
||||||
|
</div>
|
||||||
|
`).join('')}
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
|
||||||
<section class="korr-refine-panel" id="korrRefinePanel" aria-labelledby="korrRefineTitle">
|
<section class="korr-refine-panel" id="korrRefinePanel" aria-labelledby="korrRefineTitle">
|
||||||
<h3 id="korrRefineTitle">${esc(t('refine_title'))} <small>${esc(t('one_extra_credit'))}</small></h3>
|
<h3 id="korrRefineTitle">${esc(t('refine_title'))} <small>${esc(t('one_extra_credit'))}</small></h3>
|
||||||
<p class="upload-hint">${esc(t('refine_hint'))}</p>
|
<p class="upload-hint">${esc(t('refine_hint'))}</p>
|
||||||
@@ -682,6 +698,22 @@
|
|||||||
`).join('')}
|
`).join('')}
|
||||||
</div>
|
</div>
|
||||||
</details>` : ''}
|
</details>` : ''}
|
||||||
|
|
||||||
|
${(data.legal_check && data.legal_check.length) ? `
|
||||||
|
<div class="korr-legal-check">
|
||||||
|
<h4 class="korr-legal-check__title">⚖ Legal threshold check <small>(dbn-legal-agent-v2)</small></h4>
|
||||||
|
${data.legal_check.map((f) => `
|
||||||
|
<div class="bvj-red-flag">
|
||||||
|
<div class="bvj-red-flag__head">
|
||||||
|
<div class="bvj-red-flag__desc">${esc(f.description || '')}</div>
|
||||||
|
<span class="bvj-severity bvj-severity-${esc(f.severity || 'low')}">${esc(f.severity || 'low')}</span>
|
||||||
|
</div>
|
||||||
|
${f.legal_basis ? `<span class="bvj-red-flag__legal">${esc(f.legal_basis)}</span>` : ''}
|
||||||
|
${f.what_to_check ? `<details class="bvj-red-flag__details"><summary>What to verify</summary><p class="bvj-red-flag__check">${esc(f.what_to_check)}</p></details>` : ''}
|
||||||
|
</div>
|
||||||
|
`).join('')}
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -968,7 +968,7 @@ PROMPT;
|
|||||||
foreach ($checkFindings as $cf) {
|
foreach ($checkFindings as $cf) {
|
||||||
$json['procedural_red_flags'][] = $cf;
|
$json['procedural_red_flags'][] = $cf;
|
||||||
}
|
}
|
||||||
$json['check_model'] = 'dbn-legal-agent';
|
$json['check_model'] = 'dbn-legal-agent-v2';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -494,7 +494,7 @@ PROMPT;
|
|||||||
$userMsg = ['role' => 'user', 'content' => $prompt];
|
$userMsg = ['role' => 'user', 'content' => $prompt];
|
||||||
if ($language === 'no' || $advocateRole !== '') {
|
if ($language === 'no' || $advocateRole !== '') {
|
||||||
$resp = dbnToolsCallGpuLlm([$sysMsg, $userMsg], [
|
$resp = dbnToolsCallGpuLlm([$sysMsg, $userMsg], [
|
||||||
'model' => 'dbn-legal-agent', 'json' => true,
|
'model' => 'dbn-legal-agent-v2', 'json' => true,
|
||||||
'temperature' => 0.1, 'max_tokens' => 500, 'timeout' => 40,
|
'temperature' => 0.1, 'max_tokens' => 500, 'timeout' => 40,
|
||||||
]);
|
]);
|
||||||
$raw = (string)($resp['choices'][0]['message']['content'] ?? '');
|
$raw = (string)($resp['choices'][0]['message']['content'] ?? '');
|
||||||
@@ -593,7 +593,7 @@ PROMPT;
|
|||||||
$userMsg = ['role' => 'user', 'content' => $prompt];
|
$userMsg = ['role' => 'user', 'content' => $prompt];
|
||||||
if ($language === 'no') {
|
if ($language === 'no') {
|
||||||
$resp = dbnToolsCallGpuLlm([$sysMsg, $userMsg], [
|
$resp = dbnToolsCallGpuLlm([$sysMsg, $userMsg], [
|
||||||
'model' => 'dbn-legal-agent', 'json' => true,
|
'model' => 'dbn-legal-agent-v2', 'json' => true,
|
||||||
'temperature' => 0.2, 'max_tokens' => 700, 'timeout' => 50,
|
'temperature' => 0.2, 'max_tokens' => 700, 'timeout' => 50,
|
||||||
]);
|
]);
|
||||||
$raw = (string)($resp['choices'][0]['message']['content'] ?? '');
|
$raw = (string)($resp['choices'][0]['message']['content'] ?? '');
|
||||||
@@ -981,7 +981,7 @@ PROMPT;
|
|||||||
],
|
],
|
||||||
'deploy_label' => match($engine) {
|
'deploy_label' => match($engine) {
|
||||||
'gpu' => 'GPU (cuttlefish)',
|
'gpu' => 'GPU (cuttlefish)',
|
||||||
'dbn_legal' => 'dbn-legal-agent',
|
'dbn_legal' => 'dbn-legal-agent-v2',
|
||||||
'azure_full'=> 'gpt-4o',
|
'azure_full'=> 'gpt-4o',
|
||||||
default => $this->azure->chatDeployment(),
|
default => $this->azure->chatDeployment(),
|
||||||
},
|
},
|
||||||
@@ -1122,8 +1122,8 @@ PROMPT;
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if ($engine === 'dbn_legal') {
|
if ($engine === 'dbn_legal') {
|
||||||
$response = dbnToolsCallGpuLlm($messages, array_merge($opts, ['model' => 'dbn-legal-agent', 'timeout' => 180]));
|
$response = dbnToolsCallGpuLlm($messages, array_merge($opts, ['model' => 'dbn-legal-agent-v2', 'timeout' => 180]));
|
||||||
$deployLabel = 'dbn-legal-agent';
|
$deployLabel = 'dbn-legal-agent-v2';
|
||||||
$raw = (string)($response['choices'][0]['message']['content'] ?? '');
|
$raw = (string)($response['choices'][0]['message']['content'] ?? '');
|
||||||
} elseif ($engine === 'gpu') {
|
} elseif ($engine === 'gpu') {
|
||||||
$response = dbnToolsCallGpuLlm($messages, $opts);
|
$response = dbnToolsCallGpuLlm($messages, $opts);
|
||||||
|
|||||||
@@ -257,6 +257,12 @@ PROMPT;
|
|||||||
if ($emit) { $emit('progress', ['detail' => self::L('quality_check', $userLang)]); }
|
if ($emit) { $emit('progress', ['detail' => self::L('quality_check', $userLang)]); }
|
||||||
$checked = $this->selfCheck($draftNo, $retrieval['sources'], $classify, $goal, $tone);
|
$checked = $this->selfCheck($draftNo, $retrieval['sources'], $classify, $goal, $tone);
|
||||||
|
|
||||||
|
// ── Legal check: dbn-legal-agent-v2 threshold verification ────────────────
|
||||||
|
$legalCheck = [];
|
||||||
|
try {
|
||||||
|
$legalCheck = dbnToolsRunLegalCheck($checked['draft'], $body);
|
||||||
|
} catch (Throwable $e) { /* silent — non-critical */ }
|
||||||
|
|
||||||
// ── Translate to user language (if not Norwegian) ───────────────────────
|
// ── Translate to user language (if not Norwegian) ───────────────────────
|
||||||
$draftUser = $checked['draft'];
|
$draftUser = $checked['draft'];
|
||||||
if ($userLang !== 'no') {
|
if ($userLang !== 'no') {
|
||||||
@@ -278,6 +284,7 @@ PROMPT;
|
|||||||
'draft_user_lang'=> $userLang,
|
'draft_user_lang'=> $userLang,
|
||||||
'cited_law' => $checked['cited_sources'],
|
'cited_law' => $checked['cited_sources'],
|
||||||
'self_check' => $checked['flags'],
|
'self_check' => $checked['flags'],
|
||||||
|
'legal_check' => $legalCheck,
|
||||||
'applicable_acts'=> $classify['applicable_acts'] ?? [],
|
'applicable_acts'=> $classify['applicable_acts'] ?? [],
|
||||||
'deadlines' => $classify['deadlines'] ?? [],
|
'deadlines' => $classify['deadlines'] ?? [],
|
||||||
'parties' => $classify['parties'] ?? [],
|
'parties' => $classify['parties'] ?? [],
|
||||||
@@ -756,6 +763,11 @@ EOT,
|
|||||||
if ($emit) { $emit('progress', ['detail' => self::L('check_and_authorities', $userLang)]); }
|
if ($emit) { $emit('progress', ['detail' => self::L('check_and_authorities', $userLang)]); }
|
||||||
$checked = $this->selfCheck($refinedNo, $retrieval['sources'], $classify, $goal, $tone);
|
$checked = $this->selfCheck($refinedNo, $retrieval['sources'], $classify, $goal, $tone);
|
||||||
|
|
||||||
|
$legalCheckRefine = [];
|
||||||
|
try {
|
||||||
|
$legalCheckRefine = dbnToolsRunLegalCheck($checked['draft'], $body);
|
||||||
|
} catch (Throwable $e) { /* silent — non-critical */ }
|
||||||
|
|
||||||
$draftUser = $checked['draft'];
|
$draftUser = $checked['draft'];
|
||||||
if ($userLang !== 'no') {
|
if ($userLang !== 'no') {
|
||||||
if ($emit) { $emit('progress', ['detail' => self::L('translating_to', $userLang, ['lang' => dbnToolsLanguageName($userLang)])]); }
|
if ($emit) { $emit('progress', ['detail' => self::L('translating_to', $userLang, ['lang' => dbnToolsLanguageName($userLang)])]); }
|
||||||
@@ -774,6 +786,7 @@ EOT,
|
|||||||
'draft_user_lang'=> $userLang,
|
'draft_user_lang'=> $userLang,
|
||||||
'cited_law' => $checked['cited_sources'],
|
'cited_law' => $checked['cited_sources'],
|
||||||
'self_check' => $checked['flags'],
|
'self_check' => $checked['flags'],
|
||||||
|
'legal_check' => $legalCheckRefine,
|
||||||
'applied_slices' => $retrieval['applied_slices'],
|
'applied_slices' => $retrieval['applied_slices'],
|
||||||
'disclaimer' => dbnToolsDisclaimer($userLang),
|
'disclaimer' => dbnToolsDisclaimer($userLang),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -863,7 +863,7 @@ function dbnToolsRunLegalCheck(string $brief, string $docType): array
|
|||||||
}
|
}
|
||||||
|
|
||||||
$opts = [
|
$opts = [
|
||||||
'model' => 'dbn-legal-agent',
|
'model' => 'dbn-legal-agent-v2',
|
||||||
'temperature' => 0.1,
|
'temperature' => 0.1,
|
||||||
'max_tokens' => 350,
|
'max_tokens' => 350,
|
||||||
'timeout' => 120,
|
'timeout' => 120,
|
||||||
@@ -895,7 +895,7 @@ function dbnToolsRunLegalCheck(string $brief, string $docType): array
|
|||||||
'legal_basis' => dbnToolsExtractCheckLegalBasis($clean),
|
'legal_basis' => dbnToolsExtractCheckLegalBasis($clean),
|
||||||
'source_refs' => [],
|
'source_refs' => [],
|
||||||
'what_to_check'=> 'Verifiser med norsk familieretsadvokat',
|
'what_to_check'=> 'Verifiser med norsk familieretsadvokat',
|
||||||
'check_model' => 'dbn-legal-agent',
|
'check_model' => 'dbn-legal-agent-v2',
|
||||||
]];
|
]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user