diff --git a/api/korrespond.php b/api/korrespond.php index fd9bf0f..a249c84 100644 --- a/api/korrespond.php +++ b/api/korrespond.php @@ -171,6 +171,8 @@ try { if (in_array($inputEngine, ['azure_mini', 'claude_sonnet'], true)) { $engine = $inputEngine; } + $length = in_array($input['length'] ?? '', ['concise', 'standard', 'detailed'], true) + ? (string)$input['length'] : 'standard'; $ftRemaining = dbnToolsFreeTierDeduct($ftUid, 'korrespond'); $creditDeducted = true; @@ -179,7 +181,7 @@ try { : null; // ── Pass 2: retrieve law → draft → self-check → translate ────────────────── - $result = $agent->generate($intake, $classify, $emit, $engine, $personaSlug); + $result = $agent->generate($intake, $classify, $emit, $engine, $personaSlug, $length); $result['ok'] = true; $result['latency_ms'] = (int)round((microtime(true) - $startTime) * 1000); if ($ftRemaining >= 0) { diff --git a/api/summarize.php b/api/summarize.php index d4d0886..2e6de66 100644 --- a/api/summarize.php +++ b/api/summarize.php @@ -11,6 +11,8 @@ $ftUid = dbnToolsFreeTierCheck('summarize'); $input = dbnToolsJsonInput(400000); $language = dbnToolsNormalizeLanguage($input['language'] ?? 'en'); $engine = ToolModels::engineForUser($ftUid, (string)($input['engine'] ?? 'azure_mini')); +$depth = in_array($input['depth'] ?? '', ['brief', 'standard', 'detailed'], true) + ? (string)$input['depth'] : 'standard'; $slices = is_array($input['slices'] ?? null) ? array_values(array_filter($input['slices'])) : []; // Streaming headers — flush each NDJSON line as it's written @@ -68,7 +70,7 @@ try { 'detail' => 'Generating summary…', ]); - $result = (new DbnLegalToolsService())->summarizeWithContext($text, $language, $engine, $corpusContext); + $result = (new DbnLegalToolsService())->summarizeWithContext($text, $language, $engine, $corpusContext, $depth); if ($ftUid > 0) { $balance = dbnToolsFreeTierDeduct($ftUid, 'summarize'); diff --git a/assets/js/korrespond.js b/assets/js/korrespond.js index 0893455..932af30 100644 --- a/assets/js/korrespond.js +++ b/assets/js/korrespond.js @@ -281,6 +281,7 @@ force_draft: !!forceDraft, use_my_case: (typeof window.dbnGetUseMyCase === 'function') ? window.dbnGetUseMyCase() : false, engine: (document.querySelector('[name="korrEngine"]:checked')?.value ?? 'azure_mini'), + length: (document.querySelector('[name="korrLength"]:checked')?.value ?? 'standard'), }; if (korrDocIds.length) payload.doc_ids = korrDocIds; if (persona) payload.profile = persona; diff --git a/assets/js/summarize.js b/assets/js/summarize.js index 2bb2d81..3f69455 100644 --- a/assets/js/summarize.js +++ b/assets/js/summarize.js @@ -186,6 +186,7 @@ text: combined, language: _currentLang, engine: engine, + depth: (document.querySelector('input[name="sumDepth"]:checked') || {}).value || 'standard', slices: slices, }; if (docIds.length) payload.doc_ids = docIds; diff --git a/includes/KorrespondAgent.php b/includes/KorrespondAgent.php index c2474c4..d2edb30 100644 --- a/includes/KorrespondAgent.php +++ b/includes/KorrespondAgent.php @@ -243,7 +243,7 @@ PROMPT; * * @return array Final result payload (matches NDJSON 'final' event shape). */ - public function generate(array $intake, array $classify, ?callable $emit = null, string $engine = 'azure_mini', ?string $persona = null): array + public function generate(array $intake, array $classify, ?callable $emit = null, string $engine = 'azure_mini', ?string $persona = null, string $length = 'standard'): array { $draftDeployment = ($this->azure instanceof DbnBedrockGateway) ? (($engine === 'claude_sonnet' || $engine === 'azure_full') @@ -270,7 +270,7 @@ PROMPT; // ── Draft in Norwegian bokmål ─────────────────────────────────────────── if ($emit) { $emit('progress', ['detail' => self::L('drafting_no', $userLang)]); } $draftNo = $this->draftNorwegian( - $intake, $classify, $retrieval['sources'], $bodyLabel, $outputType, $tone, $goal, $draftDeployment + $intake, $classify, $retrieval['sources'], $bodyLabel, $outputType, $tone, $goal, $draftDeployment, $length ); // ── Self-check: verify citations, deadline, goal, tone ────────────────── @@ -550,7 +550,8 @@ PROMPT; private function draftNorwegian( array $intake, array $classify, array $sources, string $bodyLabel, - string $outputType, string $tone, string $goal, string $draftDeployment = self::DRAFT_DEPLOYMENT + string $outputType, string $tone, string $goal, string $draftDeployment = self::DRAFT_DEPLOYMENT, + string $length = 'standard' ): string { $context = $this->buildContextBlob($intake); $toneLabel = $this->toneLabelNorsk($tone); @@ -574,9 +575,16 @@ PROMPT; $goalLine = $goal !== '' ? ('Brukerens mål: ' . $goal) : 'Brukerens mål: ikke spesifisert — utled fra konteksten.'; + $lengthLabel = match($length) { + 'concise' => 'Kort og poengtert — maks 2-3 avsnitt. Kom raskt til poenget.', + 'detailed' => 'Utfyllende — inkluder full bakgrunn, alle argumenter og rettslig begrunnelse.', + default => 'Standard lengde — 4-6 avsnitt.', + }; + $prompt = <<requirePasteText($text); $engine = in_array($engine, ['azure_mini', 'azure_full', 'gpu'], true) ? $engine : 'azure_mini'; @@ -1870,16 +1871,34 @@ PROMPT; . $text; } + $depthInstructions = match($depth) { + 'brief' => [ + 'what_we_found' => '1-2 sentence executive summary covering the main outcome', + 'key_facts' => 'up to 3 most important facts', + 'coverage' => '', + ], + 'detailed' => [ + 'what_we_found' => 'comprehensive 6-10 sentence summary covering every fact, decision, party, date, and legal implication', + 'key_facts' => 'every fact, decision, and legal reference mentioned in the document', + 'coverage' => "\nCover ALL parties, ALL key decisions, ALL dates, and ALL legal references present in the document. Do not omit facts because they seem minor — err on the side of inclusion.", + ], + default => [ + 'what_we_found' => '3-5 sentence summary covering all key outcomes, parties, and decisions', + 'key_facts' => 'all key facts', + 'coverage' => "\nCover ALL parties, ALL key decisions, ALL dates, and ALL legal references present in the document.", + ], + }; + $prompt = << Conciliatory-warm + +
+ Letter length + + + +
+

Concise: short and to-the-point (2-3 paragraphs). Standard: balanced correspondence. Detailed: full background, all arguments, and complete legal reasoning.

+
Engine diff --git a/summarize.php b/summarize.php index e7ae84e..a2c0396 100644 --- a/summarize.php +++ b/summarize.php @@ -24,6 +24,14 @@ require_once __DIR__ . '/includes/layout.php';

Azure engines use your BNL Azure credits. GPU runs the local LiteLLM proxy on the GPU server.

+
+ Summary depth + + + +
+

Brief: 1-2 sentence executive summary. Standard: balanced summary with all key facts. Detailed: comprehensive — covers every fact, party, date, and legal reference.

+
Legal corpus enrichment (optional)

When one or more slices are enabled, the tool searches the Do Better Norge legal corpus for relevant passages and prepends them to the prompt. All slices are off by default — enable only what applies to your document.