diff --git a/frontend/src/components/LLMSelection/AwsBedrockLLMOptions/index.jsx b/frontend/src/components/LLMSelection/AwsBedrockLLMOptions/index.jsx index 779d487b92..6a966ac295 100644 --- a/frontend/src/components/LLMSelection/AwsBedrockLLMOptions/index.jsx +++ b/frontend/src/components/LLMSelection/AwsBedrockLLMOptions/index.jsx @@ -3,10 +3,21 @@ import { AWS_REGIONS } from "./regions"; import { useState } from "react"; export default function AwsBedrockLLMOptions({ settings }) { - const [useSessionToken, setUseSessionToken] = useState( - settings?.AwsBedrockLLMConnectionMethod === "sessionToken" + const [authMethod, setAuthMethod] = useState( + settings?.AwsBedrockLLMConnectionMethod || "iam" ); + const renderAuthInputs = () => { + switch (authMethod) { + case "profile": + return ; + case "sessionToken": + return ; + default: + return ; + } + }; + return (
{!settings?.credentialsOnly && ( @@ -19,6 +30,7 @@ export default function AwsBedrockLLMOptions({ settings }) { Read more on how to use AWS Bedrock in AnythingLLM @@ -33,101 +45,39 @@ export default function AwsBedrockLLMOptions({ settings }) {

Select the method to authenticate with AWS Bedrock.

- - IAM - - - - Session Token - + {["iam", "sessionToken", "profile"].map((method) => ( + setAuthMethod(method)} + className={`text-sm cursor-pointer ${ + authMethod === method + ? "text-theme-text-primary" + : "text-theme-text-secondary" + }`} + > + {method === "iam" + ? "IAM User" + : method === "sessionToken" + ? "Session Token" + : "Profile"} + + ))}
-
- - -
-
- - -
- {useSessionToken && ( -
- - -
- )} + {renderAuthInputs()}
); } + +function IAMUserInputs({ settings }) { + return ( + <> +
+ + +
+
+ + +
+ + ); +} + +function SessionTokenInputs({ settings }) { + return ( + <> + +
+ + +
+ + ); +} + +function ProfileInputs({ settings }) { + return ( +
+ + +
+ ); +} diff --git a/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx b/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx index f4cead2b81..ab91a4483f 100644 --- a/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx +++ b/frontend/src/pages/GeneralSettings/LLMPreference/index.jsx @@ -253,12 +253,7 @@ export const AVAILABLE_LLM_PROVIDERS = [ logo: AWSBedrockLogo, options: (settings) => , description: "Run powerful foundation models privately with AWS Bedrock.", - requiredConfig: [ - "AwsBedrockLLMAccessKeyId", - "AwsBedrockLLMAccessKey", - "AwsBedrockLLMRegion", - "AwsBedrockLLMModel", - ], + requiredConfig: ["AwsBedrockLLMRegion", "AwsBedrockLLMModel"], }, { name: "APIpie", diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js index 1af5d8cdd9..2e6d64f5cc 100644 --- a/server/models/systemSettings.js +++ b/server/models/systemSettings.js @@ -527,6 +527,7 @@ const SystemSettings = { AwsBedrockLLMAccessKeyId: !!process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID, AwsBedrockLLMAccessKey: !!process.env.AWS_BEDROCK_LLM_ACCESS_KEY, AwsBedrockLLMSessionToken: !!process.env.AWS_BEDROCK_LLM_SESSION_TOKEN, + AwsBedrockLLMProfileName: process.env.AWS_BEDROCK_LLM_PROFILE_NAME, AwsBedrockLLMRegion: process.env.AWS_BEDROCK_LLM_REGION, AwsBedrockLLMModel: process.env.AWS_BEDROCK_LLM_MODEL_PREFERENCE, AwsBedrockLLMTokenLimit: process.env.AWS_BEDROCK_LLM_MODEL_TOKEN_LIMIT, diff --git a/server/utils/AiProviders/bedrock/index.js b/server/utils/AiProviders/bedrock/index.js index 171d7b4595..3e8f6df9ec 100644 --- a/server/utils/AiProviders/bedrock/index.js +++ b/server/utils/AiProviders/bedrock/index.js @@ -25,22 +25,40 @@ class AWSBedrockLLM { ]; constructor(embedder = null, modelPreference = null) { - if (!process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID) - throw new Error("No AWS Bedrock LLM profile id was set."); - - if (!process.env.AWS_BEDROCK_LLM_ACCESS_KEY) - throw new Error("No AWS Bedrock LLM access key was set."); + const method = process.env.AWS_BEDROCK_LLM_CONNECTION_METHOD || "iam"; - if (!process.env.AWS_BEDROCK_LLM_REGION) + if (!process.env.AWS_BEDROCK_LLM_REGION) { throw new Error("No AWS Bedrock LLM region was set."); + } + + if (method === "profile") { + if (!process.env.AWS_BEDROCK_LLM_PROFILE_NAME) { + throw new Error( + "No AWS Bedrock LLM profile name was set for profile authentication method." + ); + } + } else { + if (!process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID) { + throw new Error( + "No AWS Bedrock LLM access key ID was set for iam authentication method." + ); + } + if (!process.env.AWS_BEDROCK_LLM_ACCESS_KEY) { + throw new Error( + "No AWS Bedrock LLM access key was set for iam authentication method." + ); + } - if ( - process.env.AWS_BEDROCK_LLM_CONNECTION_METHOD === "sessionToken" && - !process.env.AWS_BEDROCK_LLM_SESSION_TOKEN - ) - throw new Error( - "No AWS Bedrock LLM session token was set while using session token as the authentication method." - ); + // Additional validation for sessionToken method + if ( + method === "sessionToken" && + !process.env.AWS_BEDROCK_LLM_SESSION_TOKEN + ) { + throw new Error( + "No AWS Bedrock LLM session token was set while using session token as the authentication method." + ); + } + } this.model = modelPreference || process.env.AWS_BEDROCK_LLM_MODEL_PREFERENCE; @@ -59,12 +77,12 @@ class AWSBedrockLLM { /** * Get the authentication method for the AWS Bedrock LLM. - * There are only two valid values for this setting - anything else will default to "iam". - * @returns {"iam"|"sessionToken"} + * There are only three valid values for this setting - anything else will default to "iam". + * @returns {"iam"|"sessionToken"|"profile"} */ get authMethod() { const method = process.env.AWS_BEDROCK_LLM_CONNECTION_METHOD || "iam"; - if (!["iam", "sessionToken"].includes(method)) return "iam"; + if (!["iam", "sessionToken", "profile"].includes(method)) return "iam"; return method; } @@ -73,13 +91,19 @@ class AWSBedrockLLM { return new ChatBedrockConverse({ model: this.model, region: process.env.AWS_BEDROCK_LLM_REGION, - credentials: { - accessKeyId: process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID, - secretAccessKey: process.env.AWS_BEDROCK_LLM_ACCESS_KEY, - ...(this.authMethod === "sessionToken" - ? { sessionToken: process.env.AWS_BEDROCK_LLM_SESSION_TOKEN } - : {}), - }, + ...(this.authMethod === "profile" + ? { + profile: process.env.AWS_BEDROCK_LLM_PROFILE_NAME, + } + : { + credentials: { + accessKeyId: process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_BEDROCK_LLM_ACCESS_KEY, + ...(this.authMethod === "sessionToken" && { + sessionToken: process.env.AWS_BEDROCK_LLM_SESSION_TOKEN, + }), + }, + }), temperature, }); } diff --git a/server/utils/agents/aibitat/providers/ai-provider.js b/server/utils/agents/aibitat/providers/ai-provider.js index bd7920611b..d0acaf0598 100644 --- a/server/utils/agents/aibitat/providers/ai-provider.js +++ b/server/utils/agents/aibitat/providers/ai-provider.js @@ -116,16 +116,28 @@ class Provider { ), ...config, }); - case "bedrock": + case "bedrock": { + const awsAuthMethod = + process.env.AWS_BEDROCK_LLM_CONNECTION_METHOD || "iam"; return new ChatBedrockConverse({ model: process.env.AWS_BEDROCK_LLM_MODEL_PREFERENCE, region: process.env.AWS_BEDROCK_LLM_REGION, - credentials: { - accessKeyId: process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID, - secretAccessKey: process.env.AWS_BEDROCK_LLM_ACCESS_KEY, - }, + ...(awsAuthMethod === "profile" + ? { + profile: process.env.AWS_BEDROCK_LLM_PROFILE_NAME, + } + : { + credentials: { + accessKeyId: process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_BEDROCK_LLM_ACCESS_KEY, + ...(awsAuthMethod === "sessionToken" && { + sessionToken: process.env.AWS_BEDROCK_LLM_SESSION_TOKEN, + }), + }, + }), ...config, }); + } case "fireworksai": return new ChatOpenAI({ apiKey: process.env.FIREWORKS_AI_LLM_API_KEY, diff --git a/server/utils/agents/aibitat/providers/bedrock.js b/server/utils/agents/aibitat/providers/bedrock.js index 6cdb92897a..c3db907a1a 100644 --- a/server/utils/agents/aibitat/providers/bedrock.js +++ b/server/utils/agents/aibitat/providers/bedrock.js @@ -19,15 +19,19 @@ class AWSBedrockProvider extends InheritMultiple([Provider, UnTooled]) { const model = process.env.AWS_BEDROCK_LLM_MODEL_PREFERENCE ?? null; const client = new ChatBedrockConverse({ region: process.env.AWS_BEDROCK_LLM_REGION, - credentials: { - accessKeyId: process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID, - secretAccessKey: process.env.AWS_BEDROCK_LLM_ACCESS_KEY, - // If we're using a session token, we need to pass it in as a credential - // otherwise we must omit it so it does not conflict if using IAM auth - ...(this.authMethod === "sessionToken" - ? { sessionToken: process.env.AWS_BEDROCK_LLM_SESSION_TOKEN } - : {}), - }, + ...(this.authMethod === "profile" + ? { + profile: process.env.AWS_BEDROCK_LLM_PROFILE_NAME, + } + : { + credentials: { + accessKeyId: process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_BEDROCK_LLM_ACCESS_KEY, + ...(this.authMethod === "sessionToken" && { + sessionToken: process.env.AWS_BEDROCK_LLM_SESSION_TOKEN, + }), + }, + }), model, }); @@ -38,12 +42,12 @@ class AWSBedrockProvider extends InheritMultiple([Provider, UnTooled]) { /** * Get the authentication method for the AWS Bedrock LLM. - * There are only two valid values for this setting - anything else will default to "iam". - * @returns {"iam"|"sessionToken"} + * There are only three valid values for this setting - anything else will default to "iam". + * @returns {"iam"|"sessionToken"|"profile"} */ get authMethod() { const method = process.env.AWS_BEDROCK_LLM_CONNECTION_METHOD || "iam"; - if (!["iam", "sessionToken"].includes(method)) return "iam"; + if (!["iam", "sessionToken", "profile"].includes(method)) return "iam"; return method; } diff --git a/server/utils/agents/index.js b/server/utils/agents/index.js index 2263a59682..b88a6cfac3 100644 --- a/server/utils/agents/index.js +++ b/server/utils/agents/index.js @@ -140,14 +140,26 @@ class AgentHandler { ); break; case "bedrock": - if ( - !process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID || - !process.env.AWS_BEDROCK_LLM_ACCESS_KEY || - !process.env.AWS_BEDROCK_LLM_REGION - ) - throw new Error( - "AWS Bedrock Access Keys and region must be provided to use agents." - ); + if (process.env.AWS_BEDROCK_LLM_CONNECTION_METHOD === "profile") { + if ( + !process.env.AWS_BEDROCK_LLM_PROFILE_NAME || + !process.env.AWS_BEDROCK_LLM_REGION + ) { + throw new Error( + "AWS Bedrock requires a profile name and region to use agents for the profile authentication method." + ); + } + } else { + if ( + !process.env.AWS_BEDROCK_LLM_ACCESS_KEY_ID || + !process.env.AWS_BEDROCK_LLM_ACCESS_KEY || + !process.env.AWS_BEDROCK_LLM_REGION + ) { + throw new Error( + "AWS Bedrock requires valid access keys and a region to use agents for the iam authentication method." + ); + } + } break; case "fireworksai": if (!process.env.FIREWORKS_AI_LLM_API_KEY) diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js index bdf4e63d68..89bb6a895b 100644 --- a/server/utils/helpers/updateENV.js +++ b/server/utils/helpers/updateENV.js @@ -219,7 +219,9 @@ const KEY_MAPPING = { envKey: "AWS_BEDROCK_LLM_CONNECTION_METHOD", checks: [ (input) => - ["iam", "sessionToken"].includes(input) ? null : "Invalid value", + ["iam", "sessionToken", "profile"].includes(input) + ? null + : "Invalid value", ], }, AwsBedrockLLMAccessKeyId: { @@ -234,6 +236,10 @@ const KEY_MAPPING = { envKey: "AWS_BEDROCK_LLM_SESSION_TOKEN", checks: [], }, + AwsBedrockLLMProfileName: { + envKey: "AWS_BEDROCK_LLM_PROFILE_NAME", + checks: [isNotEmpty], + }, AwsBedrockLLMRegion: { envKey: "AWS_BEDROCK_LLM_REGION", checks: [isNotEmpty],