Skip to content

feat(dotAI): Dot AI LangChain4J - Amazon Bedrock#35242

Draft
ihoffmann-dot wants to merge 10 commits intodot-ai-langchain-azure-openaifrom
dot-ai-langchain-amazon-bedrock
Draft

feat(dotAI): Dot AI LangChain4J - Amazon Bedrock#35242
ihoffmann-dot wants to merge 10 commits intodot-ai-langchain-azure-openaifrom
dot-ai-langchain-amazon-bedrock

Conversation

@ihoffmann-dot
Copy link
Copy Markdown
Member

Summary

Adds AWS Bedrock as a supported provider. Bedrock is a managed platform that
proxies multiple model families (Anthropic, Amazon Titan, Cohere, Meta, etc.)
via a unified Converse API — a single integration covers all of them.

  • Add langchain4j-bedrock dependency
  • Add bedrock case to LangChain4jModelFactory switch
  • Implement buildBedrockChatModel using BedrockRuntimeClient with explicit or IAM role credentials
  • Implement buildBedrockEmbeddingModel with automatic Titan/Cohere dispatch by model ID prefix
  • Add embeddingInputType field to ProviderConfig (Cohere-specific; default: search_document)
  • buildBedrockImageModel throws UnsupportedOperationException (no LangChain4J support)
  • Add 4 unit tests in LangChain4jModelFactoryTest

Configuration

{
  "chat": {
    "provider": "bedrock",
    "region": "us-east-1",
    "accessKeyId": "...",
    "secretAccessKey": "...",
    "model": "anthropic.claude-3-5-sonnet-20241022-v2:0",
    "maxTokens": 16384,
    "temperature": 1.0
  },
  "embeddings": {
    "provider": "bedrock",
    "region": "us-east-1",
    "accessKeyId": "...",
    "secretAccessKey": "...",
    "model": "amazon.titan-embed-text-v2:0"
  }
}

Notes

  • If accessKeyId / secretAccessKey are omitted, credentials resolve via DefaultCredentialsProvider (IAM role, environment, ~/.aws/credentials).
  • Embedding dispatch: model IDs starting with cohere. → BedrockCohereEmbeddingModel; all others → BedrockTitanEmbeddingModel.
  • embeddingInputType is Cohere-only. Use search_document when indexing content, search_query when embedding a search query. Titan silently ignores this field.
  • Image generation via Bedrock is not available through LangChain4J. Attempting it throws UnsupportedOperationException.

Related Issue

This PR fixes #35183
EPIC: dotAI Multi-Provider Support #33970

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

❌ Issue Linking Required

This PR could not be linked to an issue. All PRs must be linked to an issue for tracking purposes.

How to fix this:

Option 1: Add keyword to PR body (Recommended - auto-removes this comment)
Edit this PR description and add one of these lines:

  • This PR fixes #123 or Fixes: #123

  • This PR closes #123 or Closes: #123

  • This PR resolves #123 or Resolves: #123

  • Other supported keywords: fix, fixed, close, closed, resolve, resolved
    Option 2: Link via GitHub UI (Note: won't clear the failed check)

  1. Go to the PR → Development section (right sidebar)

  2. Click "Link issue" and select an existing issue

  3. Push a new commit or re-run the workflow to clear the failed check
    Option 3: Use branch naming
    Create a new branch with one of these patterns:

  • 123-feature-description (number at start)

  • issue-123-feature-description (issue-number at start)

  • feature-issue-123 (issue-number anywhere)

Why is this required?

Issue linking ensures proper tracking, documentation, and helps maintain project history. It connects your code changes to the problem they solve.---

This comment was automatically generated by the issue linking workflow

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Apr 7, 2026

Claude finished @ihoffmann-dot's task in 1m 41s —— View job


PR Review

  • Read changed files
  • Analyze for issues
  • Post review

Issues

1. Resource leak — AWS clients are never closed (LangChain4jModelFactory.java:271-283)

bedrockClient() and bedrockAsyncClient() each return a new BedrockRuntimeClient / BedrockRuntimeAsyncClient on every call. These hold internal HTTP connection pools and thread pools and implement Closeable. They're passed into model builders but ownership is not transferred — LangChain4J won't close an externally-supplied client. Nothing in this call site closes them. Each model construction leaks a client. Fix this →

2. Silent fallback on partial credentials (LangChain4jModelFactory.java:263-268)

if (config.accessKeyId() != null && config.secretAccessKey() != null) {

If a user sets accessKeyId but forgets secretAccessKey (or vice versa), the code silently falls through to DefaultCredentialsProvider. They'll get IAM-role credentials with no warning, or an IAM auth failure with a cryptic message. Should throw IllegalArgumentException when exactly one of the two is present. Fix this →

3. Streaming model silently drops temperature and maxTokens (LangChain4jModelFactory.java:299-303)

buildBedrockStreamingChatModel ignores config.temperature() and config.maxTokens() entirely. buildBedrockChatModel applies both via BedrockChatRequestParameters. If BedrockStreamingChatModel.builder() supports request parameters, they should be applied here too. If it doesn't, it should be documented. Fix this →

4. Redundant .region() on chat model builder (LangChain4jModelFactory.java:287-289)

BedrockChatModel.builder()
    .modelId(config.model())
    .region(Region.of(config.region()))   // ← redundant
    .client(bedrockClient(config));       // ← client already has the region

When an explicit .client() is provided, the builder's .region() is typically ignored. This is harmless today but will confuse anyone who later removes the .client() call expecting region to still be set. Pick one approach: either pass the client (and remove the redundant .region()), or don't pass a client and let the builder construct one using .region() and .credentialsProvider() (which also fixes issue #1).

5. No validation of embeddingInputType (ProviderConfig.java:80-81)

Any string is accepted. Cohere's API will reject invalid values at inference time with an opaque error. The two supported values (search_document, search_query) are well-known and could be validated in validateBedrock with a clear error message. Minor, but a sharper user experience.

6. Growing build() method signature (LangChain4jModelFactory.java:102-106)

Adding Bedrock required adding a fourth positional Function<ProviderConfig, T> parameter. Adding vertex_ai will require a fifth. A Map<String, Function<ProviderConfig, T>> passed at each call site (or a registration approach) would remove the need to change the method signature for each new provider. This is a design smell to address before the next provider lands.


The dependency and BOM wiring (langchain4j-bedrock without an explicit version, resolved through langchain4j-bom) is correct per project conventions.

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Apr 7, 2026

Claude finished @ihoffmann-dot's task in 54s —— View job


I'll analyze this and get back to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant