From 9adea6c5657900503f39ad2da9ef57c28ef7a1cf Mon Sep 17 00:00:00 2001 From: rxliuli Date: Fri, 23 Aug 2024 17:10:38 +0800 Subject: [PATCH 1/4] anthropic support custom create client --- libs/langchain-anthropic/package.json | 1 + libs/langchain-anthropic/src/chat_models.ts | 14 +++++-- .../src/tests/chat_models.int.test.ts | 14 +++++++ yarn.lock | 40 +++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/libs/langchain-anthropic/package.json b/libs/langchain-anthropic/package.json index fe8027f36ffb..6e037683cd15 100644 --- a/libs/langchain-anthropic/package.json +++ b/libs/langchain-anthropic/package.json @@ -42,6 +42,7 @@ "zod-to-json-schema": "^3.22.4" }, "devDependencies": { + "@anthropic-ai/vertex-sdk": "^0.4.1", "@jest/globals": "^29.5.0", "@langchain/scripts": ">=0.1.0 <0.2.0", "@langchain/standard-tests": "0.0.0", diff --git a/libs/langchain-anthropic/src/chat_models.ts b/libs/langchain-anthropic/src/chat_models.ts index 11d683cba8cc..bb32842a260a 100644 --- a/libs/langchain-anthropic/src/chat_models.ts +++ b/libs/langchain-anthropic/src/chat_models.ts @@ -145,6 +145,8 @@ export interface AnthropicInput { * @default true */ streamUsage?: boolean; + + createClient?: (options: ClientOptions) => Anthropic } /** @@ -604,13 +606,15 @@ export class ChatAnthropicMessages< clientOptions: ClientOptions; // Used for non-streaming requests - protected batchClient: Anthropic; + protected batchClient!: Anthropic; // Used for streaming requests - protected streamingClient: Anthropic; + protected streamingClient!: Anthropic; streamUsage = true; + createClient: (options: ClientOptions) => Anthropic; + constructor(fields?: AnthropicInput & BaseChatModelParams) { super(fields ?? {}); @@ -644,6 +648,8 @@ export class ChatAnthropicMessages< this.streaming = fields?.streaming ?? false; this.streamUsage = fields?.streamUsage ?? this.streamUsage; + + this.createClient = fields?.createClient ?? ((options: ClientOptions) => new Anthropic(options)); } getLsParams(options: this["ParsedCallOptions"]): LangSmithParams { @@ -908,7 +914,7 @@ export class ChatAnthropicMessages< ): Promise> { if (!this.streamingClient) { const options_ = this.apiUrl ? { baseURL: this.apiUrl } : undefined; - this.streamingClient = new Anthropic({ + this.streamingClient = this.createClient({ ...this.clientOptions, ...options_, apiKey: this.apiKey, @@ -938,7 +944,7 @@ export class ChatAnthropicMessages< if (!this.apiKey) { throw new Error("Missing Anthropic API key."); } - this.batchClient = new Anthropic({ + this.batchClient = this.createClient({ ...this.clientOptions, ...options, apiKey: this.apiKey, diff --git a/libs/langchain-anthropic/src/tests/chat_models.int.test.ts b/libs/langchain-anthropic/src/tests/chat_models.int.test.ts index 29d12a22dcb5..03791af3e638 100644 --- a/libs/langchain-anthropic/src/tests/chat_models.int.test.ts +++ b/libs/langchain-anthropic/src/tests/chat_models.int.test.ts @@ -17,6 +17,7 @@ import { import { CallbackManager } from "@langchain/core/callbacks/manager"; import { concat } from "@langchain/core/utils/stream"; import { ChatAnthropic } from "../chat_models.js"; +import { AnthropicVertex } from "@anthropic-ai/vertex-sdk"; test("Test ChatAnthropic", async () => { const chat = new ChatAnthropic({ @@ -735,3 +736,16 @@ test.skip("tool caching", async () => { 0 ); }); + +test.skip("Test ChatAnthropic with custom client", async () => { + const client = new AnthropicVertex(); + const chat = new ChatAnthropic({ + modelName: "claude-3-sonnet-20240229", + maxRetries: 0, + createClient: () => client, + }); + const message = new HumanMessage("Hello!"); + const res = await chat.invoke([message]); + // console.log({ res }); + expect(res.response_metadata.usage).toBeDefined(); +}); diff --git a/yarn.lock b/yarn.lock index 8ab30685e153..bce0658d8392 100644 --- a/yarn.lock +++ b/yarn.lock @@ -211,6 +211,21 @@ __metadata: languageName: node linkType: hard +"@anthropic-ai/sdk@npm:>=0.14 <1": + version: 0.27.0 + resolution: "@anthropic-ai/sdk@npm:0.27.0" + dependencies: + "@types/node": ^18.11.18 + "@types/node-fetch": ^2.6.4 + abort-controller: ^3.0.0 + agentkeepalive: ^4.2.1 + form-data-encoder: 1.7.2 + formdata-node: ^4.3.2 + node-fetch: ^2.6.7 + checksum: 5cb980769a38a660fa607d9985f4cdae7aabc49053b94fe892f6c3b30f2714c32c6e86c6cf94c8bce9ceea6eed2cd5bac2e1d9d58c9aad0da43681f0a060263d + languageName: node + linkType: hard + "@anthropic-ai/sdk@npm:^0.25.2": version: 0.25.2 resolution: "@anthropic-ai/sdk@npm:0.25.2" @@ -226,6 +241,16 @@ __metadata: languageName: node linkType: hard +"@anthropic-ai/vertex-sdk@npm:^0.4.1": + version: 0.4.1 + resolution: "@anthropic-ai/vertex-sdk@npm:0.4.1" + dependencies: + "@anthropic-ai/sdk": ">=0.14 <1" + google-auth-library: ^9.4.2 + checksum: 3983c6f1b0e0aa2ce6896a0269177d1374343ba86169a30ad6cc0d9beef40ddcf410159baaa3f0942afbf62930951d067a870aa5c5e0624fe2c47981dc8d8c55 + languageName: node + linkType: hard + "@apache-arrow/ts@npm:^12.0.0": version: 12.0.0 resolution: "@apache-arrow/ts@npm:12.0.0" @@ -10852,6 +10877,7 @@ __metadata: resolution: "@langchain/anthropic@workspace:libs/langchain-anthropic" dependencies: "@anthropic-ai/sdk": ^0.25.2 + "@anthropic-ai/vertex-sdk": ^0.4.1 "@jest/globals": ^29.5.0 "@langchain/core": ">=0.2.21 <0.3.0" "@langchain/scripts": ">=0.1.0 <0.2.0" @@ -28562,6 +28588,20 @@ __metadata: languageName: node linkType: hard +"google-auth-library@npm:^9.4.2": + version: 9.14.0 + resolution: "google-auth-library@npm:9.14.0" + dependencies: + base64-js: ^1.3.0 + ecdsa-sig-formatter: ^1.0.11 + gaxios: ^6.1.1 + gcp-metadata: ^6.1.0 + gtoken: ^7.0.0 + jws: ^4.0.0 + checksum: ff2a66e84726b3a25711a64583d86cf9e0c0df857d538ce8127822d220e81e1e7d0defcedecb2be7fc407c104bb7d5ca26a4f201bde871c8d09ef72cc83603f8 + languageName: node + linkType: hard + "google-gax@npm:^4.0.3": version: 4.3.3 resolution: "google-gax@npm:4.3.3" From 2c6009ecc6975d4f529a967dbf4d79fde18391df Mon Sep 17 00:00:00 2001 From: rxliuli Date: Tue, 27 Aug 2024 15:02:36 +0800 Subject: [PATCH 2/4] fix: run lint and format --- libs/langchain-anthropic/src/chat_models.ts | 6 ++++-- libs/langchain-anthropic/src/tests/chat_models.int.test.ts | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/langchain-anthropic/src/chat_models.ts b/libs/langchain-anthropic/src/chat_models.ts index bb32842a260a..83e24b8f6897 100644 --- a/libs/langchain-anthropic/src/chat_models.ts +++ b/libs/langchain-anthropic/src/chat_models.ts @@ -146,7 +146,7 @@ export interface AnthropicInput { */ streamUsage?: boolean; - createClient?: (options: ClientOptions) => Anthropic + createClient?: (options: ClientOptions) => Anthropic; } /** @@ -649,7 +649,9 @@ export class ChatAnthropicMessages< this.streaming = fields?.streaming ?? false; this.streamUsage = fields?.streamUsage ?? this.streamUsage; - this.createClient = fields?.createClient ?? ((options: ClientOptions) => new Anthropic(options)); + this.createClient = + fields?.createClient ?? + ((options: ClientOptions) => new Anthropic(options)); } getLsParams(options: this["ParsedCallOptions"]): LangSmithParams { diff --git a/libs/langchain-anthropic/src/tests/chat_models.int.test.ts b/libs/langchain-anthropic/src/tests/chat_models.int.test.ts index 03791af3e638..d6864e92aa3d 100644 --- a/libs/langchain-anthropic/src/tests/chat_models.int.test.ts +++ b/libs/langchain-anthropic/src/tests/chat_models.int.test.ts @@ -16,8 +16,8 @@ import { } from "@langchain/core/prompts"; import { CallbackManager } from "@langchain/core/callbacks/manager"; import { concat } from "@langchain/core/utils/stream"; -import { ChatAnthropic } from "../chat_models.js"; import { AnthropicVertex } from "@anthropic-ai/vertex-sdk"; +import { ChatAnthropic } from "../chat_models.js"; test("Test ChatAnthropic", async () => { const chat = new ChatAnthropic({ From 32330966cd19b5926c029cc915aec689fb2906d0 Mon Sep 17 00:00:00 2001 From: jacoblee93 Date: Wed, 4 Sep 2024 12:26:39 -0700 Subject: [PATCH 3/4] Remove unnecessary assertion --- libs/langchain-anthropic/src/chat_models.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/langchain-anthropic/src/chat_models.ts b/libs/langchain-anthropic/src/chat_models.ts index 83e24b8f6897..74fb4e359568 100644 --- a/libs/langchain-anthropic/src/chat_models.ts +++ b/libs/langchain-anthropic/src/chat_models.ts @@ -606,10 +606,10 @@ export class ChatAnthropicMessages< clientOptions: ClientOptions; // Used for non-streaming requests - protected batchClient!: Anthropic; + protected batchClient: Anthropic; // Used for streaming requests - protected streamingClient!: Anthropic; + protected streamingClient: Anthropic; streamUsage = true; From a2b1ceb1bd7ff8bcff1e86edf9a91f58192f6432 Mon Sep 17 00:00:00 2001 From: jacoblee93 Date: Wed, 4 Sep 2024 12:42:27 -0700 Subject: [PATCH 4/4] Adds docs --- .../docs/integrations/chat/anthropic.ipynb | 30 +++++++++++++++++++ docs/core_docs/package.json | 1 + libs/langchain-anthropic/src/chat_models.ts | 13 +++++++- yarn.lock | 1 + 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/docs/core_docs/docs/integrations/chat/anthropic.ipynb b/docs/core_docs/docs/integrations/chat/anthropic.ipynb index 7cf4bbb7c6d0..4786d1f68a9b 100644 --- a/docs/core_docs/docs/integrations/chat/anthropic.ipynb +++ b/docs/core_docs/docs/integrations/chat/anthropic.ipynb @@ -931,6 +931,36 @@ "For more on how prompt caching works, see [Anthropic's docs](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching#how-prompt-caching-works)." ] }, + { + "cell_type": "markdown", + "id": "f8dece4e", + "metadata": {}, + "source": [ + "## Custom clients\n", + "\n", + "Anthropic models [may be hosted on cloud services such as Google Vertex](https://docs.anthropic.com/en/api/claude-on-vertex-ai) that rely on a different underlying client with the same interface as the primary Anthropic client. You can access these services by providing a `createClient` method that returns an initialized instance of an Anthropic client. Here's an example:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00ec6d41", + "metadata": {}, + "outputs": [], + "source": [ + "import { AnthropicVertex } from \"@anthropic-ai/vertex-sdk\";\n", + "\n", + "const customClient = new AnthropicVertex();\n", + "\n", + "const modelWithCustomClient = new ChatAnthropic({\n", + " modelName: \"claude-3-sonnet-20240229\",\n", + " maxRetries: 0,\n", + " createClient: () => customClient,\n", + "});\n", + "\n", + "await modelWithCustomClient.invoke([{ role: \"user\", content: \"Hello!\" }]);" + ] + }, { "cell_type": "markdown", "id": "3a5bb5ca-c3ae-4a58-be67-2cd18574b9a3", diff --git a/docs/core_docs/package.json b/docs/core_docs/package.json index 9a74b1014673..ee79afc2e105 100644 --- a/docs/core_docs/package.json +++ b/docs/core_docs/package.json @@ -30,6 +30,7 @@ "validate": "yarn notebook_validate" }, "dependencies": { + "@anthropic-ai/vertex-sdk": "^0.4.1", "@docusaurus/core": "2.4.3", "@docusaurus/preset-classic": "2.4.3", "@docusaurus/remark-plugin-npm2yarn": "2.4.3", diff --git a/libs/langchain-anthropic/src/chat_models.ts b/libs/langchain-anthropic/src/chat_models.ts index 74fb4e359568..1d561194faa7 100644 --- a/libs/langchain-anthropic/src/chat_models.ts +++ b/libs/langchain-anthropic/src/chat_models.ts @@ -146,7 +146,13 @@ export interface AnthropicInput { */ streamUsage?: boolean; - createClient?: (options: ClientOptions) => Anthropic; + /** + * Optional method that returns an initialized underlying Anthropic client. + * Useful for accessing Anthropic models hosted on other cloud services + * such as Google Vertex. + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + createClient?: (options: ClientOptions) => any; } /** @@ -613,6 +619,11 @@ export class ChatAnthropicMessages< streamUsage = true; + /** + * Optional method that returns an initialized underlying Anthropic client. + * Useful for accessing Anthropic models hosted on other cloud services + * such as Google Vertex. + */ createClient: (options: ClientOptions) => Anthropic; constructor(fields?: AnthropicInput & BaseChatModelParams) { diff --git a/yarn.lock b/yarn.lock index 66bb1a804890..669c640e7d71 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23288,6 +23288,7 @@ __metadata: version: 0.0.0-use.local resolution: "core_docs@workspace:docs/core_docs" dependencies: + "@anthropic-ai/vertex-sdk": ^0.4.1 "@babel/eslint-parser": ^7.18.2 "@docusaurus/core": 2.4.3 "@docusaurus/preset-classic": 2.4.3