Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AWS credential profile support for AWS Bedrock #2951

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 118 additions & 84 deletions frontend/src/components/LLMSelection/AwsBedrockLLMOptions/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 <ProfileInputs settings={settings} />;
case "sessionToken":
return <SessionTokenInputs settings={settings} />;
default:
return <IAMUserInputs settings={settings} />;
}
};

return (
<div className="w-full flex flex-col">
{!settings?.credentialsOnly && (
Expand All @@ -19,6 +30,7 @@ export default function AwsBedrockLLMOptions({ settings }) {
<a
href="https://docs.anythingllm.com/setup/llm-configuration/cloud/aws-bedrock"
target="_blank"
rel="noreferrer"
className="underline flex gap-x-1 items-center"
>
Read more on how to use AWS Bedrock in AnythingLLM
Expand All @@ -33,101 +45,39 @@ export default function AwsBedrockLLMOptions({ settings }) {
<input
type="hidden"
name="AwsBedrockLLMConnectionMethod"
value={useSessionToken ? "sessionToken" : "iam"}
value={authMethod}
/>
<div className="flex flex-col w-full">
<label className="text-theme-text-primary text-sm font-semibold block mb-3">
Use session token
Authentication Method
</label>
<p className="text-theme-text-secondary text-sm">
Select the method to authenticate with AWS Bedrock.
</p>
</div>
<div className="flex items-center justify-start gap-x-4 bg-theme-settings-input-bg p-2.5 rounded-lg w-fit">
<span
className={`text-sm ${
!useSessionToken
? "text-theme-text-primary"
: "text-theme-text-secondary"
}`}
>
IAM
</span>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
className="sr-only peer"
checked={useSessionToken}
onChange={(e) => setUseSessionToken(e.target.checked)}
/>
<div className="w-11 h-6 bg-[#4b5563] light:bg-[#e5e7eb] peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-[#d1d5db] light:after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary-button"></div>
</label>
<span
className={`text-sm ${
useSessionToken
? "text-theme-text-primary"
: "text-theme-text-secondary"
}`}
>
Session Token
</span>
{["iam", "sessionToken", "profile"].map((method) => (
<span
key={method}
onClick={() => 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"}
</span>
))}
</div>
</div>

<div className="w-full flex items-center gap-[36px] my-1.5">
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
AWS Bedrock IAM Access ID
</label>
<input
type="password"
name="AwsBedrockLLMAccessKeyId"
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="AWS Bedrock IAM User Access ID"
defaultValue={
settings?.AwsBedrockLLMAccessKeyId ? "*".repeat(20) : ""
}
required={true}
autoComplete="off"
spellCheck={false}
/>
</div>
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
AWS Bedrock IAM Access Key
</label>
<input
type="password"
name="AwsBedrockLLMAccessKey"
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="AWS Bedrock IAM User Access Key"
defaultValue={
settings?.AwsBedrockLLMAccessKey ? "*".repeat(20) : ""
}
required={true}
autoComplete="off"
spellCheck={false}
/>
</div>
{useSessionToken && (
<div className="flex flex-col w-60">
<label className="text-theme-text-primary text-sm font-semibold block mb-3">
AWS Bedrock Session Token
</label>
<input
type="password"
name="AwsBedrockLLMSessionToken"
className="border-none bg-theme-settings-input-bg text-theme-text-primary placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="AWS Bedrock Session Token"
defaultValue={
settings?.AwsBedrockLLMSessionToken ? "*".repeat(20) : ""
}
required={true}
autoComplete="off"
spellCheck={false}
/>
</div>
)}
{renderAuthInputs()}
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
AWS region
Expand Down Expand Up @@ -189,3 +139,87 @@ export default function AwsBedrockLLMOptions({ settings }) {
</div>
);
}

function IAMUserInputs({ settings }) {
return (
<>
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
AWS Bedrock IAM Access ID
</label>
<input
type="password"
name="AwsBedrockLLMAccessKeyId"
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="AWS Bedrock IAM User Access ID"
defaultValue={
settings?.AwsBedrockLLMAccessKeyId ? "*".repeat(20) : ""
}
required={true}
autoComplete="off"
spellCheck={false}
/>
</div>
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
AWS Bedrock IAM Access Key
</label>
<input
type="password"
name="AwsBedrockLLMAccessKey"
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="AWS Bedrock IAM User Access Key"
defaultValue={settings?.AwsBedrockLLMAccessKey ? "*".repeat(20) : ""}
required={true}
autoComplete="off"
spellCheck={false}
/>
</div>
</>
);
}

function SessionTokenInputs({ settings }) {
return (
<>
<IAMUserInputs settings={settings} />
<div className="flex flex-col w-60">
<label className="text-theme-text-primary text-sm font-semibold block mb-3">
AWS Bedrock Session Token
</label>
<input
type="password"
name="AwsBedrockLLMSessionToken"
className="border-none bg-theme-settings-input-bg text-theme-text-primary placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="AWS Bedrock Session Token"
defaultValue={
settings?.AwsBedrockLLMSessionToken ? "*".repeat(20) : ""
}
required={true}
autoComplete="off"
spellCheck={false}
/>
</div>
</>
);
}

function ProfileInputs({ settings }) {
return (
<div className="flex flex-col w-60">
<label className="text-white text-sm font-semibold block mb-3">
AWS Credential Profile
</label>
<input
type="text"
name="AwsBedrockLLMProfileName"
className="border-none bg-theme-settings-input-bg text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
placeholder="AWS Credential Profile name"
defaultValue={settings?.AwsBedrockLLMProfileName || ""}
required={true}
autoComplete="off"
spellCheck={false}
/>
</div>
);
}
7 changes: 1 addition & 6 deletions frontend/src/pages/GeneralSettings/LLMPreference/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,7 @@ export const AVAILABLE_LLM_PROVIDERS = [
logo: AWSBedrockLogo,
options: (settings) => <AWSBedrockLLMOptions settings={settings} />,
description: "Run powerful foundation models privately with AWS Bedrock.",
requiredConfig: [
"AwsBedrockLLMAccessKeyId",
"AwsBedrockLLMAccessKey",
"AwsBedrockLLMRegion",
"AwsBedrockLLMModel",
],
requiredConfig: ["AwsBedrockLLMRegion", "AwsBedrockLLMModel"],
},
{
name: "APIpie",
Expand Down
1 change: 1 addition & 0 deletions server/models/systemSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
70 changes: 47 additions & 23 deletions server/utils/AiProviders/bedrock/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand All @@ -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,
});
}
Expand Down
22 changes: 17 additions & 5 deletions server/utils/agents/aibitat/providers/ai-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading