-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
langchain[minor]: feat(LLM Integration): WatsonX AI Integration #3399
Merged
Merged
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
295c2d1
base watsonx file
chasemcdo 7d56c63
base setup route
chasemcdo 33091c5
build
chasemcdo d433840
add project id lc secret
chasemcdo 857a0d1
WatsonX AI Functional MVP
chasemcdo cd5adb3
enable custom model parameters
chasemcdo 2386716
enable custom model selection with llama 2 default
chasemcdo 6d5bf19
wrap fetch in `this.caller.call`
chasemcdo fef8725
run format
chasemcdo dac1a29
add request error handling
chasemcdo fbc0aa9
update typedoc string
chasemcdo 6ed469c
yarn format
chasemcdo 94353dc
add watsonx ai example
chasemcdo e053e80
watsonx-ai -> watsonx_ai
chasemcdo c198c91
Add watson x documentation
chasemcdo eaa1e88
delete old files
chasemcdo fd6cd2d
yarn format
chasemcdo bbd6250
add error for missing project id
chasemcdo 90c6d3c
Add setup note about secrets to docs
chasemcdo 8d0f378
format
chasemcdo ed24072
remove redundant count
chasemcdo 0862eb9
add var set on class instantiation example
chasemcdo 2359544
format
chasemcdo 8bc32c4
Merge branch 'langchain-ai:main' into watsonx
chasemcdo a99b22d
update ibm cloud api key to follow common convention
chasemcdo 5ce78f4
Merge branch 'watsonx' of https://github.com/chasemcdo/langchainjs in…
chasemcdo ed87ed4
fix type cast
chasemcdo cc3a0d1
Merge branch 'main' into watsonx
chasemcdo befcbd4
Merge branch 'main' into watsonx
chasemcdo 46e6a7a
update llmType casing
chasemcdo c2814c6
add iam token caching
chasemcdo 76ddf01
Merge branch 'main' into watsonx
chasemcdo f49e04e
use expiration field
chasemcdo 6319947
Merge branch 'watsonx' of https://github.com/chasemcdo/langchainjs in…
chasemcdo fefd080
Merge branch 'main' into watsonx
chasemcdo 56941d5
Merge branch 'main' into watsonx
chasemcdo 1b96f2d
Small style fixes in dos
jacoblee93 e320536
Merge branch 'main' into watsonx
chasemcdo 8085417
Merge branch 'main' into watsonx
chasemcdo 1baeba8
Update watsonx_ai.ts
jacoblee93 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# WatsonX AI | ||
|
||
LangChain.js supports integration with IBM WatsonX AI. Checkout [WatsonX AI](https://www.ibm.com/products/watsonx-ai) for a list of available models. | ||
|
||
## Setup | ||
|
||
You will need to set the following environment variables for using the WatsonX AI API. | ||
|
||
1. `IBM_CLOUD_API_KEY` which can be generated via [IBM Cloud](https://cloud.ibm.com/iam/apikeys) | ||
2. `WATSONX_PROJECT_ID` which can be found in your [project's manage tab](https://dataplatform.cloud.ibm.com/projects/?context=wx) | ||
|
||
Alternatively, these can be set during the WatsonxAI Class instantiation as `ibmCloudApiKey` and `projectId` respectively. | ||
For example: | ||
|
||
```typescript | ||
const model = new WatsonxAI({ | ||
ibmCloudApiKey: "My secret IBM Cloud API Key" | ||
projectId: "My secret WatsonX AI Project id" | ||
}); | ||
``` | ||
|
||
## Usage | ||
|
||
import CodeBlock from "@theme/CodeBlock"; | ||
import WatsonxAiExample from "@examples/llms/watsonx_ai.ts"; | ||
|
||
<CodeBlock language="typescript">{WatsonxAiExample}</CodeBlock> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { WatsonxAI } from "langchain/llms/watsonx_ai"; | ||
|
||
export const run = async () => { | ||
// Note that modelParameters are optional | ||
const model = new WatsonxAI({ | ||
modelId: "meta-llama/llama-2-70b-chat", | ||
modelParameters: { | ||
max_new_tokens: 100, | ||
min_new_tokens: 0, | ||
stop_sequences: [], | ||
repetition_penalty: 1, | ||
}, | ||
}); | ||
|
||
const res = await model.invoke( | ||
"What would be a good company name for a company that makes colorful socks?" | ||
); | ||
|
||
console.log({ res }); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
import { BaseLLMCallOptions, BaseLLMParams, LLM } from "./base.js"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This PR adds code that explicitly requires an environment variable via the |
||
import { getEnvironmentVariable } from "../util/env.js"; | ||
|
||
/** | ||
* The WatsonxAIParams interface defines the input parameters for | ||
* the WatsonxAI class. | ||
*/ | ||
export interface WatsonxAIParams extends BaseLLMParams { | ||
/** | ||
* WatsonX AI Complete Endpoint. | ||
* Can be used if you want a fully custom endpoint. | ||
*/ | ||
endpoint?: string; | ||
/** | ||
* IBM Cloud Compute Region. | ||
* eg. us-south, us-east, etc. | ||
*/ | ||
region?: string; | ||
/** | ||
* WatsonX AI Version. | ||
* Date representing the WatsonX AI Version. | ||
* eg. 2023-05-29 | ||
*/ | ||
version?: string; | ||
/** | ||
* WatsonX AI Key. | ||
* Provide API Key if you do not wish to automatically pull from env. | ||
*/ | ||
ibmCloudApiKey?: string; | ||
/** | ||
* WatsonX AI Key. | ||
* Provide API Key if you do not wish to automatically pull from env. | ||
*/ | ||
projectId?: string; | ||
/** | ||
* Parameters accepted by the WatsonX AI Endpoint. | ||
*/ | ||
modelParameters?: Record<string, unknown>; | ||
/** | ||
* WatsonX AI Model ID. | ||
*/ | ||
modelId?: string; | ||
} | ||
|
||
const endpointConstructor = (region: string, version: string) => | ||
`https://${region}.ml.cloud.ibm.com/ml/v1-beta/generation/text?version=${version}`; | ||
|
||
/** | ||
* The WatsonxAI class is used to interact with Watsonx AI | ||
* Inference Endpoint models. It uses IBM Cloud for authentication. | ||
* This requires your IBM Cloud API Key which is autoloaded if not specified. | ||
*/ | ||
|
||
export class WatsonxAI extends LLM<BaseLLMCallOptions> { | ||
static lc_name() { | ||
return "WatsonxAI"; | ||
} | ||
|
||
get lc_secrets(): { [key: string]: string } | undefined { | ||
return { | ||
ibmCloudApiKey: "IBM_CLOUD_API_KEY", | ||
projectId: "WATSONX_PROJECT_ID", | ||
}; | ||
} | ||
|
||
endpoint: string; | ||
|
||
region = "us-south"; | ||
|
||
version = "2023-05-29"; | ||
|
||
modelId = "meta-llama/llama-2-70b-chat"; | ||
|
||
modelKwargs?: Record<string, unknown>; | ||
|
||
ibmCloudApiKey?: string; | ||
|
||
ibmCloudToken?: string; | ||
|
||
ibmCloudTokenExpiresAt?: number; | ||
|
||
projectId?: string; | ||
|
||
modelParameters?: Record<string, unknown>; | ||
|
||
constructor(fields: WatsonxAIParams) { | ||
super(fields); | ||
|
||
this.region = fields?.region ?? this.region; | ||
this.version = fields?.version ?? this.version; | ||
this.modelId = fields?.modelId ?? this.modelId; | ||
this.ibmCloudApiKey = | ||
fields?.ibmCloudApiKey ?? getEnvironmentVariable("IBM_CLOUD_API_KEY"); | ||
this.projectId = | ||
fields?.projectId ?? getEnvironmentVariable("WATSONX_PROJECT_ID"); | ||
|
||
this.endpoint = | ||
fields?.endpoint ?? endpointConstructor(this.region, this.version); | ||
this.modelParameters = fields.modelParameters; | ||
|
||
if (!this.ibmCloudApiKey) { | ||
throw new Error("Missing IBM Cloud API Key"); | ||
} | ||
|
||
if (!this.projectId) { | ||
throw new Error("Missing WatsonX AI Project ID"); | ||
} | ||
} | ||
|
||
_llmType() { | ||
return "watsonx_ai"; | ||
} | ||
|
||
/** | ||
* Calls the WatsonX AI endpoint and retrieves the result. | ||
* @param {string} prompt The input prompt. | ||
* @returns {Promise<string>} A promise that resolves to the generated string. | ||
*/ | ||
/** @ignore */ | ||
async _call( | ||
prompt: string, | ||
_options: this["ParsedCallOptions"] | ||
): Promise<string> { | ||
interface WatsonxAIResponse { | ||
results: { | ||
generated_text: string; | ||
generated_token_count: number; | ||
input_token_count: number; | ||
}[]; | ||
errors: { | ||
code: string; | ||
message: string; | ||
}[]; | ||
} | ||
const response = (await this.caller.call(async () => | ||
fetch(this.endpoint, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
Accept: "application/json", | ||
Authorization: `Bearer ${await this.generateToken()}`, | ||
chasemcdo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
body: JSON.stringify({ | ||
project_id: this.projectId, | ||
model_id: this.modelId, | ||
input: prompt, | ||
parameters: this.modelParameters, | ||
}), | ||
}).then((res) => res.json()) | ||
)) as WatsonxAIResponse; | ||
|
||
/** | ||
* Handle Errors for invalid requests. | ||
*/ | ||
if (response.errors) { | ||
throw new Error(response.errors[0].message); | ||
} | ||
|
||
return response.results[0].generated_text; | ||
} | ||
|
||
async generateToken(): Promise<string> { | ||
if (this.ibmCloudToken && this.ibmCloudTokenExpiresAt) { | ||
if (this.ibmCloudTokenExpiresAt > Date.now()) { | ||
return this.ibmCloudToken; | ||
} | ||
} | ||
|
||
interface TokenResponse { | ||
access_token: string; | ||
expiration: number; | ||
} | ||
|
||
const urlTokenParams = new URLSearchParams(); | ||
urlTokenParams.append( | ||
"grant_type", | ||
"urn:ibm:params:oauth:grant-type:apikey" | ||
); | ||
urlTokenParams.append("apikey", this.ibmCloudApiKey as string); | ||
|
||
const data = (await fetch("https://iam.cloud.ibm.com/identity/token", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
}, | ||
body: urlTokenParams, | ||
}).then((res) => res.json())) as TokenResponse; | ||
|
||
this.ibmCloudTokenExpiresAt = data.expiration * 1000; | ||
this.ibmCloudToken = data.access_token; | ||
|
||
return this.ibmCloudToken; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR adds a new HTTP request using fetch to the WatsonxAI class. This comment is flagging the change for maintainers to review.