Add AWS Bedrock three-tier gateway routing (LiteLLM via Colin)

Routes AI tools across three tiers based on task complexity:
- Azure GPT-4o-mini always: redact, translate, timeline-basic, search-legal (mechanical tasks)
- Claude Haiku 4.5 (Bedrock): ask, summarize, timeline-deep, citations (Norwegian nuance)
- Claude Sonnet 4.6 (Bedrock): korrespond, legal-analysis, deep-research, barnevernet-analyze,
  discrepancy-find, advocate (public-facing legal output)

No AWS credentials in app — credentials live in LiteLLM on Colin (same as nova-lite).
Rollback: DBN_BEDROCK_ENABLED=false in .env, no code push needed.

Includes extended thinking support for Pro deep-research via chatWithThinking().
Claude Opus 4.7 constant added for future premium tier (needs litellm_config.yaml entry).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 15:22:48 +02:00
parent 17ad54cf36
commit 8a11001bff
11 changed files with 520 additions and 43 deletions
+35 -7
View File
@@ -3,6 +3,8 @@ declare(strict_types=1);
require_once __DIR__ . '/bootstrap.php';
require_once __DIR__ . '/AzureOpenAiGateway.php';
require_once __DIR__ . '/DbnGatewayFactory.php';
require_once __DIR__ . '/DbnBedrockModelRouter.php';
final class DbnDeepResearchAgent
{
@@ -13,13 +15,13 @@ final class DbnDeepResearchAgent
private const MIN_CHUNK_WORDS = 50;
private const POOL_CAP = 30;
private DbnAzureOpenAiGateway $azure;
private DbnAzureOpenAiGateway|DbnBedrockGateway $azure;
private array $uploadVecs = [];
private array $stepTimings = [];
public function __construct(?DbnAzureOpenAiGateway $azure = null)
public function __construct(DbnAzureOpenAiGateway|DbnBedrockGateway|null $azure = null)
{
$this->azure = $azure ?: new DbnAzureOpenAiGateway();
$this->azure = $azure ?: DbnGatewayFactory::makeForTool('deep-research');
}
public function run(
@@ -984,8 +986,10 @@ PROMPT;
'dbn_legal' => 'dbn-legal-agent-v2',
'dbn_legal_v3' => 'dbn-legal-agent-v3',
'azure_full' => 'gpt-4o',
'claude_sonnet'=> 'Claude 3.5 Sonnet',
default => $this->azure->chatDeployment(),
},
'thinking_trace'=> null,
];
}
@@ -1118,8 +1122,9 @@ PROMPT;
['role' => 'system', 'content' => 'You return valid JSON only. No markdown fences. Every legal claim must be supported by a source from the numbered list. Do not invent statute sections, case names, paragraph numbers, or dates. If no source supports a point, omit it entirely.'],
['role' => 'user', 'content' => $prompt],
];
$synthTemp = ($advocateRole !== '') ? min($temperature, 0.20) : $temperature;
$opts = ['json' => true, 'temperature' => $synthTemp, 'max_tokens' => 4000, 'timeout' => 180];
$synthTemp = ($advocateRole !== '') ? min($temperature, 0.20) : $temperature;
$opts = ['json' => true, 'temperature' => $synthTemp, 'max_tokens' => 4000, 'timeout' => 180];
$thinkingTrace = null;
try {
if ($engine === 'dbn_legal_v3') {
@@ -1137,6 +1142,28 @@ PROMPT;
} elseif ($engine === 'azure_full') {
$raw = $this->azure->withDeployment('gpt-4o')->chatText($messages, $opts);
$deployLabel = 'gpt-4o';
} elseif ($engine === 'claude_sonnet' || ($this->azure instanceof DbnBedrockGateway)) {
if (
$this->azure instanceof DbnBedrockGateway
&& dbnToolsEnv('DBN_BEDROCK_THINKING_ENABLED', 'false') === 'true'
&& DbnBedrockModelRouter::supportsThinking($this->azure->chatDeployment())
) {
// Extended thinking — Pro showcase
$thinkResult = $this->azure->chatWithThinking($messages, [
'max_tokens' => 16000,
'thinking_budget'=> (int)dbnToolsEnv('DBN_BEDROCK_THINKING_BUDGET', '8000'),
'timeout' => 300,
]);
$raw = $thinkResult['text'];
$thinkingTrace = $thinkResult['thinking'] ?? null;
$deployLabel = 'Claude 3.5 Sonnet (extended thinking)';
} else {
$raw = $this->azure->chatText($messages, $opts);
$thinkingTrace = null;
$deployLabel = $this->azure instanceof DbnBedrockGateway
? 'Claude 3.5 Sonnet'
: $this->azure->chatDeployment();
}
} else {
$raw = $this->azure->chatText($messages, $opts);
$deployLabel = $this->azure->chatDeployment();
@@ -1157,8 +1184,9 @@ PROMPT;
}
return [
'json' => $json,
'deploy_label' => $deployLabel,
'json' => $json,
'deploy_label' => $deployLabel,
'thinking_trace'=> $thinkingTrace,
];
}