e09ee62c62
New dbn-tools-redesign.css with warm paper surface, navy tools nav, gold accent, and per-tool themes via body[data-active-tool]. Updated all 21 tool PHP pages, shared layout/nav/footer includes, and advocate route (new). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
301 lines
16 KiB
PHP
301 lines
16 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require_once __DIR__ . '/includes/bootstrap.php';
|
|
|
|
$uiLang = dbnToolsCurrentLanguage();
|
|
$isAuthed = dbnToolsIsAuthenticated();
|
|
$langPath = '/advocate-tech.php';
|
|
$toolsLogin = 'https://dobetternorge.no/tools-login.php?return=' . urlencode('/advocate.php');
|
|
$registerUrl = 'https://dobetternorge.no/register.php';
|
|
$ctaUrl = $isAuthed ? '/advocate.php' : $toolsLogin;
|
|
|
|
$_pt = require __DIR__ . '/translations/advocate-tech.php';
|
|
$t = $_pt[$uiLang] ?? $_pt['en'];
|
|
?>
|
|
<!doctype html>
|
|
<html lang="<?= htmlspecialchars($uiLang) ?>">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Advocate — How it works: Hard-RAG pipeline and fine-tuned LLM · Do Better Norge Tools</title>
|
|
<meta name="description" content="Technical deep-dive into Advocate's 7-step pipeline: adversarial query expansion, hybrid Hard-RAG retrieval, dbn-legal-agent synthesis, and citation confidence verification.">
|
|
<meta name="robots" content="index, follow">
|
|
<link rel="canonical" href="https://tools.dobetternorge.no/advocate-tech.php">
|
|
<meta property="og:title" content="Advocate — How it works: Hard-RAG and fine-tuned Norwegian law LLM">
|
|
<meta property="og:description" content="7-step pipeline: query expansion, slice resolution, hybrid retrieval with RRF and reranking, dbn-legal-agent synthesis, citation confidence. 220K+ passages indexed.">
|
|
<meta property="og:type" content="website">
|
|
<meta name="theme-color" content="#00205B">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;600;700&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap">
|
|
<link rel="stylesheet" href="assets/css/tools.css">
|
|
<link rel="stylesheet" href="assets/css/dbn-tools-redesign.css">
|
|
</head>
|
|
<body class="kdoc-page">
|
|
|
|
<header class="lt-nav">
|
|
<a href="https://dobetternorge.no" class="lt-nav__brand">
|
|
<picture>
|
|
<source srcset="assets/images/logo-header.webp" type="image/webp">
|
|
<img class="lt-nav__logo" src="assets/images/logo-header.png" alt="Do Better Norge" width="140" height="36" loading="eager">
|
|
</picture>
|
|
<span class="lt-nav__badge">Legal Tools</span>
|
|
</a>
|
|
<div class="lt-nav__right">
|
|
<nav class="shell-lang-switcher" aria-label="Language">
|
|
<?php foreach (dbnToolsSupportedLanguages() as $langCode): ?>
|
|
<a href="<?= htmlspecialchars($langPath . '?lang=' . $langCode) ?>" class="<?= $langCode === $uiLang ? 'is-active' : '' ?>"><?= htmlspecialchars(dbnToolsLanguageLabel($langCode)) ?></a>
|
|
<?php endforeach; ?>
|
|
</nav>
|
|
<?php if ($isAuthed): ?>
|
|
<a href="/advocate.php" class="lt-nav__cta lt-nav__cta--enter"><?= htmlspecialchars($t['nav_open']) ?></a>
|
|
<?php else: ?>
|
|
<a href="<?= htmlspecialchars($toolsLogin) ?>" class="lt-nav__cta"><?= htmlspecialchars($t['nav_signin']) ?></a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</header>
|
|
|
|
<nav class="kdoc-doc-nav" aria-label="Advocate documentation">
|
|
<div class="kdoc-doc-nav__inner">
|
|
<a href="/advocate-about.php"><?= htmlspecialchars($t['nav_about']) ?></a>
|
|
<a href="/advocate-guide.php"><?= htmlspecialchars($t['nav_guide']) ?></a>
|
|
<a href="/advocate-tech.php" class="is-active"><?= htmlspecialchars($t['nav_howit']) ?></a>
|
|
<?php if ($isAuthed): ?>
|
|
<a href="/advocate.php"><?= htmlspecialchars($t['nav_opentool']) ?></a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Hero -->
|
|
<section class="kdoc-hero" style="background: linear-gradient(rgba(5,15,40,0.85),rgba(5,15,40,0.92)), url('assets/images/advocate/hero-tech.png') center/cover no-repeat;">
|
|
<div class="kdoc-hero__inner">
|
|
<p class="kdoc-hero__kicker"><?= htmlspecialchars($t['hero_kicker']) ?></p>
|
|
<h1 class="kdoc-hero__title"><?= htmlspecialchars($t['hero_title']) ?></h1>
|
|
<p class="kdoc-hero__sub"><?= htmlspecialchars($t['hero_sub']) ?></p>
|
|
|
|
<div class="kdoc-hero__stats">
|
|
<div class="kdoc-hero__stat">
|
|
<strong>220K+</strong>
|
|
<span><?= htmlspecialchars($t['stat_legal']) ?></span>
|
|
</div>
|
|
<div class="kdoc-hero__stat">
|
|
<strong>8</strong>
|
|
<span><?= htmlspecialchars($t['stat_slices']) ?></span>
|
|
</div>
|
|
<div class="kdoc-hero__stat">
|
|
<strong>7</strong>
|
|
<span><?= htmlspecialchars($t['stat_steps']) ?></span>
|
|
</div>
|
|
<div class="kdoc-hero__stat">
|
|
<strong>dbn</strong>
|
|
<span><?= htmlspecialchars($t['stat_model']) ?></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- 7-step pipeline -->
|
|
<div class="kdoc-section">
|
|
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['pipe_eyebrow']) ?></p>
|
|
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['pipe_title']) ?></h2>
|
|
<p class="kdoc-section__sub"><?= htmlspecialchars($t['pipe_sub']) ?></p>
|
|
|
|
<div class="kdoc-pipeline">
|
|
<div class="kdoc-pipeline__step">
|
|
<span class="kdoc-pipeline__num">1</span>
|
|
<h3 class="kdoc-pipeline__title"><?= htmlspecialchars($t['step1_title']) ?></h3>
|
|
<p class="kdoc-pipeline__body"><?= htmlspecialchars($t['step1_body']) ?></p>
|
|
</div>
|
|
<span class="kdoc-pipeline__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-pipeline__step">
|
|
<span class="kdoc-pipeline__num">2</span>
|
|
<h3 class="kdoc-pipeline__title"><?= htmlspecialchars($t['step2_title']) ?></h3>
|
|
<p class="kdoc-pipeline__body"><?= htmlspecialchars($t['step2_body']) ?></p>
|
|
</div>
|
|
<span class="kdoc-pipeline__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-pipeline__step">
|
|
<span class="kdoc-pipeline__num">3</span>
|
|
<h3 class="kdoc-pipeline__title"><?= htmlspecialchars($t['step3_title']) ?></h3>
|
|
<p class="kdoc-pipeline__body"><?= htmlspecialchars($t['step3_body']) ?></p>
|
|
</div>
|
|
<span class="kdoc-pipeline__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-pipeline__step">
|
|
<span class="kdoc-pipeline__num">4</span>
|
|
<h3 class="kdoc-pipeline__title"><?= htmlspecialchars($t['step4_title']) ?></h3>
|
|
<p class="kdoc-pipeline__body"><?= htmlspecialchars($t['step4_body']) ?></p>
|
|
</div>
|
|
<span class="kdoc-pipeline__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-pipeline__step">
|
|
<span class="kdoc-pipeline__num">5</span>
|
|
<h3 class="kdoc-pipeline__title"><?= htmlspecialchars($t['step5_title']) ?></h3>
|
|
<p class="kdoc-pipeline__body"><?= htmlspecialchars($t['step5_body']) ?></p>
|
|
</div>
|
|
<span class="kdoc-pipeline__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-pipeline__step">
|
|
<span class="kdoc-pipeline__num">6</span>
|
|
<h3 class="kdoc-pipeline__title"><?= htmlspecialchars($t['step6_title']) ?></h3>
|
|
<p class="kdoc-pipeline__body"><?= htmlspecialchars($t['step6_body']) ?></p>
|
|
</div>
|
|
<span class="kdoc-pipeline__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-pipeline__step">
|
|
<span class="kdoc-pipeline__num">7</span>
|
|
<h3 class="kdoc-pipeline__title"><?= htmlspecialchars($t['step7_title']) ?></h3>
|
|
<p class="kdoc-pipeline__body"><?= htmlspecialchars($t['step7_body']) ?></p>
|
|
</div>
|
|
</div>
|
|
|
|
<img src="assets/images/advocate/reasoning-pipeline.png" alt="7-step reasoning panel showing query expansion, retrieval, and synthesis completing in sequence" class="kdoc-screenshot" style="margin-top:2rem" loading="lazy">
|
|
</div>
|
|
|
|
<!-- Hard-RAG retrieval -->
|
|
<section class="kdoc-section--alt">
|
|
<div class="kdoc-section">
|
|
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['rag_eyebrow']) ?></p>
|
|
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['rag_title']) ?></h2>
|
|
<p class="kdoc-section__sub"><?= htmlspecialchars($t['rag_sub']) ?></p>
|
|
|
|
<div class="kdoc-rag-flow">
|
|
<div class="kdoc-rag-flow__box"><?= htmlspecialchars($t['rag_step1']) ?></div>
|
|
<span class="kdoc-rag-flow__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-rag-flow__box"><?= htmlspecialchars($t['rag_step2']) ?></div>
|
|
<span class="kdoc-rag-flow__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-rag-flow__box"><?= htmlspecialchars($t['rag_step3']) ?></div>
|
|
<span class="kdoc-rag-flow__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-rag-flow__box"><?= htmlspecialchars($t['rag_step4']) ?></div>
|
|
<span class="kdoc-rag-flow__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-rag-flow__box"><?= htmlspecialchars($t['rag_step5']) ?></div>
|
|
<span class="kdoc-rag-flow__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-rag-flow__box"><?= htmlspecialchars($t['rag_step6']) ?></div>
|
|
<span class="kdoc-rag-flow__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-rag-flow__box"><?= htmlspecialchars($t['rag_step7']) ?></div>
|
|
<span class="kdoc-rag-flow__arrow" aria-hidden="true">↓</span>
|
|
<div class="kdoc-rag-flow__box kdoc-rag-flow__box--final"><?= htmlspecialchars($t['rag_step8']) ?></div>
|
|
</div>
|
|
|
|
<img src="assets/images/advocate/sub-questions.png" alt="Sub-question research trail showing retrieved ECHR cases and uploaded document sources" class="kdoc-screenshot" style="margin-top:2rem" loading="lazy">
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Corpus slices -->
|
|
<div class="kdoc-section">
|
|
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['corpus_eyebrow']) ?></p>
|
|
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['corpus_title']) ?></h2>
|
|
<p class="kdoc-section__sub"><?= htmlspecialchars($t['corpus_sub']) ?></p>
|
|
|
|
<div class="kdoc-corpus-stats">
|
|
<div class="kdoc-corpus-stat"><strong>220K+</strong><span>passages indexed</span></div>
|
|
<div class="kdoc-corpus-stat"><strong>8</strong><span>corpus slices</span></div>
|
|
<div class="kdoc-corpus-stat"><strong>1,731</strong><span>tribunal decisions</span></div>
|
|
<div class="kdoc-corpus-stat"><strong>23+</strong><span>ECHR judgments vs Norway</span></div>
|
|
<div class="kdoc-corpus-stat"><strong>nomic-embed</strong><span>embedding model</span></div>
|
|
<div class="kdoc-corpus-stat"><strong>Hybrid</strong><span>BM25 + vector search</span></div>
|
|
</div>
|
|
|
|
<div class="kdoc-chips" style="margin-top:1.5rem">
|
|
<span class="kdoc-chip">family_core</span>
|
|
<span class="kdoc-chip">child_welfare</span>
|
|
<span class="kdoc-chip">echr</span>
|
|
<span class="kdoc-chip">hague_convention</span>
|
|
<span class="kdoc-chip">norwegian_courts</span>
|
|
<span class="kdoc-chip">bufdir_guidance</span>
|
|
<span class="kdoc-chip">broader_legal</span>
|
|
<span class="kdoc-chip">dbn_resources</span>
|
|
</div>
|
|
|
|
<div class="kdoc-table-wrap" style="margin-top:2rem">
|
|
<table class="kdoc-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Party role</th>
|
|
<th>Recommended slices</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td>Biological parents</td><td>family_core · child_welfare · echr · norwegian_courts</td></tr>
|
|
<tr><td>Foster carer / adoptive parent</td><td>child_welfare · echr · bufdir_guidance</td></tr>
|
|
<tr><td>Child (via representative)</td><td>family_core · child_welfare · echr · dbn_resources</td></tr>
|
|
<tr><td>Extended family</td><td>family_core · echr · norwegian_courts</td></tr>
|
|
<tr><td>Barnevernet</td><td>child_welfare · bufdir_guidance · broader_legal</td></tr>
|
|
<tr><td>Cross-border / international</td><td>hague_convention · echr · family_core</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- dbn-legal-agent fine-tune -->
|
|
<section class="kdoc-section--alt">
|
|
<div class="kdoc-section">
|
|
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['llm_eyebrow']) ?></p>
|
|
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['llm_title']) ?></h2>
|
|
<div class="kdoc-llm-spotlight">
|
|
<div>
|
|
<span class="kdoc-llm-spotlight__badge">Fine-tuned model</span>
|
|
<h3 class="kdoc-llm-spotlight__title">dbn-legal-agent</h3>
|
|
<p class="kdoc-llm-spotlight__body"><?= $t['llm_body_html'] ?></p>
|
|
|
|
<div class="kdoc-chips" style="margin-top:1rem">
|
|
<span class="kdoc-chip">QLoRA</span>
|
|
<span class="kdoc-chip">barnevernsloven</span>
|
|
<span class="kdoc-chip">barneloven</span>
|
|
<span class="kdoc-chip">ECHR Art. 8</span>
|
|
<span class="kdoc-chip">child-welfare corpus</span>
|
|
<span class="kdoc-chip">gpt-4o co-pipeline</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="kdoc-table-wrap" style="margin-top:2rem">
|
|
<table class="kdoc-table">
|
|
<thead>
|
|
<tr>
|
|
<th><?= htmlspecialchars($t['llm_table_col1']) ?></th>
|
|
<th><?= htmlspecialchars($t['llm_table_col2']) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td>Query interpretation</td><td>Classifies case type, identifies applicable statute sets</td></tr>
|
|
<tr><td>Query expansion</td><td>Generates adversarial sub-questions framed for the selected party</td></tr>
|
|
<tr><td>Slice resolution</td><td>Maps case facts to relevant corpus slices</td></tr>
|
|
<tr><td>Synthesis — argument structure</td><td>Shapes YOUR STRONGEST ARGUMENTS using child-welfare procedural vocabulary</td></tr>
|
|
<tr><td>Synthesis — brief text</td><td>Drafts partisan advocate brief in grounded legal register</td></tr>
|
|
<tr><td>Synthesis — gaps + uncertainties</td><td>Identifies weaknesses in opposing position from same retrieval pass</td></tr>
|
|
<tr><td>Citation confidence</td><td>Verifies each § number against source passage; flags low-confidence citations</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Privacy by design -->
|
|
<div class="kdoc-section">
|
|
<p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['privacy_eyebrow']) ?></p>
|
|
<h2 class="kdoc-section__title"><?= htmlspecialchars($t['privacy_title']) ?></h2>
|
|
<ul class="kdoc-privacy-list">
|
|
<li><?= htmlspecialchars($t['privacy_p1']) ?></li>
|
|
<li><?= htmlspecialchars($t['privacy_p2']) ?></li>
|
|
<li><?= htmlspecialchars($t['privacy_p3']) ?></li>
|
|
<li><?= htmlspecialchars($t['privacy_p4']) ?></li>
|
|
<li><?= htmlspecialchars($t['privacy_p5']) ?></li>
|
|
<li><?= htmlspecialchars($t['privacy_p6']) ?></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- CTA strip -->
|
|
<section class="kdoc-cta-strip">
|
|
<h2 class="kdoc-cta-strip__title"><?= htmlspecialchars($t['cta_title']) ?></h2>
|
|
<p class="kdoc-cta-strip__sub"><?= htmlspecialchars($t['cta_sub']) ?></p>
|
|
<div class="kdoc-hero__ctas">
|
|
<?php if ($isAuthed): ?>
|
|
<a href="/advocate.php" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_open']) ?></a>
|
|
<?php else: ?>
|
|
<a href="<?= htmlspecialchars($toolsLogin) ?>" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_signin_cta']) ?></a>
|
|
<a href="<?= htmlspecialchars($registerUrl) ?>" class="kdoc-btn-secondary"><?= htmlspecialchars($t['btn_register']) ?></a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</section>
|
|
|
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
|
<script src="assets/js/tools.js" defer></script>
|
|
</body>
|
|
</html>
|